frontend permissions dialogs

This commit is contained in:
Michael Shamoon
2022-11-13 22:58:07 -08:00
parent b6f1ced455
commit f461485aa0
13 changed files with 164 additions and 82 deletions

View File

@@ -8,7 +8,7 @@
<div class="row">
<div class="col">
<app-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></app-input-text>
<app-permissions-select i18n-title title="Permissions" formControlName="permissions"></app-permissions-select>
<app-permissions-select i18n-title title="Permissions" formControlName="permissions" [error]="error?.permissions"></app-permissions-select>
</div>
</div>
</div>

View File

@@ -26,7 +26,7 @@ export class GroupEditDialogComponent extends EditDialogComponent<PaperlessGroup
getForm(): FormGroup {
return new FormGroup({
name: new FormControl(''),
permissions: new FormControl(''),
permissions: new FormControl(null),
})
}
}

View File

@@ -11,19 +11,21 @@
<app-input-text i18n-title title="First name" formControlName="first_name" [error]="error?.first_name"></app-input-text>
<app-input-text i18n-title title="Last name" formControlName="last_name" [error]="error?.first_name"></app-input-text>
<div class="form-check form-switch">
<input type="checkbox" class="form-check-input" id="is_active" formControlName="is_active">
<label class="form-check-label" for="is_active" i18n>Active</label>
<div class="mb-2">
<div class="form-check form-switch form-check-inline">
<input type="checkbox" class="form-check-input" id="is_active" formControlName="is_active">
<label class="form-check-label" for="is_active" i18n>Active</label>
</div>
<div class="form-check form-switch form-check-inline">
<input type="checkbox" class="form-check-input" id="is_superuser" formControlName="is_superuser">
<label class="form-check-label" for="is_superuser" i18n>Superuser</label>
</div>
</div>
<div class="form-check form-switch">
<input type="checkbox" class="form-check-input" id="is_superuser" formControlName="is_superuser">
<label class="form-check-label" for="is_superuser" i18n>Superuser</label>
</div>
<app-input-select i18n-title title="Groups" [items]="groups" multiple="true" formControlName="groups"></app-input-select>
</div>
<div class="col">
<app-input-select i18n-title title="Groups" [items]="groups" multiple="true" formControlName="groups"></app-input-select>
<app-permissions-select i18n-title title="Permissions" formControlName="permissions"></app-permissions-select>
<app-permissions-select i18n-title title="Permissions" formControlName="user_permissions" [error]="error?.user_permissions"></app-permissions-select>
</div>
</div>
</div>

View File

@@ -42,10 +42,10 @@ export class UserEditDialogComponent extends EditDialogComponent<PaperlessUser>
username: new FormControl(''),
first_name: new FormControl(''),
last_name: new FormControl(''),
is_active: new FormControl(''),
is_superuser: new FormControl(''),
groups: new FormControl(''),
permissions: new FormControl(''),
is_active: new FormControl(null),
is_superuser: new FormControl(null),
groups: new FormControl(null),
user_permissions: new FormControl(null),
})
}
}

View File

