feat: Added file formatting
This commit is contained in:
8
.prettierignore
Normal file
8
.prettierignore
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
angular.json
|
||||||
|
compose.yml
|
||||||
|
*.md
|
||||||
|
tsconfig*.json
|
||||||
|
*.html
|
||||||
|
.vscode
|
||||||
|
package*.json
|
||||||
|
ngsw-config.json
|
||||||
6
.prettierrc
Normal file
6
.prettierrc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"semi": false,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"bracketSpacing": true
|
||||||
|
}
|
||||||
17
package-lock.json
generated
17
package-lock.json
generated
@@ -40,6 +40,7 @@
|
|||||||
"karma-coverage": "~2.2.0",
|
"karma-coverage": "~2.2.0",
|
||||||
"karma-jasmine": "~5.1.0",
|
"karma-jasmine": "~5.1.0",
|
||||||
"karma-jasmine-html-reporter": "~2.0.0",
|
"karma-jasmine-html-reporter": "~2.0.0",
|
||||||
|
"prettier": "3.5.3",
|
||||||
"typescript": "~5.8.3"
|
"typescript": "~5.8.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -7794,6 +7795,22 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/prettier": {
|
||||||
|
"version": "3.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
|
||||||
|
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"prettier": "bin/prettier.cjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/proc-log": {
|
"node_modules/proc-log": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz",
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
"karma-coverage": "~2.2.0",
|
"karma-coverage": "~2.2.0",
|
||||||
"karma-jasmine": "~5.1.0",
|
"karma-jasmine": "~5.1.0",
|
||||||
"karma-jasmine-html-reporter": "~2.0.0",
|
"karma-jasmine-html-reporter": "~2.0.0",
|
||||||
|
"prettier": "3.5.3",
|
||||||
"typescript": "~5.8.3"
|
"typescript": "~5.8.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
:host {
|
:host {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-paginator {
|
mat-paginator {
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-form-field {
|
mat-form-field {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#upper-bar {
|
#upper-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
button[mat-icon-button] {
|
button[mat-icon-button] {
|
||||||
margin-left: 4pt;
|
margin-left: 4pt;
|
||||||
margin-right: 4pt;
|
margin-right: 4pt;
|
||||||
margin-top: 4pt;
|
margin-top: 4pt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +1,50 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { AccountMgmtComponent } from './account-mgmt.component';
|
import { AccountMgmtComponent } from './account-mgmt.component'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog'
|
||||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
import { MatSnackBarModule } from '@angular/material/snack-bar'
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
import { MatPaginatorModule } from '@angular/material/paginator'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
import { MatTableModule } from '@angular/material/table';
|
import { MatTableModule } from '@angular/material/table'
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input'
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'
|
||||||
|
|
||||||
describe('AccountMgmtComponent', () => {
|
describe('AccountMgmtComponent', () => {
|
||||||
let component: AccountMgmtComponent;
|
let component: AccountMgmtComponent
|
||||||
let fixture: ComponentFixture<AccountMgmtComponent>;
|
let fixture: ComponentFixture<AccountMgmtComponent>
|
||||||
let acMock
|
let acMock
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
acMock = {
|
acMock = {
|
||||||
accs: {
|
accs: {
|
||||||
getAccs: jasmine.createSpy("getAccs").and.returnValue(of())
|
getAccs: jasmine.createSpy('getAccs').and.returnValue(of()),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [AccountMgmtComponent],
|
declarations: [AccountMgmtComponent],
|
||||||
providers: [
|
providers: [{ provide: AdminCommService, useValue: acMock }],
|
||||||
{provide: AdminCommService, useValue: acMock}
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
MatFormFieldModule,
|
MatFormFieldModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
MatPaginatorModule,
|
MatPaginatorModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
MatProgressSpinnerModule
|
MatProgressSpinnerModule,
|
||||||
]
|
],
|
||||||
}).compileComponents();
|
}).compileComponents()
|
||||||
fixture = TestBed.createComponent(AccountMgmtComponent);
|
fixture = TestBed.createComponent(AccountMgmtComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,49 +1,57 @@
|
|||||||
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog'
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table'
|
||||||
import { MatPaginator } from '@angular/material/paginator';
|
import { MatPaginator } from '@angular/material/paginator'
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar'
|
||||||
import { UserEditComponent } from './user-edit/user-edit.component';
|
import { UserEditComponent } from './user-edit/user-edit.component'
|
||||||
import { LocalStorageService } from 'src/app/services/local-storage.service';
|
import { LocalStorageService } from 'src/app/services/local-storage.service'
|
||||||
import { Group } from 'src/app/types/group';
|
import { Group } from 'src/app/types/group'
|
||||||
import User from 'src/app/types/user';
|
import User from 'src/app/types/user'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-account-mgmt',
|
selector: 'app-account-mgmt',
|
||||||
templateUrl: './account-mgmt.component.html',
|
templateUrl: './account-mgmt.component.html',
|
||||||
styleUrls: ['./account-mgmt.component.scss'],
|
styleUrls: ['./account-mgmt.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
export class AccountMgmtComponent implements OnInit, AfterViewInit {
|
export class AccountMgmtComponent implements OnInit, AfterViewInit {
|
||||||
protected groups: Group[] = []
|
protected groups: Group[] = []
|
||||||
users: MatTableDataSource<Omit<User, "pass">>
|
users: MatTableDataSource<Omit<User, 'pass'>>
|
||||||
loading = false
|
loading = false
|
||||||
@ViewChild(MatPaginator) paginator!: MatPaginator
|
@ViewChild(MatPaginator) paginator!: MatPaginator
|
||||||
|
|
||||||
constructor(readonly ac:AdminCommService, private dialog: MatDialog, private sb: MatSnackBar, protected readonly ls: LocalStorageService) {
|
constructor(
|
||||||
this.users = new MatTableDataSource<Omit<User, "pass">>();
|
readonly ac: AdminCommService,
|
||||||
this.users.filterPredicate = (data: Record<string, any>, filter: string): boolean => {
|
private dialog: MatDialog,
|
||||||
const dataStr = Object.keys(data).reduce((curr: string, key: string) => {
|
private sb: MatSnackBar,
|
||||||
if (["_id", "admin", "groups", "__v", "locked"].find(v => v == key)) {
|
protected readonly ls: LocalStorageService
|
||||||
return curr + ''
|
) {
|
||||||
}
|
this.users = new MatTableDataSource<Omit<User, 'pass'>>()
|
||||||
return curr + data[key] + '⫂'
|
this.users.filterPredicate = (
|
||||||
}, '').toLowerCase()
|
data: Record<string, any>,
|
||||||
|
filter: string
|
||||||
|
): boolean => {
|
||||||
|
const dataStr = Object.keys(data)
|
||||||
|
.reduce((curr: string, key: string) => {
|
||||||
|
if (['_id', 'admin', 'groups', '__v', 'locked'].find(v => v == key)) {
|
||||||
|
return curr + ''
|
||||||
|
}
|
||||||
|
return curr + data[key] + '⫂'
|
||||||
|
}, '')
|
||||||
|
.toLowerCase()
|
||||||
const filternew = filter.trim().toLowerCase()
|
const filternew = filter.trim().toLowerCase()
|
||||||
return dataStr.indexOf(filternew) != -1
|
return dataStr.indexOf(filternew) != -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
this.users.paginator = this.paginator
|
this.users.paginator = this.paginator
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.ac.accs.getAccs().subscribe((data)=>{
|
this.ac.accs.getAccs().subscribe(data => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.users.data = data.users
|
this.users.data = data.users
|
||||||
this.groups = data.groups
|
this.groups = data.groups
|
||||||
@@ -56,9 +64,18 @@ export class AccountMgmtComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openUserCard(id?: string) {
|
openUserCard(id?: string) {
|
||||||
this.dialog.open<UserEditComponent, UserEditComponent.InputData, UserEditComponent.ReturnData>(UserEditComponent, {data: {id: id, type: id ? "edit" : "new", groups: this.groups}}).afterClosed().subscribe(r => {
|
this.dialog
|
||||||
if (r) this.ngOnInit()
|
.open<
|
||||||
})
|
UserEditComponent,
|
||||||
|
UserEditComponent.InputData,
|
||||||
|
UserEditComponent.ReturnData
|
||||||
|
>(UserEditComponent, {
|
||||||
|
data: { id: id, type: id ? 'edit' : 'new', groups: this.groups },
|
||||||
|
})
|
||||||
|
.afterClosed()
|
||||||
|
.subscribe(r => {
|
||||||
|
if (r) this.ngOnInit()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
collumns = ['name', 'surname', 'uname', 'actions']
|
collumns = ['name', 'surname', 'uname', 'actions']
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { UserDeleteComponent } from './user-delete.component';
|
import { UserDeleteComponent } from './user-delete.component'
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog'
|
||||||
|
|
||||||
describe('UserDeleteComponent', () => {
|
describe('UserDeleteComponent', () => {
|
||||||
let component: UserDeleteComponent;
|
let component: UserDeleteComponent
|
||||||
let fixture: ComponentFixture<UserDeleteComponent>;
|
let fixture: ComponentFixture<UserDeleteComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [UserDeleteComponent],
|
declarations: [UserDeleteComponent],
|
||||||
imports: [MatDialogModule]
|
imports: [MatDialogModule],
|
||||||
});
|
})
|
||||||
fixture = TestBed.createComponent(UserDeleteComponent);
|
fixture = TestBed.createComponent(UserDeleteComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-user-delete',
|
selector: 'app-user-delete',
|
||||||
templateUrl: './user-delete.component.html',
|
templateUrl: './user-delete.component.html',
|
||||||
styleUrls: ['./user-delete.component.scss'],
|
styleUrls: ['./user-delete.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class UserDeleteComponent {
|
export class UserDeleteComponent {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
:host {
|
:host {
|
||||||
padding: 8pt;
|
padding: 8pt;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
margin-top: 1ch !important;
|
margin-top: 1ch !important;
|
||||||
display: flex;
|
display: flex;
|
||||||
grid-auto-flow: column;
|
grid-auto-flow: column;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
column-gap: 3ch;
|
||||||
|
div {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: repeat(5, 1fr);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
button {
|
||||||
column-gap: 3ch;
|
align-self: stretch;
|
||||||
div {
|
justify-self: stretch;
|
||||||
display: grid;
|
height: auto;
|
||||||
grid-template-columns: 1fr;
|
margin-bottom: 1lh;
|
||||||
grid-template-rows: repeat(5, 1fr);
|
|
||||||
align-items: center;
|
|
||||||
button {
|
|
||||||
align-self: stretch;
|
|
||||||
justify-self: stretch;
|
|
||||||
height: auto;
|
|
||||||
margin-bottom: 1lh;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-dialog-actions {
|
mat-dialog-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,26 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { UserEditComponent } from './user-edit.component';
|
import { UserEditComponent } from './user-edit.component'
|
||||||
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
import {
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
MAT_DIALOG_DATA,
|
||||||
import { NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
|
MatDialogModule,
|
||||||
import { MatInputModule } from '@angular/material/input';
|
MatDialogRef,
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
} from '@angular/material/dialog'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { MatFormFieldModule } from '@angular/material/form-field'
|
||||||
import { forwardRef } from '@angular/core';
|
import { NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms'
|
||||||
import { MatSelectModule } from '@angular/material/select';
|
import { MatInputModule } from '@angular/material/input'
|
||||||
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
|
import { forwardRef } from '@angular/core'
|
||||||
|
import { MatSelectModule } from '@angular/material/select'
|
||||||
|
|
||||||
describe('UserEditComponent', () => {
|
describe('UserEditComponent', () => {
|
||||||
let component: UserEditComponent;
|
let component: UserEditComponent
|
||||||
let fixture: ComponentFixture<UserEditComponent>;
|
let fixture: ComponentFixture<UserEditComponent>
|
||||||
let acMock
|
let acMock
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
acMock = {
|
acMock = {}
|
||||||
|
|
||||||
}
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [UserEditComponent],
|
declarations: [UserEditComponent],
|
||||||
imports: [
|
imports: [
|
||||||
@@ -27,20 +29,20 @@ describe('UserEditComponent', () => {
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
NoopAnimationsModule,
|
NoopAnimationsModule,
|
||||||
MatSelectModule
|
MatSelectModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: MatDialogRef, useValue: {} },
|
{ provide: MatDialogRef, useValue: {} },
|
||||||
{ provide: MAT_DIALOG_DATA, useValue: { groups: [] } },
|
{ provide: MAT_DIALOG_DATA, useValue: { groups: [] } },
|
||||||
{ provide: AdminCommService, useValue: acMock },
|
{ provide: AdminCommService, useValue: acMock },
|
||||||
]
|
],
|
||||||
}).compileComponents();
|
}).compileComponents()
|
||||||
fixture = TestBed.createComponent(UserEditComponent);
|
fixture = TestBed.createComponent(UserEditComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,53 +1,57 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core'
|
||||||
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
|
import {
|
||||||
import { FormControl, FormGroup } from '@angular/forms';
|
MAT_DIALOG_DATA,
|
||||||
import { LocalStorageService } from 'src/app/services/local-storage.service';
|
MatDialog,
|
||||||
import { Group } from 'src/app/types/group';
|
MatDialogRef,
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
} from '@angular/material/dialog'
|
||||||
import { UserDeleteComponent } from '../user-delete/user-delete.component';
|
import { FormControl, FormGroup } from '@angular/forms'
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { LocalStorageService } from 'src/app/services/local-storage.service'
|
||||||
import { UserResetComponent } from '../user-reset/user-reset.component';
|
import { Group } from 'src/app/types/group'
|
||||||
import { catchError, throwError } from 'rxjs';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
import { DateTime } from 'luxon';
|
import { UserDeleteComponent } from '../user-delete/user-delete.component'
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar'
|
||||||
|
import { UserResetComponent } from '../user-reset/user-reset.component'
|
||||||
|
import { catchError, throwError } from 'rxjs'
|
||||||
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
export namespace UserEditComponent {
|
export namespace UserEditComponent {
|
||||||
export type InputData = {type: "new" | "edit", id?: string, groups: Group[]}
|
export type InputData = { type: 'new' | 'edit'; id?: string; groups: Group[] }
|
||||||
export type ReturnData = true | undefined
|
export type ReturnData = true | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-user-edit',
|
selector: 'app-user-edit',
|
||||||
templateUrl: './user-edit.component.html',
|
templateUrl: './user-edit.component.html',
|
||||||
styleUrls: ['./user-edit.component.scss'],
|
styleUrls: ['./user-edit.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class UserEditComponent {
|
export class UserEditComponent {
|
||||||
lockout = false;
|
lockout = false
|
||||||
locked = false;
|
locked = false
|
||||||
loading = false;
|
loading = false
|
||||||
form: FormGroup = new FormGroup({
|
form: FormGroup = new FormGroup({
|
||||||
fname: new FormControl<string>(""),
|
fname: new FormControl<string>(''),
|
||||||
surname: new FormControl<string>(""),
|
surname: new FormControl<string>(''),
|
||||||
room: new FormControl<string>(""),
|
room: new FormControl<string>(''),
|
||||||
uname: new FormControl<string>(""),
|
uname: new FormControl<string>(''),
|
||||||
groups: new FormControl<Array<string>>([]),
|
groups: new FormControl<Array<string>>([]),
|
||||||
flags: new FormControl<Array<number>>([]),
|
flags: new FormControl<Array<number>>([]),
|
||||||
})
|
})
|
||||||
groups: Group[]
|
groups: Group[]
|
||||||
id?: string
|
id?: string
|
||||||
regDate?: DateTime;
|
regDate?: DateTime
|
||||||
constructor (
|
constructor(
|
||||||
public dialogRef: MatDialogRef<UserEditComponent>,
|
public dialogRef: MatDialogRef<UserEditComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: UserEditComponent.InputData,
|
@Inject(MAT_DIALOG_DATA) public data: UserEditComponent.InputData,
|
||||||
readonly ls: LocalStorageService,
|
readonly ls: LocalStorageService,
|
||||||
readonly acu: AdminCommService,
|
readonly acu: AdminCommService,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private sb: MatSnackBar
|
private sb: MatSnackBar
|
||||||
) {
|
) {
|
||||||
this.groups = data.groups
|
this.groups = data.groups
|
||||||
if (data.type == "edit") {
|
if (data.type == 'edit') {
|
||||||
this.id = data.id
|
this.id = data.id
|
||||||
this.acu.accs.getUser(data.id!).subscribe((r) => {
|
this.acu.accs.getUser(data.id!).subscribe(r => {
|
||||||
this.regDate = DateTime.fromISO(r.regDate)
|
this.regDate = DateTime.fromISO(r.regDate)
|
||||||
var flags: Array<number> = []
|
var flags: Array<number> = []
|
||||||
if (r.admin) {
|
if (r.admin) {
|
||||||
@@ -62,64 +66,83 @@ export class UserEditComponent {
|
|||||||
}
|
}
|
||||||
this.locked = r.locked ? true : false
|
this.locked = r.locked ? true : false
|
||||||
this.lockout = r.lockout
|
this.lockout = r.lockout
|
||||||
this.form.get("fname")?.setValue(r.fname)
|
this.form.get('fname')?.setValue(r.fname)
|
||||||
this.form.get("surname")?.setValue(r.surname)
|
this.form.get('surname')?.setValue(r.surname)
|
||||||
this.form.get("room")?.setValue(r.room)
|
this.form.get('room')?.setValue(r.room)
|
||||||
this.form.get("uname")?.setValue(r.uname)
|
this.form.get('uname')?.setValue(r.uname)
|
||||||
this.form.get("groups")?.setValue(r.groups)
|
this.form.get('groups')?.setValue(r.groups)
|
||||||
this.form.get("flags")?.setValue(flags)
|
this.form.get('flags')?.setValue(flags)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected submit() {
|
protected submit() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
if (this.data.type == "edit") {
|
if (this.data.type == 'edit') {
|
||||||
this.acu.accs.putAcc(this.id!, this.getForm()).pipe(catchError((err)=>{
|
this.acu.accs
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
.putAcc(this.id!, this.getForm())
|
||||||
return throwError(()=> new Error(err.message))
|
.pipe(
|
||||||
})).subscribe((data)=> {
|
catchError(err => {
|
||||||
if (data.status == 200) {
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
this.sb.open("Użytkownik został zmodyfikowany.", undefined, {duration: 2500})
|
return throwError(() => new Error(err.message))
|
||||||
this.dialogRef.close(true)
|
})
|
||||||
} else {
|
)
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
.subscribe(data => {
|
||||||
this.loading = false
|
if (data.status == 200) {
|
||||||
}
|
this.sb.open('Użytkownik został zmodyfikowany.', undefined, {
|
||||||
})
|
duration: 2500,
|
||||||
|
})
|
||||||
|
this.dialogRef.close(true)
|
||||||
|
} else {
|
||||||
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
this.acu.accs.postAcc(this.getForm()).pipe(catchError((err)=>{
|
this.acu.accs
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
.postAcc(this.getForm())
|
||||||
return throwError(()=> new Error(err.message))
|
.pipe(
|
||||||
})).subscribe((data)=> {
|
catchError(err => {
|
||||||
if (data.status == 201) {
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
this.sb.open("Użytkownik został utworzony.", undefined, {duration: 2500})
|
return throwError(() => new Error(err.message))
|
||||||
this.dialogRef.close(true)
|
})
|
||||||
} else {
|
)
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
.subscribe(data => {
|
||||||
this.loading = false
|
if (data.status == 201) {
|
||||||
}
|
this.sb.open('Użytkownik został utworzony.', undefined, {
|
||||||
})
|
duration: 2500,
|
||||||
|
})
|
||||||
|
this.dialogRef.close(true)
|
||||||
|
} else {
|
||||||
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected disableLockout() {
|
protected disableLockout() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.acu.accs.clearLockout(this.id!).pipe(catchError((err)=>{
|
this.acu.accs
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
.clearLockout(this.id!)
|
||||||
return throwError(()=> new Error(err.message))
|
.pipe(
|
||||||
})).subscribe((s) => {
|
catchError(err => {
|
||||||
if (s.status == 200) {
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
this.loading = false
|
return throwError(() => new Error(err.message))
|
||||||
this.lockout = false
|
})
|
||||||
} else {
|
)
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
.subscribe(s => {
|
||||||
this.loading = false
|
if (s.status == 200) {
|
||||||
}
|
this.loading = false
|
||||||
})
|
this.lockout = false
|
||||||
|
} else {
|
||||||
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getForm() {
|
protected getForm() {
|
||||||
return {
|
return {
|
||||||
fname: this.form.get('fname')?.value,
|
fname: this.form.get('fname')?.value,
|
||||||
surname: this.form.get('surname')?.value,
|
surname: this.form.get('surname')?.value,
|
||||||
@@ -127,48 +150,60 @@ export class UserEditComponent {
|
|||||||
uname: this.form.get('uname')?.value,
|
uname: this.form.get('uname')?.value,
|
||||||
groups: this.form.get('groups')?.value,
|
groups: this.form.get('groups')?.value,
|
||||||
flags: (() => {
|
flags: (() => {
|
||||||
var value = this.form.get('flags')?.value.reduce((a: number,b: number)=>a+b,0)
|
var value = this.form
|
||||||
|
.get('flags')
|
||||||
|
?.value.reduce((a: number, b: number) => a + b, 0)
|
||||||
if (this.ls.capCheck(32)) {
|
if (this.ls.capCheck(32)) {
|
||||||
return value
|
return value
|
||||||
} else {
|
} else {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
})()
|
})(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected delete() {
|
protected delete() {
|
||||||
this.dialog.open(UserDeleteComponent).afterClosed().subscribe(reply => {
|
this.dialog
|
||||||
if (reply) {
|
.open(UserDeleteComponent)
|
||||||
this.acu.accs.deleteAcc(this.id!).subscribe((res) => {
|
.afterClosed()
|
||||||
if (res.status == 200) {
|
.subscribe(reply => {
|
||||||
this.sb.open("Użytkownik został usunięty.", undefined, {duration: 2500})
|
if (reply) {
|
||||||
this.dialogRef.close()
|
this.acu.accs.deleteAcc(this.id!).subscribe(res => {
|
||||||
} else {
|
if (res.status == 200) {
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
this.sb.open('Użytkownik został usunięty.', undefined, {
|
||||||
console.error(res);
|
duration: 2500,
|
||||||
}
|
})
|
||||||
})
|
this.dialogRef.close()
|
||||||
}
|
} else {
|
||||||
})
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
|
console.error(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
protected resetPass() {
|
protected resetPass() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.dialog.open(UserResetComponent).afterClosed().subscribe((res) => {
|
this.dialog
|
||||||
if (res == true) {
|
.open(UserResetComponent)
|
||||||
this.acu.accs.resetPass(this.id!).subscribe((patch)=>{
|
.afterClosed()
|
||||||
if (patch.status == 200) {
|
.subscribe(res => {
|
||||||
this.sb.open("Hasło zostało zresetowane", undefined, {duration: 2500})
|
if (res == true) {
|
||||||
this.loading = false
|
this.acu.accs.resetPass(this.id!).subscribe(patch => {
|
||||||
}
|
if (patch.status == 200) {
|
||||||
})
|
this.sb.open('Hasło zostało zresetowane', undefined, {
|
||||||
}
|
duration: 2500,
|
||||||
})
|
})
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
protected toggleLock(state: boolean) {
|
protected toggleLock(state: boolean) {
|
||||||
this.acu.accs.putAcc(this.id!, {locked: state}).subscribe((res) => {
|
this.acu.accs.putAcc(this.id!, { locked: state }).subscribe(res => {
|
||||||
if (res.status == 200) {
|
if (res.status == 200) {
|
||||||
this.locked = state
|
this.locked = state
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,23 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { UserResetComponent } from './user-reset.component';
|
import { UserResetComponent } from './user-reset.component'
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog'
|
||||||
|
|
||||||
describe('UserResetComponent', () => {
|
describe('UserResetComponent', () => {
|
||||||
let component: UserResetComponent;
|
let component: UserResetComponent
|
||||||
let fixture: ComponentFixture<UserResetComponent>;
|
let fixture: ComponentFixture<UserResetComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [UserResetComponent],
|
declarations: [UserResetComponent],
|
||||||
imports: [
|
imports: [MatDialogModule],
|
||||||
MatDialogModule
|
})
|
||||||
]
|
fixture = TestBed.createComponent(UserResetComponent)
|
||||||
});
|
component = fixture.componentInstance
|
||||||
fixture = TestBed.createComponent(UserResetComponent);
|
fixture.detectChanges()
|
||||||
component = fixture.componentInstance;
|
})
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-user-reset',
|
selector: 'app-user-reset',
|
||||||
templateUrl: './user-reset.component.html',
|
templateUrl: './user-reset.component.html',
|
||||||
styleUrls: ['./user-reset.component.scss'],
|
styleUrls: ['./user-reset.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class UserResetComponent {
|
export class UserResetComponent {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,25 +1,35 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { AdminCommService } from './admin-comm.service';
|
import { AdminCommService } from './admin-comm.service'
|
||||||
import { HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
import {
|
||||||
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
HttpClient,
|
||||||
|
provideHttpClient,
|
||||||
|
withInterceptorsFromDi,
|
||||||
|
} from '@angular/common/http'
|
||||||
|
import {
|
||||||
|
HttpTestingController,
|
||||||
|
provideHttpClientTesting,
|
||||||
|
} from '@angular/common/http/testing'
|
||||||
|
|
||||||
describe('AdminCommService', () => {
|
describe('AdminCommService', () => {
|
||||||
let service: AdminCommService;
|
let service: AdminCommService
|
||||||
let httpClient: HttpClient
|
let httpClient: HttpClient
|
||||||
let httpTestingController: HttpTestingController
|
let httpTestingController: HttpTestingController
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [],
|
imports: [],
|
||||||
providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
|
providers: [
|
||||||
});
|
provideHttpClient(withInterceptorsFromDi()),
|
||||||
service = TestBed.inject(AdminCommService);
|
provideHttpClientTesting(),
|
||||||
httpClient = TestBed.inject(HttpClient);
|
],
|
||||||
httpTestingController = TestBed.inject(HttpTestingController);
|
})
|
||||||
});
|
service = TestBed.inject(AdminCommService)
|
||||||
|
httpClient = TestBed.inject(HttpClient)
|
||||||
|
httpTestingController = TestBed.inject(HttpTestingController)
|
||||||
|
})
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
expect(service).toBeTruthy();
|
expect(service).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,285 +1,468 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http'
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core'
|
||||||
import { environment } from 'src/environments/environment';
|
import { environment } from 'src/environments/environment'
|
||||||
import { Menu } from '../types/menu';
|
import { Menu } from '../types/menu'
|
||||||
import { Status } from '../types/status';
|
import { Status } from '../types/status'
|
||||||
import { Group } from '../types/group';
|
import { Group } from '../types/group'
|
||||||
import { map } from 'rxjs';
|
import { map } from 'rxjs'
|
||||||
import { Notification } from '../types/notification';
|
import { Notification } from '../types/notification'
|
||||||
import { News } from '../types/news';
|
import { News } from '../types/news'
|
||||||
import { AKey } from '../types/key';
|
import { AKey } from '../types/key'
|
||||||
import { IUSettings } from './settings/settings.component';
|
import { IUSettings } from './settings/settings.component'
|
||||||
import User from '../types/user';
|
import User from '../types/user'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class AdminCommService {
|
export class AdminCommService {
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
constructor(private http: HttpClient) { }
|
|
||||||
|
|
||||||
//#region Menu
|
//#region Menu
|
||||||
menu = {
|
menu = {
|
||||||
getMenu: (start?: DateTime | null, end?: DateTime | null) => {
|
getMenu: (start?: DateTime | null, end?: DateTime | null) => {
|
||||||
if (start && end) {
|
if (start && end) {
|
||||||
const body = {start: start.toString(), end: end.toString()}
|
const body = { start: start.toString(), end: end.toString() }
|
||||||
return this.http.get<(Omit<Menu, "day"> & {day: string})[]>(environment.apiEndpoint+"/admin/menu", {withCredentials: true, params: body})
|
return this.http.get<(Omit<Menu, 'day'> & { day: string })[]>(
|
||||||
|
environment.apiEndpoint + '/admin/menu',
|
||||||
|
{ withCredentials: true, params: body }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
},
|
},
|
||||||
|
|
||||||
getOpts: () => {
|
getOpts: () => {
|
||||||
return this.http.get<any>(environment.apiEndpoint+`/admin/menu/opts`, {withCredentials: true})
|
return this.http.get<any>(environment.apiEndpoint + `/admin/menu/opts`, {
|
||||||
|
withCredentials: true,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
postMenu: (file: File) => {
|
postMenu: (file: File) => {
|
||||||
if (file) {
|
if (file) {
|
||||||
const formData = new FormData();
|
const formData = new FormData()
|
||||||
formData.append("menu", file)
|
formData.append('menu', file)
|
||||||
return this.http.post<Status>(environment.apiEndpoint+"/admin/menu/upload", formData, {withCredentials: true})
|
return this.http.post<Status>(
|
||||||
|
environment.apiEndpoint + '/admin/menu/upload',
|
||||||
|
formData,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
},
|
},
|
||||||
|
|
||||||
editSn: (id: string, content: Menu['sn']) => {
|
editSn: (id: string, content: Menu['sn']) => {
|
||||||
return this.putMenu(id, {sn: content})
|
return this.putMenu(id, { sn: content })
|
||||||
},
|
},
|
||||||
|
|
||||||
editOb: (id: string, content: Menu['ob']) => {
|
editOb: (id: string, content: Menu['ob']) => {
|
||||||
return this.putMenu(id, {ob: content})
|
return this.putMenu(id, { ob: content })
|
||||||
},
|
},
|
||||||
|
|
||||||
editKol: (id: string, content: Menu['kol']) => {
|
editKol: (id: string, content: Menu['kol']) => {
|
||||||
return this.putMenu(id, {kol: content})
|
return this.putMenu(id, { kol: content })
|
||||||
},
|
},
|
||||||
|
|
||||||
editTitle: (id: string, content: Menu['dayTitle']) => {
|
editTitle: (id: string, content: Menu['dayTitle']) => {
|
||||||
return this.putMenu(id, {dayTitle: content})
|
return this.putMenu(id, { dayTitle: content })
|
||||||
},
|
},
|
||||||
|
|
||||||
print: (start?: DateTime | null, end?: DateTime | null) => {
|
print: (start?: DateTime | null, end?: DateTime | null) => {
|
||||||
if (start && end) {
|
if (start && end) {
|
||||||
const body = {start: start.toString(), end: end.toString()}
|
const body = { start: start.toString(), end: end.toString() }
|
||||||
return this.http.get(environment.apiEndpoint+"/admin/menu/print", {withCredentials: true, params: body, responseType: "text"})
|
return this.http.get(environment.apiEndpoint + '/admin/menu/print', {
|
||||||
|
withCredentials: true,
|
||||||
|
params: body,
|
||||||
|
responseType: 'text',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
},
|
},
|
||||||
|
|
||||||
stat: (day: DateTime, m: "ob" | "kol") => {
|
stat: (day: DateTime, m: 'ob' | 'kol') => {
|
||||||
return this.http.get<{y: number, n: number}>(environment.apiEndpoint+`/admin/menu/${day.toISO()}/votes/${m}`, {withCredentials: true})
|
return this.http.get<{ y: number; n: number }>(
|
||||||
|
environment.apiEndpoint + `/admin/menu/${day.toISO()}/votes/${m}`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
new: {
|
new: {
|
||||||
single: (day: DateTime) => {
|
single: (day: DateTime) => {
|
||||||
return this.http.post<Status>(environment.apiEndpoint+`/admin/menu/${day.toISO()}`, null, {withCredentials: true})
|
return this.http.post<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/menu/${day.toISO()}`,
|
||||||
|
null,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
range: (start: DateTime, count: number) => {
|
range: (start: DateTime, count: number) => {
|
||||||
return this.http.post<Status>(environment.apiEndpoint+`/admin/menu/${start.toISO()}/${count}/`, null, {withCredentials: true})
|
return this.http.post<Status>(
|
||||||
}
|
environment.apiEndpoint + `/admin/menu/${start.toISO()}/${count}/`,
|
||||||
|
null,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
rm: (id: string) => {
|
rm: (id: string) => {
|
||||||
return this.http.delete<Status>(environment.apiEndpoint+`/admin/menu/${id}`, {withCredentials: true})
|
return this.http.delete<Status>(
|
||||||
}
|
environment.apiEndpoint + `/admin/menu/${id}`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
private putMenu(id: string, update: Partial<Menu>) {
|
private putMenu(id: string, update: Partial<Menu>) {
|
||||||
return this.http.put<Status>(environment.apiEndpoint+`/admin/menu/${id}`, update, {withCredentials: true})
|
return this.http.put<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/menu/${id}`,
|
||||||
|
update,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
//#region News
|
//#region News
|
||||||
news = {
|
news = {
|
||||||
getNews: () => {
|
getNews: () => {
|
||||||
return this.http.get<News[]>(environment.apiEndpoint+`/admin/news`, {withCredentials: true})
|
return this.http.get<News[]>(environment.apiEndpoint + `/admin/news`, {
|
||||||
|
withCredentials: true,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
postNews: (title: string, content: string) => {
|
postNews: (title: string, content: string) => {
|
||||||
return this.http.post<any>(environment.apiEndpoint+`/admin/news`, {title: title, content: content}, {withCredentials: true})
|
return this.http.post<any>(
|
||||||
|
environment.apiEndpoint + `/admin/news`,
|
||||||
|
{ title: title, content: content },
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteNews: (id: string) => {
|
deleteNews: (id: string) => {
|
||||||
return this.http.delete<any>(environment.apiEndpoint+`/admin/news/${id}`, {withCredentials: true})
|
return this.http.delete<any>(
|
||||||
|
environment.apiEndpoint + `/admin/news/${id}`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleNews: (id: string, inverter: boolean) => {
|
toggleNews: (id: string, inverter: boolean) => {
|
||||||
return this.putNews(id,{visible: !inverter})
|
return this.putNews(id, { visible: !inverter })
|
||||||
},
|
},
|
||||||
|
|
||||||
togglePin: (id: string, inverter: boolean) => {
|
togglePin: (id: string, inverter: boolean) => {
|
||||||
return this.putNews(id,{pinned: !inverter})
|
return this.putNews(id, { pinned: !inverter })
|
||||||
},
|
},
|
||||||
|
|
||||||
updateNews: (id: string, title: string, content: string) => {
|
updateNews: (id: string, title: string, content: string) => {
|
||||||
return this.putNews(id,{title: title, content: content, date: Date.now})
|
return this.putNews(id, {
|
||||||
}
|
title: title,
|
||||||
|
content: content,
|
||||||
|
date: Date.now,
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
private putNews(id: string, update: object) {
|
private putNews(id: string, update: object) {
|
||||||
return this.http.put<any>(environment.apiEndpoint+`/admin/news/${id}`, update, {withCredentials: true})
|
return this.http.put<any>(
|
||||||
|
environment.apiEndpoint + `/admin/news/${id}`,
|
||||||
|
update,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
//#region amgmt
|
//#region amgmt
|
||||||
accs = {
|
accs = {
|
||||||
getAccs: () => {
|
getAccs: () => {
|
||||||
return this.http.get<{
|
return this.http.get<{
|
||||||
users: Omit<User, "pass">[],
|
users: Omit<User, 'pass'>[]
|
||||||
groups: Group[]
|
groups: Group[]
|
||||||
}>(environment.apiEndpoint+`/admin/accs`, {withCredentials: true})
|
}>(environment.apiEndpoint + `/admin/accs`, { withCredentials: true })
|
||||||
},
|
},
|
||||||
|
|
||||||
postAcc: (item: any) => {
|
postAcc: (item: any) => {
|
||||||
return this.http.post<Status>(environment.apiEndpoint+`/admin/accs`, item, {withCredentials: true})
|
return this.http.post<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/accs`,
|
||||||
|
item,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
putAcc: (id: string, update: Partial<User>) => {
|
putAcc: (id: string, update: Partial<User>) => {
|
||||||
return this.http.put<Status>(environment.apiEndpoint+`/admin/accs/${id}`, update, {withCredentials: true})
|
return this.http.put<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/accs/${id}`,
|
||||||
|
update,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
resetPass: (id: string) => {
|
resetPass: (id: string) => {
|
||||||
return this.http.patch<Status>(environment.apiEndpoint+`/admin/accs/${id}/reset`, {}, {withCredentials: true})
|
return this.http.patch<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/accs/${id}/reset`,
|
||||||
|
{},
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteAcc: (id: string) => {
|
deleteAcc: (id: string) => {
|
||||||
return this.http.delete<Status>(environment.apiEndpoint+`/admin/accs/${id}`, {withCredentials: true})
|
return this.http.delete<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/accs/${id}`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
getUser: (id: string) => {
|
getUser: (id: string) => {
|
||||||
return this.http.get<Omit<User, "pass" | "regDate"> & {lockout: boolean, regDate: string}>(environment.apiEndpoint+`/admin/accs/${id}`, {withCredentials: true})
|
return this.http.get<
|
||||||
|
Omit<User, 'pass' | 'regDate'> & { lockout: boolean; regDate: string }
|
||||||
|
>(environment.apiEndpoint + `/admin/accs/${id}`, {
|
||||||
|
withCredentials: true,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
clearLockout: (id: string) => {
|
clearLockout: (id: string) => {
|
||||||
return this.http.delete<Status>(environment.apiEndpoint+`/admin/accs/${id}/lockout`, {withCredentials: true})
|
return this.http.delete<Status>(
|
||||||
}
|
environment.apiEndpoint + `/admin/accs/${id}/lockout`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
//#region Groups
|
//#region Groups
|
||||||
groups = {
|
groups = {
|
||||||
getGroups: () => {
|
getGroups: () => {
|
||||||
return this.http.get<Group[]>(environment.apiEndpoint+`/admin/groups`, {withCredentials: true})
|
return this.http.get<Group[]>(environment.apiEndpoint + `/admin/groups`, {
|
||||||
|
withCredentials: true,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
newGroup: (name: string) => {
|
newGroup: (name: string) => {
|
||||||
return this.http.post<Status>(environment.apiEndpoint+`/admin/groups`, {name: name}, {withCredentials: true})
|
return this.http.post<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/groups`,
|
||||||
|
{ name: name },
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
editName: (id: string, name: string) => {
|
editName: (id: string, name: string) => {
|
||||||
return this.putGroups(id, {name: name.trim()})
|
return this.putGroups(id, { name: name.trim() })
|
||||||
},
|
},
|
||||||
|
|
||||||
remove: (id: string) => {
|
remove: (id: string) => {
|
||||||
return this.http.delete<Status>(environment.apiEndpoint+`/admin/groups/${id}`, {withCredentials: true})
|
return this.http.delete<Status>(
|
||||||
}
|
environment.apiEndpoint + `/admin/groups/${id}`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
private putGroups(id: string, update: Partial<Group>) {
|
private putGroups(id: string, update: Partial<Group>) {
|
||||||
return this.http.put<Status>(environment.apiEndpoint+`/admin/groups/${id}`, update, {withCredentials: true})
|
return this.http.put<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/groups/${id}`,
|
||||||
|
update,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
//#region Notif
|
//#region Notif
|
||||||
notif = {
|
notif = {
|
||||||
send: (n: Notification) => {
|
send: (n: Notification) => {
|
||||||
return this.http.post<{sent: number, possible: number}>(environment.apiEndpoint+"/admin/notif/send", n, {withCredentials: true})
|
return this.http.post<{ sent: number; possible: number }>(
|
||||||
|
environment.apiEndpoint + '/admin/notif/send',
|
||||||
|
n,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
getGroups: () => {
|
getGroups: () => {
|
||||||
return this.http.get<Group[]>(environment.apiEndpoint+"/admin/notif/groups", {withCredentials: true})
|
return this.http.get<Group[]>(
|
||||||
|
environment.apiEndpoint + '/admin/notif/groups',
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
outbox: {
|
outbox: {
|
||||||
getSent: () => {
|
getSent: () => {
|
||||||
return this.http.get<{_id: string, sentDate: string, title: string}[]>(environment.apiEndpoint+"/admin/notif/outbox", {withCredentials: true}).pipe(map(v => v.map(i => ({
|
return this.http
|
||||||
...i,
|
.get<
|
||||||
sentDate: DateTime.fromISO(i.sentDate)
|
{ _id: string; sentDate: string; title: string }[]
|
||||||
}))))
|
>(environment.apiEndpoint + '/admin/notif/outbox', { withCredentials: true })
|
||||||
|
.pipe(
|
||||||
|
map(v =>
|
||||||
|
v.map(i => ({
|
||||||
|
...i,
|
||||||
|
sentDate: DateTime.fromISO(i.sentDate),
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
)
|
||||||
},
|
},
|
||||||
getBody: (id: string) => {
|
getBody: (id: string) => {
|
||||||
return this.http.get(environment.apiEndpoint+`/admin/notif/outbox/${id}/message`, {withCredentials: true, responseType: "text"})
|
return this.http.get(
|
||||||
|
environment.apiEndpoint + `/admin/notif/outbox/${id}/message`,
|
||||||
|
{ withCredentials: true, responseType: 'text' }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
getRcpts: (id: string) => {
|
getRcpts: (id: string) => {
|
||||||
return this.http.get<{_id: string, uname: string, room?: string, fname?: string, surname?: string}[]>(environment.apiEndpoint+`/admin/notif/outbox/${id}/rcpts`, {withCredentials: true})
|
return this.http.get<
|
||||||
}
|
{
|
||||||
}
|
_id: string
|
||||||
|
uname: string
|
||||||
|
room?: string
|
||||||
|
fname?: string
|
||||||
|
surname?: string
|
||||||
|
}[]
|
||||||
|
>(environment.apiEndpoint + `/admin/notif/outbox/${id}/rcpts`, {
|
||||||
|
withCredentials: true,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
//#region Keys
|
//#region Keys
|
||||||
keys = {
|
keys = {
|
||||||
getKeys: () => {
|
getKeys: () => {
|
||||||
return this.http.get<(Omit<AKey, "borrow" | "tb"> & {borrow: string, tb?: string})[]>(environment.apiEndpoint+`/admin/keys`, {withCredentials: true}).pipe(map((v) => {
|
return this.http
|
||||||
return v.map((r) => {
|
.get<
|
||||||
let newkey: any = {...r}
|
(Omit<AKey, 'borrow' | 'tb'> & { borrow: string; tb?: string })[]
|
||||||
newkey.borrow = DateTime.fromISO(r.borrow!)
|
>(environment.apiEndpoint + `/admin/keys`, { withCredentials: true })
|
||||||
if (newkey.tb) newkey.tb = DateTime.fromISO(r.tb!)
|
.pipe(
|
||||||
return newkey as AKey
|
map(v => {
|
||||||
})
|
return v.map(r => {
|
||||||
}))
|
let newkey: any = { ...r }
|
||||||
|
newkey.borrow = DateTime.fromISO(r.borrow!)
|
||||||
|
if (newkey.tb) newkey.tb = DateTime.fromISO(r.tb!)
|
||||||
|
return newkey as AKey
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
avalKeys: () => {
|
avalKeys: () => {
|
||||||
return this.http.get<string[]>(environment.apiEndpoint+`/admin/keys/available`, {withCredentials: true})
|
return this.http.get<string[]>(
|
||||||
|
environment.apiEndpoint + `/admin/keys/available`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
postKey: (room: string, uname: string) => {
|
postKey: (room: string, uname: string) => {
|
||||||
return this.http.post<Status>(environment.apiEndpoint+`/admin/keys/`, {room: room, whom: uname}, {withCredentials: true})
|
return this.http.post<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/keys/`,
|
||||||
|
{ room: room, whom: uname },
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
returnKey: (id: string) => {
|
returnKey: (id: string) => {
|
||||||
return this.putKeys(id, {tb: DateTime.now()})
|
return this.putKeys(id, { tb: DateTime.now() })
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
private putKeys(id: string, update: Partial<AKey>) {
|
private putKeys(id: string, update: Partial<AKey>) {
|
||||||
return this.http.put<Status>(environment.apiEndpoint+`/admin/keys/${id}`, update, {withCredentials: true})
|
return this.http.put<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/keys/${id}`,
|
||||||
|
update,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
//#region Clean
|
//#region Clean
|
||||||
clean = {
|
clean = {
|
||||||
getConfig: () => {
|
getConfig: () => {
|
||||||
return this.http.get<{rooms: string[], things: string[]}>(environment.apiEndpoint+`/admin/clean/config`, {withCredentials: true})
|
return this.http.get<{ rooms: string[]; things: string[] }>(
|
||||||
|
environment.apiEndpoint + `/admin/clean/config`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
getClean: (date: string, room: string) => {
|
getClean: (date: string, room: string) => {
|
||||||
return this.http.get<{_id: string, date: string, grade: number, gradeDate: string, notes: {label: string, weight: number}[], room: string, tips: string} | null>(environment.apiEndpoint+`/admin/clean/${date}/${room}`, {withCredentials: true})
|
return this.http.get<{
|
||||||
|
_id: string
|
||||||
|
date: string
|
||||||
|
grade: number
|
||||||
|
gradeDate: string
|
||||||
|
notes: { label: string; weight: number }[]
|
||||||
|
room: string
|
||||||
|
tips: string
|
||||||
|
} | null>(environment.apiEndpoint + `/admin/clean/${date}/${room}`, {
|
||||||
|
withCredentials: true,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
postClean: (obj: Object) => {
|
postClean: (obj: Object) => {
|
||||||
return this.http.post<Status>(environment.apiEndpoint+`/admin/clean/`, obj, {withCredentials: true})
|
return this.http.post<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/clean/`,
|
||||||
|
obj,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
delete: (id: string) => {
|
delete: (id: string) => {
|
||||||
return this.http.delete<Status>(environment.apiEndpoint+`/admin/clean/${id}`, {withCredentials: true})
|
return this.http.delete<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/clean/${id}`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
summary: {
|
summary: {
|
||||||
getSummary: (start: DateTime, end: DateTime) => {
|
getSummary: (start: DateTime, end: DateTime) => {
|
||||||
return this.http.get<{room: string, avg: number}[]>(environment.apiEndpoint+`/admin/clean/summary/${start.toISO()}/${end.toISO()}`, {withCredentials: true})
|
return this.http.get<{ room: string; avg: number }[]>(
|
||||||
}
|
environment.apiEndpoint +
|
||||||
|
`/admin/clean/summary/${start.toISO()}/${end.toISO()}`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
attendence: {
|
attendence: {
|
||||||
getUsers: (room: string) => {
|
getUsers: (room: string) => {
|
||||||
return this.http.get<{users: {fname: string, surname: string, _id: string}[], attendence?: {auto: {id: string, hour?: string}[], notes: string}}>(environment.apiEndpoint+`/admin/clean/attendence/${room}`, {withCredentials: true})
|
return this.http.get<{
|
||||||
|
users: { fname: string; surname: string; _id: string }[]
|
||||||
|
attendence?: { auto: { id: string; hour?: string }[]; notes: string }
|
||||||
|
}>(environment.apiEndpoint + `/admin/clean/attendence/${room}`, {
|
||||||
|
withCredentials: true,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
postAttendence: (room: string, attendence: {auto: {id: string, hour?: string}[], notes: string}) => {
|
postAttendence: (
|
||||||
return this.http.post<Status>(environment.apiEndpoint+`/admin/clean/attendence/${room}`, attendence, {withCredentials: true})
|
room: string,
|
||||||
|
attendence: { auto: { id: string; hour?: string }[]; notes: string }
|
||||||
|
) => {
|
||||||
|
return this.http.post<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/clean/attendence/${room}`,
|
||||||
|
attendence,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
getSummary: () => {
|
getSummary: () => {
|
||||||
return this.http.get<{room: string, hours: string[], notes: string, auto: boolean}[]>(environment.apiEndpoint+`/admin/clean/attendenceSummary`, {withCredentials: true})
|
return this.http.get<
|
||||||
|
{ room: string; hours: string[]; notes: string; auto: boolean }[]
|
||||||
|
>(environment.apiEndpoint + `/admin/clean/attendenceSummary`, {
|
||||||
|
withCredentials: true,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
deleteRoom: (room: string) => {
|
deleteRoom: (room: string) => {
|
||||||
return this.http.delete<Status>(environment.apiEndpoint+`/admin/clean/attendence/${room}`, {withCredentials: true})
|
return this.http.delete<Status>(
|
||||||
}
|
environment.apiEndpoint + `/admin/clean/attendence/${room}`,
|
||||||
}
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
//#region Settings
|
//#region Settings
|
||||||
settings = {
|
settings = {
|
||||||
getAll: () => {
|
getAll: () => {
|
||||||
return this.http.get<IUSettings>(environment.apiEndpoint+`/admin/settings/`, {withCredentials: true})
|
return this.http.get<IUSettings>(
|
||||||
|
environment.apiEndpoint + `/admin/settings/`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
post: (settings: IUSettings) => {
|
post: (settings: IUSettings) => {
|
||||||
return this.http.post<Status>(environment.apiEndpoint+`/admin/settings/`, settings, {withCredentials: true})
|
return this.http.post<Status>(
|
||||||
|
environment.apiEndpoint + `/admin/settings/`,
|
||||||
|
settings,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
},
|
},
|
||||||
reload: () => {
|
reload: () => {
|
||||||
return this.http.get<Status>(environment.apiEndpoint+`/admin/settings/reload/`, {withCredentials: true})
|
return this.http.get<Status>(
|
||||||
}
|
environment.apiEndpoint + `/admin/settings/reload/`,
|
||||||
|
{ withCredentials: true }
|
||||||
|
)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region misc
|
//#region misc
|
||||||
userFilter = (query: string) => {
|
userFilter = (query: string) => {
|
||||||
return this.http.get<any[]>(environment.apiEndpoint+`/admin/usearch`, {params: {q: query}, withCredentials: true})
|
return this.http.get<any[]>(environment.apiEndpoint + `/admin/usearch`, {
|
||||||
|
params: { q: query },
|
||||||
|
withCredentials: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
:host {
|
:host {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-sidenav, mat-toolbar {
|
mat-sidenav,
|
||||||
padding: 8pt
|
mat-toolbar {
|
||||||
|
padding: 8pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-sidenav-container {
|
mat-sidenav-container {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,45 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { AdminViewComponent } from './admin-view.component';
|
import { AdminViewComponent } from './admin-view.component'
|
||||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
import { MatToolbarModule } from '@angular/material/toolbar'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
import { MatDrawer, MatSidenavModule } from '@angular/material/sidenav';
|
import { MatDrawer, MatSidenavModule } from '@angular/material/sidenav'
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
import { MatListModule } from '@angular/material/list';
|
import { MatListModule } from '@angular/material/list'
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router'
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-toolbar", template: '',
|
selector: 'app-toolbar',
|
||||||
standalone: false
|
template: '',
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class ToolbarMock {
|
class ToolbarMock {
|
||||||
@Input() drawer!: MatDrawer;
|
@Input() drawer!: MatDrawer
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('AdminViewComponent', () => {
|
describe('AdminViewComponent', () => {
|
||||||
let component: AdminViewComponent;
|
let component: AdminViewComponent
|
||||||
let fixture: ComponentFixture<AdminViewComponent>;
|
let fixture: ComponentFixture<AdminViewComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [AdminViewComponent, ToolbarMock],
|
declarations: [AdminViewComponent, ToolbarMock],
|
||||||
imports: [MatToolbarModule, MatIconModule, MatSidenavModule, BrowserAnimationsModule, MatListModule, RouterModule.forRoot([])]
|
imports: [
|
||||||
});
|
MatToolbarModule,
|
||||||
fixture = TestBed.createComponent(AdminViewComponent);
|
MatIconModule,
|
||||||
component = fixture.componentInstance;
|
MatSidenavModule,
|
||||||
fixture.detectChanges();
|
BrowserAnimationsModule,
|
||||||
});
|
MatListModule,
|
||||||
|
RouterModule.forRoot([]),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
fixture = TestBed.createComponent(AdminViewComponent)
|
||||||
|
component = fixture.componentInstance
|
||||||
|
fixture.detectChanges()
|
||||||
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,30 +1,78 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core'
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router'
|
||||||
import { LocalStorageService } from '../services/local-storage.service';
|
import { LocalStorageService } from '../services/local-storage.service'
|
||||||
import { Link } from '../types/link';
|
import { Link } from '../types/link'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-admin-view',
|
selector: 'app-admin-view',
|
||||||
templateUrl: './admin-view.component.html',
|
templateUrl: './admin-view.component.html',
|
||||||
styleUrls: ['./admin-view.component.scss'],
|
styleUrls: ['./admin-view.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class AdminViewComponent {
|
export class AdminViewComponent {
|
||||||
private readonly _LINKS: Link[] = [
|
private readonly _LINKS: Link[] = [
|
||||||
{ title: "Wiadomości", icon: "newspaper", href: "news", enabled: this.ls.permChecker(1) && this.ls.capCheck(1) },
|
{
|
||||||
{ title: "Jadłospis", icon: "restaurant_menu", href: "menu", enabled: this.ls.permChecker(2) && this.ls.capCheck(2) },
|
title: 'Wiadomości',
|
||||||
{ title: "Wysyłanie powiadomień", icon: "notifications", href: "notifications", enabled: this.ls.permChecker(4) && this.ls.capCheck(4) },
|
icon: 'newspaper',
|
||||||
{ title: "Grupy", icon: "groups", href: "groups", enabled: this.ls.permChecker(8) && this.ls.capCheck(8) },
|
href: 'news',
|
||||||
{ title: "Zarządzanie kontami", icon: "manage_accounts", href: "accounts", enabled: this.ls.permChecker(16) },
|
enabled: this.ls.permChecker(1) && this.ls.capCheck(1),
|
||||||
{ title: "Klucze", icon: "key", href: "keys", enabled: this.ls.permChecker(64) && this.ls.capCheck(32) },
|
},
|
||||||
{ title: "Czystość", icon: "cleaning_services", href: "grades", enabled: this.ls.permChecker(128) && this.ls.capCheck(16) },
|
{
|
||||||
{ title: "Frekwencja", icon: "checklist", href: "attendence", enabled: false },
|
title: 'Jadłospis',
|
||||||
{ title: "Ustawienia", icon: "settings_applications", href: "settings", enabled: this.ls.permChecker(32) },
|
icon: 'restaurant_menu',
|
||||||
];
|
href: 'menu',
|
||||||
|
enabled: this.ls.permChecker(2) && this.ls.capCheck(2),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Wysyłanie powiadomień',
|
||||||
|
icon: 'notifications',
|
||||||
|
href: 'notifications',
|
||||||
|
enabled: this.ls.permChecker(4) && this.ls.capCheck(4),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Grupy',
|
||||||
|
icon: 'groups',
|
||||||
|
href: 'groups',
|
||||||
|
enabled: this.ls.permChecker(8) && this.ls.capCheck(8),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Zarządzanie kontami',
|
||||||
|
icon: 'manage_accounts',
|
||||||
|
href: 'accounts',
|
||||||
|
enabled: this.ls.permChecker(16),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Klucze',
|
||||||
|
icon: 'key',
|
||||||
|
href: 'keys',
|
||||||
|
enabled: this.ls.permChecker(64) && this.ls.capCheck(32),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Czystość',
|
||||||
|
icon: 'cleaning_services',
|
||||||
|
href: 'grades',
|
||||||
|
enabled: this.ls.permChecker(128) && this.ls.capCheck(16),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Frekwencja',
|
||||||
|
icon: 'checklist',
|
||||||
|
href: 'attendence',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Ustawienia',
|
||||||
|
icon: 'settings_applications',
|
||||||
|
href: 'settings',
|
||||||
|
enabled: this.ls.permChecker(32),
|
||||||
|
},
|
||||||
|
]
|
||||||
public get LINKS(): Link[] {
|
public get LINKS(): Link[] {
|
||||||
return this._LINKS.filter(v => v.enabled);
|
return this._LINKS.filter(v => v.enabled)
|
||||||
}
|
}
|
||||||
constructor(readonly router: Router, readonly ls: LocalStorageService) { }
|
constructor(
|
||||||
|
readonly router: Router,
|
||||||
|
readonly ls: LocalStorageService
|
||||||
|
) {}
|
||||||
goNormal() {
|
goNormal() {
|
||||||
this.router.navigateByUrl('app')
|
this.router.navigateByUrl('app')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
@use 'sass:list';
|
@use "sass:list";
|
||||||
|
|
||||||
#guide {
|
#guide {
|
||||||
margin: 1em
|
margin: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#legend {
|
#legend {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
gap: 3ch;
|
gap: 3ch;
|
||||||
* {
|
* {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.circle {
|
.circle {
|
||||||
&::before {
|
&::before {
|
||||||
border-radius: 7.5%;
|
border-radius: 7.5%;
|
||||||
width: 2.5ch;
|
width: 2.5ch;
|
||||||
height: 2.5ch;
|
height: 2.5ch;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
content: "";
|
content: "";
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
$list: (red, yellow, green);
|
$list: (red, yellow, green);
|
||||||
|
|
||||||
@for $n from 1 through 3 {
|
@for $n from 1 through 3 {
|
||||||
&:nth-of-type(#{$n})::before {
|
&:nth-of-type(#{$n})::before {
|
||||||
background-color: list.nth($list, $n);
|
background-color: list.nth($list, $n);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,42 +1,36 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { AttendenceSummaryComponent } from './attendence-summary.component';
|
import { AttendenceSummaryComponent } from './attendence-summary.component'
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
import { MatTableModule } from '@angular/material/table';
|
import { MatTableModule } from '@angular/material/table'
|
||||||
|
|
||||||
describe('AttendenceSummaryComponent', () => {
|
describe('AttendenceSummaryComponent', () => {
|
||||||
let component: AttendenceSummaryComponent;
|
let component: AttendenceSummaryComponent
|
||||||
let fixture: ComponentFixture<AttendenceSummaryComponent>;
|
let fixture: ComponentFixture<AttendenceSummaryComponent>
|
||||||
let acMock
|
let acMock
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
acMock = {
|
acMock = {
|
||||||
clean: {
|
clean: {
|
||||||
attendence: {
|
attendence: {
|
||||||
getSummary: jasmine.createSpy("getSummary").and.returnValue(of())
|
getSummary: jasmine.createSpy('getSummary').and.returnValue(of()),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [AttendenceSummaryComponent],
|
declarations: [AttendenceSummaryComponent],
|
||||||
imports: [
|
imports: [RouterModule.forRoot([]), MatTableModule],
|
||||||
RouterModule.forRoot([]),
|
providers: [{ provide: AdminCommService, useValue: acMock }],
|
||||||
MatTableModule
|
}).compileComponents()
|
||||||
],
|
|
||||||
providers: [
|
fixture = TestBed.createComponent(AttendenceSummaryComponent)
|
||||||
{provide: AdminCommService, useValue: acMock}
|
component = fixture.componentInstance
|
||||||
]
|
fixture.detectChanges()
|
||||||
})
|
})
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(AttendenceSummaryComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,24 +1,38 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { ToolbarService } from '../../toolbar/toolbar.service';
|
import { ToolbarService } from '../../toolbar/toolbar.service'
|
||||||
import { Router, ActivatedRoute } from '@angular/router';
|
import { Router, ActivatedRoute } from '@angular/router'
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-attendence-summary',
|
selector: 'app-attendence-summary',
|
||||||
templateUrl: './attendence-summary.component.html',
|
templateUrl: './attendence-summary.component.html',
|
||||||
styleUrl: './attendence-summary.component.scss',
|
styleUrl: './attendence-summary.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class AttendenceSummaryComponent implements OnInit {
|
export class AttendenceSummaryComponent implements OnInit {
|
||||||
|
data: MatTableDataSource<{
|
||||||
data: MatTableDataSource<{room: string, hours: string[], notes: string, auto: boolean}> = new MatTableDataSource<{room: string, hours: string[], notes: string, auto: boolean}>();
|
room: string
|
||||||
|
hours: string[]
|
||||||
|
notes: string
|
||||||
|
auto: boolean
|
||||||
|
}> = new MatTableDataSource<{
|
||||||
|
room: string
|
||||||
|
hours: string[]
|
||||||
|
notes: string
|
||||||
|
auto: boolean
|
||||||
|
}>()
|
||||||
collumns = ['room', 'hours', 'actions']
|
collumns = ['room', 'hours', 'actions']
|
||||||
|
|
||||||
constructor (private toolbar: ToolbarService, private router: Router, private route: ActivatedRoute, private ac: AdminCommService) {
|
constructor(
|
||||||
|
private toolbar: ToolbarService,
|
||||||
|
private router: Router,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private ac: AdminCommService
|
||||||
|
) {
|
||||||
this.toolbar.comp = this
|
this.toolbar.comp = this
|
||||||
this.toolbar.menu = [
|
this.toolbar.menu = [
|
||||||
{check: true, title: "Ocenianie", fn: "goBack", icon: "arrow_back"}
|
{ check: true, title: 'Ocenianie', fn: 'goBack', icon: 'arrow_back' },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,6 +49,6 @@ export class AttendenceSummaryComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
goBack() {
|
goBack() {
|
||||||
this.router.navigate(['../'], {relativeTo: this.route})
|
this.router.navigate(['../'], { relativeTo: this.route })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
:host {
|
:host {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-radius: 7.5%;
|
border-radius: 7.5%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,22 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { HourDisplayComponent } from './hour-display.component';
|
import { HourDisplayComponent } from './hour-display.component'
|
||||||
|
|
||||||
describe('HourDisplayComponent', () => {
|
describe('HourDisplayComponent', () => {
|
||||||
let component: HourDisplayComponent;
|
let component: HourDisplayComponent
|
||||||
let fixture: ComponentFixture<HourDisplayComponent>;
|
let fixture: ComponentFixture<HourDisplayComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [HourDisplayComponent]
|
declarations: [HourDisplayComponent],
|
||||||
})
|
}).compileComponents()
|
||||||
.compileComponents();
|
|
||||||
|
fixture = TestBed.createComponent(HourDisplayComponent)
|
||||||
fixture = TestBed.createComponent(HourDisplayComponent);
|
component = fixture.componentInstance
|
||||||
component = fixture.componentInstance;
|
fixture.detectChanges()
|
||||||
fixture.detectChanges();
|
})
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core'
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-hour-display',
|
selector: 'app-hour-display',
|
||||||
templateUrl: './hour-display.component.html',
|
templateUrl: './hour-display.component.html',
|
||||||
styleUrl: './hour-display.component.scss',
|
styleUrl: './hour-display.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class HourDisplayComponent {
|
export class HourDisplayComponent {
|
||||||
@Input() value = "";
|
@Input() value = ''
|
||||||
|
|
||||||
style () {
|
style() {
|
||||||
if (/(0+[0-9]|1[0-9]|2[0-3]):(0+[0-9]|[1-5][0-9])/g.test(this.value)) {
|
if (/(0+[0-9]|1[0-9]|2[0-3]):(0+[0-9]|[1-5][0-9])/g.test(this.value)) {
|
||||||
var diff = DateTime.fromFormat(this.value, "HH:mm").diffNow("minutes")
|
var diff = DateTime.fromFormat(this.value, 'HH:mm').diffNow('minutes')
|
||||||
if (diff.as("minutes") > 30) {
|
if (diff.as('minutes') > 30) {
|
||||||
return { "background-color": "red" }
|
return { 'background-color': 'red' }
|
||||||
} else if (diff.as("minutes") > 0) {
|
} else if (diff.as('minutes') > 0) {
|
||||||
return { "background-color": "yellow", "color": "black"}
|
return { 'background-color': 'yellow', color: 'black' }
|
||||||
} else {
|
} else {
|
||||||
return { "background-color": "green"}
|
return { 'background-color': 'green' }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return { "color": "gray"}
|
return { color: 'gray' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,36 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { AttendenceComponent } from './attendence.component';
|
import { AttendenceComponent } from './attendence.component'
|
||||||
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
import {
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
MAT_DIALOG_DATA,
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
MatDialogModule,
|
||||||
import { of } from 'rxjs';
|
MatDialogRef,
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
} from '@angular/material/dialog'
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { MatFormFieldModule } from '@angular/material/form-field'
|
||||||
|
import { of } from 'rxjs'
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||||
|
import { MatInputModule } from '@angular/material/input'
|
||||||
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
|
|
||||||
describe('AttendenceComponent', () => {
|
describe('AttendenceComponent', () => {
|
||||||
let component: AttendenceComponent;
|
let component: AttendenceComponent
|
||||||
let fixture: ComponentFixture<AttendenceComponent>;
|
let fixture: ComponentFixture<AttendenceComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const acMock = {
|
const acMock = {
|
||||||
clean: {
|
clean: {
|
||||||
attendence: {
|
attendence: {
|
||||||
getUsers: jasmine.createSpy("getUsers").and.returnValue(of())
|
getUsers: jasmine.createSpy('getUsers').and.returnValue(of()),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [AttendenceComponent],
|
declarations: [AttendenceComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: MAT_DIALOG_DATA, useValue: {}},
|
{ provide: MAT_DIALOG_DATA, useValue: {} },
|
||||||
{provide: MatDialogRef, useValue: {}},
|
{ provide: MatDialogRef, useValue: {} },
|
||||||
{provide: AdminCommService, useValue: acMock}
|
{ provide: AdminCommService, useValue: acMock },
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
@@ -34,17 +38,16 @@ describe('AttendenceComponent', () => {
|
|||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
NoopAnimationsModule
|
NoopAnimationsModule,
|
||||||
]
|
],
|
||||||
})
|
}).compileComponents()
|
||||||
.compileComponents();
|
|
||||||
|
fixture = TestBed.createComponent(AttendenceComponent)
|
||||||
fixture = TestBed.createComponent(AttendenceComponent);
|
component = fixture.componentInstance
|
||||||
component = fixture.componentInstance;
|
fixture.detectChanges()
|
||||||
fixture.detectChanges();
|
})
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,29 +1,37 @@
|
|||||||
import { Component, Inject, OnInit } from '@angular/core';
|
import { Component, Inject, OnInit } from '@angular/core'
|
||||||
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
|
import { FormArray, FormBuilder, FormGroup } from '@angular/forms'
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-attendence',
|
selector: 'app-attendence',
|
||||||
templateUrl: './attendence.component.html',
|
templateUrl: './attendence.component.html',
|
||||||
styleUrl: './attendence.component.scss',
|
styleUrl: './attendence.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class AttendenceComponent implements OnInit {
|
export class AttendenceComponent implements OnInit {
|
||||||
|
constructor(
|
||||||
constructor(private fb: FormBuilder, @Inject(MAT_DIALOG_DATA) public data: { room: string }, public dialogRef: MatDialogRef<AttendenceComponent>, private ac: AdminCommService) { }
|
private fb: FormBuilder,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: { room: string },
|
||||||
|
public dialogRef: MatDialogRef<AttendenceComponent>,
|
||||||
|
private ac: AdminCommService
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.room = this.data.room
|
this.room = this.data.room
|
||||||
this.ac.clean.attendence.getUsers(this.room).subscribe(query => {
|
this.ac.clean.attendence.getUsers(this.room).subscribe(query => {
|
||||||
query.users.forEach(v => {
|
query.users.forEach(v => {
|
||||||
var att = query.attendence ? query.attendence.auto.find(z => z.id == v._id) : false
|
var att = query.attendence
|
||||||
this.users.push(this.fb.group({
|
? query.attendence.auto.find(z => z.id == v._id)
|
||||||
id: v._id,
|
: false
|
||||||
label: `${v.fname} ${v.surname}`,
|
this.users.push(
|
||||||
att: this.fb.control(att),
|
this.fb.group({
|
||||||
hour: this.fb.control(att ? att.hour : ""),
|
id: v._id,
|
||||||
}))
|
label: `${v.fname} ${v.surname}`,
|
||||||
|
att: this.fb.control(att),
|
||||||
|
hour: this.fb.control(att ? att.hour : ''),
|
||||||
|
})
|
||||||
|
)
|
||||||
})
|
})
|
||||||
this.form.get('notes')?.setValue(query.attendence?.notes)
|
this.form.get('notes')?.setValue(query.attendence?.notes)
|
||||||
})
|
})
|
||||||
@@ -32,15 +40,15 @@ export class AttendenceComponent implements OnInit {
|
|||||||
save() {
|
save() {
|
||||||
this.dialogRef.close({
|
this.dialogRef.close({
|
||||||
room: this.room,
|
room: this.room,
|
||||||
...this.form.value
|
...this.form.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
room: string = "";
|
room: string = ''
|
||||||
|
|
||||||
form: FormGroup = this.fb.group({
|
form: FormGroup = this.fb.group({
|
||||||
users: this.fb.array([]),
|
users: this.fb.array([]),
|
||||||
notes: this.fb.control(""),
|
notes: this.fb.control(''),
|
||||||
})
|
})
|
||||||
|
|
||||||
get users() {
|
get users() {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
div#things {
|
div#things {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#buttons {
|
div#buttons {
|
||||||
* {
|
* {
|
||||||
margin: 0 2px 0 2px;
|
margin: 0 2px 0 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { GradesComponent } from './grades.component';
|
import { GradesComponent } from './grades.component'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router'
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input'
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-date-selector", template: '',
|
selector: 'app-date-selector',
|
||||||
standalone: false
|
template: '',
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class DateSelectorStub {
|
class DateSelectorStub {
|
||||||
@Input() date: string = DateTime.now().toISODate();
|
@Input() date: string = DateTime.now().toISODate()
|
||||||
@Output() dateChange = new EventEmitter<string>();
|
@Output() dateChange = new EventEmitter<string>()
|
||||||
@Input() filter: (date: DateTime | null) => boolean = () => true
|
@Input() filter: (date: DateTime | null) => boolean = () => true
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-room-chooser", template: '',
|
selector: 'app-room-chooser',
|
||||||
standalone: false
|
template: '',
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class RoomSelectorStub {
|
class RoomSelectorStub {
|
||||||
@Input() rooms: string[] = []
|
@Input() rooms: string[] = []
|
||||||
@Output() room: EventEmitter<string> = new EventEmitter<string>();
|
@Output() room: EventEmitter<string> = new EventEmitter<string>()
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('GradesComponent', () => {
|
describe('GradesComponent', () => {
|
||||||
let component: GradesComponent;
|
let component: GradesComponent
|
||||||
let fixture: ComponentFixture<GradesComponent>;
|
let fixture: ComponentFixture<GradesComponent>
|
||||||
let acMock
|
let acMock
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
acMock = {
|
acMock = {
|
||||||
clean: {
|
clean: {
|
||||||
getConfig: jasmine.createSpy("getConfig").and.returnValue(of())
|
getConfig: jasmine.createSpy('getConfig').and.returnValue(of()),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [GradesComponent, DateSelectorStub, RoomSelectorStub],
|
declarations: [GradesComponent, DateSelectorStub, RoomSelectorStub],
|
||||||
providers: [
|
providers: [{ provide: AdminCommService, useValue: acMock }],
|
||||||
{provide: AdminCommService, useValue: acMock}
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule.forRoot([]),
|
RouterModule.forRoot([]),
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
@@ -54,17 +54,16 @@ describe('GradesComponent', () => {
|
|||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
NoopAnimationsModule
|
NoopAnimationsModule,
|
||||||
]
|
],
|
||||||
})
|
}).compileComponents()
|
||||||
.compileComponents();
|
|
||||||
|
fixture = TestBed.createComponent(GradesComponent)
|
||||||
fixture = TestBed.createComponent(GradesComponent);
|
component = fixture.componentInstance
|
||||||
component = fixture.componentInstance;
|
fixture.detectChanges()
|
||||||
fixture.detectChanges();
|
})
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,46 +1,52 @@
|
|||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { FormArray, FormBuilder } from '@angular/forms';
|
import { FormArray, FormBuilder } from '@angular/forms'
|
||||||
import { weekendFilter } from 'src/app/fd.da';
|
import { weekendFilter } from 'src/app/fd.da'
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar'
|
||||||
import { ToolbarService } from '../toolbar/toolbar.service';
|
import { ToolbarService } from '../toolbar/toolbar.service'
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog'
|
||||||
import { AttendenceComponent } from './attendence/attendence.component';
|
import { AttendenceComponent } from './attendence/attendence.component'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-grades',
|
selector: 'app-grades',
|
||||||
templateUrl: './grades.component.html',
|
templateUrl: './grades.component.html',
|
||||||
styleUrl: './grades.component.scss',
|
styleUrl: './grades.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class GradesComponent implements OnInit, OnDestroy {
|
export class GradesComponent implements OnInit, OnDestroy {
|
||||||
rooms!: string[]
|
rooms!: string[]
|
||||||
room: string = "0";
|
room: string = '0'
|
||||||
protected _date: DateTime;
|
protected _date: DateTime
|
||||||
public get date(): string {
|
public get date(): string {
|
||||||
return this._date.toISODate()!;
|
return this._date.toISODate()!
|
||||||
}
|
}
|
||||||
public set date(value: string) {
|
public set date(value: string) {
|
||||||
this._date = DateTime.fromISO(value);
|
this._date = DateTime.fromISO(value)
|
||||||
}
|
}
|
||||||
grade: number = 6
|
grade: number = 6
|
||||||
gradeDate?: DateTime;
|
gradeDate?: DateTime
|
||||||
id?: string
|
id?: string
|
||||||
filter = weekendFilter
|
filter = weekendFilter
|
||||||
|
|
||||||
get notes(): { label: string, weight: number }[] {
|
get notes(): { label: string; weight: number }[] {
|
||||||
var th = this.things.value as { cb: boolean, label: string, weight: number }[]
|
var th = this.things.value as {
|
||||||
return th.filter((v) => v.cb).map((v) => {
|
cb: boolean
|
||||||
return { ...v, cb: undefined }
|
label: string
|
||||||
})
|
weight: number
|
||||||
|
}[]
|
||||||
|
return th
|
||||||
|
.filter(v => v.cb)
|
||||||
|
.map(v => {
|
||||||
|
return { ...v, cb: undefined }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
set notes(value: { label: string, weight: number }[]) {
|
set notes(value: { label: string; weight: number }[]) {
|
||||||
var things = this.things.controls
|
var things = this.things.controls
|
||||||
things.forEach((v) => {
|
things.forEach(v => {
|
||||||
var thing = value.find((s) => s.label == v.get('label')?.value)
|
var thing = value.find(s => s.label == v.get('label')?.value)
|
||||||
if (thing) {
|
if (thing) {
|
||||||
v.get('cb')?.setValue(true)
|
v.get('cb')?.setValue(true)
|
||||||
v.get('weight')?.setValue(thing.weight)
|
v.get('weight')?.setValue(thing.weight)
|
||||||
@@ -51,22 +57,35 @@ export class GradesComponent implements OnInit, OnDestroy {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private ac: AdminCommService, private fb: FormBuilder, private sb: MatSnackBar, private toolbar: ToolbarService, private router: Router, private route: ActivatedRoute, private dialog: MatDialog) {
|
constructor(
|
||||||
|
private ac: AdminCommService,
|
||||||
|
private fb: FormBuilder,
|
||||||
|
private sb: MatSnackBar,
|
||||||
|
private toolbar: ToolbarService,
|
||||||
|
private router: Router,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private dialog: MatDialog
|
||||||
|
) {
|
||||||
this._date = DateTime.now()
|
this._date = DateTime.now()
|
||||||
// if (!this.filter(this.date)) this.date.isoWeekday(8);
|
// if (!this.filter(this.date)) this.date.isoWeekday(8);
|
||||||
this.toolbar.comp = this
|
this.toolbar.comp = this
|
||||||
this.toolbar.menu = [
|
this.toolbar.menu = [
|
||||||
{ title: "Pokoje do sprawdzenia", check: true, fn: "attendenceSummary", icon: "overview"},
|
{
|
||||||
{ title: "Podsumowanie", check: true, fn: "summary", icon: "analytics" },
|
title: 'Pokoje do sprawdzenia',
|
||||||
|
check: true,
|
||||||
|
fn: 'attendenceSummary',
|
||||||
|
icon: 'overview',
|
||||||
|
},
|
||||||
|
{ title: 'Podsumowanie', check: true, fn: 'summary', icon: 'analytics' },
|
||||||
]
|
]
|
||||||
this.form.valueChanges.subscribe((v) => {
|
this.form.valueChanges.subscribe(v => {
|
||||||
this.calculate()
|
this.calculate()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
form = this.fb.group({
|
form = this.fb.group({
|
||||||
things: this.fb.array([]),
|
things: this.fb.array([]),
|
||||||
tips: this.fb.control("")
|
tips: this.fb.control(''),
|
||||||
})
|
})
|
||||||
|
|
||||||
get things() {
|
get things() {
|
||||||
@@ -74,21 +93,25 @@ export class GradesComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
summary() {
|
summary() {
|
||||||
this.router.navigate(["summary"], { relativeTo: this.route })
|
this.router.navigate(['summary'], { relativeTo: this.route })
|
||||||
}
|
}
|
||||||
|
|
||||||
attendenceSummary() {
|
attendenceSummary() {
|
||||||
this.router.navigate(["attendenceSummary"], {relativeTo: this.route})
|
this.router.navigate(['attendenceSummary'], { relativeTo: this.route })
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.ac.clean.getConfig().subscribe((s) => {
|
this.ac.clean.getConfig().subscribe(s => {
|
||||||
this.rooms = s.rooms
|
this.rooms = s.rooms
|
||||||
s.things.forEach((s) => this.things.push(this.fb.group({
|
s.things.forEach(s =>
|
||||||
cb: this.fb.control(false),
|
this.things.push(
|
||||||
label: this.fb.control(s),
|
this.fb.group({
|
||||||
weight: this.fb.control(1)
|
cb: this.fb.control(false),
|
||||||
})))
|
label: this.fb.control(s),
|
||||||
|
weight: this.fb.control(1),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,19 +121,19 @@ export class GradesComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
downloadData() {
|
downloadData() {
|
||||||
this.ac.clean.getClean(this.date, this.room).subscribe((v) => {
|
this.ac.clean.getClean(this.date, this.room).subscribe(v => {
|
||||||
if (v) {
|
if (v) {
|
||||||
this.notes = v.notes
|
this.notes = v.notes
|
||||||
this.gradeDate = DateTime.fromISO(v.gradeDate)
|
this.gradeDate = DateTime.fromISO(v.gradeDate)
|
||||||
this.grade = v.grade
|
this.grade = v.grade
|
||||||
this.id = v._id
|
this.id = v._id
|
||||||
this.form.get("tips")?.setValue(v.tips)
|
this.form.get('tips')?.setValue(v.tips)
|
||||||
} else {
|
} else {
|
||||||
this.gradeDate = undefined
|
this.gradeDate = undefined
|
||||||
this.grade = 6
|
this.grade = 6
|
||||||
this.notes = []
|
this.notes = []
|
||||||
this.id = undefined
|
this.id = undefined
|
||||||
this.form.get("tips")?.setValue("")
|
this.form.get('tips')?.setValue('')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -139,7 +162,7 @@ export class GradesComponent implements OnInit, OnDestroy {
|
|||||||
weight.setValue(weight.value - 1)
|
weight.setValue(weight.value - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
@@ -149,16 +172,16 @@ export class GradesComponent implements OnInit, OnDestroy {
|
|||||||
date: this.date,
|
date: this.date,
|
||||||
room: this.room,
|
room: this.room,
|
||||||
notes: this.notes,
|
notes: this.notes,
|
||||||
tips: this.form.get("tips")?.value
|
tips: this.form.get('tips')?.value,
|
||||||
}
|
}
|
||||||
this.ac.clean.postClean(obj).subscribe((s) => {
|
this.ac.clean.postClean(obj).subscribe(s => {
|
||||||
this.sb.open("Zapisano!", undefined, { duration: 1500 })
|
this.sb.open('Zapisano!', undefined, { duration: 1500 })
|
||||||
this.downloadData()
|
this.downloadData()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
remove() {
|
remove() {
|
||||||
this.ac.clean.delete(this.id!).subscribe((s) => {
|
this.ac.clean.delete(this.id!).subscribe(s => {
|
||||||
if (s.status == 200) {
|
if (s.status == 200) {
|
||||||
this.downloadData()
|
this.downloadData()
|
||||||
}
|
}
|
||||||
@@ -171,22 +194,35 @@ export class GradesComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
attendence() {
|
attendence() {
|
||||||
this.dialog.open(AttendenceComponent, {data: {room: this.room}}).afterClosed().subscribe((v: {room: string, users: {att: boolean, id: string, hour: string}[], notes: string}) => {
|
this.dialog
|
||||||
if (!v) return
|
.open(AttendenceComponent, { data: { room: this.room } })
|
||||||
let x: {room: string, users: {id: string, hour?: string}[]} = {
|
.afterClosed()
|
||||||
room: v.room,
|
.subscribe(
|
||||||
users: []
|
(v: {
|
||||||
}
|
room: string
|
||||||
v.users.forEach(i => {
|
users: { att: boolean; id: string; hour: string }[]
|
||||||
if (i.att && i.hour) {
|
notes: string
|
||||||
x.users.push({id: i.id, hour: i.hour})
|
}) => {
|
||||||
|
if (!v) return
|
||||||
|
let x: { room: string; users: { id: string; hour?: string }[] } = {
|
||||||
|
room: v.room,
|
||||||
|
users: [],
|
||||||
|
}
|
||||||
|
v.users.forEach(i => {
|
||||||
|
if (i.att && i.hour) {
|
||||||
|
x.users.push({ id: i.id, hour: i.hour })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.ac.clean.attendence
|
||||||
|
.postAttendence(x.room, { auto: x.users, notes: v.notes })
|
||||||
|
.subscribe(s => {
|
||||||
|
if (s.status == 200) {
|
||||||
|
this.sb.open('Zapisano obecność!', undefined, {
|
||||||
|
duration: 1500,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
this.ac.clean.attendence.postAttendence(x.room, {auto: x.users, notes: v.notes}).subscribe((s) => {
|
|
||||||
if (s.status == 200) {
|
|
||||||
this.sb.open("Zapisano obecność!", undefined, {duration: 1500})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { SummaryComponent } from './summary.component';
|
import { SummaryComponent } from './summary.component'
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field'
|
||||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
import { MatDatepickerModule } from '@angular/material/datepicker'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||||
import { MatTableModule } from '@angular/material/table';
|
import { MatTableModule } from '@angular/material/table'
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
import { provideLuxonDateAdapter } from '@angular/material-luxon-adapter';
|
import { provideLuxonDateAdapter } from '@angular/material-luxon-adapter'
|
||||||
|
|
||||||
describe('SummaryComponent', () => {
|
describe('SummaryComponent', () => {
|
||||||
let component: SummaryComponent;
|
let component: SummaryComponent
|
||||||
let fixture: ComponentFixture<SummaryComponent>;
|
let fixture: ComponentFixture<SummaryComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const acMock = {
|
const acMock = {
|
||||||
clean: {
|
clean: {
|
||||||
summary: {
|
summary: {
|
||||||
getSummary: jasmine.createSpy("getSummary").and.returnValue(of())
|
getSummary: jasmine.createSpy('getSummary').and.returnValue(of()),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [SummaryComponent],
|
declarations: [SummaryComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: AdminCommService, useValue: acMock },
|
{ provide: AdminCommService, useValue: acMock },
|
||||||
provideLuxonDateAdapter()
|
provideLuxonDateAdapter(),
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule.forRoot([]),
|
RouterModule.forRoot([]),
|
||||||
@@ -38,17 +38,16 @@ describe('SummaryComponent', () => {
|
|||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
NoopAnimationsModule
|
NoopAnimationsModule,
|
||||||
]
|
],
|
||||||
})
|
}).compileComponents()
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(SummaryComponent);
|
fixture = TestBed.createComponent(SummaryComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,58 +1,68 @@
|
|||||||
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'
|
||||||
import { ToolbarService } from '../../toolbar/toolbar.service';
|
import { ToolbarService } from '../../toolbar/toolbar.service'
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table'
|
||||||
import { FormBuilder } from '@angular/forms';
|
import { FormBuilder } from '@angular/forms'
|
||||||
import { MatSort } from '@angular/material/sort';
|
import { MatSort } from '@angular/material/sort'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-summary',
|
selector: 'app-summary',
|
||||||
templateUrl: './summary.component.html',
|
templateUrl: './summary.component.html',
|
||||||
styleUrl: './summary.component.scss',
|
styleUrl: './summary.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class SummaryComponent implements OnInit, OnDestroy {
|
export class SummaryComponent implements OnInit, OnDestroy {
|
||||||
|
data: MatTableDataSource<{ room: string; avg: number }> =
|
||||||
data: MatTableDataSource<{room: string, avg: number}> = new MatTableDataSource<{room: string, avg: number}>();
|
new MatTableDataSource<{ room: string; avg: number }>()
|
||||||
collumns = ['room', 'avg']
|
collumns = ['room', 'avg']
|
||||||
|
|
||||||
dateSelector = this.fb.group({
|
dateSelector = this.fb.group({
|
||||||
start: this.fb.control(DateTime.utc().startOf('day')),
|
start: this.fb.control(DateTime.utc().startOf('day')),
|
||||||
end: this.fb.control(DateTime.utc().endOf('day'))
|
end: this.fb.control(DateTime.utc().endOf('day')),
|
||||||
})
|
})
|
||||||
|
|
||||||
@ViewChild(MatSort, {static: false}) set content(sort: MatSort) {
|
@ViewChild(MatSort, { static: false }) set content(sort: MatSort) {
|
||||||
this.data.sort = sort
|
this.data.sort = sort
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (private toolbar: ToolbarService, private router: Router, private route: ActivatedRoute, private ac: AdminCommService, private fb: FormBuilder) {
|
constructor(
|
||||||
|
private toolbar: ToolbarService,
|
||||||
|
private router: Router,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private ac: AdminCommService,
|
||||||
|
private fb: FormBuilder
|
||||||
|
) {
|
||||||
this.toolbar.comp = this
|
this.toolbar.comp = this
|
||||||
this.toolbar.menu = [
|
this.toolbar.menu = [
|
||||||
{check: true, title: "Ocenianie", fn: "goBack", icon: "arrow_back"}
|
{ check: true, title: 'Ocenianie', fn: 'goBack', icon: 'arrow_back' },
|
||||||
]
|
]
|
||||||
this.dateSelector.valueChanges.subscribe((v) => {
|
this.dateSelector.valueChanges.subscribe(v => {
|
||||||
this.download()
|
this.download()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.download()
|
this.download()
|
||||||
}
|
}
|
||||||
|
|
||||||
download() {
|
download() {
|
||||||
this.ac.clean.summary.getSummary(this.dateSelector.get('start')?.value!.startOf('day')!, this.dateSelector.get('end')?.value!.endOf('day')!).subscribe((v) => {
|
this.ac.clean.summary
|
||||||
this.data.data = v
|
.getSummary(
|
||||||
})
|
this.dateSelector.get('start')?.value!.startOf('day')!,
|
||||||
|
this.dateSelector.get('end')?.value!.endOf('day')!
|
||||||
|
)
|
||||||
|
.subscribe(v => {
|
||||||
|
this.data.data = v
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
goBack() {
|
goBack() {
|
||||||
this.router.navigate(['../'], {relativeTo: this.route})
|
this.router.navigate(['../'], { relativeTo: this.route })
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.toolbar.comp = undefined
|
this.toolbar.comp = undefined
|
||||||
this.toolbar.menu = undefined
|
this.toolbar.menu = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
:host {
|
:host {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card {
|
mat-card {
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
padding: 1ch;
|
padding: 1ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card-title {
|
mat-card-title {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,29 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { GroupsComponent } from './groups.component';
|
import { GroupsComponent } from './groups.component'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
|
|
||||||
describe('GroupsComponent', () => {
|
describe('GroupsComponent', () => {
|
||||||
let component: GroupsComponent;
|
let component: GroupsComponent
|
||||||
let fixture: ComponentFixture<GroupsComponent>;
|
let fixture: ComponentFixture<GroupsComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const acMock = {
|
const acMock = {
|
||||||
groups: {
|
groups: {
|
||||||
getGroups: jasmine.createSpy("getGroups").and.returnValue(of())
|
getGroups: jasmine.createSpy('getGroups').and.returnValue(of()),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [GroupsComponent],
|
declarations: [GroupsComponent],
|
||||||
providers: [
|
providers: [{ provide: AdminCommService, useValue: acMock }],
|
||||||
{provide: AdminCommService, useValue: acMock}
|
})
|
||||||
]
|
fixture = TestBed.createComponent(GroupsComponent)
|
||||||
});
|
component = fixture.componentInstance
|
||||||
fixture = TestBed.createComponent(GroupsComponent);
|
fixture.detectChanges()
|
||||||
component = fixture.componentInstance;
|
})
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { Group } from 'src/app/types/group';
|
import { Group } from 'src/app/types/group'
|
||||||
import { Status } from 'src/app/types/status';
|
import { Status } from 'src/app/types/status'
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog'
|
||||||
import { RemoveConfirmComponent } from './remove-confirm/remove-confirm.component';
|
import { RemoveConfirmComponent } from './remove-confirm/remove-confirm.component'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-groups',
|
selector: 'app-groups',
|
||||||
templateUrl: './groups.component.html',
|
templateUrl: './groups.component.html',
|
||||||
styleUrls: ['./groups.component.scss'],
|
styleUrls: ['./groups.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class GroupsComponent implements OnInit {
|
export class GroupsComponent implements OnInit {
|
||||||
groups?: Group[]
|
groups?: Group[]
|
||||||
constructor (protected readonly acs: AdminCommService, private readonly dialog: MatDialog) {}
|
constructor(
|
||||||
|
protected readonly acs: AdminCommService,
|
||||||
|
private readonly dialog: MatDialog
|
||||||
|
) {}
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.acs.groups.getGroups().subscribe((v) => {
|
this.acs.groups.getGroups().subscribe(v => {
|
||||||
this.groups = v
|
this.groups = v
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -26,36 +29,41 @@ export class GroupsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get groupOptions(): {id: string, text: string}[] {
|
get groupOptions(): { id: string; text: string }[] {
|
||||||
return this.groups!.map((v)=> {return {id: v._id as string, text: v.name as string}})
|
return this.groups!.map(v => {
|
||||||
|
return { id: v._id as string, text: v.name as string }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getId(g: Group[] | undefined) {
|
protected getId(g: Group[] | undefined) {
|
||||||
if (!g) return undefined
|
if (!g) return undefined
|
||||||
return g.map((v)=>v._id)
|
return g.map(v => v._id)
|
||||||
}
|
}
|
||||||
|
|
||||||
groupNames(groups: Group[]) {
|
groupNames(groups: Group[]) {
|
||||||
return groups.flatMap((g) => g.name)
|
return groups.flatMap(g => g.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected nameEdit(id: string, name: string | string[]) {
|
protected nameEdit(id: string, name: string | string[]) {
|
||||||
name = name as string
|
name = name as string
|
||||||
this.acs.groups.editName(id, name).subscribe((s) => this.refreshIfGood(s))
|
this.acs.groups.editName(id, name).subscribe(s => this.refreshIfGood(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
protected newGroup() {
|
protected newGroup() {
|
||||||
let name = prompt("Nazwa grupy")
|
let name = prompt('Nazwa grupy')
|
||||||
if (name) {
|
if (name) {
|
||||||
this.acs.groups.newGroup(name).subscribe((s) => this.refreshIfGood(s))
|
this.acs.groups.newGroup(name).subscribe(s => this.refreshIfGood(s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected remove(id: string) {
|
protected remove(id: string) {
|
||||||
this.dialog.open(RemoveConfirmComponent).afterClosed().subscribe((v) => {
|
this.dialog
|
||||||
if (v) {
|
.open(RemoveConfirmComponent)
|
||||||
this.acs.groups.remove(id).subscribe((s) => this.refreshIfGood(s))
|
.afterClosed()
|
||||||
}
|
.subscribe(v => {
|
||||||
})
|
if (v) {
|
||||||
|
this.acs.groups.remove(id).subscribe(s => this.refreshIfGood(s))
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { RemoveConfirmComponent } from './remove-confirm.component';
|
import { RemoveConfirmComponent } from './remove-confirm.component'
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog'
|
||||||
|
|
||||||
describe('RemoveConfirmComponent', () => {
|
describe('RemoveConfirmComponent', () => {
|
||||||
let component: RemoveConfirmComponent;
|
let component: RemoveConfirmComponent
|
||||||
let fixture: ComponentFixture<RemoveConfirmComponent>;
|
let fixture: ComponentFixture<RemoveConfirmComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [RemoveConfirmComponent],
|
declarations: [RemoveConfirmComponent],
|
||||||
imports: [MatDialogModule]
|
imports: [MatDialogModule],
|
||||||
});
|
})
|
||||||
fixture = TestBed.createComponent(RemoveConfirmComponent);
|
fixture = TestBed.createComponent(RemoveConfirmComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-remove-confirm',
|
selector: 'app-remove-confirm',
|
||||||
templateUrl: './remove-confirm.component.html',
|
templateUrl: './remove-confirm.component.html',
|
||||||
styleUrls: ['./remove-confirm.component.scss'],
|
styleUrls: ['./remove-confirm.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class RemoveConfirmComponent {
|
export class RemoveConfirmComponent {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#upper-bar {
|
#upper-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
gap: 4pt;
|
gap: 4pt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,51 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { AdminKeyComponent } from './key.component';
|
import { AdminKeyComponent } from './key.component'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field'
|
||||||
import { MatChipsModule } from '@angular/material/chips';
|
import { MatChipsModule } from '@angular/material/chips'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
import { MatPaginatorModule } from '@angular/material/paginator'
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms'
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'
|
||||||
import { MatTableModule } from '@angular/material/table';
|
import { MatTableModule } from '@angular/material/table'
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input'
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
|
|
||||||
describe('AdminKeyComponent', () => {
|
describe('AdminKeyComponent', () => {
|
||||||
let component: AdminKeyComponent;
|
let component: AdminKeyComponent
|
||||||
let fixture: ComponentFixture<AdminKeyComponent>;
|
let fixture: ComponentFixture<AdminKeyComponent>
|
||||||
let acMock
|
let acMock
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
acMock = {
|
acMock = {
|
||||||
keys: {
|
keys: {
|
||||||
getKeys: jasmine.createSpy("getKeys").and.returnValue(of())
|
getKeys: jasmine.createSpy('getKeys').and.returnValue(of()),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [AdminKeyComponent],
|
declarations: [AdminKeyComponent],
|
||||||
providers: [
|
providers: [{ provide: AdminCommService, useValue: acMock }],
|
||||||
{provide: AdminCommService, useValue: acMock}
|
imports: [
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatChipsModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatPaginatorModule,
|
||||||
|
FormsModule,
|
||||||
|
MatProgressSpinnerModule,
|
||||||
|
MatTableModule,
|
||||||
|
MatInputModule,
|
||||||
|
NoopAnimationsModule,
|
||||||
],
|
],
|
||||||
imports: [MatFormFieldModule, MatChipsModule, MatIconModule, MatPaginatorModule, FormsModule, MatProgressSpinnerModule, MatTableModule, MatInputModule, NoopAnimationsModule]
|
}).compileComponents()
|
||||||
})
|
|
||||||
.compileComponents();
|
fixture = TestBed.createComponent(AdminKeyComponent)
|
||||||
|
component = fixture.componentInstance
|
||||||
fixture = TestBed.createComponent(AdminKeyComponent);
|
fixture.detectChanges()
|
||||||
component = fixture.componentInstance;
|
})
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,46 +1,50 @@
|
|||||||
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'
|
||||||
import { MatPaginator } from '@angular/material/paginator';
|
import { MatPaginator } from '@angular/material/paginator'
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table'
|
||||||
import { AKey } from 'src/app/types/key';
|
import { AKey } from 'src/app/types/key'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog'
|
||||||
import { NewKeyComponent } from './new-key/new-key.component';
|
import { NewKeyComponent } from './new-key/new-key.component'
|
||||||
import { catchError, throwError } from 'rxjs';
|
import { catchError, throwError } from 'rxjs'
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-admin-key',
|
selector: 'app-admin-key',
|
||||||
templateUrl: './key.component.html',
|
templateUrl: './key.component.html',
|
||||||
styleUrl: './key.component.scss',
|
styleUrl: './key.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class AdminKeyComponent implements AfterViewInit, OnInit {
|
export class AdminKeyComponent implements AfterViewInit, OnInit {
|
||||||
keys: MatTableDataSource<AKey> = new MatTableDataSource<AKey>();
|
keys: MatTableDataSource<AKey> = new MatTableDataSource<AKey>()
|
||||||
pureData: AKey[] = []
|
pureData: AKey[] = []
|
||||||
private _filters: string[] = [];
|
private _filters: string[] = []
|
||||||
public get filters(): string[] {
|
public get filters(): string[] {
|
||||||
return this._filters;
|
return this._filters
|
||||||
}
|
}
|
||||||
collumns = ['room', 'whom', 'borrow', 'tb', 'actions']
|
collumns = ['room', 'whom', 'borrow', 'tb', 'actions']
|
||||||
public set filters(value: string[]) {
|
public set filters(value: string[]) {
|
||||||
if (value.includes("showAll")) {
|
if (value.includes('showAll')) {
|
||||||
this.collumns = ['room', 'whom', 'borrow', 'tb', 'actions']
|
this.collumns = ['room', 'whom', 'borrow', 'tb', 'actions']
|
||||||
} else {
|
} else {
|
||||||
this.collumns = ['room', 'whom', 'borrow', 'actions']
|
this.collumns = ['room', 'whom', 'borrow', 'actions']
|
||||||
}
|
}
|
||||||
this._filters = value;
|
this._filters = value
|
||||||
this.transformData();
|
this.transformData()
|
||||||
}
|
}
|
||||||
loading = true
|
loading = true
|
||||||
@ViewChild(MatPaginator) paginator!: MatPaginator
|
@ViewChild(MatPaginator) paginator!: MatPaginator
|
||||||
|
|
||||||
constructor (private ac: AdminCommService, private dialog: MatDialog, private sb: MatSnackBar) {
|
constructor(
|
||||||
|
private ac: AdminCommService,
|
||||||
|
private dialog: MatDialog,
|
||||||
|
private sb: MatSnackBar
|
||||||
|
) {
|
||||||
this.filters = []
|
this.filters = []
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchData() {
|
fetchData() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.ac.keys.getKeys().subscribe((r) => {
|
this.ac.keys.getKeys().subscribe(r => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.pureData = r
|
this.pureData = r
|
||||||
this.transformData()
|
this.transformData()
|
||||||
@@ -49,15 +53,16 @@ export class AdminKeyComponent implements AfterViewInit, OnInit {
|
|||||||
|
|
||||||
transformData() {
|
transformData() {
|
||||||
var finalData: AKey[] = this.pureData
|
var finalData: AKey[] = this.pureData
|
||||||
if (!this.filters.includes('showAll')) finalData = finalData.filter((v) => v.tb == undefined)
|
if (!this.filters.includes('showAll'))
|
||||||
|
finalData = finalData.filter(v => v.tb == undefined)
|
||||||
this.keys.data = finalData
|
this.keys.data = finalData
|
||||||
}
|
}
|
||||||
|
|
||||||
filter(event: Event) {
|
filter(event: Event) {
|
||||||
const value = (event.target as HTMLInputElement).value
|
const value = (event.target as HTMLInputElement).value
|
||||||
this.keys.filter = value.toLowerCase().trim()
|
this.keys.filter = value.toLowerCase().trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
this.keys.paginator = this.paginator
|
this.keys.paginator = this.paginator
|
||||||
}
|
}
|
||||||
@@ -68,26 +73,36 @@ export class AdminKeyComponent implements AfterViewInit, OnInit {
|
|||||||
// {room: "Kawiarenka", borrow: moment().subtract(15, "minutes"), whom: {_id: "test", room: 303, uname: "sk"}}
|
// {room: "Kawiarenka", borrow: moment().subtract(15, "minutes"), whom: {_id: "test", room: 303, uname: "sk"}}
|
||||||
// ]
|
// ]
|
||||||
}
|
}
|
||||||
|
|
||||||
new() {
|
new() {
|
||||||
this.dialog.open(NewKeyComponent).afterClosed().subscribe(v => {
|
this.dialog
|
||||||
if (v) {
|
.open(NewKeyComponent)
|
||||||
this.ac.keys.postKey(v.room, v.user).pipe(catchError((err,caught)=>{
|
.afterClosed()
|
||||||
if (err.status == 404) {
|
.subscribe(v => {
|
||||||
this.sb.open("Nie znaleziono użytkownika", undefined, {duration: 2500})
|
if (v) {
|
||||||
}
|
this.ac.keys
|
||||||
return throwError(() => new Error(err.message))
|
.postKey(v.room, v.user)
|
||||||
})).subscribe((s) => {
|
.pipe(
|
||||||
if (s.status == 201) {
|
catchError((err, caught) => {
|
||||||
this.fetchData()
|
if (err.status == 404) {
|
||||||
}
|
this.sb.open('Nie znaleziono użytkownika', undefined, {
|
||||||
})
|
duration: 2500,
|
||||||
}
|
})
|
||||||
})
|
}
|
||||||
|
return throwError(() => new Error(err.message))
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe(s => {
|
||||||
|
if (s.status == 201) {
|
||||||
|
this.fetchData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
tb(id: string) {
|
tb(id: string) {
|
||||||
this.ac.keys.returnKey(id).subscribe((r) => {
|
this.ac.keys.returnKey(id).subscribe(r => {
|
||||||
if (r.status == 200) {
|
if (r.status == 200) {
|
||||||
this.fetchData()
|
this.fetchData()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
form {
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,58 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { NewKeyComponent } from './new-key.component';
|
import { NewKeyComponent } from './new-key.component'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'
|
||||||
import { MatFormFieldControl, MatFormFieldModule } from '@angular/material/form-field';
|
import {
|
||||||
import { MatSelectModule } from '@angular/material/select';
|
MatFormFieldControl,
|
||||||
import { Component, forwardRef, Optional, Self } from '@angular/core';
|
MatFormFieldModule,
|
||||||
import { Observable, of } from 'rxjs';
|
} from '@angular/material/form-field'
|
||||||
import { AbstractControlDirective, ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR, NgControl, ReactiveFormsModule } from '@angular/forms';
|
import { MatSelectModule } from '@angular/material/select'
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { Component, forwardRef, Optional, Self } from '@angular/core'
|
||||||
|
import { Observable, of } from 'rxjs'
|
||||||
|
import {
|
||||||
|
AbstractControlDirective,
|
||||||
|
ControlValueAccessor,
|
||||||
|
FormsModule,
|
||||||
|
NG_VALUE_ACCESSOR,
|
||||||
|
NgControl,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
} from '@angular/forms'
|
||||||
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-user-search", template: '', providers: [{
|
selector: 'app-user-search',
|
||||||
provide: NG_VALUE_ACCESSOR,
|
template: '',
|
||||||
useExisting: forwardRef(() => UserSearchStub),
|
providers: [
|
||||||
multi: true,
|
{
|
||||||
},
|
provide: NG_VALUE_ACCESSOR,
|
||||||
{
|
useExisting: forwardRef(() => UserSearchStub),
|
||||||
provide: MatFormFieldControl,
|
multi: true,
|
||||||
useExisting: UserSearchStub
|
},
|
||||||
}],
|
{
|
||||||
standalone: false
|
provide: MatFormFieldControl,
|
||||||
|
useExisting: UserSearchStub,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class UserSearchStub implements ControlValueAccessor, MatFormFieldControl<never> {
|
class UserSearchStub
|
||||||
value: null = null;
|
implements ControlValueAccessor, MatFormFieldControl<never>
|
||||||
stateChanges: Observable<void> = of();
|
{
|
||||||
id: string = "";
|
value: null = null
|
||||||
placeholder: string = "";
|
stateChanges: Observable<void> = of()
|
||||||
ngControl: NgControl | AbstractControlDirective | null = null;
|
id: string = ''
|
||||||
focused: boolean = false;
|
placeholder: string = ''
|
||||||
empty: boolean = true;
|
ngControl: NgControl | AbstractControlDirective | null = null
|
||||||
shouldLabelFloat: boolean = true;
|
focused: boolean = false
|
||||||
required: boolean = false;
|
empty: boolean = true
|
||||||
disabled: boolean = false;
|
shouldLabelFloat: boolean = true
|
||||||
errorState: boolean = false;
|
required: boolean = false
|
||||||
controlType?: string | undefined;
|
disabled: boolean = false
|
||||||
autofilled?: boolean | undefined;
|
errorState: boolean = false
|
||||||
userAriaDescribedBy?: string | undefined;
|
controlType?: string | undefined
|
||||||
|
autofilled?: boolean | undefined
|
||||||
|
userAriaDescribedBy?: string | undefined
|
||||||
setDescribedByIds(ids: string[]): void {}
|
setDescribedByIds(ids: string[]): void {}
|
||||||
onContainerClick(event: MouseEvent): void {}
|
onContainerClick(event: MouseEvent): void {}
|
||||||
writeValue(obj: any): void {}
|
writeValue(obj: any): void {}
|
||||||
@@ -46,21 +62,21 @@ class UserSearchStub implements ControlValueAccessor, MatFormFieldControl<never>
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('NewKeyComponent', () => {
|
describe('NewKeyComponent', () => {
|
||||||
let component: NewKeyComponent;
|
let component: NewKeyComponent
|
||||||
let fixture: ComponentFixture<NewKeyComponent>;
|
let fixture: ComponentFixture<NewKeyComponent>
|
||||||
let acMock
|
let acMock
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
acMock = {
|
acMock = {
|
||||||
keys: {
|
keys: {
|
||||||
avalKeys: jasmine.createSpy("avalKeys").and.returnValue(of())
|
avalKeys: jasmine.createSpy('avalKeys').and.returnValue(of()),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [NewKeyComponent, UserSearchStub],
|
declarations: [NewKeyComponent, UserSearchStub],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: AdminCommService, useValue: acMock },
|
{ provide: AdminCommService, useValue: acMock },
|
||||||
{ provide: MatDialogRef, useValue: {} }
|
{ provide: MatDialogRef, useValue: {} },
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
@@ -68,17 +84,16 @@ describe('NewKeyComponent', () => {
|
|||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
NoopAnimationsModule
|
NoopAnimationsModule,
|
||||||
]
|
],
|
||||||
})
|
}).compileComponents()
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(NewKeyComponent);
|
fixture = TestBed.createComponent(NewKeyComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
import { MatDialogRef } from '@angular/material/dialog';
|
import { MatDialogRef } from '@angular/material/dialog'
|
||||||
import { FormControl, FormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms'
|
||||||
import { UserSearchResult } from 'src/app/commonComponents/user-search/user-search.component';
|
import { UserSearchResult } from 'src/app/commonComponents/user-search/user-search.component'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-new-key',
|
selector: 'app-new-key',
|
||||||
templateUrl: './new-key.component.html',
|
templateUrl: './new-key.component.html',
|
||||||
styleUrl: './new-key.component.scss',
|
styleUrl: './new-key.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class NewKeyComponent implements OnInit {
|
export class NewKeyComponent implements OnInit {
|
||||||
rooms: string[] = []
|
rooms: string[] = []
|
||||||
form = new FormGroup({
|
form = new FormGroup({
|
||||||
room: new FormControl<string>(""),
|
room: new FormControl<string>(''),
|
||||||
user: new FormControl<UserSearchResult | null>(null)
|
user: new FormControl<UserSearchResult | null>(null),
|
||||||
})
|
})
|
||||||
unames: any[] = []
|
unames: any[] = []
|
||||||
constructor ( private ac: AdminCommService, public dialogRef: MatDialogRef<NewKeyComponent> ) {}
|
constructor(
|
||||||
|
private ac: AdminCommService,
|
||||||
|
public dialogRef: MatDialogRef<NewKeyComponent>
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.ac.keys.avalKeys().subscribe((v) => {
|
this.ac.keys.avalKeys().subscribe(v => {
|
||||||
this.rooms = v
|
this.rooms = v
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -28,7 +31,6 @@ export class NewKeyComponent implements OnInit {
|
|||||||
send() {
|
send() {
|
||||||
if (this.form.valid) {
|
if (this.form.valid) {
|
||||||
this.dialogRef.close(this.form.value)
|
this.dialogRef.close(this.form.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,39 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { MenuAddComponent } from './menu-add.component';
|
import { MenuAddComponent } from './menu-add.component'
|
||||||
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
import {
|
||||||
import { MatRadioModule } from '@angular/material/radio';
|
MAT_DIALOG_DATA,
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
MatDialogModule,
|
||||||
|
MatDialogRef,
|
||||||
|
} from '@angular/material/dialog'
|
||||||
|
import { MatRadioModule } from '@angular/material/radio'
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||||
|
|
||||||
describe('MenuAddComponent', () => {
|
describe('MenuAddComponent', () => {
|
||||||
let component: MenuAddComponent;
|
let component: MenuAddComponent
|
||||||
let fixture: ComponentFixture<MenuAddComponent>;
|
let fixture: ComponentFixture<MenuAddComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [MenuAddComponent],
|
declarations: [MenuAddComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: MAT_DIALOG_DATA, useValue: {}},
|
{ provide: MAT_DIALOG_DATA, useValue: {} },
|
||||||
{provide: MatDialogRef, useValue: {}}
|
{ provide: MatDialogRef, useValue: {} },
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
MatRadioModule,
|
MatRadioModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
FormsModule
|
FormsModule,
|
||||||
]
|
],
|
||||||
})
|
}).compileComponents()
|
||||||
.compileComponents();
|
|
||||||
|
fixture = TestBed.createComponent(MenuAddComponent)
|
||||||
fixture = TestBed.createComponent(MenuAddComponent);
|
component = fixture.componentInstance
|
||||||
component = fixture.componentInstance;
|
fixture.detectChanges()
|
||||||
fixture.detectChanges();
|
})
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,51 +1,60 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core'
|
||||||
import { MenuUploadComponent } from '../menu-upload/menu-upload.component';
|
import { MenuUploadComponent } from '../menu-upload/menu-upload.component'
|
||||||
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
import { MatDialog, MatDialogRef } from '@angular/material/dialog'
|
||||||
import { FDSelection, weekendFilter } from 'src/app/fd.da';
|
import { FDSelection, weekendFilter } from 'src/app/fd.da'
|
||||||
import { FormControl, FormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms'
|
||||||
import { MAT_DATE_RANGE_SELECTION_STRATEGY } from '@angular/material/datepicker';
|
import { MAT_DATE_RANGE_SELECTION_STRATEGY } from '@angular/material/datepicker'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-menu-add',
|
selector: 'app-menu-add',
|
||||||
templateUrl: './menu-add.component.html',
|
templateUrl: './menu-add.component.html',
|
||||||
styleUrl: './menu-add.component.scss',
|
styleUrl: './menu-add.component.scss',
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: MAT_DATE_RANGE_SELECTION_STRATEGY, useClass: FDSelection }
|
{ provide: MAT_DATE_RANGE_SELECTION_STRATEGY, useClass: FDSelection },
|
||||||
],
|
],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class MenuAddComponent {
|
export class MenuAddComponent {
|
||||||
type: string | undefined;
|
type: string | undefined
|
||||||
filter = weekendFilter
|
filter = weekendFilter
|
||||||
|
|
||||||
day: string = DateTime.now().toISODate();
|
day: string = DateTime.now().toISODate()
|
||||||
|
|
||||||
range = new FormGroup({
|
range = new FormGroup({
|
||||||
start: new FormControl<DateTime|null>(null),
|
start: new FormControl<DateTime | null>(null),
|
||||||
end: new FormControl<DateTime|null>(null),
|
end: new FormControl<DateTime | null>(null),
|
||||||
})
|
})
|
||||||
|
|
||||||
constructor (public dialogRef: MatDialogRef<MenuAddComponent>, private dialog: MatDialog) { }
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<MenuAddComponent>,
|
||||||
|
private dialog: MatDialog
|
||||||
|
) {}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case "day":
|
case 'day':
|
||||||
this.dialogRef.close({type: "day", value: this.day})
|
this.dialogRef.close({ type: 'day', value: this.day })
|
||||||
break;
|
break
|
||||||
case "week":
|
case 'week':
|
||||||
this.dialogRef.close({type: "week", value: {start: this.range.value.start?.toISODate(), count: 5}})
|
this.dialogRef.close({
|
||||||
break;
|
type: 'week',
|
||||||
|
value: { start: this.range.value.start?.toISODate(), count: 5 },
|
||||||
|
})
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activateUpload() {
|
activateUpload() {
|
||||||
this.dialog.open(MenuUploadComponent).afterClosed().subscribe((data) => {
|
this.dialog
|
||||||
if (data) {
|
.open(MenuUploadComponent)
|
||||||
this.dialogRef.close({type: "file", ...data});
|
.afterClosed()
|
||||||
}
|
.subscribe(data => {
|
||||||
})
|
if (data) {
|
||||||
|
this.dialogRef.close({ type: 'file', ...data })
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
#upper-bar {
|
#upper-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-form-field {
|
mat-form-field {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
button[mat-icon-button] {
|
button[mat-icon-button] {
|
||||||
margin-left: 4pt;
|
margin-left: 4pt;
|
||||||
margin-right: 4pt;
|
margin-right: 4pt;
|
||||||
margin-top: 4pt;
|
margin-top: 4pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
.non-editable {
|
.non-editable {
|
||||||
color: gray;
|
color: gray;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,52 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { MenuNewComponent } from './menu-new.component';
|
import { MenuNewComponent } from './menu-new.component'
|
||||||
import { MatTableModule } from '@angular/material/table';
|
import { MatTableModule } from '@angular/material/table'
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input'
|
||||||
import { MAT_DATE_RANGE_SELECTION_STRATEGY, MatDatepickerModule } from '@angular/material/datepicker';
|
import {
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
MAT_DATE_RANGE_SELECTION_STRATEGY,
|
||||||
import { FDSelection } from 'src/app/fd.da';
|
MatDatepickerModule,
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
} from '@angular/material/datepicker'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
import { of } from 'rxjs';
|
import { FDSelection } from 'src/app/fd.da'
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { ReactiveFormsModule } from '@angular/forms'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { provideLuxonDateAdapter } from '@angular/material-luxon-adapter';
|
import { of } from 'rxjs'
|
||||||
|
import { MatDialogModule } from '@angular/material/dialog'
|
||||||
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
|
import { provideLuxonDateAdapter } from '@angular/material-luxon-adapter'
|
||||||
|
|
||||||
describe('MenuNewComponent', () => {
|
describe('MenuNewComponent', () => {
|
||||||
let component: MenuNewComponent;
|
let component: MenuNewComponent
|
||||||
let fixture: ComponentFixture<MenuNewComponent>;
|
let fixture: ComponentFixture<MenuNewComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const acMock = jasmine.createSpyObj('AdminCommService', {
|
const acMock = jasmine.createSpyObj('AdminCommService', {
|
||||||
getMenu: of()
|
getMenu: of(),
|
||||||
})
|
})
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [MenuNewComponent],
|
declarations: [MenuNewComponent],
|
||||||
imports: [MatTableModule, MatInputModule, MatDatepickerModule, BrowserAnimationsModule, ReactiveFormsModule, MatDialogModule, MatIconModule],
|
imports: [
|
||||||
|
MatTableModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatDatepickerModule,
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MatDialogModule,
|
||||||
|
MatIconModule,
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
provideLuxonDateAdapter(),
|
provideLuxonDateAdapter(),
|
||||||
{provide: MAT_DATE_RANGE_SELECTION_STRATEGY, useClass: FDSelection},
|
{ provide: MAT_DATE_RANGE_SELECTION_STRATEGY, useClass: FDSelection },
|
||||||
{provide: AdminCommService, useValue: acMock}
|
{ provide: AdminCommService, useValue: acMock },
|
||||||
],
|
],
|
||||||
});
|
})
|
||||||
fixture = TestBed.createComponent(MenuNewComponent);
|
fixture = TestBed.createComponent(MenuNewComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,85 +1,105 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core'
|
||||||
import { FormControl, FormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms'
|
||||||
import { MAT_DATE_RANGE_SELECTION_STRATEGY } from '@angular/material/datepicker';
|
import { MAT_DATE_RANGE_SELECTION_STRATEGY } from '@angular/material/datepicker'
|
||||||
import { FDSelection } from 'src/app/fd.da';
|
import { FDSelection } from 'src/app/fd.da'
|
||||||
import { Menu } from 'src/app/types/menu';
|
import { Menu } from 'src/app/types/menu'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table'
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog'
|
||||||
import { MenuUploadComponent } from './menu-upload/menu-upload.component';
|
import { MenuUploadComponent } from './menu-upload/menu-upload.component'
|
||||||
import { Status } from 'src/app/types/status';
|
import { Status } from 'src/app/types/status'
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar'
|
||||||
import { MenuAddComponent } from './menu-add/menu-add.component';
|
import { MenuAddComponent } from './menu-add/menu-add.component'
|
||||||
import { LocalStorageService } from 'src/app/services/local-storage.service';
|
import { LocalStorageService } from 'src/app/services/local-storage.service'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-menu-new',
|
selector: 'app-menu-new',
|
||||||
templateUrl: './menu-new.component.html',
|
templateUrl: './menu-new.component.html',
|
||||||
styleUrls: ['./menu-new.component.scss'],
|
styleUrls: ['./menu-new.component.scss'],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: MAT_DATE_RANGE_SELECTION_STRATEGY, useClass: FDSelection }
|
{ provide: MAT_DATE_RANGE_SELECTION_STRATEGY, useClass: FDSelection },
|
||||||
],
|
],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class MenuNewComponent {
|
export class MenuNewComponent {
|
||||||
dcols: string[] = ['day', 'sn', 'ob', 'kol']
|
dcols: string[] = ['day', 'sn', 'ob', 'kol']
|
||||||
dataSource: MatTableDataSource<Menu> = new MatTableDataSource<Menu>()
|
dataSource: MatTableDataSource<Menu> = new MatTableDataSource<Menu>()
|
||||||
range = new FormGroup({
|
range = new FormGroup({
|
||||||
start: new FormControl<DateTime|null>(null),
|
start: new FormControl<DateTime | null>(null),
|
||||||
end: new FormControl<DateTime|null>(null),
|
end: new FormControl<DateTime | null>(null),
|
||||||
})
|
})
|
||||||
loading = false
|
loading = false
|
||||||
public options: any;
|
public options: any
|
||||||
|
|
||||||
constructor (private ac: AdminCommService, private dialog: MatDialog, private sb: MatSnackBar, readonly ls: LocalStorageService) { }
|
constructor(
|
||||||
|
private ac: AdminCommService,
|
||||||
|
private dialog: MatDialog,
|
||||||
|
private sb: MatSnackBar,
|
||||||
|
readonly ls: LocalStorageService
|
||||||
|
) {}
|
||||||
|
|
||||||
print() {
|
print() {
|
||||||
this.ac.menu.print(this.range.value.start, this.range.value.end)?.subscribe((r) => {
|
this.ac.menu
|
||||||
if (r && r.length > 0) {
|
.print(this.range.value.start, this.range.value.end)
|
||||||
var mywindow = window.open(undefined, 'Drukowanie', 'height=400,width=400')
|
?.subscribe(r => {
|
||||||
mywindow?.document.write(r)
|
if (r && r.length > 0) {
|
||||||
mywindow?.print()
|
var mywindow = window.open(
|
||||||
mywindow?.close()
|
undefined,
|
||||||
}
|
'Drukowanie',
|
||||||
})
|
'height=400,width=400'
|
||||||
|
)
|
||||||
|
mywindow?.document.write(r)
|
||||||
|
mywindow?.print()
|
||||||
|
mywindow?.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
addDate() {
|
addDate() {
|
||||||
this.dialog.open(MenuAddComponent).afterClosed().subscribe((data) => {
|
this.dialog
|
||||||
if (data) {
|
.open(MenuAddComponent)
|
||||||
switch (data.type) {
|
.afterClosed()
|
||||||
case "day":
|
.subscribe(data => {
|
||||||
this.ac.menu.new.single(data.value).subscribe(s => this.refreshIfGood(s))
|
if (data) {
|
||||||
break;
|
switch (data.type) {
|
||||||
case "week":
|
case 'day':
|
||||||
this.ac.menu.new.range(data.value.start, data.value.count).subscribe(s => this.refreshIfGood(s))
|
this.ac.menu.new
|
||||||
break;
|
.single(data.value)
|
||||||
case "file":
|
.subscribe(s => this.refreshIfGood(s))
|
||||||
this.requestData()
|
break
|
||||||
break;
|
case 'week':
|
||||||
default:
|
this.ac.menu.new
|
||||||
break;
|
.range(data.value.start, data.value.count)
|
||||||
|
.subscribe(s => this.refreshIfGood(s))
|
||||||
|
break
|
||||||
|
case 'file':
|
||||||
|
this.requestData()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
requestData() {
|
requestData() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.ac.menu.getOpts().subscribe((o) => {
|
this.ac.menu.getOpts().subscribe(o => {
|
||||||
this.options = o;
|
this.options = o
|
||||||
})
|
})
|
||||||
this.ac.menu.getMenu(this.range.value.start, this.range.value.end)?.subscribe((data) => {
|
this.ac.menu
|
||||||
this.loading = false
|
.getMenu(this.range.value.start, this.range.value.end)
|
||||||
this.dataSource.data = data.map((v) => {
|
?.subscribe(data => {
|
||||||
let newMenu: Menu = {
|
this.loading = false
|
||||||
...v,
|
this.dataSource.data = data.map(v => {
|
||||||
day: DateTime.fromISO(v.day)
|
let newMenu: Menu = {
|
||||||
}
|
...v,
|
||||||
return newMenu
|
day: DateTime.fromISO(v.day),
|
||||||
|
}
|
||||||
|
return newMenu
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private refreshIfGood(s: Status) {
|
private refreshIfGood(s: Status) {
|
||||||
@@ -87,33 +107,52 @@ export class MenuNewComponent {
|
|||||||
this.requestData()
|
this.requestData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activateUpload() {
|
activateUpload() {
|
||||||
this.dialog.open(MenuUploadComponent).afterClosed().subscribe((data) => {
|
this.dialog
|
||||||
if (data) {
|
.open(MenuUploadComponent)
|
||||||
this.requestData()
|
.afterClosed()
|
||||||
}
|
.subscribe(data => {
|
||||||
})
|
if (data) {
|
||||||
|
this.requestData()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
editSn(id: string) {
|
editSn(id: string) {
|
||||||
this.ac.menu.editSn(id, this.dataSource.data.find(v => v._id == id)!.sn).subscribe(s => this.refreshIfGood(s))
|
this.ac.menu
|
||||||
|
.editSn(id, this.dataSource.data.find(v => v._id == id)!.sn)
|
||||||
|
.subscribe(s => this.refreshIfGood(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
editOb(id: string) {
|
editOb(id: string) {
|
||||||
this.ac.menu.editOb(id, this.dataSource.data.find(v => v._id == id)!.ob).subscribe(s => this.refreshIfGood(s))
|
this.ac.menu
|
||||||
|
.editOb(id, this.dataSource.data.find(v => v._id == id)!.ob)
|
||||||
|
.subscribe(s => this.refreshIfGood(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
editKol(id: string) {
|
editKol(id: string) {
|
||||||
this.ac.menu.editKol(id, this.dataSource.data.find(v => v._id == id)?.kol).subscribe(s => this.refreshIfGood(s))
|
this.ac.menu
|
||||||
|
.editKol(id, this.dataSource.data.find(v => v._id == id)?.kol)
|
||||||
|
.subscribe(s => this.refreshIfGood(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
editTitle(id: string) {
|
editTitle(id: string) {
|
||||||
this.ac.menu.editTitle(id, this.dataSource.data.find(v => v._id == id)?.dayTitle).subscribe(s => this.refreshIfGood(s))
|
this.ac.menu
|
||||||
|
.editTitle(id, this.dataSource.data.find(v => v._id == id)?.dayTitle)
|
||||||
|
.subscribe(s => this.refreshIfGood(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
getStat(day: DateTime, m: "ob" | "kol") {
|
getStat(day: DateTime, m: 'ob' | 'kol') {
|
||||||
this.ac.menu.stat(day, m).subscribe((s) => this.sb.open(`${s.y} / ${s.y+s.n} = ${((s.y/(s.y+s.n))*100).toFixed(2)}%`, "Zamknij", {duration: 2500}))
|
this.ac.menu
|
||||||
|
.stat(day, m)
|
||||||
|
.subscribe(s =>
|
||||||
|
this.sb.open(
|
||||||
|
`${s.y} / ${s.y + s.n} = ${((s.y / (s.y + s.n)) * 100).toFixed(2)}%`,
|
||||||
|
'Zamknij',
|
||||||
|
{ duration: 2500 }
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(id: string) {
|
remove(id: string) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
:host {
|
:host {
|
||||||
margin: 8pt;
|
margin: 8pt;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { MenuUploadComponent } from './menu-upload.component';
|
import { MenuUploadComponent } from './menu-upload.component'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'
|
||||||
|
|
||||||
describe('MenuUploadComponent', () => {
|
describe('MenuUploadComponent', () => {
|
||||||
let component: MenuUploadComponent;
|
let component: MenuUploadComponent
|
||||||
let fixture: ComponentFixture<MenuUploadComponent>;
|
let fixture: ComponentFixture<MenuUploadComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const acMock = jasmine.createSpyObj('AdminCommService', ['postMenu'])
|
const acMock = jasmine.createSpyObj('AdminCommService', ['postMenu'])
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [MenuUploadComponent],
|
declarations: [MenuUploadComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: AdminCommService, useValue: acMock},
|
{ provide: AdminCommService, useValue: acMock },
|
||||||
{provide: MatDialogRef, useValue: {}}
|
{ provide: MatDialogRef, useValue: {} },
|
||||||
],
|
],
|
||||||
imports: [MatDialogModule]
|
imports: [MatDialogModule],
|
||||||
});
|
})
|
||||||
fixture = TestBed.createComponent(MenuUploadComponent);
|
fixture = TestBed.createComponent(MenuUploadComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
import { MatDialogRef } from '@angular/material/dialog';
|
import { MatDialogRef } from '@angular/material/dialog'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-upload-edit',
|
selector: 'app-upload-edit',
|
||||||
templateUrl: './menu-upload.component.html',
|
templateUrl: './menu-upload.component.html',
|
||||||
styleUrls: ['./menu-upload.component.scss'],
|
styleUrls: ['./menu-upload.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class MenuUploadComponent {
|
export class MenuUploadComponent {
|
||||||
constructor(private ac:AdminCommService, public dialogRef: MatDialogRef<MenuUploadComponent>) {}
|
constructor(
|
||||||
protected file: File | undefined;
|
private ac: AdminCommService,
|
||||||
|
public dialogRef: MatDialogRef<MenuUploadComponent>
|
||||||
|
) {}
|
||||||
|
protected file: File | undefined
|
||||||
onFileChange(event: Event) {
|
onFileChange(event: Event) {
|
||||||
const file:File = (event.target as HTMLInputElement).files![0];
|
const file: File = (event.target as HTMLInputElement).files![0]
|
||||||
if (file) {
|
if (file) {
|
||||||
this.file = file
|
this.file = file
|
||||||
} else {
|
} else {
|
||||||
this.file = undefined
|
this.file = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
this.ac.menu.postMenu(this.file!)?.subscribe((value) => {
|
this.ac.menu.postMenu(this.file!)?.subscribe(value => {
|
||||||
this.dialogRef.close(value)
|
this.dialogRef.close(value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
:host {
|
:host {
|
||||||
padding: 8pt;
|
padding: 8pt;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,41 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { NewPostComponent } from './edit-post.component';
|
import { NewPostComponent } from './edit-post.component'
|
||||||
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
import {
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
MAT_DIALOG_DATA,
|
||||||
import { MatInputModule } from '@angular/material/input';
|
MatDialogModule,
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
MatDialogRef,
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
} from '@angular/material/dialog'
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field'
|
||||||
|
import { MatInputModule } from '@angular/material/input'
|
||||||
|
import { ReactiveFormsModule } from '@angular/forms'
|
||||||
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
|
|
||||||
describe('NewPostComponent', () => {
|
describe('NewPostComponent', () => {
|
||||||
let component: NewPostComponent;
|
let component: NewPostComponent
|
||||||
let fixture: ComponentFixture<NewPostComponent>;
|
let fixture: ComponentFixture<NewPostComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [NewPostComponent],
|
declarations: [NewPostComponent],
|
||||||
imports: [MatDialogModule, MatFormFieldModule, MatInputModule, ReactiveFormsModule, BrowserAnimationsModule],
|
imports: [
|
||||||
|
MatDialogModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatInputModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: MatDialogRef, useValue: {}},
|
{ provide: MatDialogRef, useValue: {} },
|
||||||
{provide: MAT_DIALOG_DATA, useValue: {}}
|
{ provide: MAT_DIALOG_DATA, useValue: {} },
|
||||||
]
|
],
|
||||||
});
|
})
|
||||||
fixture = TestBed.createComponent(NewPostComponent);
|
fixture = TestBed.createComponent(NewPostComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,32 +1,35 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core'
|
||||||
import { FormControl, FormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms'
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-edit-post',
|
selector: 'app-edit-post',
|
||||||
templateUrl: './edit-post.component.html',
|
templateUrl: './edit-post.component.html',
|
||||||
styleUrls: ['./edit-post.component.scss'],
|
styleUrls: ['./edit-post.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class NewPostComponent {
|
export class NewPostComponent {
|
||||||
form: FormGroup;
|
form: FormGroup
|
||||||
constructor (public dialogRef: MatDialogRef<NewPostComponent>, @Inject(MAT_DIALOG_DATA) public data: any) {
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<NewPostComponent>,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: any
|
||||||
|
) {
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
data = {
|
data = {
|
||||||
title:"",
|
title: '',
|
||||||
content:"",
|
content: '',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.form = new FormGroup({
|
this.form = new FormGroup({
|
||||||
title: new FormControl(data.title),
|
title: new FormControl(data.title),
|
||||||
content: new FormControl(data.content)
|
content: new FormControl(data.content),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
protected makePost() {
|
protected makePost() {
|
||||||
this.dialogRef.close({
|
this.dialogRef.close({
|
||||||
title: this.form.get('title')?.value,
|
title: this.form.get('title')?.value,
|
||||||
content: this.form.get('content')?.value
|
content: this.form.get('content')?.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,38 @@
|
|||||||
mat-card {
|
mat-card {
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
padding: 1ch;
|
padding: 1ch;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card-title {
|
mat-card-title {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card-footer p {
|
mat-card-footer p {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
color: #4a4a4a;
|
color: #4a4a4a;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
text-align: end;
|
text-align: end;
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
color: #999999
|
color: #999999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card-content p {
|
mat-card-content p {
|
||||||
white-space: pre-line;
|
white-space: pre-line;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card p {
|
mat-card p {
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
margin-right: 4pt;
|
margin-right: 4pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
padding: 8pt;
|
padding: 8pt;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,34 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { NewsEditComponent } from './news-edit.component';
|
import { NewsEditComponent } from './news-edit.component'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog'
|
||||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
import { MatSnackBarModule } from '@angular/material/snack-bar'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card'
|
||||||
|
|
||||||
describe('NewsEditComponent', () => {
|
describe('NewsEditComponent', () => {
|
||||||
let component: NewsEditComponent;
|
let component: NewsEditComponent
|
||||||
let fixture: ComponentFixture<NewsEditComponent>;
|
let fixture: ComponentFixture<NewsEditComponent>
|
||||||
let acMock
|
let acMock
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
acMock = {
|
acMock = {
|
||||||
news: {
|
news: {
|
||||||
getNews: jasmine.createSpy('getNews').and.returnValue(of([]))
|
getNews: jasmine.createSpy('getNews').and.returnValue(of([])),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [NewsEditComponent],
|
declarations: [NewsEditComponent],
|
||||||
providers: [
|
providers: [{ provide: AdminCommService, useValue: acMock }],
|
||||||
{provide: AdminCommService, useValue: acMock}
|
imports: [MatDialogModule, MatSnackBarModule, MatCardModule],
|
||||||
],
|
})
|
||||||
imports: [MatDialogModule, MatSnackBarModule, MatCardModule]
|
fixture = TestBed.createComponent(NewsEditComponent)
|
||||||
});
|
component = fixture.componentInstance
|
||||||
fixture = TestBed.createComponent(NewsEditComponent);
|
fixture.detectChanges()
|
||||||
component = fixture.componentInstance;
|
})
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,32 +1,38 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog'
|
||||||
import { NewPostComponent } from './new-post/edit-post.component';
|
import { NewPostComponent } from './new-post/edit-post.component'
|
||||||
import { catchError, throwError } from 'rxjs';
|
import { catchError, throwError } from 'rxjs'
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar'
|
||||||
import { News } from 'src/app/types/news';
|
import { News } from 'src/app/types/news'
|
||||||
import { marked } from 'marked';
|
import { marked } from 'marked'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-news-edit',
|
selector: 'app-news-edit',
|
||||||
templateUrl: './news-edit.component.html',
|
templateUrl: './news-edit.component.html',
|
||||||
styleUrls: ['./news-edit.component.scss'],
|
styleUrls: ['./news-edit.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class NewsEditComponent implements OnInit {
|
export class NewsEditComponent implements OnInit {
|
||||||
news:Array<News & {formatted: string}> = new Array<News & {formatted: string}>
|
news: Array<News & { formatted: string }> = new Array<
|
||||||
|
News & { formatted: string }
|
||||||
|
>()
|
||||||
loading = true
|
loading = true
|
||||||
|
|
||||||
constructor(private ac:AdminCommService, private dialog:MatDialog, private sb:MatSnackBar) {}
|
constructor(
|
||||||
|
private ac: AdminCommService,
|
||||||
|
private dialog: MatDialog,
|
||||||
|
private sb: MatSnackBar
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.ac.news.getNews().subscribe(data => {
|
this.ac.news.getNews().subscribe(data => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.news = data.map(v => {
|
this.news = data.map(v => {
|
||||||
var nd: News & {formatted: string} = {
|
var nd: News & { formatted: string } = {
|
||||||
...v,
|
...v,
|
||||||
formatted: marked.parse(v.content, {breaks: true}).toString()
|
formatted: marked.parse(v.content, { breaks: true }).toString(),
|
||||||
}
|
}
|
||||||
return nd
|
return nd
|
||||||
})
|
})
|
||||||
@@ -34,35 +40,51 @@ export class NewsEditComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newPost() {
|
newPost() {
|
||||||
this.dialog.open(NewPostComponent, {width: "90vw"}).afterClosed().subscribe(result=> {
|
this.dialog
|
||||||
if (result == undefined) return
|
.open(NewPostComponent, { width: '90vw' })
|
||||||
this.ac.news.postNews(result.title, result.content).pipe(catchError((err)=>{
|
.afterClosed()
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
.subscribe(result => {
|
||||||
return throwError(() => new Error(err.message))
|
if (result == undefined) return
|
||||||
})).subscribe((data)=>{
|
this.ac.news
|
||||||
if (data.status == 201) {
|
.postNews(result.title, result.content)
|
||||||
this.ngOnInit()
|
.pipe(
|
||||||
} else {
|
catchError(err => {
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
}
|
return throwError(() => new Error(err.message))
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe(data => {
|
||||||
|
if (data.status == 201) {
|
||||||
|
this.ngOnInit()
|
||||||
|
} else {
|
||||||
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
editPost(item: any) {
|
editPost(item: any) {
|
||||||
this.dialog.open(NewPostComponent, {data: item, width: "90vh"}).afterClosed().subscribe(result=>{
|
this.dialog
|
||||||
if (result == undefined) return
|
.open(NewPostComponent, { data: item, width: '90vh' })
|
||||||
this.ac.news.updateNews(item._id, result.title, result.content).pipe(catchError((err)=>{
|
.afterClosed()
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
.subscribe(result => {
|
||||||
return throwError(()=> new Error(err.message))
|
if (result == undefined) return
|
||||||
})).subscribe((data)=> {
|
this.ac.news
|
||||||
if (data.status == 200) {
|
.updateNews(item._id, result.title, result.content)
|
||||||
this.ngOnInit()
|
.pipe(
|
||||||
} else {
|
catchError(err => {
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
}
|
return throwError(() => new Error(err.message))
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe(data => {
|
||||||
|
if (data.status == 200) {
|
||||||
|
this.ngOnInit()
|
||||||
|
} else {
|
||||||
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(id: string) {
|
delete(id: string) {
|
||||||
@@ -74,29 +96,39 @@ export class NewsEditComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
visibleToggle(item: any) {
|
visibleToggle(item: any) {
|
||||||
this.ac.news.toggleNews(item._id, item.visible).pipe(catchError((err)=>{
|
this.ac.news
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
.toggleNews(item._id, item.visible)
|
||||||
return throwError(()=> new Error(err.message))
|
.pipe(
|
||||||
})).subscribe((data)=> {
|
catchError(err => {
|
||||||
if (data.status == 200) {
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
this.ngOnInit()
|
return throwError(() => new Error(err.message))
|
||||||
} else {
|
})
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
)
|
||||||
}
|
.subscribe(data => {
|
||||||
})
|
if (data.status == 200) {
|
||||||
|
this.ngOnInit()
|
||||||
|
} else {
|
||||||
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pinToggle(item:any) {
|
pinToggle(item: any) {
|
||||||
console.log(item.pinned)
|
console.log(item.pinned)
|
||||||
this.ac.news.togglePin(item._id, item.pinned).pipe(catchError((err)=>{
|
this.ac.news
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
.togglePin(item._id, item.pinned)
|
||||||
return throwError(()=> new Error(err.message))
|
.pipe(
|
||||||
})).subscribe((data)=> {
|
catchError(err => {
|
||||||
if (data.status == 200) {
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
this.ngOnInit()
|
return throwError(() => new Error(err.message))
|
||||||
} else {
|
})
|
||||||
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
|
)
|
||||||
}
|
.subscribe(data => {
|
||||||
})
|
if (data.status == 200) {
|
||||||
|
this.ngOnInit()
|
||||||
|
} else {
|
||||||
|
this.sb.open('Wystąpił błąd. Skontaktuj się z obsługą programu.')
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
mat-radio-button {
|
mat-radio-button {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,60 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { NotificationsComponent } from './notifications.component';
|
import { NotificationsComponent } from './notifications.component'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router'
|
||||||
import { MatRadioModule } from '@angular/material/radio';
|
import { MatRadioModule } from '@angular/material/radio'
|
||||||
import { MatFormFieldControl, MatFormFieldModule } from '@angular/material/form-field';
|
import {
|
||||||
import { Component, forwardRef } from '@angular/core';
|
MatFormFieldControl,
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
MatFormFieldModule,
|
||||||
import { Observable, of } from 'rxjs';
|
} from '@angular/material/form-field'
|
||||||
import { AbstractControlDirective, ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR, NgControl, ReactiveFormsModule } from '@angular/forms';
|
import { Component, forwardRef } from '@angular/core'
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { Observable, of } from 'rxjs'
|
||||||
|
import {
|
||||||
|
AbstractControlDirective,
|
||||||
|
ControlValueAccessor,
|
||||||
|
FormsModule,
|
||||||
|
NG_VALUE_ACCESSOR,
|
||||||
|
NgControl,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
} from '@angular/forms'
|
||||||
|
import { MatInputModule } from '@angular/material/input'
|
||||||
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-user-search", template: '', providers: [{
|
selector: 'app-user-search',
|
||||||
provide: NG_VALUE_ACCESSOR,
|
template: '',
|
||||||
useExisting: forwardRef(() => UserSearchStub),
|
providers: [
|
||||||
multi: true,
|
{
|
||||||
},
|
provide: NG_VALUE_ACCESSOR,
|
||||||
{
|
useExisting: forwardRef(() => UserSearchStub),
|
||||||
provide: MatFormFieldControl,
|
multi: true,
|
||||||
useExisting: UserSearchStub
|
},
|
||||||
}],
|
{
|
||||||
standalone: false
|
provide: MatFormFieldControl,
|
||||||
|
useExisting: UserSearchStub,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class UserSearchStub implements ControlValueAccessor, MatFormFieldControl<never> {
|
class UserSearchStub
|
||||||
value: null = null;
|
implements ControlValueAccessor, MatFormFieldControl<never>
|
||||||
stateChanges: Observable<void> = of();
|
{
|
||||||
id: string = "";
|
value: null = null
|
||||||
placeholder: string = "";
|
stateChanges: Observable<void> = of()
|
||||||
ngControl: NgControl | AbstractControlDirective | null = null;
|
id: string = ''
|
||||||
focused: boolean = false;
|
placeholder: string = ''
|
||||||
empty: boolean = true;
|
ngControl: NgControl | AbstractControlDirective | null = null
|
||||||
shouldLabelFloat: boolean = true;
|
focused: boolean = false
|
||||||
required: boolean = false;
|
empty: boolean = true
|
||||||
disabled: boolean = false;
|
shouldLabelFloat: boolean = true
|
||||||
errorState: boolean = false;
|
required: boolean = false
|
||||||
controlType?: string | undefined;
|
disabled: boolean = false
|
||||||
autofilled?: boolean | undefined;
|
errorState: boolean = false
|
||||||
userAriaDescribedBy?: string | undefined;
|
controlType?: string | undefined
|
||||||
|
autofilled?: boolean | undefined
|
||||||
|
userAriaDescribedBy?: string | undefined
|
||||||
setDescribedByIds(ids: string[]): void {}
|
setDescribedByIds(ids: string[]): void {}
|
||||||
onContainerClick(event: MouseEvent): void {}
|
onContainerClick(event: MouseEvent): void {}
|
||||||
writeValue(obj: any): void {}
|
writeValue(obj: any): void {}
|
||||||
@@ -48,20 +64,18 @@ class UserSearchStub implements ControlValueAccessor, MatFormFieldControl<never>
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('NotificationsComponent', () => {
|
describe('NotificationsComponent', () => {
|
||||||
let component: NotificationsComponent;
|
let component: NotificationsComponent
|
||||||
let fixture: ComponentFixture<NotificationsComponent>;
|
let fixture: ComponentFixture<NotificationsComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const acMock = {
|
const acMock = {
|
||||||
notif: {
|
notif: {
|
||||||
getGroups: jasmine.createSpy("getGroups").and.returnValue(of())
|
getGroups: jasmine.createSpy('getGroups').and.returnValue(of()),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [NotificationsComponent, UserSearchStub],
|
declarations: [NotificationsComponent, UserSearchStub],
|
||||||
providers: [
|
providers: [{ provide: AdminCommService, useValue: acMock }],
|
||||||
{provide: AdminCommService, useValue: acMock}
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule.forRoot([]),
|
RouterModule.forRoot([]),
|
||||||
MatRadioModule,
|
MatRadioModule,
|
||||||
@@ -70,15 +84,15 @@ describe('NotificationsComponent', () => {
|
|||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
NoopAnimationsModule
|
NoopAnimationsModule,
|
||||||
]
|
],
|
||||||
});
|
})
|
||||||
fixture = TestBed.createComponent(NotificationsComponent);
|
fixture = TestBed.createComponent(NotificationsComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,46 +1,52 @@
|
|||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core'
|
||||||
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
|
import { FormBuilder, FormControl, FormGroup } from '@angular/forms'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { Notification } from 'src/app/types/notification';
|
import { Notification } from 'src/app/types/notification'
|
||||||
import { Group } from 'src/app/types/group';
|
import { Group } from 'src/app/types/group'
|
||||||
import { LocalStorageService } from 'src/app/services/local-storage.service';
|
import { LocalStorageService } from 'src/app/services/local-storage.service'
|
||||||
import { ToolbarService } from '../toolbar/toolbar.service';
|
import { ToolbarService } from '../toolbar/toolbar.service'
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { UserSearchResult } from 'src/app/commonComponents/user-search/user-search.component';
|
import { UserSearchResult } from 'src/app/commonComponents/user-search/user-search.component'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-notifications',
|
selector: 'app-notifications',
|
||||||
templateUrl: './notifications.component.html',
|
templateUrl: './notifications.component.html',
|
||||||
styleUrls: ['./notifications.component.scss'],
|
styleUrls: ['./notifications.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class NotificationsComponent implements OnInit, OnDestroy {
|
export class NotificationsComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
groups!: Group[]
|
groups!: Group[]
|
||||||
form = this.fb.group({
|
form = this.fb.group({
|
||||||
recp: this.fb.group({
|
recp: this.fb.group({
|
||||||
uid: this.fb.control<UserSearchResult | null>(null),
|
uid: this.fb.control<UserSearchResult | null>(null),
|
||||||
room: this.fb.control<string|null>(null),
|
room: this.fb.control<string | null>(null),
|
||||||
group: this.fb.control<string>(''),
|
group: this.fb.control<string>(''),
|
||||||
type: this.fb.control<"room" | "uname" | "group">('uname', {nonNullable: true})
|
type: this.fb.control<'room' | 'uname' | 'group'>('uname', {
|
||||||
|
nonNullable: true,
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
title: this.fb.control('', {nonNullable: true}),
|
title: this.fb.control('', { nonNullable: true }),
|
||||||
body: this.fb.control('', {nonNullable: true})
|
body: this.fb.control('', { nonNullable: true }),
|
||||||
})
|
})
|
||||||
|
|
||||||
constructor (private readonly acs: AdminCommService, readonly ls: LocalStorageService, private toolbar: ToolbarService, private router: Router, private route: ActivatedRoute, private fb: FormBuilder ) {
|
constructor(
|
||||||
|
private readonly acs: AdminCommService,
|
||||||
|
readonly ls: LocalStorageService,
|
||||||
|
private toolbar: ToolbarService,
|
||||||
|
private router: Router,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private fb: FormBuilder
|
||||||
|
) {
|
||||||
this.toolbar.comp = this
|
this.toolbar.comp = this
|
||||||
this.toolbar.menu = [
|
this.toolbar.menu = [{ title: 'Wysłane', fn: 'outbox', icon: 'outbox' }]
|
||||||
{ title: "Wysłane", fn: "outbox", icon: "outbox" }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
outbox() {
|
outbox() {
|
||||||
this.router.navigate(["outbox"], { relativeTo: this.route })
|
this.router.navigate(['outbox'], { relativeTo: this.route })
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.acs.notif.getGroups().subscribe((v) => {
|
this.acs.notif.getGroups().subscribe(v => {
|
||||||
this.groups = v
|
this.groups = v
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -50,16 +56,21 @@ export class NotificationsComponent implements OnInit, OnDestroy {
|
|||||||
this.toolbar.menu = undefined
|
this.toolbar.menu = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
public inbox() {
|
public inbox() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
success?: { sent: number; possible: number; };
|
|
||||||
|
|
||||||
|
success?: { sent: number; possible: number }
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
this.acs.notif.send({...this.form.value, recp: {...this.form.get("recp")?.value, uid: this.form.controls['recp'].controls['uid'].value?._id}} as Notification).subscribe((data) => {
|
this.acs.notif
|
||||||
this.success = data
|
.send({
|
||||||
})
|
...this.form.value,
|
||||||
|
recp: {
|
||||||
|
...this.form.get('recp')?.value,
|
||||||
|
uid: this.form.controls['recp'].controls['uid'].value?._id,
|
||||||
|
},
|
||||||
|
} as Notification)
|
||||||
|
.subscribe(data => {
|
||||||
|
this.success = data
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
mat-card-title {
|
mat-card-title {
|
||||||
font-size: 24pt;
|
font-size: 24pt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,28 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
import { MessageComponent } from './message.component';
|
import { MessageComponent } from './message.component'
|
||||||
import { AdminCommService } from 'src/app/admin-view/admin-comm.service';
|
import { AdminCommService } from 'src/app/admin-view/admin-comm.service'
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
describe('MessageComponent', () => {
|
describe('MessageComponent', () => {
|
||||||
let component: MessageComponent;
|
let component: MessageComponent
|
||||||
let fixture: ComponentFixture<MessageComponent>;
|
let fixture: ComponentFixture<MessageComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const acMock = {
|
const acMock = {}
|
||||||
|
|
||||||
}
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [MessageComponent],
|
declarations: [MessageComponent],
|
||||||
providers: [
|
providers: [{ provide: AdminCommService, useValue: acMock }],
|
||||||
{provide: AdminCommService, useValue: acMock}
|
imports: [MatCardModule],
|
||||||
],
|
}).compileComponents()
|
||||||
imports: [
|
|
||||||
MatCardModule
|
fixture = TestBed.createComponent(MessageComponent)
|
||||||
]
|
component = fixture.componentInstance
|
||||||
})
|
component.item = { _id: 'test', sentDate: DateTime.now(), title: 'Test' }
|
||||||
.compileComponents();
|
fixture.detectChanges()
|
||||||
|
})
|
||||||
fixture = TestBed.createComponent(MessageComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
component.item = {_id: "test", sentDate: DateTime.now(), title: "Test"}
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,19 +1,25 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
import { AdminCommService } from 'src/app/admin-view/admin-comm.service';
|
import { AdminCommService } from 'src/app/admin-view/admin-comm.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-message',
|
selector: 'app-message',
|
||||||
templateUrl: './message.component.html',
|
templateUrl: './message.component.html',
|
||||||
styleUrl: './message.component.scss',
|
styleUrl: './message.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class MessageComponent {
|
export class MessageComponent {
|
||||||
@Input() item!: {_id: string, sentDate: DateTime, title: string}
|
@Input() item!: { _id: string; sentDate: DateTime; title: string }
|
||||||
body?: string
|
body?: string
|
||||||
rcpts?: {_id: string, uname: string, room?: string, fname?: string, surname?: string}[]
|
rcpts?: {
|
||||||
|
_id: string
|
||||||
|
uname: string
|
||||||
|
room?: string
|
||||||
|
fname?: string
|
||||||
|
surname?: string
|
||||||
|
}[]
|
||||||
loading: boolean = false
|
loading: boolean = false
|
||||||
constructor (readonly acu: AdminCommService) {}
|
constructor(readonly acu: AdminCommService) {}
|
||||||
|
|
||||||
getMessage() {
|
getMessage() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.cardContainer {
|
.cardContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 1ch;
|
gap: 1ch;
|
||||||
margin: 1ch;
|
margin: 1ch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,34 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { OutboxComponent } from './outbox.component';
|
import { OutboxComponent } from './outbox.component'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
|
|
||||||
describe('OutboxComponent', () => {
|
describe('OutboxComponent', () => {
|
||||||
let component: OutboxComponent;
|
let component: OutboxComponent
|
||||||
let fixture: ComponentFixture<OutboxComponent>;
|
let fixture: ComponentFixture<OutboxComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const acMock = {
|
const acMock = {
|
||||||
notif: {
|
notif: {
|
||||||
outbox: {
|
outbox: {
|
||||||
getSent: jasmine.createSpy("getSent").and.returnValue(of())
|
getSent: jasmine.createSpy('getSent').and.returnValue(of()),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [OutboxComponent],
|
declarations: [OutboxComponent],
|
||||||
providers: [
|
providers: [{ provide: AdminCommService, useValue: acMock }],
|
||||||
{provide: AdminCommService, useValue: acMock}
|
imports: [RouterModule.forRoot([])],
|
||||||
],
|
}).compileComponents()
|
||||||
imports: [
|
|
||||||
RouterModule.forRoot([])
|
fixture = TestBed.createComponent(OutboxComponent)
|
||||||
]
|
component = fixture.componentInstance
|
||||||
})
|
fixture.detectChanges()
|
||||||
.compileComponents();
|
})
|
||||||
|
|
||||||
fixture = TestBed.createComponent(OutboxComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,38 +1,41 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service'
|
||||||
import { Router, ActivatedRoute } from '@angular/router';
|
import { Router, ActivatedRoute } from '@angular/router'
|
||||||
import { ToolbarService } from '../../toolbar/toolbar.service';
|
import { ToolbarService } from '../../toolbar/toolbar.service'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-outbox',
|
selector: 'app-outbox',
|
||||||
templateUrl: './outbox.component.html',
|
templateUrl: './outbox.component.html',
|
||||||
styleUrl: './outbox.component.scss',
|
styleUrl: './outbox.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class OutboxComponent implements OnInit {
|
export class OutboxComponent implements OnInit {
|
||||||
|
|
||||||
messages!: {
|
messages!: {
|
||||||
_id: string;
|
_id: string
|
||||||
sentDate: DateTime;
|
sentDate: DateTime
|
||||||
title: string;
|
title: string
|
||||||
}[]
|
}[]
|
||||||
|
|
||||||
constructor (private readonly acs: AdminCommService, private toolbar: ToolbarService, private router: Router, private route: ActivatedRoute ) {
|
constructor(
|
||||||
|
private readonly acs: AdminCommService,
|
||||||
|
private toolbar: ToolbarService,
|
||||||
|
private router: Router,
|
||||||
|
private route: ActivatedRoute
|
||||||
|
) {
|
||||||
this.toolbar.comp = this
|
this.toolbar.comp = this
|
||||||
this.toolbar.menu = [
|
this.toolbar.menu = [
|
||||||
{ title: "Powiadomienia", fn: "goBack", icon: "arrow_back" }
|
{ title: 'Powiadomienia', fn: 'goBack', icon: 'arrow_back' },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
goBack() {
|
goBack() {
|
||||||
this.router.navigate(['../'], {relativeTo: this.route})
|
this.router.navigate(['../'], { relativeTo: this.route })
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.acs.notif.outbox.getSent().subscribe((v) => {
|
this.acs.notif.outbox.getSent().subscribe(v => {
|
||||||
this.messages = v
|
this.messages = v
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
:host {
|
:host {
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,40 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { SettingsComponent } from './settings.component';
|
import { SettingsComponent } from './settings.component'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { MatExpansionModule } from '@angular/material/expansion';
|
import { MatExpansionModule } from '@angular/material/expansion'
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core'
|
||||||
import { MatTabsModule } from '@angular/material/tabs';
|
import { MatTabsModule } from '@angular/material/tabs'
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field'
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-list-editor', template: '',
|
selector: 'app-list-editor',
|
||||||
standalone: false
|
template: '',
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class ListEditorStub {
|
class ListEditorStub {
|
||||||
@Input() converter?: any[];
|
@Input() converter?: any[]
|
||||||
@Input() list?: string[];
|
@Input() list?: string[]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('SettingsComponent', () => {
|
describe('SettingsComponent', () => {
|
||||||
let component: SettingsComponent;
|
let component: SettingsComponent
|
||||||
let fixture: ComponentFixture<SettingsComponent>;
|
let fixture: ComponentFixture<SettingsComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const acMock = {
|
const acMock = {
|
||||||
settings: {
|
settings: {
|
||||||
getAll: jasmine.createSpy("getAll").and.returnValue(of())
|
getAll: jasmine.createSpy('getAll').and.returnValue(of()),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [SettingsComponent, ListEditorStub],
|
declarations: [SettingsComponent, ListEditorStub],
|
||||||
providers: [
|
providers: [{ provide: AdminCommService, useValue: acMock }],
|
||||||
{provide: AdminCommService, useValue: acMock}
|
|
||||||
],
|
|
||||||
imports: [
|
imports: [
|
||||||
MatExpansionModule,
|
MatExpansionModule,
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
@@ -45,17 +43,16 @@ describe('SettingsComponent', () => {
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
NoopAnimationsModule,
|
NoopAnimationsModule,
|
||||||
MatInputModule
|
MatInputModule,
|
||||||
]
|
],
|
||||||
})
|
}).compileComponents()
|
||||||
.compileComponents();
|
|
||||||
|
fixture = TestBed.createComponent(SettingsComponent)
|
||||||
fixture = TestBed.createComponent(SettingsComponent);
|
component = fixture.componentInstance
|
||||||
component = fixture.componentInstance;
|
fixture.detectChanges()
|
||||||
fixture.detectChanges();
|
})
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,28 +1,38 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service'
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar'
|
||||||
import { FormBuilder } from '@angular/forms';
|
import { FormBuilder } from '@angular/forms'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings',
|
selector: 'app-settings',
|
||||||
templateUrl: './settings.component.html',
|
templateUrl: './settings.component.html',
|
||||||
styleUrl: './settings.component.scss',
|
styleUrl: './settings.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class SettingsComponent implements OnInit {
|
export class SettingsComponent implements OnInit {
|
||||||
usettings: IUSettings = {cleanThings: [], keyrooms: [], menu: {defaultItems: {kol: [], sn: []}}, rooms: [], security: {loginTimeout: {attempts: 0, lockout: 0, time: 0}}}
|
usettings: IUSettings = {
|
||||||
reloadTimeout: boolean = false;
|
cleanThings: [],
|
||||||
|
keyrooms: [],
|
||||||
|
menu: { defaultItems: { kol: [], sn: [] } },
|
||||||
|
rooms: [],
|
||||||
|
security: { loginTimeout: { attempts: 0, lockout: 0, time: 0 } },
|
||||||
|
}
|
||||||
|
reloadTimeout: boolean = false
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly acu: AdminCommService,
|
||||||
|
private readonly sb: MatSnackBar,
|
||||||
|
private readonly fb: FormBuilder
|
||||||
|
) {}
|
||||||
|
|
||||||
constructor (private readonly acu: AdminCommService, private readonly sb: MatSnackBar, private readonly fb: FormBuilder) { }
|
|
||||||
|
|
||||||
accSec = this.fb.nonNullable.group({
|
accSec = this.fb.nonNullable.group({
|
||||||
attempts: this.fb.nonNullable.control(1),
|
attempts: this.fb.nonNullable.control(1),
|
||||||
time: this.fb.nonNullable.control(1),
|
time: this.fb.nonNullable.control(1),
|
||||||
lockout: this.fb.nonNullable.control(1),
|
lockout: this.fb.nonNullable.control(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.acu.settings.getAll().subscribe((r) => {
|
this.acu.settings.getAll().subscribe(r => {
|
||||||
this.usettings = r
|
this.usettings = r
|
||||||
this.accSecTimeouts = r.security.loginTimeout
|
this.accSecTimeouts = r.security.loginTimeout
|
||||||
})
|
})
|
||||||
@@ -59,23 +69,23 @@ export class SettingsComponent implements OnInit {
|
|||||||
this.accSec.setValue({
|
this.accSec.setValue({
|
||||||
attempts: value.attempts,
|
attempts: value.attempts,
|
||||||
lockout: value.lockout / 60,
|
lockout: value.lockout / 60,
|
||||||
time: value.time / 60
|
time: value.time / 60,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
get accSecTimeouts(): IUSettings['security']['loginTimeout'] {
|
get accSecTimeouts(): IUSettings['security']['loginTimeout'] {
|
||||||
return {
|
return {
|
||||||
attempts: this.accSec.controls['attempts'].value,
|
attempts: this.accSec.controls['attempts'].value,
|
||||||
lockout: this.accSec.controls['lockout'].value * 60,
|
lockout: this.accSec.controls['lockout'].value * 60,
|
||||||
time: this.accSec.controls['time'].value * 60
|
time: this.accSec.controls['time'].value * 60,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
send() {
|
send() {
|
||||||
this.acu.settings.post(this.usettings).subscribe((s) => {
|
this.acu.settings.post(this.usettings).subscribe(s => {
|
||||||
if (s.status == 200) {
|
if (s.status == 200) {
|
||||||
this.sb.open("Zapisano!", undefined, { duration: 1000 })
|
this.sb.open('Zapisano!', undefined, { duration: 1000 })
|
||||||
} else {
|
} else {
|
||||||
console.error(s);
|
console.error(s)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -87,32 +97,32 @@ export class SettingsComponent implements OnInit {
|
|||||||
this.reloadTimeout = true
|
this.reloadTimeout = true
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.reloadTimeout = false
|
this.reloadTimeout = false
|
||||||
}, 5000);
|
}, 5000)
|
||||||
this.acu.settings.reload().subscribe((s) => {
|
this.acu.settings.reload().subscribe(s => {
|
||||||
if (s.status == 200) {
|
if (s.status == 200) {
|
||||||
this.sb.open("Przeładowano ustawienia!", undefined, { duration: 3000 })
|
this.sb.open('Przeładowano ustawienia!', undefined, { duration: 3000 })
|
||||||
} else {
|
} else {
|
||||||
console.error(s);
|
console.error(s)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUSettings {
|
export interface IUSettings {
|
||||||
keyrooms: string[];
|
keyrooms: string[]
|
||||||
rooms: string[];
|
rooms: string[]
|
||||||
cleanThings: string[];
|
cleanThings: string[]
|
||||||
menu: {
|
menu: {
|
||||||
defaultItems: {
|
defaultItems: {
|
||||||
sn: string[];
|
sn: string[]
|
||||||
kol: string[];
|
kol: string[]
|
||||||
}
|
|
||||||
};
|
|
||||||
security: {
|
|
||||||
loginTimeout: {
|
|
||||||
attempts: number;
|
|
||||||
time: number;
|
|
||||||
lockout: number;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
security: {
|
||||||
|
loginTimeout: {
|
||||||
|
attempts: number
|
||||||
|
time: number
|
||||||
|
lockout: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
.main {
|
.main {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
margin-left: 16px;
|
margin-left: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 1ch;
|
gap: 1ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
font-size: 32pt;
|
font-size: 32pt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,24 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { StartAdminComponent } from './start.component';
|
import { StartAdminComponent } from './start.component'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
|
|
||||||
describe('StartAdminComponent', () => {
|
describe('StartAdminComponent', () => {
|
||||||
let component: StartAdminComponent;
|
let component: StartAdminComponent
|
||||||
let fixture: ComponentFixture<StartAdminComponent>;
|
let fixture: ComponentFixture<StartAdminComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [StartAdminComponent],
|
declarations: [StartAdminComponent],
|
||||||
imports: [
|
imports: [MatIconModule],
|
||||||
MatIconModule
|
}).compileComponents()
|
||||||
]
|
|
||||||
})
|
fixture = TestBed.createComponent(StartAdminComponent)
|
||||||
.compileComponents();
|
component = fixture.componentInstance
|
||||||
|
fixture.detectChanges()
|
||||||
fixture = TestBed.createComponent(StartAdminComponent);
|
})
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-start',
|
selector: 'app-start',
|
||||||
templateUrl: './start.component.html',
|
templateUrl: './start.component.html',
|
||||||
styleUrl: './start.component.scss',
|
styleUrl: './start.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class StartAdminComponent {
|
export class StartAdminComponent {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,27 +1,26 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { ToolbarComponent } from './toolbar.component';
|
import { ToolbarComponent } from './toolbar.component'
|
||||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
import { MatToolbarModule } from '@angular/material/toolbar'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu'
|
||||||
|
|
||||||
describe('ToolbarComponent', () => {
|
describe('ToolbarComponent', () => {
|
||||||
let component: ToolbarComponent;
|
let component: ToolbarComponent
|
||||||
let fixture: ComponentFixture<ToolbarComponent>;
|
let fixture: ComponentFixture<ToolbarComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [ToolbarComponent],
|
declarations: [ToolbarComponent],
|
||||||
imports: [MatToolbarModule, MatIconModule, MatMenuModule]
|
imports: [MatToolbarModule, MatIconModule, MatMenuModule],
|
||||||
})
|
}).compileComponents()
|
||||||
.compileComponents();
|
|
||||||
|
fixture = TestBed.createComponent(ToolbarComponent)
|
||||||
fixture = TestBed.createComponent(ToolbarComponent);
|
component = fixture.componentInstance
|
||||||
component = fixture.componentInstance;
|
fixture.detectChanges()
|
||||||
fixture.detectChanges();
|
})
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,26 +1,27 @@
|
|||||||
import { Component, Input, ViewChild } from '@angular/core';
|
import { Component, Input, ViewChild } from '@angular/core'
|
||||||
import { MatDrawer } from '@angular/material/sidenav';
|
import { MatDrawer } from '@angular/material/sidenav'
|
||||||
import { Title } from '@angular/platform-browser';
|
import { Title } from '@angular/platform-browser'
|
||||||
import { ToolbarService } from './toolbar.service';
|
import { ToolbarService } from './toolbar.service'
|
||||||
import { MatMenuTrigger } from '@angular/material/menu';
|
import { MatMenuTrigger } from '@angular/material/menu'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-toolbar',
|
selector: 'app-toolbar',
|
||||||
templateUrl: './toolbar.component.html',
|
templateUrl: './toolbar.component.html',
|
||||||
styleUrl: './toolbar.component.scss',
|
styleUrl: './toolbar.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class ToolbarComponent {
|
export class ToolbarComponent {
|
||||||
@Input() drawer!: MatDrawer;
|
@Input() drawer!: MatDrawer
|
||||||
@ViewChild(MatMenuTrigger) trigger!: MatMenuTrigger;
|
@ViewChild(MatMenuTrigger) trigger!: MatMenuTrigger
|
||||||
|
|
||||||
protected _menu?: typeof this.toolbar.menu
|
protected _menu?: typeof this.toolbar.menu
|
||||||
|
|
||||||
constructor(readonly title: Title, protected toolbar: ToolbarService) {
|
constructor(
|
||||||
|
readonly title: Title,
|
||||||
}
|
protected toolbar: ToolbarService
|
||||||
|
) {}
|
||||||
|
|
||||||
openMenu () {
|
openMenu() {
|
||||||
this._menu = this.toolbar.menu
|
this._menu = this.toolbar.menu
|
||||||
this.trigger.openMenu()
|
this.trigger.openMenu()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { ToolbarService } from './toolbar.service';
|
import { ToolbarService } from './toolbar.service'
|
||||||
|
|
||||||
describe('ToolbarService', () => {
|
describe('ToolbarService', () => {
|
||||||
let service: ToolbarService;
|
let service: ToolbarService
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({});
|
TestBed.configureTestingModule({})
|
||||||
service = TestBed.inject(ToolbarService);
|
service = TestBed.inject(ToolbarService)
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
expect(service).toBeTruthy();
|
expect(service).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core'
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class ToolbarService {
|
export class ToolbarService {
|
||||||
|
public comp?: any
|
||||||
public comp?: any;
|
public menu?: { title: string; check?: boolean; icon?: string; fn: string }[]
|
||||||
public menu?: {title: string, check?: boolean, icon?: string, fn: string}[]
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing'
|
||||||
import { CanActivateChildFn } from '@angular/router';
|
import { CanActivateChildFn } from '@angular/router'
|
||||||
|
|
||||||
import { adminGuard } from './admin.guard';
|
import { adminGuard } from './admin.guard'
|
||||||
|
|
||||||
describe('adminGuard', () => {
|
describe('adminGuard', () => {
|
||||||
const executeGuard: CanActivateChildFn = (...guardParameters) =>
|
const executeGuard: CanActivateChildFn = (...guardParameters) =>
|
||||||
TestBed.runInInjectionContext(() => adminGuard(...guardParameters));
|
TestBed.runInInjectionContext(() => adminGuard(...guardParameters))
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({});
|
TestBed.configureTestingModule({})
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
expect(executeGuard).toBeTruthy();
|
expect(executeGuard).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { inject } from '@angular/core';
|
import { inject } from '@angular/core'
|
||||||
import { CanActivateChildFn, RedirectCommand, Router } from '@angular/router';
|
import { CanActivateChildFn, RedirectCommand, Router } from '@angular/router'
|
||||||
import { LocalStorageService } from './services/local-storage.service';
|
import { LocalStorageService } from './services/local-storage.service'
|
||||||
|
|
||||||
export const adminGuard: CanActivateChildFn = (childRoute, state) => {
|
export const adminGuard: CanActivateChildFn = (childRoute, state) => {
|
||||||
const router = inject(Router)
|
const router = inject(Router)
|
||||||
if (inject(LocalStorageService).admin == undefined) return new RedirectCommand(router.parseUrl('/'))
|
if (inject(LocalStorageService).admin == undefined)
|
||||||
|
return new RedirectCommand(router.parseUrl('/'))
|
||||||
return true
|
return true
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,58 +1,106 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core'
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router'
|
||||||
import { NewsComponent } from './app-view/news/news.component';
|
import { NewsComponent } from './app-view/news/news.component'
|
||||||
import { MenuComponent } from './app-view/menu/menu.component';
|
import { MenuComponent } from './app-view/menu/menu.component'
|
||||||
import { AppViewComponent } from './app-view/app-view.component';
|
import { AppViewComponent } from './app-view/app-view.component'
|
||||||
import { LoginComponent } from './login/login.component';
|
import { LoginComponent } from './login/login.component'
|
||||||
import { authGuard } from './auth.guard';
|
import { authGuard } from './auth.guard'
|
||||||
import { PersonalComponent } from './app-view/personal/personal.component';
|
import { PersonalComponent } from './app-view/personal/personal.component'
|
||||||
import { AdminViewComponent } from './admin-view/admin-view.component';
|
import { AdminViewComponent } from './admin-view/admin-view.component'
|
||||||
import { NewsEditComponent } from './admin-view/news-edit/news-edit.component';
|
import { NewsEditComponent } from './admin-view/news-edit/news-edit.component'
|
||||||
import { AccountMgmtComponent } from './admin-view/account-mgmt/account-mgmt.component';
|
import { AccountMgmtComponent } from './admin-view/account-mgmt/account-mgmt.component'
|
||||||
import { MenuNewComponent } from './admin-view/menu-new/menu-new.component';
|
import { MenuNewComponent } from './admin-view/menu-new/menu-new.component'
|
||||||
import { adminGuard } from './admin.guard';
|
import { adminGuard } from './admin.guard'
|
||||||
import { GroupsComponent } from './admin-view/groups/groups.component';
|
import { GroupsComponent } from './admin-view/groups/groups.component'
|
||||||
import { StartComponent } from './app-view/start/start.component';
|
import { StartComponent } from './app-view/start/start.component'
|
||||||
import { AdminKeyComponent } from './admin-view/key/key.component';
|
import { AdminKeyComponent } from './admin-view/key/key.component'
|
||||||
import { GradesComponent } from './admin-view/grades/grades.component';
|
import { GradesComponent } from './admin-view/grades/grades.component'
|
||||||
import { SummaryComponent } from './admin-view/grades/summary/summary.component';
|
import { SummaryComponent } from './admin-view/grades/summary/summary.component'
|
||||||
import { SettingsComponent } from './admin-view/settings/settings.component';
|
import { SettingsComponent } from './admin-view/settings/settings.component'
|
||||||
import { AttendenceSummaryComponent } from './admin-view/grades/attendence-summary/attendence-summary.component';
|
import { AttendenceSummaryComponent } from './admin-view/grades/attendence-summary/attendence-summary.component'
|
||||||
import { NotificationsComponent } from './admin-view/notifications/notifications.component';
|
import { NotificationsComponent } from './admin-view/notifications/notifications.component'
|
||||||
import { OutboxComponent } from './admin-view/notifications/outbox/outbox.component';
|
import { OutboxComponent } from './admin-view/notifications/outbox/outbox.component'
|
||||||
import { StartAdminComponent } from './admin-view/start/start.component';
|
import { StartAdminComponent } from './admin-view/start/start.component'
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: "", redirectTo: "login", pathMatch: "full"},
|
{ path: '', redirectTo: 'login', pathMatch: 'full' },
|
||||||
{path: "login", component: LoginComponent},
|
{ path: 'login', component: LoginComponent },
|
||||||
{path: "app", component: AppViewComponent, title: "Internat", canActivateChild: [authGuard], children: [
|
{
|
||||||
{path: "", component: StartComponent, pathMatch: "full"},
|
path: 'app',
|
||||||
{path: "news",component: NewsComponent, title: "Wiadomości"},
|
component: AppViewComponent,
|
||||||
{path: "menu", component: MenuComponent, title: "Jadłospis"},
|
title: 'Internat',
|
||||||
{path: "grades", component: PersonalComponent, title: "Konto"}
|
canActivateChild: [authGuard],
|
||||||
]},
|
children: [
|
||||||
{path: "admin", component: AdminViewComponent, title: "Panel administracyjny", canActivateChild: [authGuard, adminGuard], children: [
|
{ path: '', component: StartComponent, pathMatch: 'full' },
|
||||||
{path: "", pathMatch: "full", component: StartAdminComponent},
|
{ path: 'news', component: NewsComponent, title: 'Wiadomości' },
|
||||||
{path: "news", title: "Edytowanie wiadomości", component: NewsEditComponent},
|
{ path: 'menu', component: MenuComponent, title: 'Jadłospis' },
|
||||||
{path: "menu", title: "Edytowanie jadłospisu", component: MenuNewComponent},
|
{ path: 'grades', component: PersonalComponent, title: 'Konto' },
|
||||||
{path: "accounts", title: "Użytkownicy", component: AccountMgmtComponent},
|
],
|
||||||
{path: "notifications", children: [
|
},
|
||||||
{path: "", pathMatch: "full", title: "Powiadomienia", component: NotificationsComponent},
|
{
|
||||||
{path: "outbox", title: "Wysłane", component: OutboxComponent}
|
path: 'admin',
|
||||||
]},
|
component: AdminViewComponent,
|
||||||
{path: "groups", title: "Grupy", component: GroupsComponent},
|
title: 'Panel administracyjny',
|
||||||
{path: "keys", title: "Klucze", component: AdminKeyComponent},
|
canActivateChild: [authGuard, adminGuard],
|
||||||
{path: "grades", children: [
|
children: [
|
||||||
{path: "", pathMatch: "full", title: "Oceny", component: GradesComponent},
|
{ path: '', pathMatch: 'full', component: StartAdminComponent },
|
||||||
{path: "summary", title: "Podsumowanie ocen", component: SummaryComponent},
|
{
|
||||||
{path: "attendenceSummary", title: "Obecność", component: AttendenceSummaryComponent}
|
path: 'news',
|
||||||
]},
|
title: 'Edytowanie wiadomości',
|
||||||
{path: "settings", title: "Ustawienia", component: SettingsComponent}
|
component: NewsEditComponent,
|
||||||
]}
|
},
|
||||||
];
|
{
|
||||||
|
path: 'menu',
|
||||||
|
title: 'Edytowanie jadłospisu',
|
||||||
|
component: MenuNewComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'accounts',
|
||||||
|
title: 'Użytkownicy',
|
||||||
|
component: AccountMgmtComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'notifications',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
pathMatch: 'full',
|
||||||
|
title: 'Powiadomienia',
|
||||||
|
component: NotificationsComponent,
|
||||||
|
},
|
||||||
|
{ path: 'outbox', title: 'Wysłane', component: OutboxComponent },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ path: 'groups', title: 'Grupy', component: GroupsComponent },
|
||||||
|
{ path: 'keys', title: 'Klucze', component: AdminKeyComponent },
|
||||||
|
{
|
||||||
|
path: 'grades',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
pathMatch: 'full',
|
||||||
|
title: 'Oceny',
|
||||||
|
component: GradesComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'summary',
|
||||||
|
title: 'Podsumowanie ocen',
|
||||||
|
component: SummaryComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'attendenceSummary',
|
||||||
|
title: 'Obecność',
|
||||||
|
component: AttendenceSummaryComponent,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ path: 'settings', title: 'Ustawienia', component: SettingsComponent },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [RouterModule.forRoot(routes)],
|
imports: [RouterModule.forRoot(routes)],
|
||||||
exports: [RouterModule]
|
exports: [RouterModule],
|
||||||
})
|
})
|
||||||
export class AppRoutingModule { }
|
export class AppRoutingModule {}
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
#bot-navigation {
|
#bot-navigation {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#outlet {
|
#outlet {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#scrollable {
|
#scrollable {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@supports (-webkit-touch-callout: none) {
|
@supports (-webkit-touch-callout: none) {
|
||||||
height: 95vh;
|
height: 95vh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration-line: none;
|
text-decoration-line: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,40 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { AppViewComponent } from './app-view.component';
|
import { AppViewComponent } from './app-view.component'
|
||||||
import { AuthClient } from '../services/auth.client';
|
import { AuthClient } from '../services/auth.client'
|
||||||
import { SwPush } from '@angular/service-worker';
|
import { SwPush } from '@angular/service-worker'
|
||||||
import { UpdatesService } from '../services/updates.service';
|
import { UpdatesService } from '../services/updates.service'
|
||||||
import { MatTabsModule } from '@angular/material/tabs';
|
import { MatTabsModule } from '@angular/material/tabs'
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
|
|
||||||
describe('AppViewComponent', () => {
|
describe('AppViewComponent', () => {
|
||||||
let component: AppViewComponent;
|
let component: AppViewComponent
|
||||||
let fixture: ComponentFixture<AppViewComponent>;
|
let fixture: ComponentFixture<AppViewComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const authSpy = jasmine.createSpyObj('AuthClient', ['check'])
|
const authSpy = jasmine.createSpyObj('AuthClient', ['check'])
|
||||||
const pushSpy = jasmine.createSpyObj('SwPush', ['requestSubscription'])
|
const pushSpy = jasmine.createSpyObj('SwPush', ['requestSubscription'])
|
||||||
const updatesSpy = jasmine.createSpyObj('UpdatesService', {
|
const updatesSpy = jasmine.createSpyObj('UpdatesService', {
|
||||||
newsCheck: of()
|
newsCheck: of(),
|
||||||
})
|
})
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [AppViewComponent],
|
declarations: [AppViewComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: AuthClient, useValue: authSpy},
|
{ provide: AuthClient, useValue: authSpy },
|
||||||
{provide: SwPush, useValue: pushSpy},
|
{ provide: SwPush, useValue: pushSpy },
|
||||||
{provide: UpdatesService, useValue: updatesSpy}
|
{ provide: UpdatesService, useValue: updatesSpy },
|
||||||
],
|
],
|
||||||
imports: [MatTabsModule, RouterModule.forRoot([]), MatIconModule]
|
imports: [MatTabsModule, RouterModule.forRoot([]), MatIconModule],
|
||||||
});
|
})
|
||||||
fixture = TestBed.createComponent(AppViewComponent);
|
fixture = TestBed.createComponent(AppViewComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,49 +1,61 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { AuthClient } from '../services/auth.client';
|
import { AuthClient } from '../services/auth.client'
|
||||||
import { SwPush } from '@angular/service-worker';
|
import { SwPush } from '@angular/service-worker'
|
||||||
import { UpdatesService } from '../services/updates.service';
|
import { UpdatesService } from '../services/updates.service'
|
||||||
import { Link } from '../types/link';
|
import { Link } from '../types/link'
|
||||||
import { LocalStorageService } from '../services/local-storage.service';
|
import { LocalStorageService } from '../services/local-storage.service'
|
||||||
import { interval } from 'rxjs';
|
import { interval } from 'rxjs'
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar'
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog'
|
||||||
import { NotifDialogComponent } from './notif-dialog/notif-dialog.component';
|
import { NotifDialogComponent } from './notif-dialog/notif-dialog.component'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-app-view',
|
selector: 'app-app-view',
|
||||||
templateUrl: './app-view.component.html',
|
templateUrl: './app-view.component.html',
|
||||||
styleUrls: ['./app-view.component.scss'],
|
styleUrls: ['./app-view.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class AppViewComponent implements OnInit {
|
export class AppViewComponent implements OnInit {
|
||||||
private readonly _LINKS: Link[] = [
|
private readonly _LINKS: Link[] = [
|
||||||
{ title: "Jadłospis", href: "menu", icon: "restaurant_menu", enabled: this.ls.capCheck(2) },
|
{
|
||||||
{ title: "Wiadomości", href: "news", icon: "newspaper", enabled: this.ls.capCheck(1) },
|
title: 'Jadłospis',
|
||||||
{ title: "Konto", href: "grades", icon: "account_circle", enabled: true }
|
href: 'menu',
|
||||||
];
|
icon: 'restaurant_menu',
|
||||||
|
enabled: this.ls.capCheck(2),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Wiadomości',
|
||||||
|
href: 'news',
|
||||||
|
icon: 'newspaper',
|
||||||
|
enabled: this.ls.capCheck(1),
|
||||||
|
},
|
||||||
|
{ title: 'Konto', href: 'grades', icon: 'account_circle', enabled: true },
|
||||||
|
]
|
||||||
|
|
||||||
public get LINKS() {
|
public get LINKS() {
|
||||||
return this._LINKS.filter((v) => {
|
return this._LINKS.filter(v => {
|
||||||
return v.enabled
|
return v.enabled
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (
|
constructor(
|
||||||
private ac: AuthClient,
|
private ac: AuthClient,
|
||||||
readonly swPush: SwPush,
|
readonly swPush: SwPush,
|
||||||
private us: UpdatesService,
|
private us: UpdatesService,
|
||||||
private ls: LocalStorageService,
|
private ls: LocalStorageService,
|
||||||
private sb: MatSnackBar,
|
private sb: MatSnackBar,
|
||||||
private dialog: MatDialog
|
private dialog: MatDialog
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
subscribeToNotif() {
|
subscribeToNotif() {
|
||||||
if (this.swPush.isEnabled && this.ls.capCheck(4)) {
|
if (this.swPush.isEnabled && this.ls.capCheck(4)) {
|
||||||
this.swPush.requestSubscription({
|
this.swPush
|
||||||
serverPublicKey: this.ls.vapid
|
.requestSubscription({
|
||||||
}).then(sub => {
|
serverPublicKey: this.ls.vapid,
|
||||||
this.us.postNotif(sub)
|
})
|
||||||
})
|
.then(sub => {
|
||||||
|
this.us.postNotif(sub)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,18 +68,21 @@ export class AppViewComponent implements OnInit {
|
|||||||
|
|
||||||
newsCheck() {
|
newsCheck() {
|
||||||
if (this.ls.capCheck(4)) {
|
if (this.ls.capCheck(4)) {
|
||||||
this.us.getNotifCheck().subscribe((s) => {
|
this.us.getNotifCheck().subscribe(s => {
|
||||||
s.forEach(v => {
|
s.forEach(v => {
|
||||||
this.dialog.open(NotifDialogComponent, {data: v})
|
this.dialog.open(NotifDialogComponent, { data: v })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (this.ls.newsflag) return;
|
if (this.ls.newsflag) return
|
||||||
this.us.newsCheck().subscribe((s) => {
|
this.us.newsCheck().subscribe(s => {
|
||||||
if (s.hash != this.ls.newsCheck.hash) {
|
if (s.hash != this.ls.newsCheck.hash) {
|
||||||
this.ls.newsflag = this.ls.newsCheck.count - s.count
|
this.ls.newsflag = this.ls.newsCheck.count - s.count
|
||||||
this.ls.newsCheck = s
|
this.ls.newsCheck = s
|
||||||
this.sb.open("Nowe wiadomości", "Zamknij", {duration: 5000, verticalPosition: 'bottom'})
|
this.sb.open('Nowe wiadomości', 'Zamknij', {
|
||||||
|
duration: 5000,
|
||||||
|
verticalPosition: 'bottom',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
ol>li::marker {
|
ol > li::marker {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { AllergensComponent } from './allergens.component';
|
import { AllergensComponent } from './allergens.component'
|
||||||
|
|
||||||
describe('AllergensComponent', () => {
|
describe('AllergensComponent', () => {
|
||||||
let component: AllergensComponent;
|
let component: AllergensComponent
|
||||||
let fixture: ComponentFixture<AllergensComponent>;
|
let fixture: ComponentFixture<AllergensComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [AllergensComponent]
|
declarations: [AllergensComponent],
|
||||||
});
|
})
|
||||||
fixture = TestBed.createComponent(AllergensComponent);
|
fixture = TestBed.createComponent(AllergensComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-allergens',
|
selector: 'app-allergens',
|
||||||
templateUrl: './allergens.component.html',
|
templateUrl: './allergens.component.html',
|
||||||
styleUrls: ['./allergens.component.scss'],
|
styleUrls: ['./allergens.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class AllergensComponent {
|
export class AllergensComponent {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,41 +1,41 @@
|
|||||||
:host {
|
:host {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: none;
|
overflow: none;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#cards {
|
#cards {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#alrg {
|
#alrg {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-spinner {
|
mat-spinner {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card {
|
mat-card {
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
padding: 1ch;
|
padding: 1ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
#no-data {
|
#no-data {
|
||||||
color: #777;
|
color: #777;
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
color: #AAA
|
color: #aaa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card-title {
|
mat-card-title {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
app-date-selector {
|
app-date-selector {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +1,54 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { MenuComponent } from './menu.component';
|
import { MenuComponent } from './menu.component'
|
||||||
import { UpdatesService } from 'src/app/services/updates.service';
|
import { UpdatesService } from 'src/app/services/updates.service'
|
||||||
import { DateSelectorComponent } from '../../commonComponents/date-selector/date-selector.component';
|
import { DateSelectorComponent } from '../../commonComponents/date-selector/date-selector.component'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field'
|
||||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
import { MatDatepickerModule } from '@angular/material/datepicker'
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card'
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms'
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input'
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
import { MatDialogRef } from '@angular/material/dialog';
|
import { MatDialogRef } from '@angular/material/dialog'
|
||||||
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
import { MatBottomSheetModule } from '@angular/material/bottom-sheet'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'
|
||||||
import { provideLuxonDateAdapter } from '@angular/material-luxon-adapter';
|
import { provideLuxonDateAdapter } from '@angular/material-luxon-adapter'
|
||||||
|
|
||||||
describe('MenuComponent', () => {
|
describe('MenuComponent', () => {
|
||||||
let component: MenuComponent;
|
let component: MenuComponent
|
||||||
let fixture: ComponentFixture<MenuComponent>;
|
let fixture: ComponentFixture<MenuComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const updatesSpy = jasmine.createSpyObj('UpdatesService', {
|
const updatesSpy = jasmine.createSpyObj('UpdatesService', {
|
||||||
getMenu: of()
|
getMenu: of(),
|
||||||
})
|
})
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [ MenuComponent, DateSelectorComponent],
|
declarations: [MenuComponent, DateSelectorComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: UpdatesService, useValue: updatesSpy},
|
{ provide: UpdatesService, useValue: updatesSpy },
|
||||||
provideLuxonDateAdapter()
|
provideLuxonDateAdapter(),
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
MatFormFieldModule,
|
MatFormFieldModule,
|
||||||
MatDatepickerModule,
|
MatDatepickerModule,
|
||||||
MatCardModule,
|
MatCardModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
MatBottomSheetModule,
|
MatBottomSheetModule,
|
||||||
MatProgressSpinnerModule
|
MatProgressSpinnerModule,
|
||||||
]
|
],
|
||||||
})
|
}).compileComponents()
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(MenuComponent);
|
fixture = TestBed.createComponent(MenuComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,42 +1,60 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { UpdatesService } from '../../services/updates.service';
|
import { UpdatesService } from '../../services/updates.service'
|
||||||
import { Menu } from '../../types/menu';
|
import { Menu } from '../../types/menu'
|
||||||
import { MatBottomSheet } from '@angular/material/bottom-sheet';
|
import { MatBottomSheet } from '@angular/material/bottom-sheet'
|
||||||
import { AllergensComponent } from './allergens/allergens.component';
|
import { AllergensComponent } from './allergens/allergens.component'
|
||||||
import { weekendFilter } from "../../fd.da";
|
import { weekendFilter } from '../../fd.da'
|
||||||
import { LocalStorageService } from 'src/app/services/local-storage.service';
|
import { LocalStorageService } from 'src/app/services/local-storage.service'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-menu',
|
selector: 'app-menu',
|
||||||
templateUrl: './menu.component.html',
|
templateUrl: './menu.component.html',
|
||||||
styleUrls: ['./menu.component.scss'],
|
styleUrls: ['./menu.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class MenuComponent {
|
export class MenuComponent {
|
||||||
constructor(private uc: UpdatesService, readonly bs: MatBottomSheet, readonly ls: LocalStorageService) {
|
constructor(
|
||||||
|
private uc: UpdatesService,
|
||||||
|
readonly bs: MatBottomSheet,
|
||||||
|
readonly ls: LocalStorageService
|
||||||
|
) {
|
||||||
this._day = DateTime.now().toISODate()
|
this._day = DateTime.now().toISODate()
|
||||||
}
|
}
|
||||||
loading = true
|
loading = true
|
||||||
|
|
||||||
public filter = weekendFilter
|
public filter = weekendFilter
|
||||||
|
|
||||||
private _day: string;
|
private _day: string
|
||||||
public get day(): string {
|
public get day(): string {
|
||||||
return this._day;
|
return this._day
|
||||||
}
|
}
|
||||||
public set day(value: string) {
|
public set day(value: string) {
|
||||||
this._day = value;
|
this._day = value
|
||||||
this.updateMenu()
|
this.updateMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
menu?: Menu;
|
menu?: Menu
|
||||||
get getsn() { return (this.menu && this.checkIfAnyProperty(this.menu.sn)) ? this.menu.sn : null }
|
get getsn() {
|
||||||
get getob() { return (this.menu && this.checkIfAnyProperty(this.menu.ob)) ? this.menu.ob : null }
|
return this.menu && this.checkIfAnyProperty(this.menu.sn)
|
||||||
get getkol() { return (this.menu && this.menu.kol) ? this.menu.kol : null }
|
? this.menu.sn
|
||||||
get gettitle() { return (this.menu && this.menu.dayTitle && this.menu.dayTitle != "") ? this.menu.dayTitle : null }
|
: null
|
||||||
|
}
|
||||||
|
get getob() {
|
||||||
|
return this.menu && this.checkIfAnyProperty(this.menu.ob)
|
||||||
|
? this.menu.ob
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
get getkol() {
|
||||||
|
return this.menu && this.menu.kol ? this.menu.kol : null
|
||||||
|
}
|
||||||
|
get gettitle() {
|
||||||
|
return this.menu && this.menu.dayTitle && this.menu.dayTitle != ''
|
||||||
|
? this.menu.dayTitle
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
|
||||||
private checkIfAnyProperty(obj: { [x: string]: string | string[]; }) {
|
private checkIfAnyProperty(obj: { [x: string]: string | string[] }) {
|
||||||
for (let i in obj) {
|
for (let i in obj) {
|
||||||
if (Array.isArray(obj[i])) {
|
if (Array.isArray(obj[i])) {
|
||||||
if (obj[i].length > 0) return true
|
if (obj[i].length > 0) return true
|
||||||
@@ -57,7 +75,7 @@ export class MenuComponent {
|
|||||||
this.uc.getMenu(this.day).subscribe(m => {
|
this.uc.getMenu(this.day).subscribe(m => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.menu = m
|
this.menu = m
|
||||||
console.log(m);
|
console.log(m)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,14 +84,14 @@ export class MenuComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected vegeColor(text: string) {
|
protected vegeColor(text: string) {
|
||||||
if (text.startsWith("V: ")) {
|
if (text.startsWith('V: ')) {
|
||||||
return "#43A047"
|
return '#43A047'
|
||||||
}
|
}
|
||||||
return "inherit"
|
return 'inherit'
|
||||||
}
|
}
|
||||||
|
|
||||||
vote(type: "ob" | "kol", vote: "-" | "+" | "n") {
|
vote(type: 'ob' | 'kol', vote: '-' | '+' | 'n') {
|
||||||
this.uc.postVote(this.menu!.day.toISO()!, type, vote).subscribe((data) => {
|
this.uc.postVote(this.menu!.day.toISO()!, type, vote).subscribe(data => {
|
||||||
this.updateMenu(true)
|
this.updateMenu(true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
:host {
|
:host {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card {
|
mat-card {
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
padding: 1ch;
|
padding: 1ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-spinner {
|
mat-spinner {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card-title {
|
mat-card-title {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card-footer p {
|
mat-card-footer p {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
color: #4a4a4a;
|
color: #4a4a4a;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
text-align: end;
|
text-align: end;
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
color: #999999
|
color: #999999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card-content p {
|
mat-card-content p {
|
||||||
white-space: pre-line;
|
white-space: pre-line;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card p {
|
mat-card p {
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,39 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { NewsComponent } from './news.component';
|
import { NewsComponent } from './news.component'
|
||||||
import { UpdatesService } from 'src/app/services/updates.service';
|
import { UpdatesService } from 'src/app/services/updates.service'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
import { LocalStorageService } from 'src/app/services/local-storage.service';
|
import { LocalStorageService } from 'src/app/services/local-storage.service'
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card'
|
||||||
|
|
||||||
describe('NewsComponent', () => {
|
describe('NewsComponent', () => {
|
||||||
let component: NewsComponent;
|
let component: NewsComponent
|
||||||
let fixture: ComponentFixture<NewsComponent>;
|
let fixture: ComponentFixture<NewsComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const updatesMock = jasmine.createSpyObj('UpdatesService', {
|
const updatesMock = jasmine.createSpyObj('UpdatesService', {
|
||||||
getNews: of()
|
getNews: of(),
|
||||||
})
|
})
|
||||||
const lsMock = {
|
const lsMock = {
|
||||||
news: []
|
news: [],
|
||||||
}
|
}
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [ NewsComponent ],
|
declarations: [NewsComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: UpdatesService, useValue: updatesMock},
|
{ provide: UpdatesService, useValue: updatesMock },
|
||||||
{provide: LocalStorageService, useValue: lsMock}
|
{ provide: LocalStorageService, useValue: lsMock },
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [MatProgressSpinnerModule, NoopAnimationsModule, MatCardModule],
|
||||||
MatProgressSpinnerModule,
|
}).compileComponents()
|
||||||
NoopAnimationsModule,
|
|
||||||
MatCardModule
|
|
||||||
]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(NewsComponent);
|
fixture = TestBed.createComponent(NewsComponent)
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance
|
||||||
fixture.detectChanges();
|
fixture.detectChanges()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { UpdatesService } from '../../services/updates.service';
|
import { UpdatesService } from '../../services/updates.service'
|
||||||
import { LocalStorageService } from 'src/app/services/local-storage.service';
|
import { LocalStorageService } from 'src/app/services/local-storage.service'
|
||||||
import { News } from 'src/app/types/news';
|
import { News } from 'src/app/types/news'
|
||||||
import { marked } from 'marked';
|
import { marked } from 'marked'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-news',
|
selector: 'app-news',
|
||||||
templateUrl: './news.component.html',
|
templateUrl: './news.component.html',
|
||||||
styleUrls: ['./news.component.scss'],
|
styleUrls: ['./news.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class NewsComponent implements OnInit {
|
export class NewsComponent implements OnInit {
|
||||||
news:Array<News> = new Array<News>
|
news: Array<News> = new Array<News>()
|
||||||
loading = true
|
loading = true
|
||||||
constructor(private newsapi:UpdatesService, private ls: LocalStorageService) { }
|
constructor(
|
||||||
|
private newsapi: UpdatesService,
|
||||||
|
private ls: LocalStorageService
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.ls.newsflag = false
|
this.ls.newsflag = false
|
||||||
@@ -22,9 +25,9 @@ export class NewsComponent implements OnInit {
|
|||||||
this.newsapi.getNews().subscribe(data => {
|
this.newsapi.getNews().subscribe(data => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.news = data.map(v => {
|
this.news = data.map(v => {
|
||||||
v.content = marked.parse(v.content, {breaks: true}).toString()
|
v.content = marked.parse(v.content, { breaks: true }).toString()
|
||||||
return v
|
return v
|
||||||
});
|
})
|
||||||
this.ls.news = this.news
|
this.ls.news = this.news
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,38 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { NotifDialogComponent } from './notif-dialog.component';
|
import { NotifDialogComponent } from './notif-dialog.component'
|
||||||
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
import {
|
||||||
import { UpdatesService } from 'src/app/services/updates.service';
|
MAT_DIALOG_DATA,
|
||||||
import { of } from 'rxjs';
|
MatDialogModule,
|
||||||
|
MatDialogRef,
|
||||||
|
} from '@angular/material/dialog'
|
||||||
|
import { UpdatesService } from 'src/app/services/updates.service'
|
||||||
|
import { of } from 'rxjs'
|
||||||
|
|
||||||
describe('NotifDialogComponent', () => {
|
describe('NotifDialogComponent', () => {
|
||||||
let component: NotifDialogComponent;
|
let component: NotifDialogComponent
|
||||||
let fixture: ComponentFixture<NotifDialogComponent>;
|
let fixture: ComponentFixture<NotifDialogComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const uMock = jasmine.createSpyObj<UpdatesService>("UpdatesService", {
|
const uMock = jasmine.createSpyObj<UpdatesService>('UpdatesService', {
|
||||||
postInfoAck: of()
|
postInfoAck: of(),
|
||||||
})
|
})
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [NotifDialogComponent],
|
declarations: [NotifDialogComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: MAT_DIALOG_DATA, useValue: {message: "Test"}},
|
{ provide: MAT_DIALOG_DATA, useValue: { message: 'Test' } },
|
||||||
{provide: MatDialogRef, useValue: {}},
|
{ provide: MatDialogRef, useValue: {} },
|
||||||
{provide: UpdatesService, useValue: uMock}
|
{ provide: UpdatesService, useValue: uMock },
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [MatDialogModule],
|
||||||
MatDialogModule
|
}).compileComponents()
|
||||||
]
|
|
||||||
})
|
fixture = TestBed.createComponent(NotifDialogComponent)
|
||||||
.compileComponents();
|
component = fixture.componentInstance
|
||||||
|
fixture.detectChanges()
|
||||||
fixture = TestBed.createComponent(NotifDialogComponent);
|
})
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,30 +1,33 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core'
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
import { UpdatesService } from 'src/app/services/updates.service';
|
import { UpdatesService } from 'src/app/services/updates.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-notif-dialog',
|
selector: 'app-notif-dialog',
|
||||||
templateUrl: './notif-dialog.component.html',
|
templateUrl: './notif-dialog.component.html',
|
||||||
styleUrl: './notif-dialog.component.scss',
|
styleUrl: './notif-dialog.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class NotifDialogComponent {
|
export class NotifDialogComponent {
|
||||||
|
|
||||||
date: DateTime
|
date: DateTime
|
||||||
|
|
||||||
constructor (
|
constructor(
|
||||||
@Inject(MAT_DIALOG_DATA) public data: {_id: string, message: {title: string, body: string}, sentDate: string},
|
@Inject(MAT_DIALOG_DATA)
|
||||||
|
public data: {
|
||||||
|
_id: string
|
||||||
|
message: { title: string; body: string }
|
||||||
|
sentDate: string
|
||||||
|
},
|
||||||
public dialogRef: MatDialogRef<NotifDialogComponent>,
|
public dialogRef: MatDialogRef<NotifDialogComponent>,
|
||||||
private uc: UpdatesService
|
private uc: UpdatesService
|
||||||
) {
|
) {
|
||||||
this.date = DateTime.fromISO(data.sentDate)
|
this.date = DateTime.fromISO(data.sentDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
ack () {
|
ack() {
|
||||||
this.uc.postInfoAck(this.data._id).subscribe((v) => {
|
this.uc.postInfoAck(this.data._id).subscribe(v => {
|
||||||
this.dialogRef.close()
|
this.dialogRef.close()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,25 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { AboutComponent } from './about.component';
|
import { AboutComponent } from './about.component'
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog'
|
||||||
import { MatListModule } from '@angular/material/list';
|
import { MatListModule } from '@angular/material/list'
|
||||||
|
|
||||||
describe('AboutComponent', () => {
|
describe('AboutComponent', () => {
|
||||||
let component: AboutComponent;
|
let component: AboutComponent
|
||||||
let fixture: ComponentFixture<AboutComponent>;
|
let fixture: ComponentFixture<AboutComponent>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [AboutComponent],
|
declarations: [AboutComponent],
|
||||||
imports: [
|
imports: [MatDialogModule, MatListModule],
|
||||||
MatDialogModule,
|
}).compileComponents()
|
||||||
MatListModule
|
|
||||||
]
|
fixture = TestBed.createComponent(AboutComponent)
|
||||||
})
|
component = fixture.componentInstance
|
||||||
.compileComponents();
|
fixture.detectChanges()
|
||||||
|
})
|
||||||
fixture = TestBed.createComponent(AboutComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core'
|
||||||
import { Link } from 'src/app/types/link';
|
import { Link } from 'src/app/types/link'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-about',
|
selector: 'app-about',
|
||||||
templateUrl: './about.component.html',
|
templateUrl: './about.component.html',
|
||||||
styleUrl: './about.component.scss',
|
styleUrl: './about.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class AboutComponent {
|
export class AboutComponent {
|
||||||
LINKS: { title: string, info: string, icon: string, link: string }[] = [
|
LINKS: { title: string; info: string; icon: string; link: string }[] = [
|
||||||
{
|
{
|
||||||
title: "Autor",
|
title: 'Autor',
|
||||||
info: "Jan Szumotalski",
|
info: 'Jan Szumotalski',
|
||||||
icon: "person",
|
icon: 'person',
|
||||||
link: "https://github.com/Slasherss1/"
|
link: 'https://github.com/Slasherss1/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Źrodło',
|
title: 'Źrodło',
|
||||||
info: 'Aplikacja jest darmowa i może ją uruchomić każdy!',
|
info: 'Aplikacja jest darmowa i może ją uruchomić każdy!',
|
||||||
icon: 'code',
|
icon: 'code',
|
||||||
link: 'https://github.com/Slasherss1/ipwa-selfhosted'
|
link: 'https://github.com/Slasherss1/ipwa-selfhosted',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Licencja",
|
title: 'Licencja',
|
||||||
info: 'GPL-3.0',
|
info: 'GPL-3.0',
|
||||||
icon: 'license',
|
icon: 'license',
|
||||||
link: 'https://www.gnu.org/licenses/gpl-3.0-standalone.html'
|
link: 'https://www.gnu.org/licenses/gpl-3.0-standalone.html',
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
mat-error {
|
mat-error {
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
}
|
}
|
||||||
form {
|
form {
|
||||||
margin: 1rem;
|
margin: 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,39 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { ChangePasswordDialogComponent } from './change-password-dialog.component';
|
import { ChangePasswordDialogComponent } from './change-password-dialog.component'
|
||||||
import { AuthClient } from 'src/app/services/auth.client';
|
import { AuthClient } from 'src/app/services/auth.client'
|
||||||
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field'
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms'
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input'
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
|
||||||
|
|
||||||
describe('ChangePasswordDialogComponent', () => {
|
describe('ChangePasswordDialogComponent', () => {
|
||||||
let component: ChangePasswordDialogComponent;
|
let component: ChangePasswordDialogComponent
|
||||||
let fixture: ComponentFixture<ChangePasswordDialogComponent>;
|
let fixture: ComponentFixture<ChangePasswordDialogComponent>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const authMock = jasmine.createSpyObj('AuthClient', ['chpass'])
|
const authMock = jasmine.createSpyObj('AuthClient', ['chpass'])
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [ChangePasswordDialogComponent],
|
declarations: [ChangePasswordDialogComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: AuthClient, useValue: authMock},
|
{ provide: AuthClient, useValue: authMock },
|
||||||
{provide: MatDialogRef, useValue: {}}
|
{ provide: MatDialogRef, useValue: {} },
|
||||||
],
|
],
|
||||||
imports: [MatDialogModule, MatFormFieldModule, ReactiveFormsModule, MatInputModule, BrowserAnimationsModule]
|
imports: [
|
||||||
});
|
MatDialogModule,
|
||||||
fixture = TestBed.createComponent(ChangePasswordDialogComponent);
|
MatFormFieldModule,
|
||||||
component = fixture.componentInstance;
|
ReactiveFormsModule,
|
||||||
fixture.detectChanges();
|
MatInputModule,
|
||||||
});
|
BrowserAnimationsModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
fixture = TestBed.createComponent(ChangePasswordDialogComponent)
|
||||||
|
component = fixture.componentInstance
|
||||||
|
fixture.detectChanges()
|
||||||
|
})
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,34 +1,50 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core'
|
||||||
import { AuthClient } from '../../../services/auth.client';
|
import { AuthClient } from '../../../services/auth.client'
|
||||||
import { AbstractControl, FormBuilder, FormControl, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
|
import {
|
||||||
import { catchError, throwError } from 'rxjs';
|
AbstractControl,
|
||||||
import { MatDialogRef } from '@angular/material/dialog';
|
FormBuilder,
|
||||||
import { Router } from '@angular/router';
|
FormControl,
|
||||||
import { LocalStorageService } from 'src/app/services/local-storage.service';
|
FormGroup,
|
||||||
|
ValidationErrors,
|
||||||
|
ValidatorFn,
|
||||||
|
Validators,
|
||||||
|
} from '@angular/forms'
|
||||||
|
import { catchError, throwError } from 'rxjs'
|
||||||
|
import { MatDialogRef } from '@angular/material/dialog'
|
||||||
|
import { Router } from '@angular/router'
|
||||||
|
import { LocalStorageService } from 'src/app/services/local-storage.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-change-password-dialog',
|
selector: 'app-change-password-dialog',
|
||||||
templateUrl: './change-password-dialog.component.html',
|
templateUrl: './change-password-dialog.component.html',
|
||||||
styleUrls: ['./change-password-dialog.component.scss'],
|
styleUrls: ['./change-password-dialog.component.scss'],
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class ChangePasswordDialogComponent {
|
export class ChangePasswordDialogComponent {
|
||||||
error: string | null = null;
|
error: string | null = null
|
||||||
form: FormGroup;
|
form: FormGroup
|
||||||
constructor (private ac: AuthClient, public dr: MatDialogRef<ChangePasswordDialogComponent>, private router: Router, private ls: LocalStorageService) {
|
constructor(
|
||||||
this.form = new FormGroup({
|
private ac: AuthClient,
|
||||||
oldPass: new FormControl(),
|
public dr: MatDialogRef<ChangePasswordDialogComponent>,
|
||||||
newPass: new FormControl(),
|
private router: Router,
|
||||||
newPassRepeat: new FormControl(),
|
private ls: LocalStorageService
|
||||||
}, {validators: [this.matchpass(), Validators.required]})
|
) {
|
||||||
|
this.form = new FormGroup(
|
||||||
|
{
|
||||||
|
oldPass: new FormControl(),
|
||||||
|
newPass: new FormControl(),
|
||||||
|
newPassRepeat: new FormControl(),
|
||||||
|
},
|
||||||
|
{ validators: [this.matchpass(), Validators.required] }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private matchpass() : ValidatorFn {
|
private matchpass(): ValidatorFn {
|
||||||
return (control: AbstractControl) : ValidationErrors | null => {
|
return (control: AbstractControl): ValidationErrors | null => {
|
||||||
const newpass = control.get('newPass')
|
const newpass = control.get('newPass')
|
||||||
const newpassrepeat = control.get("newPassRepeat")
|
const newpassrepeat = control.get('newPassRepeat')
|
||||||
if (newpass?.value != newpassrepeat?.value) {
|
if (newpass?.value != newpassrepeat?.value) {
|
||||||
const err = {noMatch: true}
|
const err = { noMatch: true }
|
||||||
newpassrepeat?.setErrors(err)
|
newpassrepeat?.setErrors(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -39,21 +55,26 @@ export class ChangePasswordDialogComponent {
|
|||||||
|
|
||||||
protected changePass() {
|
protected changePass() {
|
||||||
if (this.form.errors) {
|
if (this.form.errors) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
this.ac.chpass(this.form.get('oldPass')?.value, this.form.get('newPass')?.value).pipe(catchError((err)=>{
|
this.ac
|
||||||
if (err.status == 401) {
|
.chpass(this.form.get('oldPass')?.value, this.form.get('newPass')?.value)
|
||||||
this.error = "Niepoprawne dane"
|
.pipe(
|
||||||
return throwError(() => new Error(err.message))
|
catchError(err => {
|
||||||
}
|
if (err.status == 401) {
|
||||||
this.error = "Nieznany błąd"
|
this.error = 'Niepoprawne dane'
|
||||||
return throwError(() => new Error(err.message))
|
return throwError(() => new Error(err.message))
|
||||||
})).subscribe((data) => {
|
}
|
||||||
if (this.error == null) {
|
this.error = 'Nieznany błąd'
|
||||||
this.dr.close()
|
return throwError(() => new Error(err.message))
|
||||||
this.ls.logOut()
|
})
|
||||||
this.router.navigateByUrl("/login")
|
)
|
||||||
}
|
.subscribe(data => {
|
||||||
})
|
if (this.error == null) {
|
||||||
|
this.dr.close()
|
||||||
|
this.ls.logOut()
|
||||||
|
this.router.navigateByUrl('/login')
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,52 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||||
|
|
||||||
import { CleanComponent } from './clean.component';
|
import { CleanComponent } from './clean.component'
|
||||||
import { UpdatesService } from 'src/app/services/updates.service';
|
import { UpdatesService } from 'src/app/services/updates.service'
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs'
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog'
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon'
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field'
|
||||||
import { MatDatepicker } from '@angular/material/datepicker';
|
import { MatDatepicker } from '@angular/material/datepicker'
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-date-selector", template: '',
|
selector: 'app-date-selector',
|
||||||
standalone: false
|
template: '',
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class DateSelectorStub {
|
class DateSelectorStub {
|
||||||
@Input() date: string = DateTime.now().toISODate();
|
@Input() date: string = DateTime.now().toISODate()
|
||||||
@Output() dateChange = new EventEmitter<string>();
|
@Output() dateChange = new EventEmitter<string>()
|
||||||
@Input() filter: (date: DateTime | null) => boolean = () => true
|
@Input() filter: (date: DateTime | null) => boolean = () => true
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('CleanComponent', () => {
|
describe('CleanComponent', () => {
|
||||||
let component: CleanComponent;
|
let component: CleanComponent
|
||||||
let fixture: ComponentFixture<CleanComponent>;
|
let fixture: ComponentFixture<CleanComponent>
|
||||||
let updates: jasmine.SpyObj<UpdatesService>
|
let updates: jasmine.SpyObj<UpdatesService>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
updates = jasmine.createSpyObj<UpdatesService>("UpdatesService", {
|
updates = jasmine.createSpyObj<UpdatesService>('UpdatesService', {
|
||||||
getClean: of()
|
getClean: of(),
|
||||||
})
|
})
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [CleanComponent, DateSelectorStub],
|
declarations: [CleanComponent, DateSelectorStub],
|
||||||
providers: [
|
providers: [{ provide: UpdatesService, useValue: updates }],
|
||||||
{provide: UpdatesService, useValue: updates}
|
imports: [
|
||||||
|
MatDialogModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatDatepicker,
|
||||||
],
|
],
|
||||||
imports: [MatDialogModule, MatIconModule, MatFormFieldModule, MatDatepicker]
|
}).compileComponents()
|
||||||
})
|
|
||||||
.compileComponents();
|
fixture = TestBed.createComponent(CleanComponent)
|
||||||
|
component = fixture.componentInstance
|
||||||
fixture = TestBed.createComponent(CleanComponent);
|
fixture.detectChanges()
|
||||||
component = fixture.componentInstance;
|
})
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon'
|
||||||
import { weekendFilter } from 'src/app/fd.da';
|
import { weekendFilter } from 'src/app/fd.da'
|
||||||
import { UpdatesService } from 'src/app/services/updates.service';
|
import { UpdatesService } from 'src/app/services/updates.service'
|
||||||
import { CleanNote } from 'src/app/types/clean-note';
|
import { CleanNote } from 'src/app/types/clean-note'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-clean',
|
selector: 'app-clean',
|
||||||
templateUrl: './clean.component.html',
|
templateUrl: './clean.component.html',
|
||||||
styleUrl: './clean.component.scss',
|
styleUrl: './clean.component.scss',
|
||||||
standalone: false
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class CleanComponent implements OnInit {
|
export class CleanComponent implements OnInit {
|
||||||
protected day: string
|
protected day: string
|
||||||
grade: number | null = null
|
grade: number | null = null
|
||||||
notes: CleanNote[] = []
|
notes: CleanNote[] = []
|
||||||
tips: string = ""
|
tips: string = ''
|
||||||
filter = weekendFilter
|
filter = weekendFilter
|
||||||
|
|
||||||
constructor (private updates: UpdatesService) {
|
constructor(private updates: UpdatesService) {
|
||||||
this.day = DateTime.now().toISODate()
|
this.day = DateTime.now().toISODate()
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.update()
|
this.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
this.updates.getClean(this.day).subscribe((v) => {
|
this.updates.getClean(this.day).subscribe(v => {
|
||||||
if (v) {
|
if (v) {
|
||||||
this.grade = v.grade
|
this.grade = v.grade
|
||||||
this.notes = v.notes
|
this.notes = v.notes
|
||||||
@@ -34,7 +34,7 @@ export class CleanComponent implements OnInit {
|
|||||||
} else {
|
} else {
|
||||||
this.grade = null
|
this.grade = null
|
||||||
this.notes = []
|
this.notes = []
|
||||||
this.tips = ""
|
this.tips = ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -42,19 +42,19 @@ export class CleanComponent implements OnInit {
|
|||||||
protected gradeColor() {
|
protected gradeColor() {
|
||||||
switch (this.grade) {
|
switch (this.grade) {
|
||||||
case 1:
|
case 1:
|
||||||
return { color: "red" }
|
return { color: 'red' }
|
||||||
case 2:
|
case 2:
|
||||||
return { color: "darkorange" }
|
return { color: 'darkorange' }
|
||||||
case 3:
|
case 3:
|
||||||
return { color: "orange" }
|
return { color: 'orange' }
|
||||||
case 4:
|
case 4:
|
||||||
return { color: "olive" }
|
return { color: 'olive' }
|
||||||
case 5:
|
case 5:
|
||||||
return { color: "green" }
|
return { color: 'green' }
|
||||||
case 6:
|
case 6:
|
||||||
return { color: "springgreen" }
|
return { color: 'springgreen' }
|
||||||
default:
|
default:
|
||||||
return { color: "inherit" }
|
return { color: 'inherit' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user