skeleton user / group admin dialogs [WIP]

This commit is contained in:
Michael Shamoon
2022-11-13 07:23:33 -08:00
parent 2c95e632ef
commit def5c1a6cb
21 changed files with 515 additions and 34 deletions

View File

@@ -221,6 +221,82 @@
</ng-template>
</li>
<li [ngbNavItem]="SettingsNavIDs.UsersGroups" *ifPermissions="{ action: PermissionAction.Add, type: PermissionType.User }" (mouseover)="maybeInitializeTab(SettingsNavIDs.UsersGroups)" (focusin)="maybeInitializeTab(SettingsNavIDs.UsersGroups)">
<a ngbNavLink i18n>Users & Groups</a>
<ng-template ngbNavContent>
<ng-container *ngIf="users && groups">
<h4 class="d-flex">
<ng-container i18n>Users</ng-container>
<button type="button" class="btn btn-sm btn-primary ms-4" (click)="editUser()" i18n>Add User</button>
</h4>
<ul class="list-group" formGroupName="usersGroup">
<li class="list-group-item">
<div class="row">
<div class="col" i18n>Username</div>
<div class="col" i18n>Name</div>
<div class="col" i18n>Groups</div>
<div class="col" i18n>Actions</div>
</div>
</li>
<li *ngFor="let user of users" class="list-group-item" [formGroupName]="user.id">
<div class="row">
<div class="col d-flex align-items-center"><button class="btn btn-link p-0" type="button" (click)="editUser(user)">{{user.username}}</button></div>
<div class="col d-flex align-items-center">{{user.first_name}} {{user.last_name}}</div>
<div class="col d-flex align-items-center">{{user.groups}}</div>
<div class="col">
<div class="btn-group">
<button class="btn btn-sm btn-primary" type="button" (click)="editUser(user)" i18n>Edit</button>
<button class="btn btn-sm btn-outline-danger" type="button" (click)="deleteUser(user)" i18n>Delete</button>
</div>
</div>
</div>
</li>
</ul>
<h4 class="mt-4 d-flex">
<ng-container i18n>Groups</ng-container>
<button type="button" class="btn btn-sm btn-primary ms-4" (click)="editGroup()" i18n>Add Group</button>
</h4>
<ul *ngIf="groups.length > 0" class="list-group" formGroupName="groupsGroup">
<li class="list-group-item">
<div class="row">
<div class="col" i18n>Name</div>
<div class="col"></div>
<div class="col"></div>
<div class="col" i18n>Actions</div>
</div>
</li>
<li *ngFor="let group of groups" class="list-group-item" [formGroupName]="group.id">
<div class="row">
<div class="col d-flex align-items-center"><button class="btn btn-link p-0" type="button" (click)="editGroup(group)">{{group.name}}</button></div>
<div class="col"></div>
<div class="col"></div>
<div class="col">
<div class="btn-group">
<button class="btn btn-sm btn-primary" type="button" (click)="editGroup(group)" i18n>Edit</button>
<button class="btn btn-sm btn-outline-danger" type="button" (click)="deleteGroup(group)" i18n>Delete</button>
</div>
</div>
</div>
</li>
</ul>
<div *ngIf="groups.length == 0">No groups defined</div>
</ng-container>
<div *ngIf="!users || !groups">
<div class="spinner-border spinner-border-sm fw-normal ms-2 me-auto" role="status"></div>
<div class="visually-hidden" i18n>Loading...</div>
</div>
</ng-template>
</li>
</ul>
<div [ngbNavOutlet]="nav" class="border-start border-end border-bottom p-3 mb-3 shadow-sm"></div>

View File

