RED-2544: User management filters

This commit is contained in:
Adina Țeudan 2021-10-22 13:39:12 +03:00
parent fa3125302f
commit b95410f6fd
5 changed files with 58 additions and 44 deletions

View File

@ -25,6 +25,7 @@
[strokeWidth]="15"
[subtitle]="'user-stats.chart.users' | translate"
direction="row"
filterKey="roleFilters"
totalType="sum"
></redaction-simple-doughnut-chart>
</div>

View File

@ -11,6 +11,7 @@ import {
IconButtonTypes,
ListingComponent,
LoadingService,
NestedFilter,
TableColumnConfig,
} from '@iqser/common-ui';
import { Observable } from 'rxjs';
@ -18,6 +19,7 @@ import { map } from 'rxjs/operators';
import { rolesTranslations } from '../../../../translations/roles-translations';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { User } from '@red/domain';
import { userTypeChecker, userTypeFilters, UserTypes } from '../../../../utils';
@Component({
templateUrl: './user-listing-screen.component.html',
@ -110,38 +112,30 @@ export class UserListingScreenComponent extends ListingComponent<User> implement
private _computeStats() {
this.chartData = this._translateChartService.translateRoles(
[
{
value: this.allEntities.filter(user => !user.isActive).length,
color: 'INACTIVE',
label: 'INACTIVE',
},
{
value: this.allEntities.filter(user => user.roles.length === 1 && user.roles[0] === 'RED_USER').length,
color: 'REGULAR',
label: 'REGULAR',
},
{
value: this.allEntities.filter(user => user.isManager && !user.isAdmin).length,
color: 'MANAGER',
label: 'RED_MANAGER',
},
{
value: this.allEntities.filter(user => user.isManager && user.isAdmin).length,
color: 'MANAGER_ADMIN',
label: 'MANAGER_ADMIN',
},
{
value: this.allEntities.filter(user => user.isUserAdmin && !user.isAdmin).length,
color: 'USER_ADMIN',
label: 'RED_USER_ADMIN',
},
{
value: this.allEntities.filter(user => user.isAdmin && !user.isManager).length,
color: 'ADMIN',
label: 'RED_ADMIN',
},
].filter(type => type.value > 0),
UserTypes.map(type => ({
value: this.allEntities.filter(userTypeFilters[type]).length,
color: type.replace('RED_', ''),
label: type,
key: type,
})).filter(type => type.value > 0),
);
this._computeAllFilters();
}
private _computeAllFilters() {
const roleFilters = this.chartData.map(
config =>
new NestedFilter({
id: config.key,
label: config.label,
}),
);
this.filterService.addFilterGroup({
slug: 'roleFilters',
filters: roleFilters,
checker: userTypeChecker,
});
}
}

View File

@ -1,6 +1,6 @@
import { Component, Input, OnChanges } from '@angular/core';
import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { Color } from '@utils/types';
import { FilterService } from '@iqser/common-ui';
import { FilterService, INestedFilter } from '@iqser/common-ui';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
@ -12,14 +12,12 @@ export interface DoughnutChartConfig {
active?: boolean;
}
const FILTER_KEY = 'statusFilters';
@Component({
selector: 'redaction-simple-doughnut-chart',
templateUrl: './simple-doughnut-chart.component.html',
styleUrls: ['./simple-doughnut-chart.component.scss'],
})
export class SimpleDoughnutChartComponent implements OnChanges {
export class SimpleDoughnutChartComponent implements OnChanges, OnInit {
@Input() subtitle: string;
@Input() config: DoughnutChartConfig[] = [];
@Input() radius = 85;
@ -27,7 +25,8 @@ export class SimpleDoughnutChartComponent implements OnChanges {
@Input() direction: 'row' | 'column' = 'column';
@Input() totalType: 'sum' | 'count' = 'sum';
@Input() counterText: string;
readonly filtersEnabled: boolean;
@Input() filterKey = 'statusFilters';
filtersEnabled: boolean;
chartData: any[] = [];
perimeter: number;
@ -35,10 +34,12 @@ export class SimpleDoughnutChartComponent implements OnChanges {
cy = 0;
size = 0;
readonly statusFilters$ = this.filterService.getFilterModels$(FILTER_KEY) ?? of([]);
filters$: Observable<INestedFilter[]>;
constructor(readonly filterService: FilterService) {
this.filtersEnabled = !!this.filterService.filterGroups.find(g => g.slug === FILTER_KEY);
this.filterService.filterGroups$.subscribe(() => {
this.filtersEnabled = !!this.filterService.filterGroups.find(g => g.slug === this.filterKey);
});
}
get circumference(): number {
@ -53,6 +54,10 @@ export class SimpleDoughnutChartComponent implements OnChanges {
return this.totalType === 'sum' ? this.dataTotal : this.config.length;
}
ngOnInit() {
this.filters$ = this.filterService.getFilterModels$(this.filterKey) ?? of([]);
}
ngOnChanges(): void {
this.calculateChartData();
this.cx = this.radius + this.strokeWidth / 2;
@ -61,7 +66,7 @@ export class SimpleDoughnutChartComponent implements OnChanges {
}
filterChecked$(key: string): Observable<boolean> {
return this.statusFilters$.pipe(map(all => all?.find(e => e.id === key)?.checked));
return this.filters$.pipe(map(all => all?.find(e => e.id === key)?.checked));
}
calculateChartData() {
@ -96,7 +101,7 @@ export class SimpleDoughnutChartComponent implements OnChanges {
selectValue(key: string): void {
if (this.filtersEnabled) {
this.filterService.toggleFilter(FILTER_KEY, key);
this.filterService.toggleFilter(this.filterKey, key);
}
}
}

View File

@ -1,5 +1,5 @@
import { File } from '@models/file/file';
import { Dossier } from '@red/domain';
import { Dossier, User } from '@red/domain';
import { handleCheckedValue, INestedFilter } from '@iqser/common-ui';
export function handleFilterDelta(oldFilters: INestedFilter[], newFilters: INestedFilter[], allFilters: INestedFilter[]) {
@ -85,3 +85,17 @@ export const dossierMemberChecker = (dw: Dossier, filter: INestedFilter) => dw.h
export const dossierTemplateChecker = (dw: Dossier, filter: INestedFilter) => dw.dossierTemplateId === filter.id;
export const dossierApproverChecker = (dw: Dossier, filter: INestedFilter) => dw.approverIds.includes(filter.id);
export const UserTypes = ['INACTIVE', 'REGULAR', 'RED_MANAGER', 'MANAGER_ADMIN', 'RED_USER_ADMIN', 'RED_ADMIN'] as const;
export type UserType = typeof UserTypes[number];
export const userTypeFilters: { [key in UserType]: (user: User) => boolean } = {
INACTIVE: (user: User) => !user.isActive,
REGULAR: (user: User) => user.roles.length === 1 && user.roles[0] === 'RED_USER',
RED_MANAGER: (user: User) => user.isManager && !user.isAdmin,
MANAGER_ADMIN: (user: User) => user.isManager && user.isAdmin,
RED_USER_ADMIN: (user: User) => user.isUserAdmin && !user.isAdmin,
RED_ADMIN: (user: User) => user.isAdmin && !user.isManager,
};
export const userTypeChecker = (user: User, filter: INestedFilter) => userTypeFilters[filter.id](user);

View File

@ -23,7 +23,7 @@ export class User implements IUser, IListable {
this.firstName = user.firstName;
this.lastName = user.lastName;
this.name = this.firstName && this.lastName ? `${this.firstName} ${this.lastName}` : this.username;
this.searchKey = `${this.name}${this.username}${this.email}`;
this.searchKey = `${this.name || '-'}${this.username || '-'}${this.email || ''}`;
}
hasRole(role: string): boolean {