@@ -1,18 +1,27 @@
<form [formGroup]="form">
<label>{{title}}</label>
<label class="form-label">{{title}}</label>
<ul class="list-group">
<li class="list-group-item" *ngFor="let type of PermissionType | keyvalue" [formGroupName]="type.key">
{{type.key}}:
<li class="list-group-item d-flex">
<div class="col-3" i18n>Type</div>
<div class="col" i18n>All</div>
<div class="col" i18n>Add</div>
<div class="col" i18n>Change</div>
<div class="col" i18n>Delete</div>
<div class="col" i18n>View</div>
</li>
<li class="list-group-item d-flex" *ngFor="let type of PermissionType | keyvalue" [formGroupName]="type.key">
<div class="col-3">{{type.key}}:</div>
<div class="form-check form-check-inline form-switch">
<input type="checkbox" class="form-check-input" id="{{type.key}}_all" formControlName="all">
<label class="form-check-label" for="{{type.key}}_all" i18n>All</label>
<div class="col form-check form-check-inline form-switch">
<input type="checkbox" class="form-check-input" id="{{type.key}}_all" (change)="toggleAll($event, type.key)" [checked]="typesWithAllActions.has(type.key)">
<label class="form-check-label visually-hidden" for="{{type.key}}_all" i18n>All</label>
</div>
<div *ngFor="let action of PermissionAction | keyvalue" class="form-check form-check-inline" [disabled]="isAll(type.key)">
<input type="checkbox" class="form-check-input" id="{{type.key}}_{{action.key}}" formControlName="{{action.key}}">
<label class="form-check-label" for="{{type.key}}_{{action.key}}" i18n>{{action.key}}</label>
<div *ngFor="let action of PermissionAction | keyvalue" class="col form-check form-check-inline">
<input type="checkbox" class="form-check-input" id="{{type.key}}_{{action.key}}" formControlName="{{action.key}}" [attr.disabled]="typesWithAllActions.has(type.key) ? true : null">
<label class="form-check-label visually-hidden" for="{{type.key}}_{{action.key}}" i18n>{{action.key}}</label>
</div>
</li>
<div *ngIf="error" class="invalid-feedback d-block">{{error}}</div>
</ul>
</form>

View File

@@ -10,7 +10,6 @@ import {
PermissionsService,
PermissionType,
} from 'src/app/services/permissions.service'
import { AbstractInputComponent } from '../input/abstract-input'
@Component({
providers: [
@@ -33,14 +32,18 @@ export class PermissionsSelectComponent
@Input()
title: string = 'Permissions'
@Input()
error: string
permissions: string[]
form = new FormGroup({})
typesWithAllActions: Set<string> = new Set()
constructor(private readonly permissionsService: PermissionsService) {
for (const type in PermissionType) {
const control = new FormGroup({})
control.addControl('all', new FormControl(null))
for (const action in PermissionAction) {
control.addControl(action, new FormControl(null))
}
@@ -50,7 +53,7 @@ export class PermissionsSelectComponent
writeValue(permissions: string[]): void {
this.permissions = permissions
this.permissions.forEach((permissionStr) => {
this.permissions?.forEach((permissionStr) => {
const { actionKey, typeKey } =
this.permissionsService.getPermissionKeys(permissionStr)
@@ -60,20 +63,70 @@ export class PermissionsSelectComponent
}
}
})
Object.keys(PermissionType).forEach((type) => {
if (Object.values(this.form.get(type).value).every((val) => val)) {
this.typesWithAllActions.add(type)
} else {
this.typesWithAllActions.delete(type)
}
})
}
onChange = (newValue: string[]) => {}
onTouched = () => {}
disabled: boolean = false
registerOnChange(fn: any): void {
throw new Error('Method not implemented.')
this.onChange = fn
}
registerOnTouched(fn: any): void {
throw new Error('Method not implemented.')
this.onTouched = fn
}
setDisabledState?(isDisabled: boolean): void {
throw new Error('Method not implemented.')
this.disabled = isDisabled
}
ngOnInit(): void {}
ngOnInit(): void {
this.form.valueChanges.subscribe((newValue) => {
let permissions = []
Object.entries(newValue).forEach(([typeKey, typeValue]) => {
// e.g. [Document, { Add: true, View: true ... }]
const selectedActions = Object.entries(typeValue).filter(
([actionKey, actionValue]) => actionValue
)
isAll(key: string): boolean {
return this.form.get(key).get('all').value == true
selectedActions.forEach(([actionKey, actionValue]) => {
permissions.push(
(PermissionType[typeKey] as string).replace(
'%s',
PermissionAction[actionKey]
)
)
})
if (selectedActions.length == Object.entries(typeValue).length) {
this.typesWithAllActions.add(typeKey)
} else {
this.typesWithAllActions.delete(typeKey)
}
})
this.onChange(permissions)
})
}
toggleAll(event, type) {
const typeGroup = this.form.get(type)
if (event.target.checked) {
Object.keys(PermissionAction).forEach((action) => {
typeGroup.get(action).patchValue(true)
})
this.typesWithAllActions.add(type)
} else {
this.typesWithAllActions.delete(type)
}
}
}