Sorting logic, added for rulesets listing
This commit is contained in:
parent
c7d76e3141
commit
7951e2e2cf
@ -30,13 +30,13 @@
|
|||||||
<div class="select-all-container">
|
<div class="select-all-container">
|
||||||
<div
|
<div
|
||||||
(click)="toggleSelectAll()"
|
(click)="toggleSelectAll()"
|
||||||
[class.active]="areAllRuleSetsSelected"
|
[class.active]="areAllEntitiesSelected"
|
||||||
class="select-oval always-visible"
|
class="select-oval always-visible"
|
||||||
*ngIf="!areAllRuleSetsSelected && !areSomeRuleSetsSelected"
|
*ngIf="!areAllEntitiesSelected && !areSomeEntitiesSelected"
|
||||||
></div>
|
></div>
|
||||||
<mat-icon *ngIf="areAllRuleSetsSelected" (click)="toggleSelectAll()" class="selection-icon active" svgIcon="red:radio-selected"></mat-icon>
|
<mat-icon *ngIf="areAllEntitiesSelected" (click)="toggleSelectAll()" class="selection-icon active" svgIcon="red:radio-selected"></mat-icon>
|
||||||
<mat-icon
|
<mat-icon
|
||||||
*ngIf="areSomeRuleSetsSelected && !areAllRuleSetsSelected"
|
*ngIf="areSomeEntitiesSelected && !areAllEntitiesSelected"
|
||||||
(click)="toggleSelectAll()"
|
(click)="toggleSelectAll()"
|
||||||
class="selection-icon"
|
class="selection-icon"
|
||||||
svgIcon="red:radio-indeterminate"
|
svgIcon="red:radio-indeterminate"
|
||||||
@ -44,11 +44,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="all-caps-label">
|
<span class="all-caps-label">
|
||||||
{{ 'project-templates-listing.table-header.title' | translate: { length: displayedRuleSets.length } }}
|
{{ 'project-templates-listing.table-header.title' | translate: { length: displayedEntities.length } }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-header" redactionSyncWidth="table-item" [class.no-data]="!ruleSets.length">
|
<div class="table-header" redactionSyncWidth="table-item" [class.no-data]="!allEntities.length">
|
||||||
<div class="select-oval-placeholder"></div>
|
<div class="select-oval-placeholder"></div>
|
||||||
|
|
||||||
<redaction-table-col-name
|
<redaction-table-col-name
|
||||||
@ -76,10 +76,10 @@
|
|||||||
<div class="scrollbar-placeholder"></div>
|
<div class="scrollbar-placeholder"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<redaction-empty-state *ngIf="!ruleSets.length" icon="red:template" screen="project-templates-listing"></redaction-empty-state>
|
<redaction-empty-state *ngIf="!allEntities.length" icon="red:template" screen="project-templates-listing"></redaction-empty-state>
|
||||||
|
|
||||||
<redaction-empty-state
|
<redaction-empty-state
|
||||||
*ngIf="ruleSets.length && !displayedRuleSets.length"
|
*ngIf="allEntities.length && !displayedEntities.length"
|
||||||
screen="project-templates-listing"
|
screen="project-templates-listing"
|
||||||
type="no-match"
|
type="no-match"
|
||||||
></redaction-empty-state>
|
></redaction-empty-state>
|
||||||
@ -87,12 +87,12 @@
|
|||||||
<cdk-virtual-scroll-viewport [itemSize]="100" redactionHasScrollbar>
|
<cdk-virtual-scroll-viewport [itemSize]="100" redactionHasScrollbar>
|
||||||
<div
|
<div
|
||||||
class="table-item pointer"
|
class="table-item pointer"
|
||||||
*cdkVirtualFor="let ruleSet of displayedRuleSets | sortBy: sortingOption.order:sortingOption.column"
|
*cdkVirtualFor="let ruleSet of displayedEntities | sortBy: sortingOption.order:sortingOption.column"
|
||||||
[routerLink]="[ruleSet.ruleSetId, 'dictionaries']"
|
[routerLink]="[ruleSet.ruleSetId, 'dictionaries']"
|
||||||
>
|
>
|
||||||
<div class="pr-0" (click)="toggleTemplateSelected($event, ruleSet)">
|
<div class="pr-0" (click)="toggleEntitySelected($event, ruleSet)">
|
||||||
<div *ngIf="!isRuleSetSelected(ruleSet)" class="select-oval"></div>
|
<div *ngIf="!isEntitySelected(ruleSet)" class="select-oval"></div>
|
||||||
<mat-icon class="selection-icon active" *ngIf="isRuleSetSelected(ruleSet)" svgIcon="red:radio-selected"></mat-icon>
|
<mat-icon class="selection-icon active" *ngIf="isEntitySelected(ruleSet)" svgIcon="red:radio-selected"></mat-icon>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -1,57 +1,43 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, Injector, OnInit } from '@angular/core';
|
||||||
import { SortingOption, SortingService } from '../../../../services/sorting.service';
|
|
||||||
import { AppStateService } from '../../../../state/app-state.service';
|
import { AppStateService } from '../../../../state/app-state.service';
|
||||||
import { PermissionsService } from '../../../../services/permissions.service';
|
import { PermissionsService } from '../../../../services/permissions.service';
|
||||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
|
||||||
import { debounce } from '../../../../utils/debounce';
|
|
||||||
import { RuleSetModel } from '@redaction/red-ui-http';
|
|
||||||
import { UserPreferenceService } from '../../../../services/user-preference.service';
|
import { UserPreferenceService } from '../../../../services/user-preference.service';
|
||||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||||
|
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-rule-sets-listing-screen',
|
selector: 'redaction-rule-sets-listing-screen',
|
||||||
templateUrl: './rule-sets-listing-screen.component.html',
|
templateUrl: './rule-sets-listing-screen.component.html',
|
||||||
styleUrls: ['./rule-sets-listing-screen.component.scss']
|
styleUrls: ['./rule-sets-listing-screen.component.scss']
|
||||||
})
|
})
|
||||||
export class RuleSetsListingScreenComponent implements OnInit {
|
export class RuleSetsListingScreenComponent extends BaseListingComponent implements OnInit {
|
||||||
public ruleSets: RuleSetModel[];
|
protected readonly _searchKey = 'name';
|
||||||
public displayedRuleSets: RuleSetModel[];
|
protected readonly _selectionKey = 'ruleSetId';
|
||||||
public selectedRuleSetIds: string[] = [];
|
protected readonly _sortKey = 'rule-sets-listing';
|
||||||
public searchForm: FormGroup;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _dialogService: AdminDialogService,
|
private readonly _dialogService: AdminDialogService,
|
||||||
private readonly _sortingService: SortingService,
|
|
||||||
private readonly _formBuilder: FormBuilder,
|
|
||||||
private readonly _appStateService: AppStateService,
|
private readonly _appStateService: AppStateService,
|
||||||
public readonly permissionsService: PermissionsService,
|
public readonly permissionsService: PermissionsService,
|
||||||
public readonly userPreferenceService: UserPreferenceService
|
public readonly userPreferenceService: UserPreferenceService,
|
||||||
|
protected readonly _injector: Injector
|
||||||
) {
|
) {
|
||||||
this.searchForm = this._formBuilder.group({
|
super(_injector);
|
||||||
query: ['']
|
|
||||||
});
|
|
||||||
|
|
||||||
this.searchForm.valueChanges.subscribe((value) => this._executeSearch(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loadRuleSetsData();
|
this.loadRuleSetsData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@debounce(200)
|
|
||||||
private _executeSearch(value: { query: string }) {
|
|
||||||
this.displayedRuleSets = this.ruleSets.filter((pt) => pt.name.toLowerCase().includes(value.query.toLowerCase()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public loadRuleSetsData() {
|
public loadRuleSetsData() {
|
||||||
this._appStateService.reset();
|
this._appStateService.reset();
|
||||||
this.ruleSets = this._appStateService.ruleSets;
|
this.allEntities = this._appStateService.ruleSets;
|
||||||
this.displayedRuleSets = [...this.ruleSets];
|
this._executeSearch();
|
||||||
this._loadRuleSetStats();
|
this._loadRuleSetStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _loadRuleSetStats() {
|
private _loadRuleSetStats() {
|
||||||
this.ruleSets.forEach((rs) => {
|
this.allEntities.forEach((rs) => {
|
||||||
const dictionaries = this._appStateService.dictionaryData[rs.ruleSetId];
|
const dictionaries = this._appStateService.dictionaryData[rs.ruleSetId];
|
||||||
if (dictionaries) {
|
if (dictionaries) {
|
||||||
rs.dictionariesCount = Object.keys(dictionaries)
|
rs.dictionariesCount = Object.keys(dictionaries)
|
||||||
@ -64,45 +50,7 @@ export class RuleSetsListingScreenComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public get sortingOption(): SortingOption {
|
public openAddRuleSetDialog() {
|
||||||
return this._sortingService.getSortingOption('rule-sets-listing');
|
|
||||||
}
|
|
||||||
|
|
||||||
public toggleSort($event) {
|
|
||||||
this._sortingService.toggleSort('rule-sets-listing', $event);
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleTemplateSelected($event: MouseEvent, ruleSet: RuleSetModel) {
|
|
||||||
$event.stopPropagation();
|
|
||||||
const idx = this.selectedRuleSetIds.indexOf(ruleSet.ruleSetId);
|
|
||||||
if (idx === -1) {
|
|
||||||
this.selectedRuleSetIds.push(ruleSet.ruleSetId);
|
|
||||||
} else {
|
|
||||||
this.selectedRuleSetIds.splice(idx, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public toggleSelectAll() {
|
|
||||||
if (this.areSomeRuleSetsSelected) {
|
|
||||||
this.selectedRuleSetIds = [];
|
|
||||||
} else {
|
|
||||||
this.selectedRuleSetIds = this.displayedRuleSets.map((rs) => rs.ruleSetId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public get areAllRuleSetsSelected() {
|
|
||||||
return this.displayedRuleSets.length !== 0 && this.selectedRuleSetIds.length === this.displayedRuleSets.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get areSomeRuleSetsSelected() {
|
|
||||||
return this.selectedRuleSetIds.length > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isRuleSetSelected(ruleSet: RuleSetModel) {
|
|
||||||
return this.selectedRuleSetIds.indexOf(ruleSet.ruleSetId) !== -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
openAddRuleSetDialog() {
|
|
||||||
this._dialogService.openAddEditRuleSetDialog(null, async (newRuleSet) => {
|
this._dialogService.openAddEditRuleSetDialog(null, async (newRuleSet) => {
|
||||||
if (newRuleSet) {
|
if (newRuleSet) {
|
||||||
this.loadRuleSetsData();
|
this.loadRuleSetsData();
|
||||||
|
|||||||
@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
<div class="table-header" redactionSyncWidth="table-item">
|
<div class="table-header" redactionSyncWidth="table-item">
|
||||||
<redaction-table-col-name
|
<redaction-table-col-name
|
||||||
(toggleSort)="sortingService.toggleSort('project-listing', $event)"
|
(toggleSort)="toggleSort($event)"
|
||||||
[activeSortingOption]="sortingOption"
|
[activeSortingOption]="sortingOption"
|
||||||
[withSort]="true"
|
[withSort]="true"
|
||||||
column="project.projectName"
|
column="project.projectName"
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import {
|
|||||||
ruleSetChecker
|
ruleSetChecker
|
||||||
} from '../../../shared/components/filter/utils/filter-utils';
|
} from '../../../shared/components/filter/utils/filter-utils';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { SortingOption, SortingService } from '../../../../services/sorting.service';
|
|
||||||
import { PermissionsService } from '../../../../services/permissions.service';
|
import { PermissionsService } from '../../../../services/permissions.service';
|
||||||
import { ProjectWrapper } from '../../../../state/model/project.wrapper';
|
import { ProjectWrapper } from '../../../../state/model/project.wrapper';
|
||||||
import { Subscription, timer } from 'rxjs';
|
import { Subscription, timer } from 'rxjs';
|
||||||
@ -32,6 +31,9 @@ import { BaseListingComponent } from '../../../shared/base/base-listing.componen
|
|||||||
styleUrls: ['./project-listing-screen.component.scss']
|
styleUrls: ['./project-listing-screen.component.scss']
|
||||||
})
|
})
|
||||||
export class ProjectListingScreenComponent extends BaseListingComponent<ProjectWrapper> implements OnInit, OnDestroy {
|
export class ProjectListingScreenComponent extends BaseListingComponent<ProjectWrapper> implements OnInit, OnDestroy {
|
||||||
|
protected readonly _searchKey = 'name';
|
||||||
|
protected readonly _sortKey = 'project-listing';
|
||||||
|
|
||||||
public projectsChartData: DoughnutChartConfig[] = [];
|
public projectsChartData: DoughnutChartConfig[] = [];
|
||||||
public documentsChartData: DoughnutChartConfig[] = [];
|
public documentsChartData: DoughnutChartConfig[] = [];
|
||||||
|
|
||||||
@ -62,7 +64,6 @@ export class ProjectListingScreenComponent extends BaseListingComponent<ProjectW
|
|||||||
private readonly _dialogService: ProjectsDialogService,
|
private readonly _dialogService: ProjectsDialogService,
|
||||||
private readonly _translateService: TranslateService,
|
private readonly _translateService: TranslateService,
|
||||||
private readonly _router: Router,
|
private readonly _router: Router,
|
||||||
public readonly sortingService: SortingService,
|
|
||||||
public readonly translateChartService: TranslateChartService,
|
public readonly translateChartService: TranslateChartService,
|
||||||
private readonly _fileManagementControllerService: FileManagementControllerService,
|
private readonly _fileManagementControllerService: FileManagementControllerService,
|
||||||
protected readonly _injector: Injector
|
protected readonly _injector: Injector
|
||||||
@ -95,10 +96,6 @@ export class ProjectListingScreenComponent extends BaseListingComponent<ProjectW
|
|||||||
this.allEntities = this._appStateService.allProjects;
|
this.allEntities = this._appStateService.allProjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get _searchKey() {
|
|
||||||
return 'name';
|
|
||||||
}
|
|
||||||
|
|
||||||
public get noData() {
|
public get noData() {
|
||||||
return this.allEntities.length === 0;
|
return this.allEntities.length === 0;
|
||||||
}
|
}
|
||||||
@ -132,10 +129,6 @@ export class ProjectListingScreenComponent extends BaseListingComponent<ProjectW
|
|||||||
return this.userService.user;
|
return this.userService.user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get sortingOption(): SortingOption {
|
|
||||||
return this.sortingService.getSortingOption('project-listing');
|
|
||||||
}
|
|
||||||
|
|
||||||
public get activeProjectsCount() {
|
public get activeProjectsCount() {
|
||||||
return this.allEntities.filter((p) => p.project.status === Project.StatusEnum.ACTIVE).length;
|
return this.allEntities.filter((p) => p.project.status === Project.StatusEnum.ACTIVE).length;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,6 +108,8 @@
|
|||||||
[selectedFileIds]="selectedEntitiesIds"
|
[selectedFileIds]="selectedEntitiesIds"
|
||||||
(reload)="bulkActionPerformed()"
|
(reload)="bulkActionPerformed()"
|
||||||
></redaction-project-overview-bulk-actions>
|
></redaction-project-overview-bulk-actions>
|
||||||
|
|
||||||
|
{{ selectedEntitiesIds.length }} selected
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-header" redactionSyncWidth="table-item" [class.no-data]="!allEntities.length">
|
<div class="table-header" redactionSyncWidth="table-item" [class.no-data]="!allEntities.length">
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import * as moment from 'moment';
|
|||||||
import { ProjectDetailsComponent } from '../../components/project-details/project-details.component';
|
import { ProjectDetailsComponent } from '../../components/project-details/project-details.component';
|
||||||
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
|
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
|
||||||
import { annotationFilterChecker, keyChecker, processFilters } from '../../../shared/components/filter/utils/filter-utils';
|
import { annotationFilterChecker, keyChecker, processFilters } from '../../../shared/components/filter/utils/filter-utils';
|
||||||
import { SortingOption, SortingService } from '../../../../services/sorting.service';
|
|
||||||
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 { FileManagementControllerService, FileStatus } from '@redaction/red-ui-http';
|
import { FileManagementControllerService, FileStatus } from '@redaction/red-ui-http';
|
||||||
@ -34,6 +33,10 @@ import { ProjectWrapper } from '../../../../state/model/project.wrapper';
|
|||||||
styleUrls: ['./project-overview-screen.component.scss']
|
styleUrls: ['./project-overview-screen.component.scss']
|
||||||
})
|
})
|
||||||
export class ProjectOverviewScreenComponent extends BaseListingComponent<FileStatusWrapper> implements OnInit, OnDestroy {
|
export class ProjectOverviewScreenComponent extends BaseListingComponent<FileStatusWrapper> implements OnInit, OnDestroy {
|
||||||
|
protected readonly _searchKey = 'filename';
|
||||||
|
protected readonly _selectionKey = 'fileId';
|
||||||
|
protected readonly _sortKey = 'project-overview';
|
||||||
|
|
||||||
public statusFilters: FilterModel[];
|
public statusFilters: FilterModel[];
|
||||||
public peopleFilters: FilterModel[];
|
public peopleFilters: FilterModel[];
|
||||||
public needsWorkFilters: FilterModel[];
|
public needsWorkFilters: FilterModel[];
|
||||||
@ -56,7 +59,6 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent<FileSta
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly _appStateService: AppStateService,
|
private readonly _appStateService: AppStateService,
|
||||||
public readonly userService: UserService,
|
public readonly userService: UserService,
|
||||||
private readonly _sortingService: SortingService,
|
|
||||||
public readonly permissionsService: PermissionsService,
|
public readonly permissionsService: PermissionsService,
|
||||||
private readonly _activatedRoute: ActivatedRoute,
|
private readonly _activatedRoute: ActivatedRoute,
|
||||||
private readonly _notificationService: NotificationService,
|
private readonly _notificationService: NotificationService,
|
||||||
@ -100,14 +102,6 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent<FileSta
|
|||||||
this.filesAutoUpdateTimer.unsubscribe();
|
this.filesAutoUpdateTimer.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get _searchKey() {
|
|
||||||
return 'filename';
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get _selectionKey() {
|
|
||||||
return 'fileId';
|
|
||||||
}
|
|
||||||
|
|
||||||
public get activeProject(): ProjectWrapper {
|
public get activeProject(): ProjectWrapper {
|
||||||
return this._appStateService.activeProject;
|
return this._appStateService.activeProject;
|
||||||
}
|
}
|
||||||
@ -144,14 +138,6 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent<FileSta
|
|||||||
return [FileStatus.StatusEnum.REPROCESS, FileStatus.StatusEnum.FULLREPROCESS, FileStatus.StatusEnum.PROCESSING].includes(fileStatusWrapper.status);
|
return [FileStatus.StatusEnum.REPROCESS, FileStatus.StatusEnum.FULLREPROCESS, FileStatus.StatusEnum.PROCESSING].includes(fileStatusWrapper.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get sortingOption(): SortingOption {
|
|
||||||
return this._sortingService.getSortingOption('project-overview');
|
|
||||||
}
|
|
||||||
|
|
||||||
public toggleSort($event) {
|
|
||||||
this._sortingService.toggleSort('project-overview', $event);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get filterComponents(): FilterComponent[] {
|
protected get filterComponents(): FilterComponent[] {
|
||||||
return [this._statusFilterComponent, this._peopleFilterComponent, this._needsWorkFilterComponent];
|
return [this._statusFilterComponent, this._peopleFilterComponent, this._needsWorkFilterComponent];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
import { ChangeDetectorRef, Component, Inject, Injector } from '@angular/core';
|
import { ChangeDetectorRef, Component, Injector } from '@angular/core';
|
||||||
import { FilterModel } from '../components/filter/model/filter.model';
|
import { FilterModel } from '../components/filter/model/filter.model';
|
||||||
import { getFilteredEntities } from '../components/filter/utils/filter-utils';
|
import { getFilteredEntities } from '../components/filter/utils/filter-utils';
|
||||||
import { FilterComponent } from '../components/filter/filter.component';
|
import { FilterComponent } from '../components/filter/filter.component';
|
||||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
import { debounce } from '../../../utils/debounce';
|
import { debounce } from '../../../utils/debounce';
|
||||||
|
import { ScreenName, SortingOption, SortingService } from '../../../services/sorting.service';
|
||||||
|
|
||||||
// Filter, search, select
|
// Functionalities: Filter, search, select, sort
|
||||||
|
|
||||||
|
// Usage: overwrite necessary methods/members in your component
|
||||||
|
|
||||||
@Component({ template: '' })
|
@Component({ template: '' })
|
||||||
export class BaseListingComponent<T = any> {
|
export class BaseListingComponent<T = any> {
|
||||||
@ -17,37 +20,57 @@ export class BaseListingComponent<T = any> {
|
|||||||
|
|
||||||
protected readonly _formBuilder: FormBuilder;
|
protected readonly _formBuilder: FormBuilder;
|
||||||
protected readonly _changeDetectorRef: ChangeDetectorRef;
|
protected readonly _changeDetectorRef: ChangeDetectorRef;
|
||||||
|
protected readonly _sortingService: SortingService;
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Overwrite in child class:
|
// Overwrite in child class:
|
||||||
protected get _searchKey(): string {
|
protected readonly _searchKey: string;
|
||||||
throw new Error('Not implemented.');
|
protected readonly _selectionKey: string;
|
||||||
}
|
protected readonly _sortKey: ScreenName;
|
||||||
|
|
||||||
protected get _selectionKey(): string {
|
|
||||||
throw new Error('Not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get filters(): { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[] {
|
protected get filters(): { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[] {
|
||||||
throw new Error('Not implemented.');
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected preFilter() {
|
protected preFilter() {
|
||||||
throw new Error('Not implemented.');
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get filterComponents(): FilterComponent[] {
|
protected get filterComponents(): FilterComponent[] {
|
||||||
throw new Error('Not implemented.');
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
constructor(protected readonly _injector: Injector) {
|
constructor(protected readonly _injector: Injector) {
|
||||||
this._formBuilder = this._injector.get<FormBuilder>(FormBuilder);
|
this._formBuilder = this._injector.get<FormBuilder>(FormBuilder);
|
||||||
this._changeDetectorRef = this._injector.get<ChangeDetectorRef>(ChangeDetectorRef);
|
this._changeDetectorRef = this._injector.get<ChangeDetectorRef>(ChangeDetectorRef);
|
||||||
|
this._sortingService = this._injector.get<SortingService>(SortingService);
|
||||||
this._initSearch();
|
this._initSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get searchKey(): string {
|
||||||
|
if (!this._searchKey) {
|
||||||
|
throw new Error('Not implemented.');
|
||||||
|
}
|
||||||
|
return this._searchKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get selectionKey(): string {
|
||||||
|
if (!this._selectionKey) {
|
||||||
|
throw new Error('Not implemented.');
|
||||||
|
}
|
||||||
|
return this._selectionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get sortKey(): ScreenName {
|
||||||
|
if (!this._sortKey) {
|
||||||
|
throw new Error('Not implemented.');
|
||||||
|
}
|
||||||
|
return this._sortKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search
|
||||||
|
|
||||||
private _initSearch() {
|
private _initSearch() {
|
||||||
this.searchForm = this._formBuilder.group({
|
this.searchForm = this._formBuilder.group({
|
||||||
query: ['']
|
query: ['']
|
||||||
@ -56,6 +79,16 @@ export class BaseListingComponent<T = any> {
|
|||||||
this.searchForm.valueChanges.subscribe(() => this._executeSearch());
|
this.searchForm.valueChanges.subscribe(() => this._executeSearch());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@debounce(200)
|
||||||
|
protected _executeSearch() {
|
||||||
|
this.displayedEntities = (this.filters.length ? this.filteredEntities : this.allEntities).filter((entity) =>
|
||||||
|
entity[this.searchKey].toLowerCase().includes(this.searchForm.get('query').value.toLowerCase())
|
||||||
|
);
|
||||||
|
this.selectedEntitiesIds = this.displayedEntities.map((entity) => entity[this.selectionKey]).filter((id) => this.selectedEntitiesIds.includes(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter
|
||||||
|
|
||||||
public filtersChanged(filters?: { [key: string]: FilterModel[] }): void {
|
public filtersChanged(filters?: { [key: string]: FilterModel[] }): void {
|
||||||
if (filters) {
|
if (filters) {
|
||||||
for (const key of Object.keys(filters)) {
|
for (const key of Object.keys(filters)) {
|
||||||
@ -67,15 +100,9 @@ export class BaseListingComponent<T = any> {
|
|||||||
this._filterEntities();
|
this._filterEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _filteredEntities(): T[] {
|
|
||||||
const filters = this.filters;
|
|
||||||
return getFilteredEntities(this.allEntities, filters);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _filterEntities() {
|
protected _filterEntities() {
|
||||||
this.preFilter();
|
this.preFilter();
|
||||||
this.filteredEntities = this._filteredEntities;
|
this.filteredEntities = getFilteredEntities(this.allEntities, this.filters);
|
||||||
this.selectedEntitiesIds = this.displayedEntities.map((entity) => entity[this._selectionKey]).filter((id) => this.selectedEntitiesIds.includes(id));
|
|
||||||
this._executeSearch();
|
this._executeSearch();
|
||||||
this._changeDetectorRef.detectChanges();
|
this._changeDetectorRef.detectChanges();
|
||||||
}
|
}
|
||||||
@ -92,19 +119,13 @@ export class BaseListingComponent<T = any> {
|
|||||||
return this.filterComponents.reduce((prev, component) => prev || component?.hasActiveFilters, false) || this.searchForm.get('query').value;
|
return this.filterComponents.reduce((prev, component) => prev || component?.hasActiveFilters, false) || this.searchForm.get('query').value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@debounce(200)
|
// Selection
|
||||||
protected _executeSearch() {
|
|
||||||
this.displayedEntities = this.filteredEntities.filter((entity) =>
|
|
||||||
entity[this._searchKey].toLowerCase().includes(this.searchForm.get('query').value.toLowerCase())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleEntitySelected($event: MouseEvent, entity: T) {
|
toggleEntitySelected($event: MouseEvent, entity: T) {
|
||||||
console.log({ entity, key: entity[this._selectionKey] });
|
|
||||||
$event.stopPropagation();
|
$event.stopPropagation();
|
||||||
const idx = this.selectedEntitiesIds.indexOf(entity[this._selectionKey]);
|
const idx = this.selectedEntitiesIds.indexOf(entity[this.selectionKey]);
|
||||||
if (idx === -1) {
|
if (idx === -1) {
|
||||||
this.selectedEntitiesIds.push(entity[this._selectionKey]);
|
this.selectedEntitiesIds.push(entity[this.selectionKey]);
|
||||||
} else {
|
} else {
|
||||||
this.selectedEntitiesIds.splice(idx, 1);
|
this.selectedEntitiesIds.splice(idx, 1);
|
||||||
}
|
}
|
||||||
@ -114,7 +135,7 @@ export class BaseListingComponent<T = any> {
|
|||||||
if (this.areSomeEntitiesSelected) {
|
if (this.areSomeEntitiesSelected) {
|
||||||
this.selectedEntitiesIds = [];
|
this.selectedEntitiesIds = [];
|
||||||
} else {
|
} else {
|
||||||
this.selectedEntitiesIds = this.displayedEntities.map((entity) => entity[this._selectionKey]);
|
this.selectedEntitiesIds = this.displayedEntities.map((entity) => entity[this.selectionKey]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +148,16 @@ export class BaseListingComponent<T = any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public isEntitySelected(entity: T) {
|
public isEntitySelected(entity: T) {
|
||||||
return this.selectedEntitiesIds.indexOf(entity[this._selectionKey]) !== -1;
|
return this.selectedEntitiesIds.indexOf(entity[this.selectionKey]) !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort
|
||||||
|
|
||||||
|
public get sortingOption(): SortingOption {
|
||||||
|
return this._sortingService.getSortingOption(this.sortKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleSort($event) {
|
||||||
|
this._sortingService.toggleSort(this.sortKey, $event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ export class SortingOption {
|
|||||||
column: string;
|
column: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Screen = 'project-listing' | 'project-overview' | 'dictionary-listing' | 'rule-sets-listing' | 'default-colors' | 'file-attributes-listing';
|
export type ScreenName = 'project-listing' | 'project-overview' | 'dictionary-listing' | 'rule-sets-listing' | 'default-colors' | 'file-attributes-listing';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -22,7 +22,7 @@ export class SortingService {
|
|||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
public toggleSort(screen: Screen, column: string) {
|
public toggleSort(screen: ScreenName, column: string) {
|
||||||
if (this._options[screen].column === column) {
|
if (this._options[screen].column === column) {
|
||||||
const currentOrder = this._options[screen].order;
|
const currentOrder = this._options[screen].order;
|
||||||
this._options[screen].order = currentOrder === 'asc' ? 'desc' : 'asc';
|
this._options[screen].order = currentOrder === 'asc' ? 'desc' : 'asc';
|
||||||
@ -31,7 +31,7 @@ export class SortingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSortingOption(screen: Screen) {
|
public getSortingOption(screen: ScreenName) {
|
||||||
return this._options[screen];
|
return this._options[screen];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user