User management updates
This commit is contained in:
parent
fe57bba05e
commit
7289c8675e
@ -30,6 +30,7 @@ import { SmtpConfigScreenComponent } from './screens/smtp-config/smtp-config-scr
|
|||||||
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 { ConfirmDeleteUserDialogComponent } from './dialogs/confirm-delete-user-dialog/confirm-delete-user-dialog.component';
|
||||||
|
import { UsersStatsComponent } from './components/users-stats/users-stats.component';
|
||||||
|
|
||||||
const dialogs = [
|
const dialogs = [
|
||||||
AddEditRuleSetDialogComponent,
|
AddEditRuleSetDialogComponent,
|
||||||
@ -63,6 +64,7 @@ const components = [
|
|||||||
TabsComponent,
|
TabsComponent,
|
||||||
ComboChartComponent,
|
ComboChartComponent,
|
||||||
ComboSeriesVerticalComponent,
|
ComboSeriesVerticalComponent,
|
||||||
|
UsersStatsComponent,
|
||||||
...dialogs,
|
...dialogs,
|
||||||
...screens
|
...screens
|
||||||
];
|
];
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
<div class="collapsed-wrapper">
|
||||||
|
<redaction-circle-button (action)="toggleCollapse.emit()" icon="red:expand" tooltip="user-stats.expand" tooltipPosition="before"></redaction-circle-button>
|
||||||
|
<div class="all-caps-label" translate="user-stats.title"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="header-wrapper mt-8">
|
||||||
|
<div class="heading-xl flex-1" translate="user-stats.title"></div>
|
||||||
|
<redaction-circle-button
|
||||||
|
(action)="toggleCollapse.emit()"
|
||||||
|
icon="red:collapse"
|
||||||
|
tooltip="user-stats.collapse"
|
||||||
|
tooltipPosition="before"
|
||||||
|
></redaction-circle-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-44">
|
||||||
|
<redaction-simple-doughnut-chart
|
||||||
|
[config]="chartData"
|
||||||
|
[strokeWidth]="15"
|
||||||
|
[radius]="63"
|
||||||
|
[subtitle]="'user-stats.chart.users'"
|
||||||
|
totalType="sum"
|
||||||
|
direction="row"
|
||||||
|
></redaction-simple-doughnut-chart>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
.header-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.heading-xl {
|
||||||
|
max-width: 88%;
|
||||||
|
}
|
||||||
|
|
||||||
|
redaction-circle-button {
|
||||||
|
position: absolute;
|
||||||
|
top: -8px;
|
||||||
|
left: 270px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-44 {
|
||||||
|
margin-top: 44px;
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
|
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'redaction-users-stats',
|
||||||
|
templateUrl: './users-stats.component.html',
|
||||||
|
styleUrls: ['./users-stats.component.scss']
|
||||||
|
})
|
||||||
|
export class UsersStatsComponent implements OnInit {
|
||||||
|
@Output() public toggleCollapse = new EventEmitter();
|
||||||
|
@Input() chartData: DoughnutChartConfig[];
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit(): void {}
|
||||||
|
}
|
||||||
@ -28,13 +28,7 @@
|
|||||||
<div class="red-input-group">
|
<div class="red-input-group">
|
||||||
<label translate="add-edit-user.form.role"></label>
|
<label translate="add-edit-user.form.role"></label>
|
||||||
<div class="roles-wrapper">
|
<div class="roles-wrapper">
|
||||||
<mat-checkbox
|
<mat-checkbox [formControlName]="role" *ngFor="let role of ROLES" color="primary">
|
||||||
*ngFor="let role of ROLES"
|
|
||||||
color="primary"
|
|
||||||
[checked]="getChecked(role)"
|
|
||||||
[disabled]="getDisabled(role)"
|
|
||||||
(change)="changeRoleValue(role, $event)"
|
|
||||||
>
|
|
||||||
{{ 'roles.' + role | translate }}
|
{{ 'roles.' + role | translate }}
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
import { User } from '@redaction/red-ui-http';
|
||||||
import { UserService } from '../../../../services/user.service';
|
import { UserService } from '../../../../services/user.service';
|
||||||
import { MatCheckboxChange } from '@angular/material/checkbox';
|
|
||||||
import { AdminDialogService } from '../../services/admin-dialog-service.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-add-edit-user-dialog',
|
selector: 'redaction-add-edit-user-dialog',
|
||||||
@ -17,19 +15,39 @@ export class AddEditUserDialogComponent {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _formBuilder: FormBuilder,
|
private readonly _formBuilder: FormBuilder,
|
||||||
private readonly _userControllerService: UserControllerService,
|
|
||||||
private readonly _userService: UserService,
|
private readonly _userService: UserService,
|
||||||
public dialogRef: MatDialogRef<AddEditUserDialogComponent>,
|
public dialogRef: MatDialogRef<AddEditUserDialogComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public user: User
|
@Inject(MAT_DIALOG_DATA) public user: User
|
||||||
) {
|
) {
|
||||||
|
const rolesControls = this.ROLES.reduce(
|
||||||
|
(prev, role) => ({
|
||||||
|
...prev,
|
||||||
|
[role]: [this.user && this.user.roles.indexOf(role) !== -1]
|
||||||
|
}),
|
||||||
|
{}
|
||||||
|
);
|
||||||
this.userForm = this._formBuilder.group({
|
this.userForm = this._formBuilder.group({
|
||||||
firstName: [this.user?.firstName, Validators.required],
|
firstName: [this.user?.firstName, Validators.required],
|
||||||
lastName: [this.user?.lastName, Validators.required],
|
lastName: [this.user?.lastName, Validators.required],
|
||||||
email: [{ value: this.user?.email, disabled: !!user }, [Validators.required, Validators.email]],
|
email: [{ value: this.user?.email, disabled: !!user }, [Validators.required, Validators.email]],
|
||||||
// password: [this.user?.password, Validators.required],
|
// password: [this.user?.password, Validators.required],
|
||||||
admin: [user && this._userService.isAdmin(user)],
|
...rolesControls
|
||||||
roles: [user?.roles || []]
|
|
||||||
});
|
});
|
||||||
|
this._setRolesRequirements();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setRolesRequirements() {
|
||||||
|
const requirements = { RED_MANAGER: 'RED_USER', RED_ADMIN: 'RED_USER_ADMIN' };
|
||||||
|
for (const key of Object.keys(requirements)) {
|
||||||
|
this.userForm.controls[key].valueChanges.subscribe((checked) => {
|
||||||
|
if (checked) {
|
||||||
|
this.userForm.patchValue({ [requirements[key]]: true });
|
||||||
|
this.userForm.controls[requirements[key]].disable();
|
||||||
|
} else {
|
||||||
|
this.userForm.controls[requirements[key]].enable();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public get changed(): boolean {
|
public get changed(): boolean {
|
||||||
@ -44,79 +62,23 @@ export class AddEditUserDialogComponent {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _updateProfile() {
|
|
||||||
const profileKeys = ['firstName', 'lastName'];
|
|
||||||
let profileChanged = false;
|
|
||||||
for (const key of profileKeys) {
|
|
||||||
if (this.userForm.get(key).value !== this.user[key]) {
|
|
||||||
profileChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!profileChanged) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await this._userControllerService.updateProfile(this.userForm.getRawValue()).toPromise();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _updateRoles() {
|
|
||||||
const newAdminValue = this.userForm.get('admin').value;
|
|
||||||
if (newAdminValue === this._userService.isAdmin(this.user)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let roles = [...this.user.roles];
|
|
||||||
if (newAdminValue) {
|
|
||||||
roles.push('RED_ADMIN');
|
|
||||||
} else {
|
|
||||||
roles = roles.filter((role) => role !== 'RED_ADMIN');
|
|
||||||
}
|
|
||||||
await this._userControllerService.addRoleToUsers(roles, this.user.userId).toPromise();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _update() {
|
|
||||||
await this._updateProfile();
|
|
||||||
await this._updateRoles();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _create() {
|
|
||||||
const roles = ['RED_USER'];
|
|
||||||
if (this.userForm.get('admin').value) {
|
|
||||||
roles.push('RED_ADMIN');
|
|
||||||
}
|
|
||||||
await this._userControllerService.createUser({ ...this.userForm.getRawValue(), roles: [] }, 'body').toPromise();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async save() {
|
public async save() {
|
||||||
if (this.user) {
|
this.dialogRef.close({
|
||||||
await this._update();
|
action: this.user ? 'UPDATE' : 'CREATE',
|
||||||
} else {
|
user: { ...this.userForm.getRawValue(), roles: this.activeRoles }
|
||||||
await this._create();
|
});
|
||||||
}
|
|
||||||
this.dialogRef.close(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async delete() {
|
public async delete() {
|
||||||
this.dialogRef.close('DELETE');
|
this.dialogRef.close('DELETE');
|
||||||
}
|
}
|
||||||
|
|
||||||
public changeRoleValue(role: string, { checked }: MatCheckboxChange) {
|
|
||||||
const roles = [...this.activeRoles];
|
|
||||||
if (checked) {
|
|
||||||
roles.push(role);
|
|
||||||
} else {
|
|
||||||
roles.splice(roles.indexOf(role), 1);
|
|
||||||
}
|
|
||||||
this.userForm.patchValue({ roles });
|
|
||||||
}
|
|
||||||
|
|
||||||
public get activeRoles(): string[] {
|
public get activeRoles(): string[] {
|
||||||
return this.userForm.get('roles').value;
|
return this.ROLES.reduce((acc, role) => {
|
||||||
|
if (this.userForm.get(role).value) {
|
||||||
|
acc.push(role);
|
||||||
}
|
}
|
||||||
|
return acc;
|
||||||
public getChecked(role: string) {
|
}, []);
|
||||||
return this.activeRoles.indexOf(role) !== -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getDisabled(role: string) {
|
|
||||||
return this.getChecked(role) && role === 'RED_USER' && this.getChecked('RED_ADMIN');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
<div class="heading" translate="confirm-delete-user.warning"></div>
|
<div class="heading" translate="confirm-delete-user.warning"></div>
|
||||||
|
|
||||||
<mat-checkbox *ngFor="let checkbox of checkboxes; let idx = index" [(ngModel)]="checkbox.value" color="primary">
|
<mat-checkbox *ngFor="let checkbox of checkboxes; let idx = index" [(ngModel)]="checkbox.value" color="primary">
|
||||||
{{ 'confirm-delete-user.checkbox-' + (idx + 1) | translate: { count: 20 } }}
|
{{ 'confirm-delete-user.checkbox-' + (idx + 1) | translate: { projectsCount: projectsCount } }}
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Component, Inject, OnInit } from '@angular/core';
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
import { User } from '@redaction/red-ui-http';
|
||||||
|
import { AppStateService } from '../../../../state/app-state.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-confirm-delete-user-dialog',
|
selector: 'redaction-confirm-delete-user-dialog',
|
||||||
@ -10,18 +11,20 @@ import { User, UserControllerService } from '@redaction/red-ui-http';
|
|||||||
export class ConfirmDeleteUserDialogComponent implements OnInit {
|
export class ConfirmDeleteUserDialogComponent implements OnInit {
|
||||||
public checkboxes = [{ value: false }, { value: false }];
|
public checkboxes = [{ value: false }, { value: false }];
|
||||||
public showToast = false;
|
public showToast = false;
|
||||||
|
public projectsCount: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(MAT_DIALOG_DATA) public user: User,
|
@Inject(MAT_DIALOG_DATA) public user: User,
|
||||||
private readonly _userControllerService: UserControllerService,
|
private readonly _appStateService: AppStateService,
|
||||||
public dialogRef: MatDialogRef<ConfirmDeleteUserDialogComponent>
|
public dialogRef: MatDialogRef<ConfirmDeleteUserDialogComponent>
|
||||||
) {}
|
) {
|
||||||
|
this.projectsCount = this._appStateService.allProjects.filter((pw) => pw.memberIds.indexOf(user.userId) !== -1).length;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {}
|
ngOnInit(): void {}
|
||||||
|
|
||||||
async deleteUser() {
|
async deleteUser() {
|
||||||
if (this.valid) {
|
if (this.valid) {
|
||||||
await this._userControllerService.deleteUser(this.user.userId).toPromise();
|
|
||||||
this.dialogRef.close(true);
|
this.dialogRef.close(true);
|
||||||
} else {
|
} else {
|
||||||
this.showToast = true;
|
this.showToast = true;
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="red-content-inner">
|
<div class="red-content-inner">
|
||||||
<div class="left-container">
|
<div class="left-container" [class.extended]="collapsedDetails">
|
||||||
<div class="header-item">
|
<div class="header-item">
|
||||||
<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 } }}
|
||||||
@ -78,7 +78,9 @@
|
|||||||
</cdk-virtual-scroll-viewport>
|
</cdk-virtual-scroll-viewport>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="right-container"></div>
|
<div class="right-container" redactionHasScrollbar [class.collapsed]="collapsedDetails">
|
||||||
|
<redaction-users-stats (toggleCollapse)="toggleCollapsedDetails()" [chartData]="chartData"></redaction-users-stats>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,15 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
width: 353px;
|
width: 353px;
|
||||||
min-width: 353px;
|
min-width: 353px;
|
||||||
|
padding: 16px 16px 16px 24px;
|
||||||
|
|
||||||
|
&.has-scrollbar:hover {
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
redaction-users-stats {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-header .actions {
|
.page-header .actions {
|
||||||
|
|||||||
@ -6,6 +6,8 @@ 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';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||||
|
import { TranslateChartService } from '../../../../services/translate-chart.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-user-listing-screen',
|
selector: 'redaction-user-listing-screen',
|
||||||
@ -14,7 +16,8 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
})
|
})
|
||||||
export class UserListingScreenComponent implements OnInit {
|
export class UserListingScreenComponent implements OnInit {
|
||||||
public viewReady = false;
|
public viewReady = false;
|
||||||
|
public collapsedDetails = false;
|
||||||
|
public chartData: DoughnutChartConfig[];
|
||||||
public users: User[];
|
public users: User[];
|
||||||
public displayedUsers: User[] = [];
|
public displayedUsers: User[] = [];
|
||||||
public searchForm: FormGroup;
|
public searchForm: FormGroup;
|
||||||
@ -25,7 +28,8 @@ export class UserListingScreenComponent implements OnInit {
|
|||||||
private readonly _formBuilder: FormBuilder,
|
private readonly _formBuilder: FormBuilder,
|
||||||
private readonly _translateService: TranslateService,
|
private readonly _translateService: TranslateService,
|
||||||
private readonly _adminDialogService: AdminDialogService,
|
private readonly _adminDialogService: AdminDialogService,
|
||||||
private readonly _userControllerService: UserControllerService
|
private readonly _userControllerService: UserControllerService,
|
||||||
|
private readonly _translateChartService: TranslateChartService
|
||||||
) {
|
) {
|
||||||
this.searchForm = this._formBuilder.group({
|
this.searchForm = this._formBuilder.group({
|
||||||
query: ['']
|
query: ['']
|
||||||
@ -46,10 +50,16 @@ export class UserListingScreenComponent implements OnInit {
|
|||||||
|
|
||||||
public openAddEditUserDialog($event: MouseEvent, user?: User) {
|
public openAddEditUserDialog($event: MouseEvent, user?: User) {
|
||||||
$event.stopPropagation();
|
$event.stopPropagation();
|
||||||
this._adminDialogService.openAddEditUserDialog(user, async (action) => {
|
this._adminDialogService.openAddEditUserDialog(user, async (result) => {
|
||||||
if (action === 'DELETE') {
|
if (result === 'DELETE') {
|
||||||
this.openDeleteUserDialog(user);
|
this.openDeleteUserDialog(user);
|
||||||
} else {
|
} else {
|
||||||
|
this.viewReady = false;
|
||||||
|
if (result.action === 'CREATE') {
|
||||||
|
await this._userControllerService.createUser(result.user).toPromise();
|
||||||
|
} else if (result.action === 'UPDATE') {
|
||||||
|
await this._userControllerService.updateProfile(result.user).toPromise();
|
||||||
|
}
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -58,6 +68,8 @@ export class UserListingScreenComponent implements OnInit {
|
|||||||
public openDeleteUserDialog(user: User, $event?: MouseEvent) {
|
public openDeleteUserDialog(user: User, $event?: MouseEvent) {
|
||||||
$event?.stopPropagation();
|
$event?.stopPropagation();
|
||||||
this._adminDialogService.openConfirmDeleteUserDialog(user, async () => {
|
this._adminDialogService.openConfirmDeleteUserDialog(user, async () => {
|
||||||
|
this.viewReady = false;
|
||||||
|
await this._userControllerService.deleteUser(user.userId).toPromise();
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -66,9 +78,47 @@ export class UserListingScreenComponent implements OnInit {
|
|||||||
this.viewReady = false;
|
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.viewReady = true;
|
this.viewReady = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _computeStats() {
|
||||||
|
this.chartData = this._translateChartService.translateRoles(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
value: this.users.filter((user) => !this.userService.isActive(user)).length,
|
||||||
|
color: 'INACTIVE',
|
||||||
|
label: 'INACTIVE'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: this.users.filter((user) => user.roles.length === 1 && user.roles[0] === 'RED_USER').length,
|
||||||
|
color: 'REGULAR',
|
||||||
|
label: 'REGULAR'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: this.users.filter((user) => this.userService.isManager(user) && !this.userService.isAdmin(user)).length,
|
||||||
|
color: 'MANAGER',
|
||||||
|
label: 'RED_MANAGER'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: this.users.filter((user) => this.userService.isManager(user) && this.userService.isAdmin(user)).length,
|
||||||
|
color: 'MANAGER_ADMIN',
|
||||||
|
label: 'MANAGER_ADMIN'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: this.users.filter((user) => this.userService.isUserAdmin(user) && !this.userService.isAdmin(user)).length,
|
||||||
|
color: 'USER_ADMIN',
|
||||||
|
label: 'RED_USER_ADMIN'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: this.users.filter((user) => this.userService.isAdmin(user) && !this.userService.isManager(user)).length,
|
||||||
|
color: 'ADMIN',
|
||||||
|
label: 'RED_ADMIN'
|
||||||
|
}
|
||||||
|
].filter((type) => type.value > 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public getDisplayRoles(user: User) {
|
public getDisplayRoles(user: User) {
|
||||||
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');
|
||||||
}
|
}
|
||||||
@ -79,4 +129,8 @@ export class UserListingScreenComponent implements OnInit {
|
|||||||
await this._userControllerService.addRoleToUsers(user.roles, user.userId).toPromise();
|
await this._userControllerService.addRoleToUsers(user.roles, user.userId).toPromise();
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public toggleCollapsedDetails() {
|
||||||
|
this.collapsedDetails = !this.collapsedDetails;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<ng-container *ngIf="appStateService.activeProject">
|
<ng-container *ngIf="appStateService.activeProject">
|
||||||
<div class="collapsed-wrapper mt-8">
|
<div class="collapsed-wrapper">
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
(action)="toggleCollapse.emit()"
|
(action)="toggleCollapse.emit()"
|
||||||
icon="red:expand"
|
icon="red:expand"
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
redaction-circle-button {
|
redaction-circle-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -5px;
|
top: -8px;
|
||||||
left: 290px;
|
left: 290px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
&:not(.column) {
|
&:not(.column) {
|
||||||
> *:not(:last-child) {
|
> *:not(:last-child) {
|
||||||
margin-right: 20px;
|
margin-right: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
.text-container {
|
.text-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@ -11,4 +11,8 @@ export class TranslateChartService {
|
|||||||
public translateStatus(config: DoughnutChartConfig[]): DoughnutChartConfig[] {
|
public translateStatus(config: DoughnutChartConfig[]): DoughnutChartConfig[] {
|
||||||
return config.map((val) => ({ ...val, label: this._translateService.instant(val.label) }));
|
return config.map((val) => ({ ...val, label: this._translateService.instant(val.label) }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public translateRoles(config: DoughnutChartConfig[]): DoughnutChartConfig[] {
|
||||||
|
return config.map((val) => ({ ...val, label: this._translateService.instant(`roles.${val.label}`).toLowerCase() }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -114,6 +114,13 @@ export class UserService {
|
|||||||
return user.roles?.indexOf('RED_USER') >= 0;
|
return user.roles?.indexOf('RED_USER') >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isUserAdmin(user?: User): boolean {
|
||||||
|
if (!user) {
|
||||||
|
user = this.user;
|
||||||
|
}
|
||||||
|
return user.roles?.indexOf('RED_USER_ADMIN') >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
isAdmin(user?: User): boolean {
|
isAdmin(user?: User): boolean {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
user = this.user;
|
user = this.user;
|
||||||
|
|||||||
@ -761,8 +761,8 @@
|
|||||||
"confirm-delete-user": {
|
"confirm-delete-user": {
|
||||||
"title": "Delete User from Workspace",
|
"title": "Delete User from Workspace",
|
||||||
"warning": "Warning: this cannot be undone!",
|
"warning": "Warning: this cannot be undone!",
|
||||||
"checkbox-1": "{{count}} projects will be impacted",
|
"checkbox-1": "{{projectsCount}} projects will be impacted",
|
||||||
"checkbox-2": "{{count}} documents waiting review will be impacted",
|
"checkbox-2": "All documents waiting review from the user will be impacted",
|
||||||
"delete": "Delete User",
|
"delete": "Delete User",
|
||||||
"cancel": "Keep User",
|
"cancel": "Keep User",
|
||||||
"toast-error": "Please confirm that you understand the ramifications of your action!"
|
"toast-error": "Please confirm that you understand the ramifications of your action!"
|
||||||
@ -807,6 +807,14 @@
|
|||||||
"cancel": "Cancel"
|
"cancel": "Cancel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"user-stats": {
|
||||||
|
"title": "Users",
|
||||||
|
"chart": {
|
||||||
|
"users": "Users in Workspace"
|
||||||
|
},
|
||||||
|
"expand": "Show Details",
|
||||||
|
"collapse": "Hide Details"
|
||||||
|
},
|
||||||
"rules-screen": {
|
"rules-screen": {
|
||||||
"error": {
|
"error": {
|
||||||
"generic": "Something went wrong... Rules update failed!"
|
"generic": "Something went wrong... Rules update failed!"
|
||||||
@ -1057,6 +1065,9 @@
|
|||||||
"RED_MANAGER": "Manager",
|
"RED_MANAGER": "Manager",
|
||||||
"RED_USER_ADMIN": "Users Admin",
|
"RED_USER_ADMIN": "Users Admin",
|
||||||
"RED_ADMIN": "Application Admin",
|
"RED_ADMIN": "Application Admin",
|
||||||
"NO_ROLE": "No role defined"
|
"NO_ROLE": "No role defined",
|
||||||
|
"INACTIVE": "Inactive",
|
||||||
|
"MANAGER_ADMIN": "Manager & Admin",
|
||||||
|
"REGULAR": "Regular"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -111,7 +111,8 @@
|
|||||||
background-color: $grey-3;
|
background-color: $grey-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.UNDER_REVIEW {
|
.UNDER_REVIEW,
|
||||||
|
.REGULAR {
|
||||||
stroke: $yellow-1;
|
stroke: $yellow-1;
|
||||||
background-color: $yellow-1;
|
background-color: $yellow-1;
|
||||||
}
|
}
|
||||||
@ -121,7 +122,8 @@
|
|||||||
background-color: $blue-4;
|
background-color: $blue-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.APPROVED {
|
.APPROVED,
|
||||||
|
.ADMIN {
|
||||||
stroke: $blue-3;
|
stroke: $blue-3;
|
||||||
background-color: $blue-3;
|
background-color: $blue-3;
|
||||||
}
|
}
|
||||||
@ -131,7 +133,8 @@
|
|||||||
background-color: $grey-1;
|
background-color: $grey-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.OCR_PROCESSING {
|
.OCR_PROCESSING,
|
||||||
|
.USER_ADMIN {
|
||||||
stroke: $green-2;
|
stroke: $green-2;
|
||||||
background-color: $green-2;
|
background-color: $green-2;
|
||||||
}
|
}
|
||||||
@ -161,6 +164,17 @@
|
|||||||
background-color: rgba(#0389ec, 0.1);
|
background-color: rgba(#0389ec, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.INACTIVE {
|
||||||
|
stroke: $grey-5;
|
||||||
|
background-color: $grey-5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MANAGER,
|
||||||
|
.MANAGER_ADMIN {
|
||||||
|
stroke: $red-1;
|
||||||
|
background-color: $red-1;
|
||||||
|
}
|
||||||
|
|
||||||
.select-oval {
|
.select-oval {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user