refactor more of frontend

This commit is contained in:
rubikscraft 2022-03-28 23:03:26 +02:00
parent 87af2c47c0
commit 27f19b03ce
No known key found for this signature in database
GPG key ID: 1463EBE9200A5CD4
13 changed files with 98 additions and 75 deletions

View file

@ -14,7 +14,6 @@
</mat-chip>
<input
placeholder="Add {{name}}..."
#fruitInput
[formControl]="inputControl"
[value]="inputControl.value"
[matAutocomplete]="auto"

View file

@ -1,5 +1,10 @@
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
import { Component, Input, OnInit } from '@angular/core';
import {
Component,
Input,
OnChanges,
OnInit
} from '@angular/core';
import { FormControl } from '@angular/forms';
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { MatChipInputEvent } from '@angular/material/chips';
@ -13,7 +18,7 @@ import { Required } from 'src/app/models/decorators/required.decorator';
templateUrl: './values-picker.component.html',
styleUrls: ['./values-picker.component.scss'],
})
export class ValuesPickerComponent implements OnInit {
export class ValuesPickerComponent implements OnInit, OnChanges {
// Static data
readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE];
@ -43,6 +48,10 @@ export class ValuesPickerComponent implements OnInit {
this.subscribeMyValue();
}
public ngOnChanges(): void {
this.updateSelectable()
}
public isDisabled(value: string): boolean {
return this.disabledSelection.includes(value);
}

View file

@ -1,6 +1,6 @@
<div class="content-border">
<div class="centered">
<h1>Processing a</h1>
<h1>Processing</h1>
<mat-spinner color="accent"></mat-spinner>
</div>
</div>

View file

@ -5,7 +5,7 @@
<h1>Add new role</h1>
</ng-container>
<form (ngSubmit)="updateUser()">
<form (ngSubmit)="updateRole()">
<div class="row" *ngIf="adding">
<div class="col-lg-6 col-12">
<mat-form-field appearance="outline" color="accent">
@ -54,5 +54,3 @@
</div>
</div>
</form>
<div class="value-picker"></div>

View file

@ -11,11 +11,9 @@ enum EditMode {
edit = 'edit',
add = 'add',
}
@Component({
selector: 'app-settings-roles-edit',
templateUrl: './settings-roles-edit.component.html',
styleUrls: ['./settings-roles-edit.component.scss'],
})
export class SettingsRolesEditComponent implements OnInit {
private mode: EditMode = EditMode.edit;
@ -78,11 +76,7 @@ export class SettingsRolesEditComponent implements OnInit {
this.allPermissions = allPermissions;
}
cancel() {
this.router.navigate(['/settings/roles']);
}
async updateUser() {
async updateRole() {
const data = this.model.getData();
if (this.adding) {
@ -111,4 +105,8 @@ export class SettingsRolesEditComponent implements OnInit {
this.router.navigate(['/settings/roles']);
}
cancel() {
this.router.navigate(['/settings/roles']);
}
}

View file

@ -7,9 +7,9 @@
</ng-container>
<ng-container matColumnDef="permissions">
<mat-header-cell class="d-none d-md-flex" *matHeaderCellDef
>Permissions</mat-header-cell
>
<mat-header-cell class="d-none d-md-flex" *matHeaderCellDef>
Permissions
</mat-header-cell>
<mat-cell class="d-none d-md-flex" *matCellDef="let role">
<mat-chip-list aria-label="Role Permissions">
<mat-chip
@ -85,6 +85,8 @@
class="fabbutton fullanimate mat-elevation-z6"
(click)="addRole()"
>
<mat-icon fontSet="material-icons-outlined">add</mat-icon>
<mat-icon fontSet="material-icons-outlined" aria-label="Add Role">
add
</mat-icon>
</button>
</div>

View file

@ -1,6 +1,5 @@
mat-table {
width: 100%;
}
.mat-column-actions {

View file

@ -6,7 +6,7 @@ import { Permission } from 'picsur-shared/dist/dto/permissions.dto';
import { ERole } from 'picsur-shared/dist/entities/role.entity';
import { HasFailed } from 'picsur-shared/dist/types';
import { UIFriendlyPermissions } from 'src/app/i18n/permissions.i18n';
import { SnackBarType } from "src/app/models/dto/snack-bar-type.dto";
import { SnackBarType } from 'src/app/models/dto/snack-bar-type.dto';
import { RolesService } from 'src/app/services/api/roles.service';
import { UtilService } from 'src/app/util/util.service';
@ -38,7 +38,7 @@ export class SettingsRolesComponent implements OnInit, AfterViewInit {
) {}
ngOnInit(): void {
this.fetchRoles().catch(console.error);
this.loadRoles().catch(console.error);
}
ngAfterViewInit() {
@ -83,7 +83,7 @@ export class SettingsRolesComponent implements OnInit, AfterViewInit {
}
}
await this.fetchRoles();
await this.loadRoles();
}
uiFriendlyPermission(permission: string) {
@ -98,16 +98,18 @@ export class SettingsRolesComponent implements OnInit, AfterViewInit {
return this.ImmutableRolesList.includes(role.name);
}
private async fetchRoles() {
const roles = await this.rolesService.getRoles();
private async loadRoles() {
const [roles, specialRoles] = await Promise.all([
this.rolesService.getRoles(),
this.rolesService.getSpecialRoles(),
]);
if (HasFailed(roles)) {
this.utilService.showSnackBar('Failed to load roles', SnackBarType.Error);
return;
}
this.dataSource.data = roles;
const specialRoles = await this.rolesService.getSpecialRoles();
if (HasFailed(specialRoles)) {
this.utilService.showSnackBar(
'Failed to load special roles',
@ -115,7 +117,6 @@ export class SettingsRolesComponent implements OnInit, AfterViewInit {
);
return;
}
this.UndeletableRolesList = specialRoles.UndeletableRoles;
this.ImmutableRolesList = specialRoles.ImmutableRoles;
}

View file

@ -6,9 +6,10 @@
mat-list-item
[routerLink]="'/settings/' + route.path"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon fontSet="material-icons-outlined" mat-list-icon>{{ route.data?.page?.icon }}</mat-icon>
<mat-icon fontSet="material-icons-outlined" mat-list-icon>
{{ route.data?.page?.icon }}
</mat-icon>
<span mat-line>{{ route.data?.page?.title }}</span>
</a>
</ng-container>
@ -24,7 +25,9 @@
[routerLink]="'/settings/' + route.path"
routerLinkActive="active"
>
<mat-icon fontSet="material-icons-outlined" mat-list-icon >{{ route.data?.page?.icon }}</mat-icon>
<mat-icon fontSet="material-icons-outlined" mat-list-icon>
{{ route.data?.page?.icon }}
</mat-icon>
<span mat-line>{{ route.data?.page?.title }}</span>
</a>
</ng-container>

View file

@ -24,29 +24,36 @@ export class SettingsSidebarComponent implements OnInit {
this.subscribePermissions();
}
private handlePermissions(permissions: string[]) {
// Filter all routes to the routes the current user can access
this.accessibleRoutes = this.settingsRoutes
.filter((route) => route.path !== '')
.filter((route) =>
route.data?.permissions !== undefined
? route.data?.permissions?.every((permission) =>
permissions.includes(permission)
)
: true
);
// Split them according to their groups
this.personalRoutes = this.accessibleRoutes.filter(
(route) => route.data?.page?.category === 'personal'
);
this.systemRoutes = this.accessibleRoutes.filter(
(route) => route.data?.page?.category === 'system'
);
// Get out of here if we have no routes
if (this.systemRoutes.length === 0 && this.personalRoutes.length === 0) {
this.router.navigate(['/']);
}
}
@AutoUnsubscribe()
private subscribePermissions() {
return this.permissionService.live.subscribe((permissions) => {
this.accessibleRoutes = this.settingsRoutes
.filter((route) => route.path !== '')
.filter((route) =>
route.data?.permissions !== undefined
? route.data?.permissions?.every((permission) =>
permissions.includes(permission)
)
: true
);
this.personalRoutes = this.accessibleRoutes.filter(
(route) => route.data?.page?.category === 'personal'
);
this.systemRoutes = this.accessibleRoutes.filter(
(route) => route.data?.page?.category === 'system'
);
if (this.systemRoutes.length === 0 && this.personalRoutes.length === 0) {
this.router.navigate(['/']);
}
});
return this.permissionService.live.subscribe(
this.handlePermissions.bind(this)
);
}
}

View file

@ -16,6 +16,7 @@
</div>
</div>
</ng-container>
<ng-container *ngIf="pref.type === 'number'">
<div class="row">
<div class="y-center col-md-6 col-12">
@ -33,6 +34,7 @@
</div>
</div>
</ng-container>
<ng-container *ngIf="pref.type === 'boolean'">
<div class="row">
<div class="y-center col-md-6 col-12">

View file

@ -1,11 +1,14 @@
import { Component, Input, OnInit } from '@angular/core';
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
import { SysPreferenceBaseResponse } from 'picsur-shared/dist/dto/api/pref.dto';
import { SysPreference, SysPrefValueType } from 'picsur-shared/dist/dto/syspreferences.dto';
import {
SysPreference,
SysPrefValueType
} from 'picsur-shared/dist/dto/syspreferences.dto';
import { HasFailed } from 'picsur-shared/dist/types';
import { Subject, throttleTime } from 'rxjs';
import { SysPreferenceFriendlyNames } from 'src/app/i18n/syspref.i18n';
import { SnackBarType } from "src/app/models/dto/snack-bar-type.dto";
import { SnackBarType } from 'src/app/models/dto/snack-bar-type.dto';
import { SysprefService } from 'src/app/services/api/syspref.service';
import { UtilService } from 'src/app/util/util.service';
@ -29,7 +32,10 @@ export class SettingsSysprefOptionComponent implements OnInit {
}
get name(): string {
return SysPreferenceFriendlyNames[this.pref.key as SysPreference] ?? this.pref.key;
return (
SysPreferenceFriendlyNames[this.pref.key as SysPreference] ??
this.pref.key
);
}
get valString(): string {
@ -65,26 +71,28 @@ export class SettingsSysprefOptionComponent implements OnInit {
this.update((e.target as HTMLInputElement).valueAsNumber);
}
private async updatePreference(value: SysPrefValueType) {
const result = await this.sysprefService.setPreference(
this.pref.key,
value
);
if (!HasFailed(result)) {
this.utilService.showSnackBar(
`Updated ${this.name}`,
SnackBarType.Success
);
} else {
this.utilService.showSnackBar(
`Failed to update ${this.name}`,
SnackBarType.Error
);
}
}
@AutoUnsubscribe()
subscribeUpdate() {
return this.updateSubject
.pipe(throttleTime(300, undefined, { leading: true, trailing: true }))
.subscribe(async (value) => {
const result = await this.sysprefService.setPreference(
this.pref.key,
value
);
if (!HasFailed(result)) {
this.utilService.showSnackBar(
`Updated ${this.name}`,
SnackBarType.Success
);
} else {
this.utilService.showSnackBar(
`Failed to update ${this.name}`,
SnackBarType.Error
);
}
});
.subscribe(this.updatePreference.bind(this));
}
}