Bulk delete users & other improvements
This commit is contained in:
parent
bf684108e4
commit
37b9236f61
@ -29,8 +29,8 @@ import { AdminDialogService } from './services/admin-dialog-service.service';
|
|||||||
import { SmtpConfigScreenComponent } from './screens/smtp-config/smtp-config-screen.component';
|
import { SmtpConfigScreenComponent } from './screens/smtp-config/smtp-config-screen.component';
|
||||||
import { SmtpAuthDialogComponent } from './dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
|
import { SmtpAuthDialogComponent } from './dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
|
||||||
import { AddEditUserDialogComponent } from './dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
|
import { AddEditUserDialogComponent } from './dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
|
||||||
import { ConfirmDeleteUserDialogComponent } from './dialogs/confirm-delete-user-dialog/confirm-delete-user-dialog.component';
|
|
||||||
import { UsersStatsComponent } from './components/users-stats/users-stats.component';
|
import { UsersStatsComponent } from './components/users-stats/users-stats.component';
|
||||||
|
import { ConfirmDeleteUsersDialogComponent } from './dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component';
|
||||||
|
|
||||||
const dialogs = [
|
const dialogs = [
|
||||||
AddEditRuleSetDialogComponent,
|
AddEditRuleSetDialogComponent,
|
||||||
@ -40,7 +40,7 @@ const dialogs = [
|
|||||||
EditColorDialogComponent,
|
EditColorDialogComponent,
|
||||||
SmtpAuthDialogComponent,
|
SmtpAuthDialogComponent,
|
||||||
AddEditUserDialogComponent,
|
AddEditUserDialogComponent,
|
||||||
ConfirmDeleteUserDialogComponent
|
ConfirmDeleteUsersDialogComponent
|
||||||
];
|
];
|
||||||
|
|
||||||
const screens = [
|
const screens = [
|
||||||
|
|||||||
@ -41,7 +41,7 @@
|
|||||||
[routerLinkActiveOptions]="{ exact: true }"
|
[routerLinkActiveOptions]="{ exact: true }"
|
||||||
routerLinkActive="active"
|
routerLinkActive="active"
|
||||||
translate="user-management"
|
translate="user-management"
|
||||||
*ngIf="root && userPreferenceService.areDevFeaturesEnabled"
|
*ngIf="root && permissionService.canManageUsers() && userPreferenceService.areDevFeaturesEnabled"
|
||||||
></a>
|
></a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import { UserService } from '../../../../services/user.service';
|
|||||||
export class AddEditUserDialogComponent {
|
export class AddEditUserDialogComponent {
|
||||||
public userForm: FormGroup;
|
public userForm: FormGroup;
|
||||||
public ROLES = ['RED_USER', 'RED_MANAGER', 'RED_USER_ADMIN', 'RED_ADMIN'];
|
public ROLES = ['RED_USER', 'RED_MANAGER', 'RED_USER_ADMIN', 'RED_ADMIN'];
|
||||||
|
private ROLE_REQUIREMENTS = { RED_MANAGER: 'RED_USER', RED_ADMIN: 'RED_USER_ADMIN' };
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _formBuilder: FormBuilder,
|
private readonly _formBuilder: FormBuilder,
|
||||||
@ -22,7 +23,16 @@ export class AddEditUserDialogComponent {
|
|||||||
const rolesControls = this.ROLES.reduce(
|
const rolesControls = this.ROLES.reduce(
|
||||||
(prev, role) => ({
|
(prev, role) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[role]: [this.user && this.user.roles.indexOf(role) !== -1]
|
[role]: [
|
||||||
|
{
|
||||||
|
value: this.user && this.user.roles.indexOf(role) !== -1,
|
||||||
|
disabled:
|
||||||
|
this.user &&
|
||||||
|
Object.keys(this.ROLE_REQUIREMENTS).reduce((value, key) => {
|
||||||
|
return value || (role === this.ROLE_REQUIREMENTS[key] && this.user.roles.indexOf(key) !== -1);
|
||||||
|
}, false)
|
||||||
|
}
|
||||||
|
]
|
||||||
}),
|
}),
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
@ -37,14 +47,13 @@ export class AddEditUserDialogComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _setRolesRequirements() {
|
private _setRolesRequirements() {
|
||||||
const requirements = { RED_MANAGER: 'RED_USER', RED_ADMIN: 'RED_USER_ADMIN' };
|
for (const key of Object.keys(this.ROLE_REQUIREMENTS)) {
|
||||||
for (const key of Object.keys(requirements)) {
|
|
||||||
this.userForm.controls[key].valueChanges.subscribe((checked) => {
|
this.userForm.controls[key].valueChanges.subscribe((checked) => {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
this.userForm.patchValue({ [requirements[key]]: true });
|
this.userForm.patchValue({ [this.ROLE_REQUIREMENTS[key]]: true });
|
||||||
this.userForm.controls[requirements[key]].disable();
|
this.userForm.controls[this.ROLE_REQUIREMENTS[key]].disable();
|
||||||
} else {
|
} else {
|
||||||
this.userForm.controls[requirements[key]].enable();
|
this.userForm.controls[this.ROLE_REQUIREMENTS[key]].enable();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,41 +0,0 @@
|
|||||||
import { Component, Inject, OnInit } from '@angular/core';
|
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
|
||||||
import { User } from '@redaction/red-ui-http';
|
|
||||||
import { AppStateService } from '../../../../state/app-state.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'redaction-confirm-delete-user-dialog',
|
|
||||||
templateUrl: './confirm-delete-user-dialog.component.html',
|
|
||||||
styleUrls: ['./confirm-delete-user-dialog.component.scss']
|
|
||||||
})
|
|
||||||
export class ConfirmDeleteUserDialogComponent implements OnInit {
|
|
||||||
public checkboxes = [{ value: false }, { value: false }];
|
|
||||||
public showToast = false;
|
|
||||||
public projectsCount: number;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
@Inject(MAT_DIALOG_DATA) public user: User,
|
|
||||||
private readonly _appStateService: AppStateService,
|
|
||||||
public dialogRef: MatDialogRef<ConfirmDeleteUserDialogComponent>
|
|
||||||
) {
|
|
||||||
this.projectsCount = this._appStateService.allProjects.filter((pw) => pw.memberIds.indexOf(user.userId) !== -1).length;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {}
|
|
||||||
|
|
||||||
async deleteUser() {
|
|
||||||
if (this.valid) {
|
|
||||||
this.dialogRef.close(true);
|
|
||||||
} else {
|
|
||||||
this.showToast = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public get valid() {
|
|
||||||
return this.checkboxes[0].value && this.checkboxes[1].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public cancel() {
|
|
||||||
this.dialogRef.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,15 +1,15 @@
|
|||||||
<section class="dialog">
|
<section class="dialog">
|
||||||
<div class="dialog-header heading-l" translate="confirm-delete-user.title"></div>
|
<div class="dialog-header heading-l" [translate]="'confirm-delete-users.title.' + type"></div>
|
||||||
|
|
||||||
<div class="inline-dialog-toast toast-error" *ngIf="showToast">
|
<div class="inline-dialog-toast toast-error" *ngIf="showToast">
|
||||||
<div translate="confirm-delete-user.toast-error"></div>
|
<div translate="confirm-delete-users.toast-error"></div>
|
||||||
<a (click)="showToast = false" class="toast-close-button">
|
<a (click)="showToast = false" class="toast-close-button">
|
||||||
<mat-icon svgIcon="red:close"></mat-icon>
|
<mat-icon svgIcon="red:close"></mat-icon>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dialog-content">
|
<div class="dialog-content">
|
||||||
<div class="heading" translate="confirm-delete-user.warning"></div>
|
<div class="heading" translate="confirm-delete-users.warning"></div>
|
||||||
|
|
||||||
<mat-checkbox
|
<mat-checkbox
|
||||||
*ngFor="let checkbox of checkboxes; let idx = index"
|
*ngFor="let checkbox of checkboxes; let idx = index"
|
||||||
@ -17,15 +17,15 @@
|
|||||||
color="primary"
|
color="primary"
|
||||||
[class.error]="!checkbox.value && showToast"
|
[class.error]="!checkbox.value && showToast"
|
||||||
>
|
>
|
||||||
{{ 'confirm-delete-user.checkbox-' + (idx + 1) | translate: { projectsCount: projectsCount } }}
|
{{ 'confirm-delete-users.' + checkbox.label | translate: { projectsCount: projectsCount } }}
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dialog-actions">
|
<div class="dialog-actions">
|
||||||
<button color="primary" mat-flat-button (click)="deleteUser()">
|
<button color="primary" mat-flat-button (click)="deleteUser()">
|
||||||
{{ 'confirm-delete-user.delete' | translate }}
|
{{ 'confirm-delete-users.delete.' + type | translate }}
|
||||||
</button>
|
</button>
|
||||||
<div class="all-caps-label cancel" (click)="cancel()" translate="confirm-delete-user.cancel"></div>
|
<div class="all-caps-label cancel" (click)="cancel()" [translate]="'confirm-delete-users.cancel.' + type"></div>
|
||||||
</div>
|
</div>
|
||||||
<redaction-circle-button icon="red:close" mat-dialog-close class="dialog-close"></redaction-circle-button>
|
<redaction-circle-button icon="red:close" mat-dialog-close class="dialog-close"></redaction-circle-button>
|
||||||
</section>
|
</section>
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
|
import { User } from '@redaction/red-ui-http';
|
||||||
|
import { AppStateService } from '../../../../state/app-state.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'redaction-confirm-delete-users-dialog',
|
||||||
|
templateUrl: './confirm-delete-users-dialog.component.html',
|
||||||
|
styleUrls: ['./confirm-delete-users-dialog.component.scss']
|
||||||
|
})
|
||||||
|
export class ConfirmDeleteUsersDialogComponent implements OnInit {
|
||||||
|
public checkboxes = [
|
||||||
|
{ value: false, label: 'impacted-projects' },
|
||||||
|
{ value: false, label: 'impacted-documents.' + this.type }
|
||||||
|
];
|
||||||
|
public showToast = false;
|
||||||
|
public projectsCount: number;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(MAT_DIALOG_DATA) public users: User[],
|
||||||
|
private readonly _appStateService: AppStateService,
|
||||||
|
public dialogRef: MatDialogRef<ConfirmDeleteUsersDialogComponent>
|
||||||
|
) {
|
||||||
|
this.projectsCount = this._appStateService.allProjects.filter((pw) => {
|
||||||
|
for (const user of this.users) {
|
||||||
|
if (pw.memberIds.indexOf(user.userId) !== -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {}
|
||||||
|
|
||||||
|
async deleteUser() {
|
||||||
|
if (this.valid) {
|
||||||
|
this.dialogRef.close(true);
|
||||||
|
} else {
|
||||||
|
this.showToast = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get valid() {
|
||||||
|
return this.checkboxes[0].value && this.checkboxes[1].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public cancel() {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public get type(): 'bulk' | 'single' {
|
||||||
|
return this.users.length > 1 ? 'bulk' : 'single';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -25,17 +25,47 @@
|
|||||||
<div class="red-content-inner">
|
<div class="red-content-inner">
|
||||||
<div class="left-container" [class.extended]="collapsedDetails">
|
<div class="left-container" [class.extended]="collapsedDetails">
|
||||||
<div class="header-item">
|
<div class="header-item">
|
||||||
|
<div class="select-all-container">
|
||||||
|
<div
|
||||||
|
(click)="toggleSelectAll()"
|
||||||
|
[class.active]="areAllUsersSelected"
|
||||||
|
class="select-oval always-visible"
|
||||||
|
*ngIf="!areAllUsersSelected && !areSomeUsersSelected"
|
||||||
|
></div>
|
||||||
|
<mat-icon *ngIf="areAllUsersSelected" (click)="toggleSelectAll()" class="selection-icon active" svgIcon="red:radio-selected"></mat-icon>
|
||||||
|
<mat-icon
|
||||||
|
*ngIf="areSomeUsersSelected && !areAllUsersSelected"
|
||||||
|
(click)="toggleSelectAll()"
|
||||||
|
class="selection-icon"
|
||||||
|
svgIcon="red:radio-indeterminate"
|
||||||
|
></mat-icon>
|
||||||
|
</div>
|
||||||
<span class="all-caps-label">
|
<span class="all-caps-label">
|
||||||
{{ 'user-listing.table-header.title' | translate: { length: displayedUsers.length } }}
|
{{ 'user-listing.table-header.title' | translate: { length: displayedUsers.length } }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<ng-container *ngIf="true || (areSomeUsersSelected && !loading)">
|
||||||
|
<redaction-circle-button
|
||||||
|
(action)="bulkDelete()"
|
||||||
|
[disabled]="!canDeleteSelected"
|
||||||
|
[tooltip]="canDeleteSelected ? 'user-listing.bulk.delete' : 'user-listing.bulk.delete-disabled'"
|
||||||
|
tooltipPosition="after"
|
||||||
|
type="dark-bg"
|
||||||
|
icon="red:trash"
|
||||||
|
></redaction-circle-button>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<mat-spinner *ngIf="loading" diameter="15"></mat-spinner>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-header" redactionSyncWidth="table-item">
|
<div class="table-header" redactionSyncWidth="table-item">
|
||||||
|
<div class="select-oval-placeholder"></div>
|
||||||
|
|
||||||
<redaction-table-col-name label="user-listing.table-col-names.name"></redaction-table-col-name>
|
<redaction-table-col-name label="user-listing.table-col-names.name"></redaction-table-col-name>
|
||||||
|
|
||||||
<redaction-table-col-name label="user-listing.table-col-names.email"></redaction-table-col-name>
|
<redaction-table-col-name label="user-listing.table-col-names.email"></redaction-table-col-name>
|
||||||
|
|
||||||
<redaction-table-col-name label="user-listing.table-col-names.active"></redaction-table-col-name>
|
<redaction-table-col-name label="user-listing.table-col-names.active" class="flex-center"></redaction-table-col-name>
|
||||||
|
|
||||||
<redaction-table-col-name label="user-listing.table-col-names.roles"></redaction-table-col-name>
|
<redaction-table-col-name label="user-listing.table-col-names.roles"></redaction-table-col-name>
|
||||||
|
|
||||||
@ -46,12 +76,16 @@
|
|||||||
<cdk-virtual-scroll-viewport [itemSize]="80" redactionHasScrollbar>
|
<cdk-virtual-scroll-viewport [itemSize]="80" redactionHasScrollbar>
|
||||||
<!-- Table lines -->
|
<!-- Table lines -->
|
||||||
<div class="table-item" *cdkVirtualFor="let user of displayedUsers">
|
<div class="table-item" *cdkVirtualFor="let user of displayedUsers">
|
||||||
|
<div class="pr-0" (click)="toggleUserSelected($event, user)">
|
||||||
|
<div *ngIf="!isUserSelected(user)" class="select-oval"></div>
|
||||||
|
<mat-icon class="selection-icon active" *ngIf="isUserSelected(user)" svgIcon="red:radio-selected"></mat-icon>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<redaction-initials-avatar [user]="user" [withName]="true" [showYou]="true" [alwaysShowName]="true"></redaction-initials-avatar>
|
<redaction-initials-avatar [user]="user" [withName]="true" [showYou]="true" [alwaysShowName]="true"></redaction-initials-avatar>
|
||||||
</div>
|
</div>
|
||||||
<div class="small-label">{{ user.email || '-' }}</div>
|
<div class="small-label">{{ user.email || '-' }}</div>
|
||||||
<div>
|
<div class="center">
|
||||||
<mat-slide-toggle [checked]="userService.isActive(user)" color="primary" (toggleChange)="changeActive(user)"></mat-slide-toggle>
|
<mat-slide-toggle [checked]="userService.isActive(user)" color="primary" (toggleChange)="toggleActive(user)"></mat-slide-toggle>
|
||||||
</div>
|
</div>
|
||||||
<div class="small-label">{{ getDisplayRoles(user) }}</div>
|
<div class="small-label">{{ getDisplayRoles(user) }}</div>
|
||||||
<div class="actions-container">
|
<div class="actions-container">
|
||||||
@ -64,7 +98,7 @@
|
|||||||
>
|
>
|
||||||
</redaction-circle-button>
|
</redaction-circle-button>
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
(action)="openDeleteUserDialog(user, $event)"
|
(action)="openDeleteUserDialog([user], $event)"
|
||||||
tooltip="user-listing.action.delete"
|
tooltip="user-listing.action.delete"
|
||||||
type="dark-bg"
|
type="dark-bg"
|
||||||
icon="red:trash"
|
icon="red:trash"
|
||||||
|
|||||||
@ -1,13 +1,23 @@
|
|||||||
.left-container {
|
.left-container {
|
||||||
width: calc(100vw - 353px);
|
width: calc(100vw - 353px);
|
||||||
|
|
||||||
|
.header-item {
|
||||||
|
padding: 0 24px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
redaction-table-col-name::ng-deep {
|
||||||
|
> div {
|
||||||
|
padding: 0 13px 0 10px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cdk-virtual-scroll-viewport {
|
cdk-virtual-scroll-viewport {
|
||||||
::ng-deep.cdk-virtual-scroll-content-wrapper {
|
::ng-deep.cdk-virtual-scroll-content-wrapper {
|
||||||
grid-template-columns: 2fr 1fr 1fr 1fr auto 11px;
|
grid-template-columns: auto 2fr 1fr 1fr 1fr auto 11px;
|
||||||
|
|
||||||
.table-item {
|
.table-item {
|
||||||
> div:not(.scrollbar-placeholder) {
|
> div:not(.scrollbar-placeholder) {
|
||||||
padding: 0 24px;
|
padding-left: 10px;
|
||||||
|
|
||||||
&.center {
|
&.center {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -18,7 +28,7 @@
|
|||||||
|
|
||||||
&.has-scrollbar:hover {
|
&.has-scrollbar:hover {
|
||||||
::ng-deep.cdk-virtual-scroll-content-wrapper {
|
::ng-deep.cdk-virtual-scroll-content-wrapper {
|
||||||
grid-template-columns: 2fr 1fr 1fr 1fr auto;
|
grid-template-columns: auto 2fr 1fr 1fr 1fr auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { PermissionsService } from '../../../../services/permissions.service';
|
import { PermissionsService } from '../../../../services/permissions.service';
|
||||||
import { UserService } from '../../../../services/user.service';
|
import { UserService } from '../../../../services/user.service';
|
||||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
import { RuleSetModel, User, UserControllerService } from '@redaction/red-ui-http';
|
||||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
import { debounce } from '../../../../utils/debounce';
|
import { debounce } from '../../../../utils/debounce';
|
||||||
import { AdminDialogService } from '../../services/admin-dialog-service.service';
|
import { AdminDialogService } from '../../services/admin-dialog-service.service';
|
||||||
@ -16,11 +16,13 @@ import { TranslateChartService } from '../../../../services/translate-chart.serv
|
|||||||
})
|
})
|
||||||
export class UserListingScreenComponent implements OnInit {
|
export class UserListingScreenComponent implements OnInit {
|
||||||
public viewReady = false;
|
public viewReady = false;
|
||||||
|
public loading = false;
|
||||||
public collapsedDetails = false;
|
public collapsedDetails = false;
|
||||||
public chartData: DoughnutChartConfig[];
|
public chartData: DoughnutChartConfig[] = [];
|
||||||
public users: User[];
|
public users: User[];
|
||||||
public displayedUsers: User[] = [];
|
public displayedUsers: User[] = [];
|
||||||
public searchForm: FormGroup;
|
public searchForm: FormGroup;
|
||||||
|
public selectedUsersIds: string[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly permissionsService: PermissionsService,
|
public readonly permissionsService: PermissionsService,
|
||||||
@ -52,34 +54,34 @@ export class UserListingScreenComponent implements OnInit {
|
|||||||
$event.stopPropagation();
|
$event.stopPropagation();
|
||||||
this._adminDialogService.openAddEditUserDialog(user, async (result) => {
|
this._adminDialogService.openAddEditUserDialog(user, async (result) => {
|
||||||
if (result === 'DELETE') {
|
if (result === 'DELETE') {
|
||||||
this.openDeleteUserDialog(user);
|
this.openDeleteUserDialog([user]);
|
||||||
} else {
|
} else {
|
||||||
this.viewReady = false;
|
this.loading = true;
|
||||||
if (result.action === 'CREATE') {
|
if (result.action === 'CREATE') {
|
||||||
await this._userControllerService.createUser(result.user).toPromise();
|
await this._userControllerService.createUser(result.user).toPromise();
|
||||||
} else if (result.action === 'UPDATE') {
|
} else if (result.action === 'UPDATE') {
|
||||||
await this._userControllerService.updateProfile(result.user).toPromise();
|
await this._userControllerService.updateProfile(result.user, user.userId).toPromise();
|
||||||
}
|
}
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public openDeleteUserDialog(user: User, $event?: MouseEvent) {
|
public openDeleteUserDialog(users: User[], $event?: MouseEvent) {
|
||||||
$event?.stopPropagation();
|
$event?.stopPropagation();
|
||||||
this._adminDialogService.openConfirmDeleteUserDialog(user, async () => {
|
this._adminDialogService.openConfirmDeleteUsersDialog(users, async () => {
|
||||||
this.viewReady = false;
|
this.loading = true;
|
||||||
await this._userControllerService.deleteUser(user.userId).toPromise();
|
await this._userControllerService.deleteUsers(users.map((u) => u.userId)).toPromise();
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _loadData() {
|
private async _loadData() {
|
||||||
this.viewReady = false;
|
|
||||||
this.users = (await this._userControllerService.getAllUsers({}).toPromise()).users;
|
this.users = (await this._userControllerService.getAllUsers({}).toPromise()).users;
|
||||||
this._executeSearch();
|
this._executeSearch();
|
||||||
this._computeStats();
|
this._computeStats();
|
||||||
this.viewReady = true;
|
this.viewReady = true;
|
||||||
|
this.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeStats() {
|
private _computeStats() {
|
||||||
@ -123,8 +125,8 @@ export class UserListingScreenComponent implements OnInit {
|
|||||||
return user.roles.map((role) => this._translateService.instant('roles.' + role)).join(', ') || this._translateService.instant('roles.NO_ROLE');
|
return user.roles.map((role) => this._translateService.instant('roles.' + role)).join(', ') || this._translateService.instant('roles.NO_ROLE');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async changeActive(user: User) {
|
public async toggleActive(user: User) {
|
||||||
this.viewReady = false;
|
this.loading = true;
|
||||||
user.roles = this.userService.isActive(user) ? [] : ['RED_USER'];
|
user.roles = this.userService.isActive(user) ? [] : ['RED_USER'];
|
||||||
await this._userControllerService.addRoleToUsers(user.roles, user.userId).toPromise();
|
await this._userControllerService.addRoleToUsers(user.roles, user.userId).toPromise();
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
@ -133,4 +135,42 @@ export class UserListingScreenComponent implements OnInit {
|
|||||||
public toggleCollapsedDetails() {
|
public toggleCollapsedDetails() {
|
||||||
this.collapsedDetails = !this.collapsedDetails;
|
this.collapsedDetails = !this.collapsedDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleUserSelected($event: MouseEvent, user: User) {
|
||||||
|
$event.stopPropagation();
|
||||||
|
const idx = this.selectedUsersIds.indexOf(user.userId);
|
||||||
|
if (idx === -1) {
|
||||||
|
this.selectedUsersIds.push(user.userId);
|
||||||
|
} else {
|
||||||
|
this.selectedUsersIds.splice(idx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleSelectAll() {
|
||||||
|
if (this.areSomeUsersSelected) {
|
||||||
|
this.selectedUsersIds = [];
|
||||||
|
} else {
|
||||||
|
this.selectedUsersIds = this.displayedUsers.map((user) => user.userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get areAllUsersSelected() {
|
||||||
|
return this.displayedUsers.length !== 0 && this.selectedUsersIds.length === this.displayedUsers.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get areSomeUsersSelected() {
|
||||||
|
return this.selectedUsersIds.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isUserSelected(user: User) {
|
||||||
|
return this.selectedUsersIds.indexOf(user.userId) !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async bulkDelete() {
|
||||||
|
this.openDeleteUserDialog(this.users.filter((u) => this.isUserSelected(u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public get canDeleteSelected(): boolean {
|
||||||
|
return this.selectedUsersIds.indexOf(this.userService.userId) === -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import { EditColorDialogComponent } from '../dialogs/edit-color-dialog/edit-colo
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { SmtpAuthDialogComponent } from '../dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
|
import { SmtpAuthDialogComponent } from '../dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
|
||||||
import { AddEditUserDialogComponent } from '../dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
|
import { AddEditUserDialogComponent } from '../dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
|
||||||
import { ConfirmDeleteUserDialogComponent } from '../dialogs/confirm-delete-user-dialog/confirm-delete-user-dialog.component';
|
import { ConfirmDeleteUsersDialogComponent } from '../dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component';
|
||||||
|
|
||||||
const dialogConfig = {
|
const dialogConfig = {
|
||||||
width: '662px',
|
width: '662px',
|
||||||
@ -188,10 +188,10 @@ export class AdminDialogService {
|
|||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
public openConfirmDeleteUserDialog(user?: User, cb?: Function): MatDialogRef<ConfirmDeleteUserDialogComponent> {
|
public openConfirmDeleteUsersDialog(users: User[], cb?: Function): MatDialogRef<ConfirmDeleteUsersDialogComponent> {
|
||||||
const ref = this._dialog.open(ConfirmDeleteUserDialogComponent, {
|
const ref = this._dialog.open(ConfirmDeleteUsersDialogComponent, {
|
||||||
...dialogConfig,
|
...dialogConfig,
|
||||||
data: user,
|
data: users,
|
||||||
autoFocus: true
|
autoFocus: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -278,6 +278,16 @@ export class PermissionsService {
|
|||||||
return user.isAdmin;
|
return user.isAdmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isUserAdmin(user?: UserWrapper) {
|
||||||
|
if (!user) {
|
||||||
|
user = this._userService.user;
|
||||||
|
}
|
||||||
|
if (!user) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return user.isUserAdmin;
|
||||||
|
}
|
||||||
|
|
||||||
isUser(user?: UserWrapper) {
|
isUser(user?: UserWrapper) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
user = this._userService.user;
|
user = this._userService.user;
|
||||||
@ -297,4 +307,8 @@ export class PermissionsService {
|
|||||||
}
|
}
|
||||||
return fileStatus.status === 'UNASSIGNED' || fileStatus.status === 'UNDER_REVIEW' || fileStatus.status === 'UNDER_APPROVAL';
|
return fileStatus.status === 'UNASSIGNED' || fileStatus.status === 'UNDER_REVIEW' || fileStatus.status === 'UNDER_APPROVAL';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canManageUsers(user?: UserWrapper) {
|
||||||
|
return this.isUserAdmin(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,10 @@ export class UserWrapper {
|
|||||||
return this.roles.indexOf('RED_ADMIN') >= 0;
|
return this.roles.indexOf('RED_ADMIN') >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isUserAdmin() {
|
||||||
|
return this.roles.indexOf('RED_USER_ADMIN') >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
get hasAnyREDRoles() {
|
get hasAnyREDRoles() {
|
||||||
return this.isUser || this.isManager || this.isAdmin;
|
return this.isUser || this.isManager || this.isAdmin;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -758,13 +758,25 @@
|
|||||||
"checkbox-2": "All inputted details on the documents will be lost",
|
"checkbox-2": "All inputted details on the documents will be lost",
|
||||||
"toast-error": "Please confirm that you understand the ramifications of your action!"
|
"toast-error": "Please confirm that you understand the ramifications of your action!"
|
||||||
},
|
},
|
||||||
"confirm-delete-user": {
|
"confirm-delete-users": {
|
||||||
"title": "Delete User from Workspace",
|
"title": {
|
||||||
|
"single": "Delete User from Workspace",
|
||||||
|
"bulk": "Delete Users from Workspace"
|
||||||
|
},
|
||||||
"warning": "Warning: this cannot be undone!",
|
"warning": "Warning: this cannot be undone!",
|
||||||
"checkbox-1": "{{projectsCount}} projects will be impacted",
|
"impacted-projects": "{{projectsCount}} projects will be impacted",
|
||||||
"checkbox-2": "All documents waiting review from the user will be impacted",
|
"impacted-documents": {
|
||||||
"delete": "Delete User",
|
"single": "All documents pending review from the user will be impacted",
|
||||||
"cancel": "Keep User",
|
"bulk": "All documents pending review from the users will be impacted"
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"single": "Delete User",
|
||||||
|
"bulk": "Delete Users"
|
||||||
|
},
|
||||||
|
"cancel": {
|
||||||
|
"single": "Keep User",
|
||||||
|
"bulk": "Keep Users"
|
||||||
|
},
|
||||||
"toast-error": "Please confirm that you understand the ramifications of your action!"
|
"toast-error": "Please confirm that you understand the ramifications of your action!"
|
||||||
},
|
},
|
||||||
"document-info": {
|
"document-info": {
|
||||||
@ -786,6 +798,10 @@
|
|||||||
"edit": "Edit User",
|
"edit": "Edit User",
|
||||||
"delete": "Delete User"
|
"delete": "Delete User"
|
||||||
},
|
},
|
||||||
|
"bulk": {
|
||||||
|
"delete": "Delete Users",
|
||||||
|
"delete-disabled": "You cannot delete your own account."
|
||||||
|
},
|
||||||
"search": "Search...",
|
"search": "Search...",
|
||||||
"add-new": "New User"
|
"add-new": "New User"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -54,3 +54,9 @@
|
|||||||
left: 100%;
|
left: 100%;
|
||||||
transform: rotate(-90deg) translateY(3px) translateX(3px);
|
transform: rotate(-90deg) translateY(3px) translateX(3px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mat-tooltip[style*='transform-origin: left center']:after {
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
transform: rotate(90deg) translateY(3px) translateX(-3px);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user