refactor more of frontend
This commit is contained in:
parent
87af2c47c0
commit
27f19b03ce
|
@ -14,7 +14,6 @@
|
|||
</mat-chip>
|
||||
<input
|
||||
placeholder="Add {{name}}..."
|
||||
#fruitInput
|
||||
[formControl]="inputControl"
|
||||
[value]="inputControl.value"
|
||||
[matAutocomplete]="auto"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
values-picker {
|
||||
width: 100%;
|
||||
}
|
|
@ -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']);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
mat-table {
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
.mat-column-actions {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue