Initial commit

This commit is contained in:
2025-03-05 21:38:10 +01:00
commit 503909d762
198 changed files with 19203 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
<div id="upper-bar">
<mat-form-field>
<mat-label>Wyszukaj</mat-label>
<input matInput (keyup)="filter($event)">
</mat-form-field>
<button mat-icon-button (click)="new()"><mat-icon>add</mat-icon></button>
</div>
<mat-spinner *ngIf="loading"></mat-spinner>
<table mat-table [dataSource]="users">
<div matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>Imię</th>
<td mat-cell *matCellDef="let element">{{element.fname}}</td>
</div>
<div matColumnDef="surname">
<th mat-header-cell *matHeaderCellDef>Nazwisko</th>
<td mat-cell *matCellDef="let element">{{element.surname}}</td>
</div>
<div matColumnDef="room">
<th mat-header-cell *matHeaderCellDef>Pokój</th>
<td mat-cell *matCellDef="let element">{{element.room}}</td>
</div>
<div matColumnDef="uname">
<th mat-header-cell *matHeaderCellDef>Nazwa użytkownika</th>
<td mat-cell *matCellDef="let element">{{element.uname}}</td>
</div>
<div matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>Akcje</th>
<td mat-cell *matCellDef="let element">
<button mat-mini-fab (click)="resetPass(element._id)"><mat-icon>lock_reset</mat-icon></button>
<button mat-mini-fab (click)="edit(element)"><mat-icon>edit</mat-icon></button>
<button mat-mini-fab (click)="toggleLock(element)">
<div [ngSwitch]="element.locked">
<mat-icon *ngSwitchCase="true">lock</mat-icon>
<mat-icon *ngSwitchDefault>lock_open</mat-icon>
</div>
</button>
<button mat-mini-fab (click)="delete(element._id)"><mat-icon>delete_forever</mat-icon></button>
</td>
</div>
<tr mat-header-row *matHeaderRowDef="collumns"></tr>
<tr mat-row *matRowDef="let row; columns: collumns"></tr>
</table>
<mat-paginator pageSize="9" [pageSizeOptions]="[9, 15, 20, 50, 160]"></mat-paginator>

View File

@@ -0,0 +1,23 @@
:host {
display: flex;
flex-direction: column;
height: 100%;
}
mat-paginator {
margin-top: auto;
}
mat-form-field {
flex-grow: 1;
}
#upper-bar {
display: flex;
}
button[mat-icon-button] {
margin-left: 4pt;
margin-right: 4pt;
margin-top: 4pt;
}

View File

