Skip to content

Commit

Permalink
skeleton user / group admin dialogs [WIP]
Browse files Browse the repository at this point in the history
  • Loading branch information
shamoon committed Nov 13, 2022
1 parent bf28a51 commit c7b46ac
Show file tree
Hide file tree
Showing 21 changed files with 515 additions and 34 deletions.
6 changes: 6 additions & 0 deletions src-ui/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ import { StoragePathEditDialogComponent } from './components/common/edit-dialog/
import { SettingsService } from './services/settings.service'
import { TasksComponent } from './components/manage/tasks/tasks.component'
import { TourNgBootstrapModule } from 'ngx-ui-tour-ng-bootstrap'
import { UserEditDialogComponent } from './components/common/edit-dialog/user-edit-dialog/user-edit-dialog.component'
import { GroupEditDialogComponent } from './components/common/edit-dialog/group-edit-dialog/group-edit-dialog.component'
import { PermissionsSelectComponent } from './components/common/permissions-select/permissions-select.component'

import localeBe from '@angular/common/locales/be'
import localeCs from '@angular/common/locales/cs'
Expand Down Expand Up @@ -183,6 +186,9 @@ function initializeApp(settings: SettingsService) {
DocumentAsnComponent,
DocumentCommentsComponent,
TasksComponent,
UserEditDialogComponent,
GroupEditDialogComponent,
PermissionsSelectComponent,
],
imports: [
BrowserModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,15 @@ import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-
import { DEFAULT_MATCHING_ALGORITHM } from 'src/app/data/matching-model'
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'
import { CorrespondentService } from 'src/app/services/rest/correspondent.service'
import { ToastService } from 'src/app/services/toast.service'

@Component({
selector: 'app-correspondent-edit-dialog',
templateUrl: './correspondent-edit-dialog.component.html',
styleUrls: ['./correspondent-edit-dialog.component.scss'],
})
export class CorrespondentEditDialogComponent extends EditDialogComponent<PaperlessCorrespondent> {
constructor(
service: CorrespondentService,
activeModal: NgbActiveModal,
toastService: ToastService
) {
super(service, activeModal, toastService)
constructor(service: CorrespondentService, activeModal: NgbActiveModal) {
super(service, activeModal)
}

getCreateTitle() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,15 @@ import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-
import { DEFAULT_MATCHING_ALGORITHM } from 'src/app/data/matching-model'
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'
import { DocumentTypeService } from 'src/app/services/rest/document-type.service'
import { ToastService } from 'src/app/services/toast.service'

@Component({
selector: 'app-document-type-edit-dialog',
templateUrl: './document-type-edit-dialog.component.html',
styleUrls: ['./document-type-edit-dialog.component.scss'],
})
export class DocumentTypeEditDialogComponent extends EditDialogComponent<PaperlessDocumentType> {
constructor(
service: DocumentTypeService,
activeModal: NgbActiveModal,
toastService: ToastService
) {
super(service, activeModal, toastService)
constructor(service: DocumentTypeService, activeModal: NgbActiveModal) {
super(service, activeModal)
}

getCreateTitle() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ export abstract class EditDialogComponent<T extends ObjectWithId>
{
constructor(
private service: AbstractPaperlessService<T>,
private activeModal: NgbActiveModal,
private toastService: ToastService
private activeModal: NgbActiveModal
) {}

@Input()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<form [formGroup]="objectForm" (ngSubmit)="save()">
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
</button>
</div>
<div class="modal-body">
<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>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
<button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
</div>
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Component } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-dialog.component'
import { PaperlessGroup } from 'src/app/data/paperless-group'
import { GroupService } from 'src/app/services/rest/group.service'

@Component({
selector: 'app-group-edit-dialog',
templateUrl: './group-edit-dialog.component.html',
styleUrls: ['./group-edit-dialog.component.scss'],
})
export class GroupEditDialogComponent extends EditDialogComponent<PaperlessGroup> {
constructor(service: GroupService, activeModal: NgbActiveModal) {
super(service, activeModal)
}

getCreateTitle() {
return $localize`Create new user group`
}

getEditTitle() {
return $localize`Edit user group`
}

getForm(): FormGroup {
return new FormGroup({
name: new FormControl(''),
permissions: new FormControl(''),
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,15 @@ import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-
import { DEFAULT_MATCHING_ALGORITHM } from 'src/app/data/matching-model'
import { PaperlessStoragePath } from 'src/app/data/paperless-storage-path'
import { StoragePathService } from 'src/app/services/rest/storage-path.service'
import { ToastService } from 'src/app/services/toast.service'

@Component({
selector: 'app-storage-path-edit-dialog',
templateUrl: './storage-path-edit-dialog.component.html',
styleUrls: ['./storage-path-edit-dialog.component.scss'],
})
export class StoragePathEditDialogComponent extends EditDialogComponent<PaperlessStoragePath> {
constructor(
service: StoragePathService,
activeModal: NgbActiveModal,
toastService: ToastService
) {
super(service, activeModal, toastService)
constructor(service: StoragePathService, activeModal: NgbActiveModal) {
super(service, activeModal)
}

get pathHint() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-dialog.component'
import { PaperlessTag } from 'src/app/data/paperless-tag'
import { TagService } from 'src/app/services/rest/tag.service'
import { ToastService } from 'src/app/services/toast.service'
import { randomColor } from 'src/app/utils/color'
import { DEFAULT_MATCHING_ALGORITHM } from 'src/app/data/matching-model'

Expand All @@ -14,12 +13,8 @@ import { DEFAULT_MATCHING_ALGORITHM } from 'src/app/data/matching-model'
styleUrls: ['./tag-edit-dialog.component.scss'],
})
export class TagEditDialogComponent extends EditDialogComponent<PaperlessTag> {
constructor(
service: TagService,
activeModal: NgbActiveModal,
toastService: ToastService
) {
super(service, activeModal, toastService)
constructor(service: TagService, activeModal: NgbActiveModal) {
super(service, activeModal)
}

getCreateTitle() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<form [formGroup]="objectForm" (ngSubmit)="save()">
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col">
<app-input-text i18n-title title="Username" formControlName="username" [error]="error?.username"></app-input-text>
<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>

<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>
</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>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button>
<button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button>
</div>
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Component } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { first } from 'rxjs'
import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-dialog.component'
import { PaperlessGroup } from 'src/app/data/paperless-group'
import { PaperlessUser } from 'src/app/data/paperless-user'
import { GroupService } from 'src/app/services/rest/group.service'
import { UserService } from 'src/app/services/rest/user.service'

@Component({
selector: 'app-user-edit-dialog',
templateUrl: './user-edit-dialog.component.html',
styleUrls: ['./user-edit-dialog.component.scss'],
})
export class UserEditDialogComponent extends EditDialogComponent<PaperlessUser> {
groups: PaperlessGroup[]

constructor(
service: UserService,
activeModal: NgbActiveModal,
groupsService: GroupService
) {
super(service, activeModal)

groupsService
.listAll()
.pipe(first())
.subscribe((result) => (this.groups = result.results))
}

getCreateTitle() {
return $localize`Create new user account`
}

getEditTitle() {
return $localize`Edit user account`
}

getForm(): FormGroup {
return new FormGroup({
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(''),
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
addTagText="Add item"
i18n-addTagText="Used for both types, correspondents, storage paths"
[placeholder]="placeholder"
[multiple]="multiple"
bindLabel="name"
bindValue="id"
(change)="onChange(value)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ export class SelectComponent extends AbstractInputComponent<number> {
@Input()
placeholder: string

@Input()
multiple: boolean = false

@Output()
createNew = new EventEmitter<string>()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<form [formGroup]="form">
<label>{{title}}</label>
<ul class="list-group">
<li class="list-group-item" *ngFor="let type of PermissionType | keyvalue" [formGroupName]="type.key">
{{type.key}}:

<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>

<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>
</li>
</ul>
</form>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Component, forwardRef, Input, OnInit } from '@angular/core'
import {
ControlValueAccessor,
FormControl,
FormGroup,
NG_VALUE_ACCESSOR,
} from '@angular/forms'
import {
PermissionAction,
PermissionsService,
PermissionType,
} from 'src/app/services/permissions.service'
import { AbstractInputComponent } from '../input/abstract-input'

@Component({
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => PermissionsSelectComponent),
multi: true,
},
],
selector: 'app-permissions-select',
templateUrl: './permissions-select.component.html',
styleUrls: ['./permissions-select.component.scss'],
})
export class PermissionsSelectComponent
implements OnInit, ControlValueAccessor
{
PermissionType = PermissionType
PermissionAction = PermissionAction

@Input()
title: string = 'Permissions'

permissions: string[]

form = new FormGroup({})

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))
}
this.form.addControl(type, control)
}
}

writeValue(permissions: string[]): void {
this.permissions = permissions
this.permissions.forEach((permissionStr) => {
const { actionKey, typeKey } =
this.permissionsService.getPermissionKeys(permissionStr)

if (actionKey && typeKey) {
if (this.form.get(typeKey)?.get(actionKey)) {
this.form.get(typeKey).get(actionKey).setValue(true)
}
}
})
}
registerOnChange(fn: any): void {
throw new Error('Method not implemented.')
}
registerOnTouched(fn: any): void {
throw new Error('Method not implemented.')
}
setDisabledState?(isDisabled: boolean): void {
throw new Error('Method not implemented.')
}

ngOnInit(): void {}

isAll(key: string): boolean {
return this.form.get(key).get('all').value == true
}
}

0 comments on commit c7b46ac

Please sign in to comment.