change base listing component
This commit is contained in:
parent
6c21b6e957
commit
bb53a1a6dc
@ -3,7 +3,7 @@
|
|||||||
<redaction-round-checkbox
|
<redaction-round-checkbox
|
||||||
(click)="toggleSelectAll()"
|
(click)="toggleSelectAll()"
|
||||||
[active]="areAllEntitiesSelected"
|
[active]="areAllEntitiesSelected"
|
||||||
[indeterminate]="areSomeEntitiesSelected && !areAllEntitiesSelected"
|
[indeterminate]="(areSomeEntitiesSelected$ | async) && !areAllEntitiesSelected"
|
||||||
></redaction-round-checkbox>
|
></redaction-round-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<span class="all-caps-label">
|
<span class="all-caps-label">
|
||||||
@ -13,22 +13,20 @@
|
|||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<ng-container *ngIf="areSomeEntitiesSelected">
|
<ng-container *ngIf="areSomeEntitiesSelected$ | async">
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
[matMenuTriggerFor]="readOnlyMenu"
|
[matMenuTriggerFor]="readOnlyMenu"
|
||||||
icon="red:read-only"
|
icon="red:read-only"
|
||||||
tooltip="file-attributes-csv-import.table-header.actions.read-only"
|
tooltip="file-attributes-csv-import.table-header.actions.read-only"
|
||||||
type="dark-bg"
|
type="dark-bg"
|
||||||
>
|
></redaction-circle-button>
|
||||||
</redaction-circle-button>
|
|
||||||
|
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
(action)="deactivateSelection()"
|
(action)="deactivateSelection()"
|
||||||
icon="red:trash"
|
icon="red:trash"
|
||||||
tooltip="file-attributes-csv-import.table-header.actions.remove-selected"
|
tooltip="file-attributes-csv-import.table-header.actions.remove-selected"
|
||||||
type="dark-bg"
|
type="dark-bg"
|
||||||
>
|
></redaction-circle-button>
|
||||||
</redaction-circle-button>
|
|
||||||
|
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
|
|
||||||
@ -92,7 +90,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<redaction-empty-state
|
<redaction-empty-state
|
||||||
*ngIf="!allEntities.length"
|
*ngIf="(allEntities$ | async)?.length === 0"
|
||||||
icon="red:attribute"
|
icon="red:attribute"
|
||||||
screen="file-attributes-csv-import"
|
screen="file-attributes-csv-import"
|
||||||
></redaction-empty-state>
|
></redaction-empty-state>
|
||||||
@ -102,7 +100,7 @@
|
|||||||
<div
|
<div
|
||||||
(mouseenter)="setHoveredColumn.emit(field.csvColumn)"
|
(mouseenter)="setHoveredColumn.emit(field.csvColumn)"
|
||||||
(mouseleave)="setHoveredColumn.emit()"
|
(mouseleave)="setHoveredColumn.emit()"
|
||||||
*cdkVirtualFor="let field of displayedEntities"
|
*cdkVirtualFor="let field of displayedEntities$ | async"
|
||||||
class="table-item"
|
class="table-item"
|
||||||
>
|
>
|
||||||
<div (click)="toggleEntitySelected($event, field)" class="selection-column">
|
<div (click)="toggleEntitySelected($event, field)" class="selection-column">
|
||||||
@ -127,23 +125,20 @@
|
|||||||
icon="red:edit"
|
icon="red:edit"
|
||||||
tooltip="file-attributes-csv-import.action.edit-name"
|
tooltip="file-attributes-csv-import.action.edit-name"
|
||||||
type="dark-bg"
|
type="dark-bg"
|
||||||
>
|
></redaction-circle-button>
|
||||||
</redaction-circle-button>
|
|
||||||
<ng-container *ngIf="field.editingName">
|
<ng-container *ngIf="field.editingName">
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
(action)="field.editingName = false; field.name = field.temporaryName"
|
(action)="field.editingName = false; field.name = field.temporaryName"
|
||||||
icon="red:check"
|
icon="red:check"
|
||||||
tooltip="file-attributes-csv-import.action.save-name"
|
tooltip="file-attributes-csv-import.action.save-name"
|
||||||
type="dark-bg"
|
type="dark-bg"
|
||||||
>
|
></redaction-circle-button>
|
||||||
</redaction-circle-button>
|
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
(action)="field.editingName = false; field.temporaryName = field.name"
|
(action)="field.editingName = false; field.temporaryName = field.name"
|
||||||
icon="red:close"
|
icon="red:close"
|
||||||
tooltip="file-attributes-csv-import.action.cancel-edit-name"
|
tooltip="file-attributes-csv-import.action.cancel-edit-name"
|
||||||
type="dark-bg"
|
type="dark-bg"
|
||||||
>
|
></redaction-circle-button>
|
||||||
</redaction-circle-button>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -174,8 +169,7 @@
|
|||||||
icon="red:trash"
|
icon="red:trash"
|
||||||
tooltip="file-attributes-csv-import.action.remove"
|
tooltip="file-attributes-csv-import.action.remove"
|
||||||
type="dark-bg"
|
type="dark-bg"
|
||||||
>
|
></redaction-circle-button>
|
||||||
</redaction-circle-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="scrollbar-placeholder"></div>
|
<div class="scrollbar-placeholder"></div>
|
||||||
|
|||||||
@ -7,13 +7,13 @@ import {
|
|||||||
Output,
|
Output,
|
||||||
SimpleChanges
|
SimpleChanges
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
|
||||||
import { Field } from '../file-attributes-csv-import-dialog.component';
|
import { Field } from '../file-attributes-csv-import-dialog.component';
|
||||||
import { FileAttributeConfig } from '@redaction/red-ui-http';
|
import { FileAttributeConfig } from '@redaction/red-ui-http';
|
||||||
import { FilterService } from '../../../../shared/services/filter.service';
|
import { FilterService } from '../../../../shared/services/filter.service';
|
||||||
import { SearchService } from '../../../../shared/services/search.service';
|
import { SearchService } from '../../../../shared/services/search.service';
|
||||||
import { ScreenStateService } from '../../../../shared/services/screen-state.service';
|
import { ScreenStateService } from '../../../../shared/services/screen-state.service';
|
||||||
import { SortingService } from '../../../../../services/sorting.service';
|
import { SortingService } from '../../../../../services/sorting.service';
|
||||||
|
import { BaseListingComponent } from '../../../../shared/base/base-listing.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-active-fields-listing',
|
selector: 'redaction-active-fields-listing',
|
||||||
@ -22,8 +22,8 @@ import { SortingService } from '../../../../../services/sorting.service';
|
|||||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||||
})
|
})
|
||||||
export class ActiveFieldsListingComponent extends BaseListingComponent<Field> implements OnChanges {
|
export class ActiveFieldsListingComponent extends BaseListingComponent<Field> implements OnChanges {
|
||||||
@Input() allEntities: Field[];
|
@Input() entities: Field[];
|
||||||
@Output() allEntitiesChange = new EventEmitter<Field[]>();
|
@Output() entitiesChange = new EventEmitter<Field[]>();
|
||||||
@Output() setHoveredColumn = new EventEmitter<string>();
|
@Output() setHoveredColumn = new EventEmitter<string>();
|
||||||
@Output() toggleFieldActive = new EventEmitter<Field>();
|
@Output() toggleFieldActive = new EventEmitter<Field>();
|
||||||
|
|
||||||
@ -33,16 +33,16 @@ export class ActiveFieldsListingComponent extends BaseListingComponent<Field> im
|
|||||||
FileAttributeConfig.TypeEnum.DATE
|
FileAttributeConfig.TypeEnum.DATE
|
||||||
];
|
];
|
||||||
|
|
||||||
protected readonly _selectionKey = 'csvColumn';
|
|
||||||
|
|
||||||
constructor(protected readonly _injector: Injector) {
|
constructor(protected readonly _injector: Injector) {
|
||||||
super(_injector);
|
super(_injector);
|
||||||
|
this._screenStateService.setIdKey('csvColumn');
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
if (changes.allEntities) {
|
if (changes.entities) {
|
||||||
this.displayedEntities = this.allEntities;
|
this._screenStateService.setEntities(this.entities);
|
||||||
this._updateSelection();
|
this._screenStateService.setDisplayedEntities(this.entities);
|
||||||
|
this._screenStateService.updateSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,13 +50,15 @@ export class ActiveFieldsListingComponent extends BaseListingComponent<Field> im
|
|||||||
this.allEntities
|
this.allEntities
|
||||||
.filter(field => this.isSelected(field))
|
.filter(field => this.isSelected(field))
|
||||||
.forEach(field => (field.primaryAttribute = false));
|
.forEach(field => (field.primaryAttribute = false));
|
||||||
this.allEntities = [...this.allEntities.filter(field => !this.isSelected(field))];
|
this._screenStateService.setEntities([
|
||||||
this.allEntitiesChange.emit(this.allEntities);
|
...this.allEntities.filter(field => !this.isSelected(field))
|
||||||
this.selectedEntitiesIds = [];
|
]);
|
||||||
|
this.entitiesChange.emit(this.allEntities);
|
||||||
|
this._screenStateService.setSelectedEntitiesIds([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
setAttributeForSelection(attribute: string, value: any) {
|
setAttributeForSelection(attribute: string, value: any) {
|
||||||
for (const csvColumn of this.selectedEntitiesIds) {
|
for (const csvColumn of this._screenStateService.selectedEntitiesIds) {
|
||||||
this.allEntities.find(f => f.csvColumn === csvColumn)[attribute] = value;
|
this.allEntities.find(f => f.csvColumn === csvColumn)[attribute] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -119,7 +119,7 @@
|
|||||||
(click)="toggleFieldActive(field)"
|
(click)="toggleFieldActive(field)"
|
||||||
(mouseenter)="setHoveredColumn(field.csvColumn)"
|
(mouseenter)="setHoveredColumn(field.csvColumn)"
|
||||||
(mouseleave)="setHoveredColumn()"
|
(mouseleave)="setHoveredColumn()"
|
||||||
*ngFor="let field of displayedEntities"
|
*ngFor="let field of displayedEntities$ | async"
|
||||||
class="csv-header-pill-wrapper"
|
class="csv-header-pill-wrapper"
|
||||||
>
|
>
|
||||||
<div [class.selected]="isActive(field)" class="csv-header-pill">
|
<div [class.selected]="isActive(field)" class="csv-header-pill">
|
||||||
@ -177,7 +177,7 @@
|
|||||||
<redaction-active-fields-listing
|
<redaction-active-fields-listing
|
||||||
(setHoveredColumn)="setHoveredColumn($event)"
|
(setHoveredColumn)="setHoveredColumn($event)"
|
||||||
(toggleFieldActive)="toggleFieldActive($event)"
|
(toggleFieldActive)="toggleFieldActive($event)"
|
||||||
[(allEntities)]="activeFields"
|
[(entities)]="activeFields"
|
||||||
></redaction-active-fields-listing>
|
></redaction-active-fields-listing>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Component, Inject, Injector } from '@angular/core';
|
import { Component, Inject, Injector } from '@angular/core';
|
||||||
import { AbstractControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
|
import { AbstractControl, FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms';
|
||||||
import { AppStateService } from '@state/app-state.service';
|
import { AppStateService } from '@state/app-state.service';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
import * as Papa from 'papaparse';
|
import * as Papa from 'papaparse';
|
||||||
@ -10,13 +10,13 @@ import {
|
|||||||
} from '@redaction/red-ui-http';
|
} from '@redaction/red-ui-http';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map, startWith } from 'rxjs/operators';
|
import { map, startWith } from 'rxjs/operators';
|
||||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
|
||||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { FilterService } from '../../../shared/services/filter.service';
|
import { FilterService } from '../../../shared/services/filter.service';
|
||||||
import { SearchService } from '../../../shared/services/search.service';
|
import { SearchService } from '../../../shared/services/search.service';
|
||||||
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
||||||
import { SortingService } from '../../../../services/sorting.service';
|
import { SortingService } from '../../../../services/sorting.service';
|
||||||
|
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||||
|
|
||||||
export interface Field {
|
export interface Field {
|
||||||
id?: string;
|
id?: string;
|
||||||
@ -55,6 +55,7 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
|
|||||||
private readonly _fileAttributesControllerService: FileAttributesControllerService,
|
private readonly _fileAttributesControllerService: FileAttributesControllerService,
|
||||||
private readonly _translateService: TranslateService,
|
private readonly _translateService: TranslateService,
|
||||||
private readonly _notificationService: NotificationService,
|
private readonly _notificationService: NotificationService,
|
||||||
|
private readonly _formBuilder: FormBuilder,
|
||||||
public dialogRef: MatDialogRef<FileAttributesCsvImportDialogComponent>,
|
public dialogRef: MatDialogRef<FileAttributesCsvImportDialogComponent>,
|
||||||
protected readonly _injector: Injector,
|
protected readonly _injector: Injector,
|
||||||
@Inject(MAT_DIALOG_DATA)
|
@Inject(MAT_DIALOG_DATA)
|
||||||
@ -102,10 +103,10 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
|
|||||||
this.parseResult.meta.fields = Object.keys(this.parseResult.data[0]);
|
this.parseResult.meta.fields = Object.keys(this.parseResult.data[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.allEntities = this.parseResult.meta.fields.map(field =>
|
this._screenStateService.setEntities(
|
||||||
this._buildAttribute(field)
|
this.parseResult.meta.fields.map(field => this._buildAttribute(field))
|
||||||
);
|
);
|
||||||
this.displayedEntities = [...this.allEntities];
|
this._screenStateService.setDisplayedEntities(this.allEntities);
|
||||||
this.activeFields = [];
|
this.activeFields = [];
|
||||||
|
|
||||||
for (const entity of this.allEntities) {
|
for (const entity of this.allEntities) {
|
||||||
@ -175,9 +176,9 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isActive(field: Field): boolean {
|
isActive(field: Field): boolean {
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
<span class="all-caps-label">
|
<span class="all-caps-label">
|
||||||
{{
|
{{
|
||||||
'default-colors-screen.table-header.title'
|
'default-colors-screen.table-header.title'
|
||||||
| translate: { length: allEntities.length }
|
| translate: { length: (allEntities$ | async).length }
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -51,7 +51,9 @@
|
|||||||
<!-- Table lines -->
|
<!-- Table lines -->
|
||||||
<div
|
<div
|
||||||
*cdkVirtualFor="
|
*cdkVirtualFor="
|
||||||
let color of allEntities | sortBy: sortingOption.order:sortingOption.column
|
let color of allEntities$
|
||||||
|
| async
|
||||||
|
| sortBy: sortingOption.order:sortingOption.column
|
||||||
"
|
"
|
||||||
class="table-item"
|
class="table-item"
|
||||||
>
|
>
|
||||||
@ -77,8 +79,7 @@
|
|||||||
icon="red:edit"
|
icon="red:edit"
|
||||||
tooltip="default-colors-screen.action.edit"
|
tooltip="default-colors-screen.action.edit"
|
||||||
type="dark-bg"
|
type="dark-bg"
|
||||||
>
|
></redaction-circle-button>
|
||||||
</redaction-circle-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="scrollbar-placeholder"></div>
|
<div class="scrollbar-placeholder"></div>
|
||||||
|
|||||||
@ -4,12 +4,12 @@ import { Colors, DictionaryControllerService } from '@redaction/red-ui-http';
|
|||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
|
||||||
import { LoadingService } from '../../../../services/loading.service';
|
import { LoadingService } from '../../../../services/loading.service';
|
||||||
import { FilterService } from '../../../shared/services/filter.service';
|
import { FilterService } from '../../../shared/services/filter.service';
|
||||||
import { SearchService } from '../../../shared/services/search.service';
|
import { SearchService } from '../../../shared/services/search.service';
|
||||||
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
||||||
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
||||||
|
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './default-colors-screen.component.html',
|
templateUrl: './default-colors-screen.component.html',
|
||||||
@ -64,10 +64,12 @@ export class DefaultColorsScreenComponent
|
|||||||
.getColors(this._appStateService.activeDossierTemplateId)
|
.getColors(this._appStateService.activeDossierTemplateId)
|
||||||
.toPromise();
|
.toPromise();
|
||||||
this._colorsObj = data;
|
this._colorsObj = data;
|
||||||
this.allEntities = Object.keys(data).map(key => ({
|
this._screenStateService.setEntities(
|
||||||
key,
|
Object.keys(data).map(key => ({
|
||||||
value: data[key]
|
key,
|
||||||
}));
|
value: data[key]
|
||||||
|
}))
|
||||||
|
);
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import { forkJoin, of } from 'rxjs';
|
|||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
|
||||||
import { TypeValueWrapper } from '../../../../models/file/type-value.wrapper';
|
import { TypeValueWrapper } from '../../../../models/file/type-value.wrapper';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { LoadingService } from '../../../../services/loading.service';
|
import { LoadingService } from '../../../../services/loading.service';
|
||||||
@ -15,7 +14,7 @@ import { FilterService } from '../../../shared/services/filter.service';
|
|||||||
import { SearchService } from '../../../shared/services/search.service';
|
import { SearchService } from '../../../shared/services/search.service';
|
||||||
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
||||||
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
||||||
import { NewBaseListingComponent } from '../../../shared/base/new-base-listing.component';
|
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||||
|
|
||||||
const toChartConfig = (dict: TypeValueWrapper): DoughnutChartConfig => ({
|
const toChartConfig = (dict: TypeValueWrapper): DoughnutChartConfig => ({
|
||||||
value: dict.entries ? dict.entries.length : 0,
|
value: dict.entries ? dict.entries.length : 0,
|
||||||
@ -30,7 +29,7 @@ const toChartConfig = (dict: TypeValueWrapper): DoughnutChartConfig => ({
|
|||||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||||
})
|
})
|
||||||
export class DictionaryListingScreenComponent
|
export class DictionaryListingScreenComponent
|
||||||
extends NewBaseListingComponent<TypeValueWrapper>
|
extends BaseListingComponent<TypeValueWrapper>
|
||||||
implements OnInit
|
implements OnInit
|
||||||
{
|
{
|
||||||
chartData: DoughnutChartConfig[] = [];
|
chartData: DoughnutChartConfig[] = [];
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { FilterService } from '../../../shared/services/filter.service';
|
|||||||
import { SearchService } from '../../../shared/services/search.service';
|
import { SearchService } from '../../../shared/services/search.service';
|
||||||
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
||||||
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
||||||
import { NewBaseListingComponent } from '../../../shared/base/new-base-listing.component';
|
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './dossier-templates-listing-screen.component.html',
|
templateUrl: './dossier-templates-listing-screen.component.html',
|
||||||
@ -19,7 +19,7 @@ import { NewBaseListingComponent } from '../../../shared/base/new-base-listing.c
|
|||||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||||
})
|
})
|
||||||
export class DossierTemplatesListingScreenComponent
|
export class DossierTemplatesListingScreenComponent
|
||||||
extends NewBaseListingComponent<DossierTemplateModelWrapper>
|
extends BaseListingComponent<DossierTemplateModelWrapper>
|
||||||
implements OnInit
|
implements OnInit
|
||||||
{
|
{
|
||||||
constructor(
|
constructor(
|
||||||
|
|||||||
@ -25,17 +25,22 @@
|
|||||||
<redaction-round-checkbox
|
<redaction-round-checkbox
|
||||||
(click)="toggleSelectAll()"
|
(click)="toggleSelectAll()"
|
||||||
[active]="areAllEntitiesSelected"
|
[active]="areAllEntitiesSelected"
|
||||||
[indeterminate]="areSomeEntitiesSelected && !areAllEntitiesSelected"
|
[indeterminate]="
|
||||||
|
(areSomeEntitiesSelected$ | async) && !areAllEntitiesSelected
|
||||||
|
"
|
||||||
></redaction-round-checkbox>
|
></redaction-round-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="all-caps-label">
|
<span class="all-caps-label">
|
||||||
{{ 'file-attributes-listing.table-header.title' | translate: { length: displayedEntities.length } }}
|
{{
|
||||||
|
'file-attributes-listing.table-header.title'
|
||||||
|
| translate: { length: (displayedEntities$ | async)?.length }
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
(click)="openConfirmDeleteAttributeDialog($event)"
|
(click)="openConfirmDeleteAttributeDialog($event)"
|
||||||
*ngIf="areSomeEntitiesSelected"
|
*ngIf="areSomeEntitiesSelected$ | async"
|
||||||
icon="red:trash"
|
icon="red:trash"
|
||||||
tooltip="file-attributes-listing.bulk-actions.delete"
|
tooltip="file-attributes-listing.bulk-actions.delete"
|
||||||
type="dark-bg"
|
type="dark-bg"
|
||||||
@ -67,7 +72,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div [class.no-data]="!allEntities.length" class="table-header" redactionSyncWidth="table-item">
|
<div
|
||||||
|
[class.no-data]="(allEntities$ | async)?.length === 0"
|
||||||
|
class="table-header"
|
||||||
|
redactionSyncWidth="table-item"
|
||||||
|
>
|
||||||
<div class="select-oval-placeholder"></div>
|
<div class="select-oval-placeholder"></div>
|
||||||
|
|
||||||
<redaction-table-col-name
|
<redaction-table-col-name
|
||||||
@ -110,13 +119,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<redaction-empty-state
|
<redaction-empty-state
|
||||||
*ngIf="!allEntities.length"
|
*ngIf="(allEntities$ | async)?.length === 0"
|
||||||
icon="red:attribute"
|
icon="red:attribute"
|
||||||
screen="file-attributes-listing"
|
screen="file-attributes-listing"
|
||||||
></redaction-empty-state>
|
></redaction-empty-state>
|
||||||
|
|
||||||
<redaction-empty-state
|
<redaction-empty-state
|
||||||
*ngIf="allEntities.length && !displayedEntities.length"
|
*ngIf="(allEntities$ | async)?.length && (displayedEntities$ | async)?.length === 0"
|
||||||
screen="file-attributes-listing"
|
screen="file-attributes-listing"
|
||||||
type="no-match"
|
type="no-match"
|
||||||
></redaction-empty-state>
|
></redaction-empty-state>
|
||||||
@ -124,7 +133,11 @@
|
|||||||
<cdk-virtual-scroll-viewport [itemSize]="80" redactionHasScrollbar>
|
<cdk-virtual-scroll-viewport [itemSize]="80" redactionHasScrollbar>
|
||||||
<!-- Table lines -->
|
<!-- Table lines -->
|
||||||
<div
|
<div
|
||||||
*cdkVirtualFor="let attribute of displayedEntities | sortBy: sortingOption.order:sortingOption.column"
|
*cdkVirtualFor="
|
||||||
|
let attribute of displayedEntities$
|
||||||
|
| async
|
||||||
|
| sortBy: sortingOption.order:sortingOption.column
|
||||||
|
"
|
||||||
class="table-item"
|
class="table-item"
|
||||||
>
|
>
|
||||||
<div (click)="toggleEntitySelected($event, attribute)" class="selection-column">
|
<div (click)="toggleEntitySelected($event, attribute)" class="selection-column">
|
||||||
|
|||||||
@ -1,26 +1,34 @@
|
|||||||
import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
Component,
|
||||||
|
ElementRef,
|
||||||
|
Injector,
|
||||||
|
OnInit,
|
||||||
|
ViewChild
|
||||||
|
} from '@angular/core';
|
||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
import { FileAttributeConfig, FileAttributesConfig, FileAttributesControllerService } from '@redaction/red-ui-http';
|
import { FileAttributeConfig, FileAttributesConfig, FileAttributesControllerService } from '@redaction/red-ui-http';
|
||||||
import { AppStateService } from '@state/app-state.service';
|
import { AppStateService } from '@state/app-state.service';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
|
||||||
import { LoadingService } from '../../../../services/loading.service';
|
import { LoadingService } from '../../../../services/loading.service';
|
||||||
import { FilterService } from '../../../shared/services/filter.service';
|
import { FilterService } from '../../../shared/services/filter.service';
|
||||||
import { SearchService } from '../../../shared/services/search.service';
|
import { SearchService } from '../../../shared/services/search.service';
|
||||||
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
||||||
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
||||||
|
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './file-attributes-listing-screen.component.html',
|
templateUrl: './file-attributes-listing-screen.component.html',
|
||||||
styleUrls: ['./file-attributes-listing-screen.component.scss'],
|
styleUrls: ['./file-attributes-listing-screen.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||||
})
|
})
|
||||||
export class FileAttributesListingScreenComponent extends BaseListingComponent<FileAttributeConfig> implements OnInit {
|
export class FileAttributesListingScreenComponent
|
||||||
protected readonly _searchKey = 'label';
|
extends BaseListingComponent<FileAttributeConfig>
|
||||||
protected readonly _selectionKey = 'id';
|
implements OnInit
|
||||||
|
{
|
||||||
private _existingConfiguration: FileAttributesConfig;
|
private _existingConfiguration: FileAttributesConfig;
|
||||||
|
|
||||||
@ViewChild('fileInput') private _fileInput: ElementRef;
|
@ViewChild('fileInput') private _fileInput: ElementRef;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -34,9 +42,9 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
|
|||||||
) {
|
) {
|
||||||
super(_injector);
|
super(_injector);
|
||||||
this._sortingService.setScreenName(ScreenNames.FILE_ATTRIBUTES_LISTING);
|
this._sortingService.setScreenName(ScreenNames.FILE_ATTRIBUTES_LISTING);
|
||||||
this._appStateService.activateDossierTemplate(
|
this._searchService.setSearchKey('label');
|
||||||
_activatedRoute.snapshot.params.dossierTemplateId
|
this._screenStateService.setIdKey('id');
|
||||||
);
|
_appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@ -67,7 +75,10 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
|
|||||||
.toPromise();
|
.toPromise();
|
||||||
} else {
|
} else {
|
||||||
await this._fileAttributesService
|
await this._fileAttributesService
|
||||||
.deleteFileAttributes(this.selectedEntitiesIds, this._appStateService.activeDossierTemplateId)
|
.deleteFileAttributes(
|
||||||
|
this._screenStateService.selectedEntitiesIds,
|
||||||
|
this._appStateService.activeDossierTemplateId
|
||||||
|
)
|
||||||
.toPromise();
|
.toPromise();
|
||||||
}
|
}
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
@ -86,9 +97,7 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
|
|||||||
dossierTemplateId: this._appStateService.activeDossierTemplateId,
|
dossierTemplateId: this._appStateService.activeDossierTemplateId,
|
||||||
existingConfiguration: this._existingConfiguration
|
existingConfiguration: this._existingConfiguration
|
||||||
},
|
},
|
||||||
async () => {
|
async () => await this._loadData()
|
||||||
await this._loadData();
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,10 +108,10 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
|
|||||||
.getFileAttributesConfiguration(this._appStateService.activeDossierTemplateId)
|
.getFileAttributesConfiguration(this._appStateService.activeDossierTemplateId)
|
||||||
.toPromise();
|
.toPromise();
|
||||||
this._existingConfiguration = response;
|
this._existingConfiguration = response;
|
||||||
this.allEntities = response?.fileAttributeConfigs || [];
|
this._screenStateService.setEntities(response?.fileAttributeConfigs || []);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
} finally {
|
} finally {
|
||||||
this._executeSearchImmediately();
|
this.filterService.filterEntities();
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -114,12 +114,6 @@
|
|||||||
>
|
>
|
||||||
{{ entity.dossierName }}
|
{{ entity.dossierName }}
|
||||||
</div>
|
</div>
|
||||||
<div class="small-label stats-subtitle">
|
|
||||||
<div>
|
|
||||||
<mat-icon svgIcon="red:template"></mat-icon>
|
|
||||||
{{ getDossierTemplate(entity.dossierTemplateId).name }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="small-label stats-subtitle">
|
<div class="small-label stats-subtitle">
|
||||||
<div>
|
<div>
|
||||||
<mat-icon svgIcon="red:user"></mat-icon>
|
<mat-icon svgIcon="red:user"></mat-icon>
|
||||||
@ -144,7 +138,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="small-label">
|
<div class="small-label">
|
||||||
{{ entity.softDeletedTime | date: 'd MMM. yyyy hh:mm' }}
|
{{ entity.softDeletedTime | date: 'd MMM. yyyy, hh:mm a' }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -30,7 +30,7 @@ redaction-table-col-name::ng-deep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
height: 90px;
|
height: 80px;
|
||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { ChangeDetectionStrategy, Component, Injector, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Injector, OnInit } from '@angular/core';
|
||||||
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 { Dossier, DossierTemplateModel } from '@redaction/red-ui-http';
|
import { Dossier, DossierTemplateModel, StatusControllerService } from '@redaction/red-ui-http';
|
||||||
import { LoadingService } from '../../../../services/loading.service';
|
import { LoadingService } from '../../../../services/loading.service';
|
||||||
import { AppConfigKey, AppConfigService } from '../../../app-config/app-config.service';
|
import { AppConfigKey, AppConfigService } from '../../../app-config/app-config.service';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
@ -9,8 +9,9 @@ import { FilterService } from '../../../shared/services/filter.service';
|
|||||||
import { SearchService } from '../../../shared/services/search.service';
|
import { SearchService } from '../../../shared/services/search.service';
|
||||||
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
||||||
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
||||||
import { NewBaseListingComponent } from '../../../shared/base/new-base-listing.component';
|
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||||
import { DossiersService } from '../../../dossier/services/dossiers.service';
|
import { DossiersService } from '../../../dossier/services/dossiers.service';
|
||||||
|
import { tap } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './trash-screen.component.html',
|
templateUrl: './trash-screen.component.html',
|
||||||
@ -18,7 +19,7 @@ import { DossiersService } from '../../../dossier/services/dossiers.service';
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
providers: [FilterService, SearchService, ScreenStateService, SortingService, DossiersService]
|
providers: [FilterService, SearchService, ScreenStateService, SortingService, DossiersService]
|
||||||
})
|
})
|
||||||
export class TrashScreenComponent extends NewBaseListingComponent<Dossier> implements OnInit {
|
export class TrashScreenComponent extends BaseListingComponent<Dossier> implements OnInit {
|
||||||
readonly itemSize = 85;
|
readonly itemSize = 85;
|
||||||
private readonly _deleteRetentionHours = this._appConfigService.getConfig(
|
private readonly _deleteRetentionHours = this._appConfigService.getConfig(
|
||||||
AppConfigKey.DELETE_RETENTION_HOURS
|
AppConfigKey.DELETE_RETENTION_HOURS
|
||||||
@ -26,6 +27,7 @@ export class TrashScreenComponent extends NewBaseListingComponent<Dossier> imple
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _appStateService: AppStateService,
|
private readonly _appStateService: AppStateService,
|
||||||
|
private readonly _statusControllerService: StatusControllerService,
|
||||||
readonly permissionsService: PermissionsService,
|
readonly permissionsService: PermissionsService,
|
||||||
protected readonly _injector: Injector,
|
protected readonly _injector: Injector,
|
||||||
private readonly _dossiersService: DossiersService,
|
private readonly _dossiersService: DossiersService,
|
||||||
@ -50,10 +52,6 @@ export class TrashScreenComponent extends NewBaseListingComponent<Dossier> imple
|
|||||||
this._screenStateService.setEntities(await this._dossiersService.getDeletedDossiers());
|
this._screenStateService.setEntities(await this._dossiersService.getDeletedDossiers());
|
||||||
}
|
}
|
||||||
|
|
||||||
getDossierTemplate(dossierTemplateId: string): DossierTemplateModel {
|
|
||||||
return this._appStateService.getDossierTemplateById(dossierTemplateId);
|
|
||||||
}
|
|
||||||
|
|
||||||
getRestoreDate(softDeletedTime: string): string {
|
getRestoreDate(softDeletedTime: string): string {
|
||||||
return moment(softDeletedTime).add(this._deleteRetentionHours, 'hours').toISOString();
|
return moment(softDeletedTime).add(this._deleteRetentionHours, 'hours').toISOString();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import { FilterService } from '../../../shared/services/filter.service';
|
|||||||
import { SearchService } from '../../../shared/services/search.service';
|
import { SearchService } from '../../../shared/services/search.service';
|
||||||
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
||||||
import { SortingService } from '../../../../services/sorting.service';
|
import { SortingService } from '../../../../services/sorting.service';
|
||||||
import { NewBaseListingComponent } from '../../../shared/base/new-base-listing.component';
|
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ import { map } from 'rxjs/operators';
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||||
})
|
})
|
||||||
export class UserListingScreenComponent extends NewBaseListingComponent<User> implements OnInit {
|
export class UserListingScreenComponent extends BaseListingComponent<User> implements OnInit {
|
||||||
collapsedDetails = false;
|
collapsedDetails = false;
|
||||||
chartData: DoughnutChartConfig[] = [];
|
chartData: DoughnutChartConfig[] = [];
|
||||||
@ViewChildren(InitialsAvatarComponent)
|
@ViewChildren(InitialsAvatarComponent)
|
||||||
|
|||||||
@ -35,7 +35,7 @@ import { ButtonConfig } from '../../../shared/components/page-header/models/butt
|
|||||||
import { FilterService } from '../../../shared/services/filter.service';
|
import { FilterService } from '../../../shared/services/filter.service';
|
||||||
import { SearchService } from '../../../shared/services/search.service';
|
import { SearchService } from '../../../shared/services/search.service';
|
||||||
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
||||||
import { NewBaseListingComponent } from '../../../shared/base/new-base-listing.component';
|
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||||
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -45,7 +45,7 @@ import { ScreenNames, SortingService } from '../../../../services/sorting.servic
|
|||||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||||
})
|
})
|
||||||
export class DossierListingScreenComponent
|
export class DossierListingScreenComponent
|
||||||
extends NewBaseListingComponent<DossierWrapper>
|
extends BaseListingComponent<DossierWrapper>
|
||||||
implements OnInit, OnDestroy, OnAttach, OnDetach
|
implements OnInit, OnDestroy, OnAttach, OnDetach
|
||||||
{
|
{
|
||||||
dossiersChartData: DoughnutChartConfig[] = [];
|
dossiersChartData: DoughnutChartConfig[] = [];
|
||||||
|
|||||||
@ -43,7 +43,7 @@ import { FilterService } from '../../../shared/services/filter.service';
|
|||||||
import { SearchService } from '../../../shared/services/search.service';
|
import { SearchService } from '../../../shared/services/search.service';
|
||||||
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
import { ScreenStateService } from '../../../shared/services/screen-state.service';
|
||||||
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
|
||||||
import { NewBaseListingComponent } from '../../../shared/base/new-base-listing.component';
|
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './dossier-overview-screen.component.html',
|
templateUrl: './dossier-overview-screen.component.html',
|
||||||
@ -51,7 +51,7 @@ import { NewBaseListingComponent } from '../../../shared/base/new-base-listing.c
|
|||||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||||
})
|
})
|
||||||
export class DossierOverviewScreenComponent
|
export class DossierOverviewScreenComponent
|
||||||
extends NewBaseListingComponent<FileStatusWrapper>
|
extends BaseListingComponent<FileStatusWrapper>
|
||||||
implements OnInit, OnDestroy, OnDetach, OnAttach
|
implements OnInit, OnDestroy, OnDetach, OnAttach
|
||||||
{
|
{
|
||||||
collapsedDetails = false;
|
collapsedDetails = false;
|
||||||
|
|||||||
@ -1,177 +1,83 @@
|
|||||||
import { ChangeDetectorRef, Component, Injector, ViewChild } from '@angular/core';
|
import { Component, Injector, ViewChild } from '@angular/core';
|
||||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
|
||||||
import { SortingOption, SortingService } from '@services/sorting.service';
|
import { SortingOption, SortingService } from '@services/sorting.service';
|
||||||
import { FilterModel } from '../components/filters/popup-filter/model/filter.model';
|
|
||||||
import { QuickFiltersComponent } from '../components/filters/quick-filters/quick-filters.component';
|
|
||||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||||
import { FilterService } from '../services/filter.service';
|
import { FilterService } from '../services/filter.service';
|
||||||
import { SearchService } from '../services/search.service';
|
import { SearchService } from '../services/search.service';
|
||||||
import { ScreenStateService } from '../services/screen-state.service';
|
import { ScreenStateService } from '../services/screen-state.service';
|
||||||
import { getFilteredEntities } from '../components/filters/popup-filter/utils/filter-utils';
|
import { Observable } from 'rxjs';
|
||||||
import { debounce } from '../../../utils/debounce';
|
import { FilterModel } from '../components/filters/popup-filter/model/filter.model';
|
||||||
import { FilterWrapper } from '../components/filters/popup-filter/model/filter-wrapper.model';
|
|
||||||
|
|
||||||
// Functionalities: Filter, search, select, sort
|
|
||||||
|
|
||||||
// Usage: overwrite necessary methods/members in your component
|
|
||||||
|
|
||||||
@Component({ template: '' })
|
@Component({ template: '' })
|
||||||
export abstract class BaseListingComponent<T = any> {
|
export abstract class BaseListingComponent<T> {
|
||||||
allEntities: T[] = [];
|
@ViewChild(CdkVirtualScrollViewport)
|
||||||
filteredEntities: T[] = [];
|
readonly scrollViewport: CdkVirtualScrollViewport;
|
||||||
displayedEntities: T[] = [];
|
|
||||||
selectedEntitiesIds: string[] = [];
|
|
||||||
searchForm: FormGroup;
|
|
||||||
showResetFilters = false;
|
|
||||||
@ViewChild(CdkVirtualScrollViewport) scrollViewport: CdkVirtualScrollViewport;
|
|
||||||
|
|
||||||
protected readonly _formBuilder: FormBuilder;
|
readonly filterService: FilterService<T>;
|
||||||
protected readonly _changeDetectorRef: ChangeDetectorRef;
|
|
||||||
protected readonly _sortingService: SortingService;
|
protected readonly _sortingService: SortingService;
|
||||||
protected readonly _filterService: FilterService<T>;
|
|
||||||
protected readonly _searchService: SearchService<T>;
|
protected readonly _searchService: SearchService<T>;
|
||||||
protected readonly _screenStateService: ScreenStateService<T>;
|
protected readonly _screenStateService: ScreenStateService<T>;
|
||||||
|
|
||||||
// ----
|
|
||||||
// Overwrite in child class:
|
|
||||||
protected readonly _searchKey: string;
|
|
||||||
protected readonly _selectionKey: string;
|
|
||||||
// Overwrite this in ngOnInit
|
|
||||||
@ViewChild(QuickFiltersComponent)
|
|
||||||
protected _quickFilters: QuickFiltersComponent<T>;
|
|
||||||
|
|
||||||
private _searchValue = '';
|
|
||||||
|
|
||||||
protected constructor(protected readonly _injector: Injector) {
|
protected constructor(protected readonly _injector: Injector) {
|
||||||
this._formBuilder = this._injector.get<FormBuilder>(FormBuilder);
|
this.filterService = this._injector.get<FilterService<T>>(FilterService);
|
||||||
this._changeDetectorRef = this._injector.get<ChangeDetectorRef>(ChangeDetectorRef);
|
|
||||||
this._sortingService = this._injector.get<SortingService>(SortingService);
|
this._sortingService = this._injector.get<SortingService>(SortingService);
|
||||||
this._filterService = this._injector.get<FilterService<T>>(FilterService);
|
|
||||||
this._searchService = this._injector.get<SearchService<T>>(SearchService);
|
this._searchService = this._injector.get<SearchService<T>>(SearchService);
|
||||||
this._screenStateService = this._injector.get<ScreenStateService<T>>(ScreenStateService);
|
this._screenStateService = this._injector.get<ScreenStateService<T>>(ScreenStateService);
|
||||||
}
|
}
|
||||||
|
|
||||||
get areAllEntitiesSelected() {
|
get selectedEntitiesIds$(): Observable<string[]> {
|
||||||
return (
|
return this._screenStateService.selectedEntitiesIds$;
|
||||||
this.displayedEntities.length !== 0 &&
|
|
||||||
this.selectedEntitiesIds.length === this.displayedEntities.length
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get areSomeEntitiesSelected() {
|
get displayedEntities$(): Observable<T[]> {
|
||||||
return this.selectedEntitiesIds.length > 0;
|
return this._screenStateService.displayedEntities$;
|
||||||
|
}
|
||||||
|
|
||||||
|
get allEntities$(): Observable<T[]> {
|
||||||
|
return this._screenStateService.entities$;
|
||||||
|
}
|
||||||
|
|
||||||
|
get allEntities(): T[] {
|
||||||
|
return this._screenStateService.entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
get areAllEntitiesSelected() {
|
||||||
|
return this._screenStateService.areAllEntitiesSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
get areSomeEntitiesSelected$() {
|
||||||
|
return this._screenStateService.areSomeEntitiesSelected$;
|
||||||
}
|
}
|
||||||
|
|
||||||
get sortingOption(): SortingOption {
|
get sortingOption(): SortingOption {
|
||||||
return this._sortingService.getSortingOption();
|
return this._sortingService.getSortingOption();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get _filters(): FilterWrapper[] {
|
getFilter$(slug: string): Observable<FilterModel[]> {
|
||||||
return [];
|
return this.filterService.getFilter$(slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----
|
get searchForm() {
|
||||||
|
return this._searchService.searchForm;
|
||||||
private get _getSearchKey(): string {
|
|
||||||
if (!this._searchKey) throw new Error('Not implemented');
|
|
||||||
|
|
||||||
return this._searchKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search
|
|
||||||
|
|
||||||
private get _getSelectionKey(): string {
|
|
||||||
if (!this._selectionKey) throw new Error('Not implemented');
|
|
||||||
|
|
||||||
return this._selectionKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
filtersChanged(filters?: { [key: string]: FilterModel[] } | FilterModel[]): void {
|
|
||||||
if (filters instanceof Array) this.showResetFilters = !!filters.find(f => f.checked);
|
|
||||||
else
|
|
||||||
for (const key of Object.keys(filters ?? {})) {
|
|
||||||
for (let idx = 0; idx < this[key]?.length; ++idx) {
|
|
||||||
this[key][idx] = filters[key][idx];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._filterEntities();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resetFilters() {
|
resetFilters() {
|
||||||
this.showResetFilters = false;
|
this.filterService.reset();
|
||||||
this.filtersChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter
|
|
||||||
toggleEntitySelected($event: MouseEvent, entity: T) {
|
|
||||||
$event.stopPropagation();
|
|
||||||
const idx = this.selectedEntitiesIds.indexOf(entity[this._getSelectionKey]);
|
|
||||||
if (idx === -1) {
|
|
||||||
this.selectedEntitiesIds.push(entity[this._getSelectionKey]);
|
|
||||||
} else {
|
|
||||||
this.selectedEntitiesIds.splice(idx, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleSelectAll() {
|
|
||||||
if (this.areSomeEntitiesSelected) {
|
|
||||||
this.selectedEntitiesIds = [];
|
|
||||||
} else {
|
|
||||||
this.selectedEntitiesIds = this.displayedEntities.map(
|
|
||||||
entity => entity[this._getSelectionKey]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isSelected(entity: T) {
|
|
||||||
return this.selectedEntitiesIds.indexOf(entity[this._getSelectionKey]) !== -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSort($event) {
|
toggleSort($event) {
|
||||||
this._sortingService.toggleSort($event);
|
this._sortingService.toggleSort($event);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selection
|
toggleSelectAll() {
|
||||||
|
return this._screenStateService.toggleSelectAll();
|
||||||
protected _preFilter() {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _searchField(entity: T): string {
|
toggleEntitySelected(event: MouseEvent, entity: T) {
|
||||||
return entity[this._getSearchKey];
|
event.stopPropagation();
|
||||||
|
return this._screenStateService.toggleEntitySelected(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@debounce(200)
|
isSelected(entity: T) {
|
||||||
executeSearch(value: string) {
|
return this._screenStateService.isSelected(entity);
|
||||||
this._searchValue = value;
|
|
||||||
this._executeSearchImmediately();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _executeSearchImmediately() {
|
|
||||||
this.displayedEntities = (
|
|
||||||
this._filters.length ? this.filteredEntities : this.allEntities
|
|
||||||
).filter(entity =>
|
|
||||||
this._searchField(entity).toLowerCase().includes(this._searchValue.toLowerCase())
|
|
||||||
);
|
|
||||||
|
|
||||||
this._updateSelection();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _updateSelection() {
|
|
||||||
if (this._selectionKey) {
|
|
||||||
this.selectedEntitiesIds = this.displayedEntities
|
|
||||||
.map(entity => entity[this._getSelectionKey])
|
|
||||||
.filter(id => this.selectedEntitiesIds.includes(id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort
|
|
||||||
|
|
||||||
protected _filterEntities() {
|
|
||||||
this._preFilter();
|
|
||||||
this.filteredEntities = getFilteredEntities(this.allEntities, this._filters);
|
|
||||||
this.executeSearch(this._searchValue);
|
|
||||||
this._changeDetectorRef.detectChanges();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,83 +0,0 @@
|
|||||||
import { Component, Injector, ViewChild } from '@angular/core';
|
|
||||||
import { SortingOption, SortingService } from '@services/sorting.service';
|
|
||||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
|
||||||
import { FilterService } from '../services/filter.service';
|
|
||||||
import { SearchService } from '../services/search.service';
|
|
||||||
import { ScreenStateService } from '../services/screen-state.service';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { FilterModel } from '../components/filters/popup-filter/model/filter.model';
|
|
||||||
|
|
||||||
@Component({ template: '' })
|
|
||||||
export abstract class NewBaseListingComponent<T> {
|
|
||||||
@ViewChild(CdkVirtualScrollViewport)
|
|
||||||
readonly scrollViewport: CdkVirtualScrollViewport;
|
|
||||||
|
|
||||||
readonly filterService: FilterService<T>;
|
|
||||||
protected readonly _sortingService: SortingService;
|
|
||||||
protected readonly _searchService: SearchService<T>;
|
|
||||||
protected readonly _screenStateService: ScreenStateService<T>;
|
|
||||||
|
|
||||||
protected constructor(protected readonly _injector: Injector) {
|
|
||||||
this.filterService = this._injector.get<FilterService<T>>(FilterService);
|
|
||||||
this._sortingService = this._injector.get<SortingService>(SortingService);
|
|
||||||
this._searchService = this._injector.get<SearchService<T>>(SearchService);
|
|
||||||
this._screenStateService = this._injector.get<ScreenStateService<T>>(ScreenStateService);
|
|
||||||
}
|
|
||||||
|
|
||||||
get selectedEntitiesIds$(): Observable<string[]> {
|
|
||||||
return this._screenStateService.selectedEntitiesIds$;
|
|
||||||
}
|
|
||||||
|
|
||||||
get displayedEntities$(): Observable<T[]> {
|
|
||||||
return this._screenStateService.displayedEntities$;
|
|
||||||
}
|
|
||||||
|
|
||||||
get allEntities$(): Observable<T[]> {
|
|
||||||
return this._screenStateService.entities$;
|
|
||||||
}
|
|
||||||
|
|
||||||
get allEntities(): T[] {
|
|
||||||
return this._screenStateService.entities;
|
|
||||||
}
|
|
||||||
|
|
||||||
get areAllEntitiesSelected() {
|
|
||||||
return this._screenStateService.areAllEntitiesSelected;
|
|
||||||
}
|
|
||||||
|
|
||||||
get areSomeEntitiesSelected$() {
|
|
||||||
return this._screenStateService.areSomeEntitiesSelected$;
|
|
||||||
}
|
|
||||||
|
|
||||||
get sortingOption(): SortingOption {
|
|
||||||
return this._sortingService.getSortingOption();
|
|
||||||
}
|
|
||||||
|
|
||||||
getFilter$(slug: string): Observable<FilterModel[]> {
|
|
||||||
return this.filterService.getFilter$(slug);
|
|
||||||
}
|
|
||||||
|
|
||||||
get searchForm() {
|
|
||||||
return this._searchService.searchForm;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetFilters() {
|
|
||||||
this.filterService.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleSort($event) {
|
|
||||||
this._sortingService.toggleSort($event);
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleSelectAll() {
|
|
||||||
return this._screenStateService.toggleSelectAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleEntitySelected(event: MouseEvent, entity: T) {
|
|
||||||
event.stopPropagation();
|
|
||||||
return this._screenStateService.toggleEntitySelected(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
isSelected(entity: T) {
|
|
||||||
return this._screenStateService.isSelected(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user