@@ -0,0 +1,38 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AccountMgmtComponent } from './account-mgmt.component';
import { AdminCommService } from '../admin-comm.service';
import { MatDialogModule } from '@angular/material/dialog';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatPaginatorModule } from '@angular/material/paginator';
import { of } from 'rxjs';
import { MatTableModule } from '@angular/material/table';
import { MatInputModule } from '@angular/material/input';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
describe('AccountMgmtComponent', () => {
let component: AccountMgmtComponent;
let fixture: ComponentFixture<AccountMgmtComponent>;
beforeEach(async () => {
const acMock = jasmine.createSpyObj("AdminCommService", {
getAccs: of()
})
await TestBed.configureTestingModule({
declarations: [AccountMgmtComponent],
providers: [
{provide: AdminCommService, useValue: acMock}
],
imports: [MatDialogModule, MatSnackBarModule, MatFormFieldModule, MatIconModule, MatPaginatorModule, MatTableModule, MatInputModule, BrowserAnimationsModule]
}).compileComponents();
fixture = TestBed.createComponent(AccountMgmtComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,130 @@
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { AdminCommService } from '../admin-comm.service';
import { MatDialog } from '@angular/material/dialog';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatSnackBar } from '@angular/material/snack-bar';
import { UserDeleteComponent } from './user-delete/user-delete.component';
import { UserEditComponent } from './user-edit/user-edit.component';
import { catchError, throwError } from 'rxjs';
import { UserResetComponent } from './user-reset/user-reset.component';
import { LocalStorageService } from 'src/app/services/local-storage.service';
@Component({
selector: 'app-account-mgmt',
templateUrl: './account-mgmt.component.html',
styleUrls: ['./account-mgmt.component.scss']
})
export class AccountMgmtComponent implements OnInit, AfterViewInit {
users: MatTableDataSource<any>
loading = false
@ViewChild(MatPaginator) paginator!: MatPaginator
constructor(readonly ac:AdminCommService, private dialog: MatDialog, private sb: MatSnackBar, protected readonly ls: LocalStorageService) {
this.users = new MatTableDataSource<any>();
this.users.filterPredicate = (data: Record<string, any>, filter: string): boolean => {
const dataStr = Object.keys(data).reduce((curr: string, key: string) => {
if (key == "_id") {
return ''
}
return curr + data[key] + '⫂'
}, '').toLowerCase()
const filternew = filter.trim().toLowerCase()
return dataStr.indexOf(filternew) != -1
}
}
ngAfterViewInit() {
this.users.paginator = this.paginator
}
ngOnInit() {
this.loading = true
this.ac.accs.getAccs().subscribe((data)=>{
this.loading = false
this.users.data = data
})
}
filter(event: Event) {
const value = (event.target as HTMLInputElement).value
this.users.filter = value.toLowerCase().trim()
}
edit(item: any) {
this.dialog.open(UserEditComponent, {data: item}).afterClosed().subscribe(reply => {
if (reply) {
this.ac.accs.putAcc(item._id, reply).pipe(catchError((err)=>{
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.sb.open("Użytkownik został zmodyfikowany.", undefined, {duration: 2500})
this.ngOnInit()
} else {
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
}
})
}
})
}
new() {
this.dialog.open(UserEditComponent).afterClosed().subscribe(reply => {
if (reply) {
this.ac.accs.postAcc(reply).pipe(catchError((err)=>{
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.sb.open("Użytkownik został utworzony.", undefined, {duration: 2500})
this.ngOnInit()
} else {
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
}
})
}
})
}
delete(id: string) {
this.dialog.open(UserDeleteComponent).afterClosed().subscribe(reply => {
if (reply) {
this.ac.accs.deleteAcc(id).subscribe((res) => {
if (res.status == 200) {
this.sb.open("Użytkownik został usunięty.", undefined, {duration: 2500})
this.ngOnInit()
} else {
this.sb.open("Wystąpił błąd. Skontaktuj się z obsługą programu.")
console.error(res);
}
})
}
})
}
resetPass(id: string) {
this.dialog.open(UserResetComponent).afterClosed().subscribe((res) => {
if (res == true) {
this.ac.accs.resetPass(id).subscribe((patch)=>{
if (patch.status == 200) {
this.sb.open("Hasło zostało zresetowane", undefined, {duration: 2500})
}
})
}
})
}
toggleLock(item: any) {
this.ac.accs.putAcc(item._id, {locked: !item.locked}).subscribe((res) => {
if (res.status == 200) {
item.locked = !item.locked
}
})
}
collumns = ['name', 'surname', 'uname', 'actions']
}

View File

@@ -0,0 +1,5 @@
<h1 mat-dialog-title>Czy na pewno chcesz usunąć tego użytkownika</h1>
<mat-dialog-actions align="end">
<button mat-button mat-dialog-close>Nie</button>
<button mat-button color="warn" [mat-dialog-close]="true">Tak</button>
</mat-dialog-actions>

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserDeleteComponent } from './user-delete.component';
import { MatDialogModule } from '@angular/material/dialog';
describe('UserDeleteComponent', () => {
let component: UserDeleteComponent;
let fixture: ComponentFixture<UserDeleteComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [UserDeleteComponent],
imports: [MatDialogModule]
});
fixture = TestBed.createComponent(UserDeleteComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,10 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-user-delete',
templateUrl: './user-delete.component.html',
styleUrls: ['./user-delete.component.scss']
})
export class UserDeleteComponent {
}

View File

@@ -0,0 +1,31 @@
<form [formGroup]="form" (ngSubmit)="editUser()">
<mat-form-field appearance="outline">
<mat-label>Imię</mat-label>
<input type="text" matInput formControlName="fname">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Nazwisko</mat-label>
<input type="text" matInput formControlName="surname">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Pokój</mat-label>
<input type="text" matInput formControlName="room">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Nazwa użytkownika</mat-label>
<input type="text" matInput required formControlName="uname">
</mat-form-field>
<mat-form-field *ngIf="this.ls.permChecker(32)">
<mat-label>Uprawnienia</mat-label>
<mat-select multiple formControlName="flags">
<mat-option [value]="1" *ngIf="ls.capCheck(1)">Wiadomości</mat-option>
<mat-option [value]="2" *ngIf="ls.capCheck(2)">Jadłospis</mat-option>
<mat-option [value]="4" *ngIf="ls.capCheck(4)">Powiadomienia</mat-option>
<mat-option [value]="8" *ngIf="ls.capCheck(8)">Grupy</mat-option>
<mat-option [value]="16">Konta</mat-option>
<mat-option [value]="64" *ngIf="ls.capCheck(32)">Klucze</mat-option>
<mat-option [value]="128" *ngIf="ls.capCheck(16)">Czystość</mat-option>
</mat-select>
</mat-form-field>
<button mat-stroked-button>Wyślij</button>
</form>

View File

@@ -0,0 +1,10 @@
:host {
padding: 8pt;
display: block;
}
form {
display: flex;
flex-direction: column;
align-items: center;
}

View File

@@ -0,0 +1,31 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserEditComponent } from './user-edit.component';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { ReactiveFormsModule } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
describe('UserEditComponent', () => {
let component: UserEditComponent;
let fixture: ComponentFixture<UserEditComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UserEditComponent],
imports: [MatDialogModule, MatFormFieldModule, ReactiveFormsModule, MatInputModule, BrowserAnimationsModule],
providers: [
{provide: MatDialogRef, useValue: {}},
{provide: MAT_DIALOG_DATA, useValue: {}}
]
}).compileComponents();
fixture = TestBed.createComponent(UserEditComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,59 @@
import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormControl, FormGroup } from '@angular/forms';
import { LocalStorageService } from 'src/app/services/local-storage.service';
@Component({
selector: 'app-user-edit',
templateUrl: './user-edit.component.html',
styleUrls: ['./user-edit.component.scss']
})
export class UserEditComponent {
form: FormGroup
constructor (public dialogRef: MatDialogRef<UserEditComponent>, @Inject(MAT_DIALOG_DATA) public data: any, readonly ls: LocalStorageService) {
if (data == null) {
data = {
fname: "",
surname: "",
room: 0,
uname: "",
admin: 0
}
}
var flags: Array<number> = []
if (data.admin) {
if ((data.admin & 1) == 1) flags.push(1)
if ((data.admin & 2) == 2) flags.push(2)
if ((data.admin & 4) == 4) flags.push(4)
if ((data.admin & 8) == 8) flags.push(8)
if ((data.admin & 16) == 16) flags.push(16)
if ((data.admin & 32) == 32) flags.push(32)
if ((data.admin & 64) == 64) flags.push(64)
if ((data.admin & 128) == 128) flags.push(128)
}
this.form = new FormGroup({
fname: new FormControl(data.fname),
surname: new FormControl(data.surname),
room: new FormControl<number>(data.room),
uname: new FormControl(data.uname),
flags: new FormControl<Array<number>>(flags),
})
}
protected editUser() {
this.dialogRef.close({
fname: this.form.get('fname')?.value,
surname: this.form.get('surname')?.value,
room: this.form.get('room')?.value,
uname: this.form.get('uname')?.value,
flags: (() => {
var value = this.form.get('flags')?.value.reduce((a: number,b: number)=>a+b,0)
if (this.ls.capCheck(32)) {
return value
} else {
return undefined
}
})()
})
}
}

View File

@@ -0,0 +1,8 @@
<h1 mat-dialog-title>Reset hasła</h1>
<mat-dialog-content>
Czy chcesz zresetować hasło temu użytkownikowi?
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button [mat-dialog-close]="true" color="warn">Tak</button>
<button mat-button mat-dialog-close>Nie</button>
</mat-dialog-actions>

View File

@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserResetComponent } from './user-reset.component';
describe('UserResetComponent', () => {
let component: UserResetComponent;
let fixture: ComponentFixture<UserResetComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [UserResetComponent]
});
fixture = TestBed.createComponent(UserResetComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,10 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-user-reset',
templateUrl: './user-reset.component.html',
styleUrls: ['./user-reset.component.scss']
})
export class UserResetComponent {
}