@@ -30,8 +30,15 @@ import { ActivatedRoute } from '@angular/router'
import { ViewportScroller } from '@angular/common'
import { TourService } from 'ngx-ui-tour-ng-bootstrap'
import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component'
import { NgbNavChangeEvent } from '@ng-bootstrap/ng-bootstrap'
import { NgbModal, NgbNavChangeEvent } from '@ng-bootstrap/ng-bootstrap'
import { Results } from 'src/app/data/results'
import { UserService } from 'src/app/services/rest/user.service'
import { GroupService } from 'src/app/services/rest/group.service'
import { PaperlessUser } from 'src/app/data/paperless-user'
import { PaperlessGroup } from 'src/app/data/paperless-group'
import { UserEditDialogComponent } from '../../common/edit-dialog/user-edit-dialog/user-edit-dialog.component'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
import { GroupEditDialogComponent } from '../../common/edit-dialog/group-edit-dialog/group-edit-dialog.component'
enum SettingsNavIDs {
General = 1,
@@ -54,6 +61,8 @@ export class SettingsComponent
activeNavID: number
savedViewGroup = new FormGroup({})
usersGroup = new FormGroup({})
groupsGroup = new FormGroup({})
settingsForm = new FormGroup({
bulkEditConfirmationDialogs: new FormControl(null),
@@ -75,6 +84,8 @@ export class SettingsComponent
notificationsConsumerSuppressOnDashboard: new FormControl(null),
commentsEnabled: new FormControl(null),
updateCheckingEnabled: new FormControl(null),
usersGroup: this.usersGroup,
groupsGroup: this.groupsGroup,
})
savedViews: PaperlessSavedView[]
@@ -86,6 +97,9 @@ export class SettingsComponent
unsubscribeNotifier: Subject<any> = new Subject()
savePending: boolean = false
users: PaperlessUser[]
groups: PaperlessGroup[]
get computedDateLocale(): string {
return (
this.settingsForm.value.dateLocale ||
@@ -102,7 +116,10 @@ export class SettingsComponent
@Inject(LOCALE_ID) public currentLocale: string,
private viewportScroller: ViewportScroller,
private activatedRoute: ActivatedRoute,
public readonly tourService: TourService
public readonly tourService: TourService,
private usersService: UserService,
private groupsService: GroupService,
private modalService: NgbModal
) {
super()
this.settings.settingsSaved.subscribe(() => {
@@ -159,6 +176,8 @@ export class SettingsComponent
updateCheckingEnabled: this.settings.get(
SETTINGS_KEYS.UPDATE_CHECKING_ENABLED
),
usersGroup: {},
groupsGroup: {},
}
}
@@ -176,6 +195,18 @@ export class SettingsComponent
this.savedViews = r.results
this.initialize()
})
} else if (
(navID == SettingsNavIDs.UsersGroups && !this.users) ||
!this.groups
) {
this.usersService.listAll().subscribe((r) => {
this.users = r.results
this.groupsService.listAll().subscribe((r) => {
this.groups = r.results
this.initialize()
})
})
}
}
@@ -204,6 +235,50 @@ export class SettingsComponent
}
}
if (this.users && this.groups) {
for (let user of this.users) {
storeData.usersGroup[user.id.toString()] = {
id: user.id,
username: user.username,
first_name: user.first_name,
last_name: user.last_name,
is_active: user.is_active,
is_superuser: user.is_superuser,
groups: user.groups,
permissions: user.permissions,
}
this.usersGroup.addControl(
user.id.toString(),
new FormGroup({
id: new FormControl(null),
username: new FormControl(null),
first_name: new FormControl(null),
last_name: new FormControl(null),
is_active: new FormControl(null),
is_superuser: new FormControl(null),
groups: new FormControl(null),
permissions: new FormControl(null),
})
)
}
for (let group of this.groups) {
storeData.groupsGroup[group.id.toString()] = {
id: group.id,
name: group.name,
permissions: group.permissions,
}
this.groupsGroup.addControl(
group.id.toString(),
new FormGroup({
id: new FormControl(null),
name: new FormControl(null),
permissions: new FormControl(null),
})
)
}
}
this.store = new BehaviorSubject(storeData)
this.storeSub = this.store.asObservable().subscribe((state) => {
@@ -400,4 +475,86 @@ export class SettingsComponent
clearThemeColor() {
this.settingsForm.get('themeColor').patchValue('')
}
editUser(user: PaperlessUser) {
var modal = this.modalService.open(UserEditDialogComponent, {
backdrop: 'static',
size: 'xl',
})
modal.componentInstance.dialogMode = user ? 'edit' : 'create'
modal.componentInstance.object = user
modal.componentInstance.success
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe({
next: (newUser) => {
this.toastService.showInfo(
$localize`Saved user "${newUser.username}".`
)
this.usersService.listAll().subscribe((r) => {
this.users = r.results
this.initialize()
})
},
error: (e) => {
this.toastService.showError(
$localize`Error saving user: ${e.toString()}.`
)
},
})
}
deleteUser(user: PaperlessUser) {
let modal = this.modalService.open(ConfirmDialogComponent, {
backdrop: 'static',
})
modal.componentInstance.title = $localize`Confirm delete user account`
modal.componentInstance.messageBold = $localize`This operation will permanently this user account.`
modal.componentInstance.message = $localize`This operation cannot be undone.`
modal.componentInstance.btnClass = 'btn-danger'
modal.componentInstance.btnCaption = $localize`Proceed`
modal.componentInstance.confirmClicked.subscribe(() => {
modal.componentInstance.buttonsEnabled = false
this.usersService.delete(user)
})
}
editGroup(group: PaperlessGroup) {
var modal = this.modalService.open(GroupEditDialogComponent, {
backdrop: 'static',
size: 'lg',
})
modal.componentInstance.dialogMode = group ? 'edit' : 'create'
modal.componentInstance.object = group
modal.componentInstance.success
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe({
next: (newGroup) => {
this.toastService.showInfo($localize`Saved group "${newGroup.name}".`)
this.groupsService.listAll().subscribe((r) => {
this.groups = r.results
this.initialize()
})
},
error: (e) => {
this.toastService.showError(
$localize`Error saving group: ${e.toString()}.`
)
},
})
}
deleteGroup(group: PaperlessGroup) {
let modal = this.modalService.open(ConfirmDialogComponent, {
backdrop: 'static',
})
modal.componentInstance.title = $localize`Confirm delete user group`
modal.componentInstance.messageBold = $localize`This operation will permanently this user group.`
modal.componentInstance.message = $localize`This operation cannot be undone.`
modal.componentInstance.btnClass = 'btn-danger'
modal.componentInstance.btnCaption = $localize`Proceed`
modal.componentInstance.confirmClicked.subscribe(() => {
modal.componentInstance.buttonsEnabled = false
this.groupsService.delete(group)
})
}
}