move entities service to common lib

This commit is contained in:
Dan Percic 2021-08-07 16:57:23 +03:00
parent b7208a085d
commit a84cc03dae
29 changed files with 123 additions and 256 deletions

View File

@ -12,7 +12,7 @@
></redaction-table-header> ></redaction-table-header>
<redaction-empty-state <redaction-empty-state
*ngIf="screenStateService.noData$ | async" *ngIf="entitiesService.noData$ | async"
[text]="'downloads-list.no-data.title' | translate" [text]="'downloads-list.no-data.title' | translate"
icon="red:download" icon="red:download"
></redaction-empty-state> ></redaction-empty-state>
@ -74,7 +74,7 @@
<ng-template #bulkActions> <ng-template #bulkActions>
<iqser-circle-button <iqser-circle-button
(action)="deleteItems()" (action)="deleteItems()"
*ngIf="screenStateService.areSomeEntitiesSelected$ | async" *ngIf="entitiesService.areSomeSelected$ | async"
[tooltip]="'downloads-list.bulk.delete' | translate" [tooltip]="'downloads-list.bulk.delete' | translate"
icon="red:trash" icon="red:trash"
[type]="circleButtonTypes.dark" [type]="circleButtonTypes.dark"

View File

@ -41,13 +41,13 @@ export class DownloadsListScreenComponent extends BaseListingComponent<DownloadS
} }
async deleteItems(downloads?: DownloadStatusWrapper[]) { async deleteItems(downloads?: DownloadStatusWrapper[]) {
const storageIds = (downloads || this.screenStateService.selectedEntities).map(d => d.storageId); const storageIds = (downloads || this.entitiesService.selected).map(d => d.storageId);
await this._downloadControllerService.deleteDownload({ storageIds }).toPromise(); await this._downloadControllerService.deleteDownload({ storageIds }).toPromise();
await this._loadData(); await this._loadData();
} }
private async _loadData() { private async _loadData() {
await this.fileDownloadService.getDownloadStatus().toPromise(); await this.fileDownloadService.getDownloadStatus().toPromise();
this.screenStateService.setEntities(this.fileDownloadService.downloads); this.entitiesService.setEntities(this.fileDownloadService.downloads);
} }
} }

View File

@ -1,14 +1,14 @@
<div class="header-item"> <div class="header-item">
<iqser-round-checkbox <iqser-round-checkbox
(click)="toggleSelectAll()" (click)="toggleSelectAll()"
[active]="screenStateService.areAllEntitiesSelected$ | async" [active]="entitiesService.areAllSelected$ | async"
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async" [indeterminate]="entitiesService.notAllSelected$ | async"
></iqser-round-checkbox> ></iqser-round-checkbox>
<span class="all-caps-label"> <span class="all-caps-label">
{{ 'file-attributes-csv-import.table-header.title' | translate: { length: (screenStateService.allEntitiesLength$ | async) } }} {{ 'file-attributes-csv-import.table-header.title' | translate: { length: (entitiesService.allLength$ | async) } }}
</span> </span>
<ng-container *ngIf="screenStateService.areSomeEntitiesSelected$ | async"> <ng-container *ngIf="entitiesService.areSomeSelected$ | async">
<iqser-circle-button <iqser-circle-button
[matMenuTriggerFor]="readOnlyMenu" [matMenuTriggerFor]="readOnlyMenu"
[tooltip]="'file-attributes-csv-import.table-header.actions.read-only' | translate" [tooltip]="'file-attributes-csv-import.table-header.actions.read-only' | translate"
@ -76,7 +76,7 @@
</div> </div>
<redaction-empty-state <redaction-empty-state
*ngIf="screenStateService.noData$ | async" *ngIf="entitiesService.noData$ | async"
[text]="'file-attributes-csv-import.no-data.title' | translate" [text]="'file-attributes-csv-import.no-data.title' | translate"
icon="red:attribute" icon="red:attribute"
></redaction-empty-state> ></redaction-empty-state>

View File

@ -12,37 +12,40 @@ import { fileAttributeTypesTranslations } from '../../../translations/file-attri
providers: [...DefaultListingServices] providers: [...DefaultListingServices]
}) })
export class ActiveFieldsListingComponent extends BaseListingComponent<Field> implements OnChanges { export class ActiveFieldsListingComponent extends BaseListingComponent<Field> implements OnChanges {
protected readonly _primaryKey = 'csvColumn';
readonly circleButtonTypes = CircleButtonTypes; readonly circleButtonTypes = CircleButtonTypes;
readonly translations = fileAttributeTypesTranslations; readonly translations = fileAttributeTypesTranslations;
readonly typeOptions = [
FileAttributeConfig.TypeEnum.TEXT,
FileAttributeConfig.TypeEnum.NUMBER,
FileAttributeConfig.TypeEnum.DATE
] as const;
@Input() entities: Field[]; @Input() entities: Field[];
@Output() entitiesChange = 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>();
readonly typeOptions = [FileAttributeConfig.TypeEnum.TEXT, FileAttributeConfig.TypeEnum.NUMBER, FileAttributeConfig.TypeEnum.DATE];
protected readonly _primaryKey = 'csvColumn';
constructor(protected readonly _injector: Injector) { constructor(protected readonly _injector: Injector) {
super(_injector); super(_injector);
} }
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
if (changes.entities) { if (changes.entities) {
this.screenStateService.setEntities(this.entities); this.entitiesService.setEntities(this.entities);
this.screenStateService.updateSelection(); this.entitiesService.updateSelection();
} }
} }
deactivateSelection() { deactivateSelection() {
this.allEntities.filter(field => this.isSelected(field)).forEach(field => (field.primaryAttribute = false)); this.allEntities.filter(field => this.isSelected(field)).forEach(field => (field.primaryAttribute = false));
this.screenStateService.setEntities(this.allEntities.filter(field => !this.isSelected(field))); this.entitiesService.setEntities(this.allEntities.filter(field => !this.isSelected(field)));
this.entitiesChange.emit(this.allEntities); this.entitiesChange.emit(this.allEntities);
this.screenStateService.setSelectedEntities([]); this.entitiesService.setSelected([]);
} }
setAttributeForSelection(attribute: string, value: any) { setAttributeForSelection(attribute: string, value: any) {
for (const item of this.screenStateService.selectedEntities) { for (const item of this.entitiesService.selected) {
this.allEntities.find(f => f.csvColumn === item.csvColumn)[attribute] = value; this.allEntities.find(f => f.csvColumn === item.csvColumn)[attribute] = value;
} }
} }

View File

@ -93,7 +93,7 @@ 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.screenStateService.setEntities(this.parseResult.meta.fields.map(field => this._buildAttribute(field))); this.entitiesService.setEntities(this.parseResult.meta.fields.map(field => this._buildAttribute(field)));
this.activeFields = []; this.activeFields = [];
for (const entity of this.allEntities) { for (const entity of this.allEntities) {

View File

@ -22,7 +22,7 @@
<div class="content-container"> <div class="content-container">
<div class="header-item"> <div class="header-item">
<span class="all-caps-label"> <span class="all-caps-label">
{{ 'default-colors-screen.table-header.title' | translate: { length: screenStateService.allEntitiesLength$ | async } }} {{ 'default-colors-screen.table-header.title' | translate: { length: entitiesService.allLength$ | async } }}
</span> </span>
</div> </div>

View File

@ -66,7 +66,7 @@ export class DefaultColorsScreenComponent
key, key,
value: data[key] value: data[key]
})); }));
this.screenStateService.setEntities(entities); this.entitiesService.setEntities(entities);
this._loadingService.stop(); this._loadingService.stop();
} }
} }

View File

@ -23,12 +23,12 @@
<div class="header-item"> <div class="header-item">
<iqser-round-checkbox <iqser-round-checkbox
(click)="toggleSelectAll()" (click)="toggleSelectAll()"
[active]="screenStateService.areAllEntitiesSelected$ | async" [active]="entitiesService.areAllSelected$ | async"
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async" [indeterminate]="entitiesService.notAllSelected$ | async"
></iqser-round-checkbox> ></iqser-round-checkbox>
<span class="all-caps-label"> <span class="all-caps-label">
{{ 'dictionary-listing.table-header.title' | translate: { length: (screenStateService.displayedLength$ | async) } }} {{ 'dictionary-listing.table-header.title' | translate: { length: (entitiesService.displayedLength$ | async) } }}
</span> </span>
<iqser-circle-button <iqser-circle-button
@ -57,7 +57,7 @@
</div> </div>
</div> </div>
<div [class.no-data]="screenStateService.noData$ | async" class="table-header" redactionSyncWidth="table-item"> <div [class.no-data]="entitiesService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
<div class="select-oval-placeholder"></div> <div class="select-oval-placeholder"></div>
<iqser-table-column-name <iqser-table-column-name
@ -83,7 +83,7 @@
<redaction-empty-state <redaction-empty-state
(action)="openAddEditDictionaryDialog()" (action)="openAddEditDictionaryDialog()"
*ngIf="screenStateService.noData$ | async" *ngIf="entitiesService.noData$ | async"
[buttonLabel]="'dictionary-listing.no-data.action' | translate" [buttonLabel]="'dictionary-listing.no-data.action' | translate"
[showButton]="permissionsService.isAdmin()" [showButton]="permissionsService.isAdmin()"
[text]="'dictionary-listing.no-data.title' | translate" [text]="'dictionary-listing.no-data.title' | translate"
@ -156,7 +156,7 @@
<div class="right-container" redactionHasScrollbar> <div class="right-container" redactionHasScrollbar>
<redaction-simple-doughnut-chart <redaction-simple-doughnut-chart
*ngIf="(screenStateService.noData$ | async) === false" *ngIf="(entitiesService.noData$ | async) === false"
[config]="chartData" [config]="chartData"
[counterText]="'dictionary-listing.stats.charts.entries' | translate" [counterText]="'dictionary-listing.stats.charts.entries' | translate"
[radius]="82" [radius]="82"

View File

@ -52,7 +52,7 @@ export class DictionaryListingScreenComponent extends BaseListingComponent<TypeV
this._loadDictionaryData(); this._loadDictionaryData();
} }
openDeleteDictionariesDialog($event?: MouseEvent, types = this.screenStateService.selectedEntities) { openDeleteDictionariesDialog($event?: MouseEvent, types = this.entitiesService.selected) {
this._dialogService.openDialog('confirm', $event, null, async () => { this._dialogService.openDialog('confirm', $event, null, async () => {
this._loadingService.start(); this._loadingService.start();
await this._dictionaryControllerService await this._dictionaryControllerService
@ -61,7 +61,7 @@ export class DictionaryListingScreenComponent extends BaseListingComponent<TypeV
this._appStateService.activeDossierTemplateId this._appStateService.activeDossierTemplateId
) )
.toPromise(); .toPromise();
this.screenStateService.setSelectedEntities([]); this.entitiesService.setSelected([]);
await this._appStateService.loadDictionaryData(); await this._appStateService.loadDictionaryData();
this._loadDictionaryData(false); this._loadDictionaryData(false);
this._calculateData(); this._calculateData();
@ -92,13 +92,13 @@ export class DictionaryListingScreenComponent extends BaseListingComponent<TypeV
const entities = Object.values(appStateDictionaryData).filter(d => !d.virtual); const entities = Object.values(appStateDictionaryData).filter(d => !d.virtual);
if (!loadEntries) if (!loadEntries)
this.screenStateService.setEntities( this.entitiesService.setEntities(
entities.map(dict => { entities.map(dict => {
dict.entries = this.allEntities.find(d => d.type === dict.type)?.entries || []; dict.entries = this.allEntities.find(d => d.type === dict.type)?.entries || [];
return dict; return dict;
}) })
); );
else this.screenStateService.setEntities(entities); else this.entitiesService.setEntities(entities);
if (!loadEntries) return; if (!loadEntries) return;

View File

@ -20,23 +20,22 @@
<redaction-admin-side-nav type="dossierTemplates"></redaction-admin-side-nav> <redaction-admin-side-nav type="dossierTemplates"></redaction-admin-side-nav>
<div class="content-container"> <div class="content-container">
<div *ngIf="(screenStateService.noData$ | async) === false" class="header-item"> <div *ngIf="(entitiesService.noData$ | async) === false" class="header-item">
<iqser-round-checkbox <iqser-round-checkbox
(click)="toggleSelectAll()" (click)="toggleSelectAll()"
[active]="screenStateService.areAllEntitiesSelected$ | async" [active]="entitiesService.areAllSelected$ | async"
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async" [indeterminate]="entitiesService.notAllSelected$ | async"
></iqser-round-checkbox> ></iqser-round-checkbox>
<span class="all-caps-label"> <span class="all-caps-label">
{{ {{
'dossier-attributes-listing.table-header.title' 'dossier-attributes-listing.table-header.title' | translate: { length: (entitiesService.displayedLength$ | async) }
| translate: { length: (screenStateService.displayedLength$ | async) }
}} }}
</span> </span>
<iqser-circle-button <iqser-circle-button
(action)="openConfirmDeleteAttributeDialog($event)" (action)="openConfirmDeleteAttributeDialog($event)"
*ngIf="permissionsService.isAdmin() && screenStateService.areSomeEntitiesSelected$ | async" *ngIf="permissionsService.isAdmin() && entitiesService.areSomeSelected$ | async"
[tooltip]="'dossier-attributes-listing.bulk.delete' | translate" [tooltip]="'dossier-attributes-listing.bulk.delete' | translate"
icon="red:trash" icon="red:trash"
[type]="circleButtonTypes.dark" [type]="circleButtonTypes.dark"
@ -59,7 +58,7 @@
</div> </div>
</div> </div>
<div *ngIf="(screenStateService.noData$ | async) === false" class="table-header" redactionSyncWidth="table-item"> <div *ngIf="(entitiesService.noData$ | async) === false" class="table-header" redactionSyncWidth="table-item">
<div class="select-oval-placeholder"></div> <div class="select-oval-placeholder"></div>
<iqser-table-column-name <iqser-table-column-name
@ -84,7 +83,7 @@
<redaction-empty-state <redaction-empty-state
(action)="openAddEditAttributeDialog($event)" (action)="openAddEditAttributeDialog($event)"
*ngIf="screenStateService.noData$ | async" *ngIf="entitiesService.noData$ | async"
[buttonLabel]="'dossier-attributes-listing.no-data.action' | translate" [buttonLabel]="'dossier-attributes-listing.no-data.action' | translate"
[showButton]="permissionsService.isAdmin()" [showButton]="permissionsService.isAdmin()"
[text]="'dossier-attributes-listing.no-data.title' | translate" [text]="'dossier-attributes-listing.no-data.title' | translate"

View File

@ -41,7 +41,7 @@ export class DossierAttributesListingScreenComponent extends BaseListingComponen
openConfirmDeleteAttributeDialog($event: MouseEvent, dossierAttribute?: DossierAttributeConfig) { openConfirmDeleteAttributeDialog($event: MouseEvent, dossierAttribute?: DossierAttributeConfig) {
this._dialogService.openDialog('confirm', $event, null, async () => { this._dialogService.openDialog('confirm', $event, null, async () => {
this._loadingService.start(); this._loadingService.start();
const ids = dossierAttribute ? [dossierAttribute.id] : this.screenStateService.selectedEntities.map(item => item.id); const ids = dossierAttribute ? [dossierAttribute.id] : this.entitiesService.selected.map(item => item.id);
await this._dossierAttributesService.deleteConfigs(ids); await this._dossierAttributesService.deleteConfigs(ids);
await this._loadData(); await this._loadData();
}); });
@ -61,7 +61,7 @@ export class DossierAttributesListingScreenComponent extends BaseListingComponen
private async _loadData() { private async _loadData() {
this._loadingService.start(); this._loadingService.start();
const attributes = await this._dossierAttributesService.getConfig(); const attributes = await this._dossierAttributesService.getConfig();
this.screenStateService.setEntities(attributes); this.entitiesService.setEntities(attributes);
this._loadingService.stop(); this._loadingService.stop();
} }
} }

View File

@ -11,14 +11,14 @@
<div class="header-item"> <div class="header-item">
<iqser-round-checkbox <iqser-round-checkbox
(click)="toggleSelectAll()" (click)="toggleSelectAll()"
[active]="screenStateService.areAllEntitiesSelected$ | async" [active]="entitiesService.areAllSelected$ | async"
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async" [indeterminate]="entitiesService.notAllSelected$ | async"
></iqser-round-checkbox> ></iqser-round-checkbox>
<span class="all-caps-label"> <span class="all-caps-label">
{{ {{
'dossier-templates-listing.table-header.title' 'dossier-templates-listing.table-header.title'
| translate: { length: (screenStateService.displayedLength$ | async) } | translate: { length: (entitiesService.displayedLength$ | async) }
}} }}
</span> </span>
@ -47,7 +47,7 @@
</div> </div>
</div> </div>
<div [class.no-data]="screenStateService.noData$ | async" class="table-header" redactionSyncWidth="table-item"> <div [class.no-data]="entitiesService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
<div class="select-oval-placeholder"></div> <div class="select-oval-placeholder"></div>
<iqser-table-column-name <iqser-table-column-name
@ -74,7 +74,7 @@
</div> </div>
<redaction-empty-state <redaction-empty-state
*ngIf="screenStateService.noData$ | async" *ngIf="entitiesService.noData$ | async"
[text]="'dossier-templates-listing.no-data.title' | translate" [text]="'dossier-templates-listing.no-data.title' | translate"
icon="red:template" icon="red:template"
></redaction-empty-state> ></redaction-empty-state>

View File

@ -41,9 +41,9 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent
return this._dialogService.openDialog('confirm', $event, null, async () => { return this._dialogService.openDialog('confirm', $event, null, async () => {
this._loadingService.start(); this._loadingService.start();
await this._dossierTemplateControllerService await this._dossierTemplateControllerService
.deleteDossierTemplates(this.screenStateService.selectedEntities.map(d => d.dossierTemplateId)) .deleteDossierTemplates(this.entitiesService.selected.map(d => d.dossierTemplateId))
.toPromise(); .toPromise();
this.screenStateService.setSelectedEntities([]); this.entitiesService.setSelected([]);
await this._appStateService.loadAllDossierTemplates(); await this._appStateService.loadAllDossierTemplates();
await this._appStateService.loadDictionaryData(); await this._appStateService.loadDictionaryData();
this.loadDossierTemplatesData(); this.loadDossierTemplatesData();
@ -53,7 +53,7 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent
loadDossierTemplatesData() { loadDossierTemplatesData() {
this._loadingService.start(); this._loadingService.start();
this._appStateService.reset(); this._appStateService.reset();
this.screenStateService.setEntities(this._appStateService.dossierTemplates); this.entitiesService.setEntities(this._appStateService.dossierTemplates);
this._loadDossierTemplateStats(); this._loadDossierTemplateStats();
this._loadingService.stop(); this._loadingService.stop();
} }
@ -67,7 +67,7 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent
} }
private _loadDossierTemplateStats() { private _loadDossierTemplateStats() {
this.screenStateService.allEntities.forEach(rs => { this.entitiesService.all.forEach(rs => {
const dictionaries = this._appStateService.dictionaryData[rs.dossierTemplateId]; const dictionaries = this._appStateService.dictionaryData[rs.dossierTemplateId];
if (dictionaries) { if (dictionaries) {
rs.dictionariesCount = Object.keys(dictionaries) rs.dictionariesCount = Object.keys(dictionaries)

View File

@ -23,14 +23,12 @@
<div class="header-item"> <div class="header-item">
<iqser-round-checkbox <iqser-round-checkbox
(click)="toggleSelectAll()" (click)="toggleSelectAll()"
[active]="screenStateService.areAllEntitiesSelected$ | async" [active]="entitiesService.areAllSelected$ | async"
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async" [indeterminate]="entitiesService.notAllSelected$ | async"
></iqser-round-checkbox> ></iqser-round-checkbox>
<span class="all-caps-label"> <span class="all-caps-label">
{{ {{ 'file-attributes-listing.table-header.title' | translate: { length: (entitiesService.displayedLength$ | async) } }}
'file-attributes-listing.table-header.title' | translate: { length: (screenStateService.displayedLength$ | async) }
}}
</span> </span>
<iqser-circle-button <iqser-circle-button
@ -68,7 +66,7 @@
</div> </div>
</div> </div>
<div [class.no-data]="screenStateService.noData$ | async" class="table-header" redactionSyncWidth="table-item"> <div [class.no-data]="entitiesService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
<div class="select-oval-placeholder"></div> <div class="select-oval-placeholder"></div>
<iqser-table-column-name <iqser-table-column-name
@ -107,7 +105,7 @@
</div> </div>
<redaction-empty-state <redaction-empty-state
*ngIf="screenStateService.noData$ | async" *ngIf="entitiesService.noData$ | async"
[text]="'file-attributes-listing.no-data.title' | translate" [text]="'file-attributes-listing.no-data.title' | translate"
icon="red:attribute" icon="red:attribute"
></redaction-empty-state> ></redaction-empty-state>

View File

@ -65,7 +65,7 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
} else { } else {
await this._fileAttributesService await this._fileAttributesService
.deleteFileAttributes( .deleteFileAttributes(
this.screenStateService.selectedEntities.map(f => f.id), this.entitiesService.selected.map(f => f.id),
this._appStateService.activeDossierTemplateId this._appStateService.activeDossierTemplateId
) )
.toPromise(); .toPromise();
@ -98,7 +98,7 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
.getFileAttributesConfiguration(this._appStateService.activeDossierTemplateId) .getFileAttributesConfiguration(this._appStateService.activeDossierTemplateId)
.toPromise(); .toPromise();
this._existingConfiguration = response; this._existingConfiguration = response;
this.screenStateService.setEntities(response?.fileAttributeConfigs || []); this.entitiesService.setEntities(response?.fileAttributeConfigs || []);
} catch (e) {} } catch (e) {}
this._loadingService.stop(); this._loadingService.stop();

View File

@ -8,17 +8,17 @@
<div class="header-item"> <div class="header-item">
<iqser-round-checkbox <iqser-round-checkbox
(click)="toggleSelectAll()" (click)="toggleSelectAll()"
[active]="screenStateService.areAllEntitiesSelected$ | async" [active]="entitiesService.areAllSelected$ | async"
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async" [indeterminate]="entitiesService.notAllSelected$ | async"
></iqser-round-checkbox> ></iqser-round-checkbox>
<span class="all-caps-label"> <span class="all-caps-label">
{{ 'trash.table-header.title' | translate: { length: (screenStateService.displayedLength$ | async) } }} {{ 'trash.table-header.title' | translate: { length: (entitiesService.displayedLength$ | async) } }}
</span> </span>
<iqser-circle-button <iqser-circle-button
(action)="bulkRestore()" (action)="bulkRestore()"
*ngIf="screenStateService.areSomeEntitiesSelected$ | async" *ngIf="entitiesService.areSomeSelected$ | async"
[tooltip]="'trash.bulk.restore' | translate" [tooltip]="'trash.bulk.restore' | translate"
icon="red:put-back" icon="red:put-back"
[type]="circleButtonTypes.dark" [type]="circleButtonTypes.dark"
@ -26,14 +26,14 @@
<iqser-circle-button <iqser-circle-button
(action)="bulkDelete()" (action)="bulkDelete()"
*ngIf="screenStateService.areSomeEntitiesSelected$ | async" *ngIf="entitiesService.areSomeSelected$ | async"
[tooltip]="'trash.bulk.delete' | translate" [tooltip]="'trash.bulk.delete' | translate"
icon="red:trash" icon="red:trash"
[type]="circleButtonTypes.dark" [type]="circleButtonTypes.dark"
></iqser-circle-button> ></iqser-circle-button>
</div> </div>
<div [class.no-data]="screenStateService.noData$ | async" class="table-header" redactionSyncWidth="table-item"> <div [class.no-data]="entitiesService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
<div class="select-oval-placeholder"></div> <div class="select-oval-placeholder"></div>
<iqser-table-column-name <iqser-table-column-name
@ -56,7 +56,7 @@
</div> </div>
<redaction-empty-state <redaction-empty-state
*ngIf="screenStateService.noData$ | async" *ngIf="entitiesService.noData$ | async"
[text]="'trash.no-data.title' | translate" [text]="'trash.no-data.title' | translate"
icon="red:template" icon="red:template"
></redaction-empty-state> ></redaction-empty-state>

View File

@ -21,9 +21,9 @@ const MINUTES_IN_AN_HOUR = 60;
providers: [...DefaultListingServices, DossiersService] providers: [...DefaultListingServices, DossiersService]
}) })
export class TrashScreenComponent extends BaseListingComponent<Dossier> implements OnInit { export class TrashScreenComponent extends BaseListingComponent<Dossier> implements OnInit {
readonly circleButtonTypes = CircleButtonTypes;
readonly itemSize = 80; readonly itemSize = 80;
protected readonly _primaryKey = 'dossierName'; protected readonly _primaryKey = 'dossierName';
readonly circleButtonTypes = CircleButtonTypes;
private readonly _deleteRetentionHours = this._appConfigService.getConfig(AppConfigKey.DELETE_RETENTION_HOURS); private readonly _deleteRetentionHours = this._appConfigService.getConfig(AppConfigKey.DELETE_RETENTION_HOURS);
constructor( constructor(
@ -46,7 +46,7 @@ export class TrashScreenComponent extends BaseListingComponent<Dossier> implemen
} }
async loadDossierTemplatesData(): Promise<void> { async loadDossierTemplatesData(): Promise<void> {
this.screenStateService.setEntities(await this._dossiersService.getDeleted()); this.entitiesService.setEntities(await this._dossiersService.getDeleted());
} }
canRestore(softDeletedTime: string): boolean { canRestore(softDeletedTime: string): boolean {
@ -66,11 +66,11 @@ export class TrashScreenComponent extends BaseListingComponent<Dossier> implemen
return moment(softDeletedTime).add(this._deleteRetentionHours, 'hours').toISOString(); return moment(softDeletedTime).add(this._deleteRetentionHours, 'hours').toISOString();
} }
bulkDelete(dossiers = this.screenStateService.selectedEntities) { bulkDelete(dossiers = this.entitiesService.selected) {
this._loadingService.loadWhile(this._hardDelete(dossiers)); this._loadingService.loadWhile(this._hardDelete(dossiers));
} }
bulkRestore(dossierIds = this.screenStateService.selectedEntities.map(d => d.dossierId)) { bulkRestore(dossierIds = this.entitiesService.selected.map(d => d.dossierId)) {
this._loadingService.loadWhile(this._restore(dossierIds)); this._loadingService.loadWhile(this._restore(dossierIds));
} }
@ -103,8 +103,8 @@ export class TrashScreenComponent extends BaseListingComponent<Dossier> implemen
} }
private _removeFromList(ids: string[]): void { private _removeFromList(ids: string[]): void {
const entities = this.screenStateService.allEntities.filter(e => !ids.includes(e.dossierId)); const entities = this.entitiesService.all.filter(e => !ids.includes(e.dossierId));
this.screenStateService.setEntities(entities); this.entitiesService.setEntities(entities);
this.screenStateService.setSelectedEntities([]); this.entitiesService.setSelected([]);
} }
} }

View File

@ -36,17 +36,17 @@
<div class="header-item"> <div class="header-item">
<iqser-round-checkbox <iqser-round-checkbox
(click)="toggleSelectAll()" (click)="toggleSelectAll()"
[active]="screenStateService.areAllEntitiesSelected$ | async" [active]="entitiesService.areAllSelected$ | async"
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async" [indeterminate]="entitiesService.notAllSelected$ | async"
></iqser-round-checkbox> ></iqser-round-checkbox>
<span class="all-caps-label"> <span class="all-caps-label">
{{ 'user-listing.table-header.title' | translate: { length: (screenStateService.displayedLength$ | async) } }} {{ 'user-listing.table-header.title' | translate: { length: (entitiesService.displayedLength$ | async) } }}
</span> </span>
<iqser-circle-button <iqser-circle-button
(action)="bulkDelete()" (action)="bulkDelete()"
*ngIf="screenStateService.areSomeEntitiesSelected$ | async" *ngIf="entitiesService.areSomeSelected$ | async"
[disabled]="(canDeleteSelected$ | async) === false" [disabled]="(canDeleteSelected$ | async) === false"
[tooltip]=" [tooltip]="
(canDeleteSelected$ | async) (canDeleteSelected$ | async)

View File

@ -44,7 +44,7 @@ export class UserListingScreenComponent extends BaseListingComponent<UserWrapper
} }
get _canDeleteSelected$(): Observable<boolean> { get _canDeleteSelected$(): Observable<boolean> {
const entities$ = this.screenStateService.selectedEntities$; const entities$ = this.entitiesService.selected$;
return entities$.pipe(map(all => all.indexOf(this.currentUser) === -1)); return entities$.pipe(map(all => all.indexOf(this.currentUser) === -1));
} }
@ -82,11 +82,11 @@ export class UserListingScreenComponent extends BaseListingComponent<UserWrapper
} }
bulkDelete() { bulkDelete() {
this.openDeleteUsersDialog(this.screenStateService.allEntities.filter(u => this.isSelected(u))); this.openDeleteUsersDialog(this.entitiesService.all.filter(u => this.isSelected(u)));
} }
private async _loadData() { private async _loadData() {
this.screenStateService.setEntities(await this.userService.loadAllUsers()); this.entitiesService.setEntities(await this.userService.loadAllUsers());
await this.userService.loadAllUsers(); await this.userService.loadAllUsers();
this._computeStats(); this._computeStats();
this._loadingService.stop(); this._loadingService.stop();

View File

@ -8,10 +8,9 @@ import { from, Observable } from 'rxjs';
import { DossiersDialogService } from '../../services/dossiers-dialog.service'; import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { LoadingService } from '@services/loading.service'; import { LoadingService } from '@services/loading.service';
import { ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component'; import { ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component';
import { ScreenStateService } from '@shared/services/screen-state.service'; import { CircleButtonTypes, EntitiesService } from '@iqser/common-ui';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { CircleButtonTypes } from '@iqser/common-ui';
@Component({ @Component({
selector: 'redaction-dossier-overview-bulk-actions', selector: 'redaction-dossier-overview-bulk-actions',
@ -33,7 +32,7 @@ export class DossierOverviewBulkActionsComponent {
private readonly _fileActionService: FileActionService, private readonly _fileActionService: FileActionService,
private readonly _loadingService: LoadingService, private readonly _loadingService: LoadingService,
private readonly _translateService: TranslateService, private readonly _translateService: TranslateService,
private readonly _screenStateService: ScreenStateService<FileStatusWrapper> private readonly _entitiesService: EntitiesService<FileStatusWrapper>
) {} ) {}
get dossier() { get dossier() {
@ -41,7 +40,7 @@ export class DossierOverviewBulkActionsComponent {
} }
get selectedFiles(): FileStatusWrapper[] { get selectedFiles(): FileStatusWrapper[] {
return this._screenStateService.selectedEntities; return this._entitiesService.selected;
} }
get areAllFilesSelected() { get areAllFilesSelected() {
@ -146,7 +145,7 @@ export class DossierOverviewBulkActionsComponent {
.toPromise(); .toPromise();
await this._appStateService.reloadActiveDossierFiles(); await this._appStateService.reloadActiveDossierFiles();
this.reload.emit(); this.reload.emit();
this._screenStateService.setSelectedEntities([]); this._entitiesService.setSelected([]);
this._loadingService.stop(); this._loadingService.stop();
} }
); );

View File

@ -15,7 +15,7 @@
<redaction-empty-state <redaction-empty-state
(action)="openAddDossierDialog()" (action)="openAddDossierDialog()"
*ngIf="screenStateService.noData$ | async" *ngIf="entitiesService.noData$ | async"
[buttonLabel]="'dossier-listing.no-data.action' | translate" [buttonLabel]="'dossier-listing.no-data.action' | translate"
[showButton]="currentUser.isManager" [showButton]="currentUser.isManager"
[text]="'dossier-listing.no-data.title' | translate" [text]="'dossier-listing.no-data.title' | translate"
@ -85,7 +85,7 @@
<div class="right-container" redactionHasScrollbar> <div class="right-container" redactionHasScrollbar>
<redaction-dossier-listing-details <redaction-dossier-listing-details
*ngIf="(screenStateService.noData$ | async) === false" *ngIf="(entitiesService.noData$ | async) === false"
[documentsChartData]="documentsChartData" [documentsChartData]="documentsChartData"
[dossiersChartData]="dossiersChartData" [dossiersChartData]="dossiersChartData"
></redaction-dossier-listing-details> ></redaction-dossier-listing-details>

View File

@ -27,6 +27,7 @@ import {
dossierStatusChecker, dossierStatusChecker,
dossierTemplateChecker dossierTemplateChecker
} from '@shared/components/filters/popup-filter/utils/filter-utils'; } from '@shared/components/filters/popup-filter/utils/filter-utils';
import { PermissionsService } from '@services/permissions.service';
const isLeavingScreen = event => event instanceof NavigationStart && event.url !== '/main/dossiers'; const isLeavingScreen = event => event instanceof NavigationStart && event.url !== '/main/dossiers';
@ -81,6 +82,7 @@ export class DossierListingScreenComponent
protected readonly _injector: Injector, protected readonly _injector: Injector,
private readonly _userService: UserService, private readonly _userService: UserService,
readonly changeDetectorRef: ChangeDetectorRef, readonly changeDetectorRef: ChangeDetectorRef,
readonly permissionsService: PermissionsService,
private readonly _appStateService: AppStateService, private readonly _appStateService: AppStateService,
private readonly _translateService: TranslateService, private readonly _translateService: TranslateService,
private readonly _dialogService: DossiersDialogService, private readonly _dialogService: DossiersDialogService,
@ -97,11 +99,11 @@ export class DossierListingScreenComponent
} }
private get _activeDossiersCount(): number { private get _activeDossiersCount(): number {
return this.screenStateService.allEntities.filter(p => p.dossier.status === Dossier.StatusEnum.ACTIVE).length; return this.entitiesService.all.filter(p => p.dossier.status === Dossier.StatusEnum.ACTIVE).length;
} }
private get _inactiveDossiersCount(): number { private get _inactiveDossiersCount(): number {
return this.screenStateService.allEntities.length - this._activeDossiersCount; return this.entitiesService.all.length - this._activeDossiersCount;
} }
ngOnInit(): void { ngOnInit(): void {
@ -176,7 +178,7 @@ export class DossierListingScreenComponent
} }
private _loadEntitiesFromState() { private _loadEntitiesFromState() {
this.screenStateService.setEntities(this._appStateService.allDossiers); this.entitiesService.setEntities(this._appStateService.allDossiers);
} }
private _computeAllFilters() { private _computeAllFilters() {
@ -185,7 +187,7 @@ export class DossierListingScreenComponent
const allDistinctNeedsWork = new Set<string>(); const allDistinctNeedsWork = new Set<string>();
const allDistinctDossierTemplates = new Set<string>(); const allDistinctDossierTemplates = new Set<string>();
this.screenStateService?.allEntities?.forEach(entry => { this.entitiesService?.all?.forEach(entry => {
// all people // all people
entry.dossier.memberIds.forEach(f => allDistinctPeople.add(f)); entry.dossier.memberIds.forEach(f => allDistinctPeople.add(f));
// Needs work // Needs work

View File

@ -5,17 +5,17 @@
[showCloseButton]="true" [showCloseButton]="true"
> >
<redaction-file-download-btn <redaction-file-download-btn
[disabled]="screenStateService.areSomeEntitiesSelected$ | async" [disabled]="entitiesService.areSomeSelected$ | async"
[dossier]="activeDossier" [dossier]="activeDossier"
[file]="screenStateService.allEntities$ | async" [file]="entitiesService.all$ | async"
tooltipPosition="below" tooltipPosition="below"
></redaction-file-download-btn> ></redaction-file-download-btn>
<iqser-circle-button <iqser-circle-button
(action)="reanalyseDossier()" (action)="reanalyseDossier()"
*ngIf="permissionsService.displayReanalyseBtn()" *ngIf="permissionsService.displayReanalyseBtn()"
[disabled]="screenStateService.areSomeEntitiesSelected$ | async" [disabled]="entitiesService.areSomeSelected$ | async"
[tooltipClass]="'small ' + ((screenStateService.areSomeEntitiesSelected$ | async) ? '' : 'warn')" [tooltipClass]="'small ' + ((entitiesService.areSomeSelected$ | async) ? '' : 'warn')"
[tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all' | translate" [tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all' | translate"
icon="red:refresh" icon="red:refresh"
tooltipPosition="below" tooltipPosition="below"
@ -45,7 +45,7 @@
<redaction-empty-state <redaction-empty-state
(action)="fileInput.click()" (action)="fileInput.click()"
*ngIf="screenStateService.noData$ | async" *ngIf="entitiesService.noData$ | async"
[buttonLabel]="'dossier-overview.no-data.action' | translate" [buttonLabel]="'dossier-overview.no-data.action' | translate"
[text]="'dossier-overview.no-data.title' | translate" [text]="'dossier-overview.no-data.title' | translate"
buttonIcon="red:upload" buttonIcon="red:upload"

View File

@ -31,6 +31,7 @@ import { workloadTranslations } from '../../translations/workload-translations';
import { fileStatusTranslations } from '../../translations/file-status-translations'; import { fileStatusTranslations } from '../../translations/file-status-translations';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { annotationFilterChecker } from '@shared/components/filters/popup-filter/utils/filter-utils'; import { annotationFilterChecker } from '@shared/components/filters/popup-filter/utils/filter-utils';
import { PermissionsService } from '@services/permissions.service';
@Component({ @Component({
templateUrl: './dossier-overview-screen.component.html', templateUrl: './dossier-overview-screen.component.html',
@ -103,6 +104,7 @@ export class DossierOverviewScreenComponent
private readonly _toaster: Toaster, private readonly _toaster: Toaster,
protected readonly _injector: Injector, protected readonly _injector: Injector,
private readonly _userService: UserService, private readonly _userService: UserService,
readonly permissionsService: PermissionsService,
private readonly _loadingService: LoadingService, private readonly _loadingService: LoadingService,
private readonly _appStateService: AppStateService, private readonly _appStateService: AppStateService,
private readonly _appConfigService: AppConfigService, private readonly _appConfigService: AppConfigService,
@ -232,7 +234,7 @@ export class DossierOverviewScreenComponent
} }
bulkActionPerformed() { bulkActionPerformed() {
this.screenStateService.setSelectedEntities([]); this.entitiesService.setSelected([]);
this.reloadDossiers(); this.reloadDossiers();
} }
@ -268,7 +270,7 @@ export class DossierOverviewScreenComponent
moment(file.lastUpdated).add(this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS), 'hours').isAfter(moment()); moment(file.lastUpdated).add(this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS), 'hours').isAfter(moment());
private _loadEntitiesFromState() { private _loadEntitiesFromState() {
if (this.activeDossier) this.screenStateService.setEntities(this.activeDossier.files); if (this.activeDossier) this.entitiesService.setEntities(this.activeDossier.files);
} }
private async _uploadFiles(files: FileUploadModel[]) { private async _uploadFiles(files: FileUploadModel[]) {
@ -284,7 +286,7 @@ export class DossierOverviewScreenComponent
const allDistinctAddedDates = new Set<string>(); const allDistinctAddedDates = new Set<string>();
const allDistinctNeedsWork = new Set<string>(); const allDistinctNeedsWork = new Set<string>();
this.screenStateService.allEntities.forEach(file => { this.entitiesService.all.forEach(file => {
allDistinctPeople.add(file.currentReviewer); allDistinctPeople.add(file.currentReviewer);
allDistinctFileStatusWrapper.add(file.status); allDistinctFileStatusWrapper.add(file.status);
allDistinctAddedDates.add(moment(file.added).format('DD/MM/YYYY')); allDistinctAddedDates.add(moment(file.added).format('DD/MM/YYYY'));
@ -362,7 +364,7 @@ export class DossierOverviewScreenComponent
private _createQuickFilters() { private _createQuickFilters() {
let quickFilters = []; let quickFilters = [];
if (this.screenStateService.allEntities.filter(this.recentlyModifiedChecker).length > 0) { if (this.entitiesService.all.filter(this.recentlyModifiedChecker).length > 0) {
const recentPeriod = this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS); const recentPeriod = this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS);
quickFilters = [ quickFilters = [
{ {

View File

@ -53,7 +53,7 @@ export class SearchScreenComponent extends BaseListingComponent<ListItem> implem
switchMap(query => this._search(query)), switchMap(query => this._search(query)),
map(searchResult => this._toMatchedDocuments(searchResult)), map(searchResult => this._toMatchedDocuments(searchResult)),
map(docs => this._toListItems(docs)), map(docs => this._toListItems(docs)),
tap(result => this.screenStateService.setEntities(result)), tap(result => this.entitiesService.setEntities(result)),
tap(() => this._loadingService.stop()) tap(() => this._loadingService.stop())
); );

View File

@ -1,6 +1,7 @@
import { Component, Injector, OnDestroy, ViewChild } from '@angular/core'; import { Component, Injector, OnDestroy, ViewChild } from '@angular/core';
import { import {
AutoUnsubscribeComponent, AutoUnsubscribeComponent,
EntitiesService,
FilterService, FilterService,
KeysOf, KeysOf,
SearchService, SearchService,
@ -9,26 +10,23 @@ import {
TableColumnConfig TableColumnConfig
} from '@iqser/common-ui'; } from '@iqser/common-ui';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import { ScreenStateService } from '../services/screen-state.service';
import { combineLatest, Observable } from 'rxjs'; import { combineLatest, Observable } from 'rxjs';
import { distinctUntilChanged, map, switchMap } from 'rxjs/operators'; import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
import { PermissionsService } from '@services/permissions.service';
export const DefaultListingServices = [FilterService, SearchService, ScreenStateService, SortingService] as const; export const DefaultListingServices = [FilterService, SearchService, EntitiesService, SortingService] as const;
@Component({ template: '' }) @Component({ template: '' })
export abstract class BaseListingComponent<T extends object> extends AutoUnsubscribeComponent implements OnDestroy { export abstract class BaseListingComponent<T extends object> extends AutoUnsubscribeComponent implements OnDestroy {
@ViewChild(CdkVirtualScrollViewport) @ViewChild(CdkVirtualScrollViewport)
readonly scrollViewport: CdkVirtualScrollViewport; readonly scrollViewport: CdkVirtualScrollViewport;
readonly permissionsService = this._injector.get(PermissionsService);
readonly filterService = this._injector.get(FilterService); readonly filterService = this._injector.get(FilterService);
readonly sortingService = this._injector.get<SortingService<T>>(SortingService);
readonly searchService = this._injector.get<SearchService<T>>(SearchService); readonly searchService = this._injector.get<SearchService<T>>(SearchService);
readonly screenStateService = this._injector.get<ScreenStateService<T>>(ScreenStateService); readonly sortingService = this._injector.get<SortingService<T>>(SortingService);
readonly entitiesService = this._injector.get<EntitiesService<T>>(EntitiesService);
readonly sortedDisplayedEntities$ = this._sortedDisplayedEntities$;
readonly noMatch$ = this._noMatch$; readonly noMatch$ = this._noMatch$;
readonly sortedDisplayedEntities$ = this._sortedDisplayedEntities$;
readonly tableColumnConfigs: TableColumnConfig<T>[]; readonly tableColumnConfigs: TableColumnConfig<T>[];
/** /**
@ -45,17 +43,17 @@ export abstract class BaseListingComponent<T extends object> extends AutoUnsubsc
} }
get allEntities(): T[] { get allEntities(): T[] {
return this.screenStateService.allEntities; return this.entitiesService.all;
} }
private get _sortedDisplayedEntities$(): Observable<T[]> { private get _sortedDisplayedEntities$(): Observable<T[]> {
const sort = entities => this.sortingService.defaultSort(entities); const sort = entities => this.sortingService.defaultSort(entities);
const sortedEntities = () => this.screenStateService.displayedEntities$.pipe(map(sort)); const sortedEntities = () => this.entitiesService.displayed$.pipe(map(sort));
return this.sortingService.sortingOption$.pipe(switchMap(sortedEntities)); return this.sortingService.sortingOption$.pipe(switchMap(sortedEntities));
} }
private get _noMatch$(): Observable<boolean> { private get _noMatch$(): Observable<boolean> {
return combineLatest([this.screenStateService.allEntitiesLength$, this.screenStateService.displayedLength$]).pipe( return combineLatest([this.entitiesService.allLength$, this.entitiesService.displayedLength$]).pipe(
map(([hasEntities, hasDisplayedEntities]) => hasEntities && !hasDisplayedEntities), map(([hasEntities, hasDisplayedEntities]) => hasEntities && !hasDisplayedEntities),
distinctUntilChanged() distinctUntilChanged()
); );
@ -70,23 +68,23 @@ export abstract class BaseListingComponent<T extends object> extends AutoUnsubsc
} }
canBulkDelete$(hasPermission = true): Observable<boolean> { canBulkDelete$(hasPermission = true): Observable<boolean> {
return this.screenStateService.areSomeEntitiesSelected$.pipe( return this.entitiesService.areSomeSelected$.pipe(
map(areSomeEntitiesSelected => areSomeEntitiesSelected && hasPermission), map(areSomeEntitiesSelected => areSomeEntitiesSelected && hasPermission),
distinctUntilChanged() distinctUntilChanged()
); );
} }
toggleSelectAll() { toggleSelectAll() {
return this.screenStateService.selectEntities(); return this.entitiesService.selectAll();
} }
toggleEntitySelected(event: MouseEvent, entity: T) { toggleEntitySelected(event: MouseEvent, entity: T) {
event.stopPropagation(); event.stopPropagation();
return this.screenStateService.selectEntities([entity]); return this.entitiesService.select(entity);
} }
isSelected(entity: T): boolean { isSelected(entity: T): boolean {
return this.screenStateService.isSelected(entity); return this.entitiesService.isSelected(entity);
} }
trackByPrimaryKey(index: number, item: T) { trackByPrimaryKey(index: number, item: T) {

View File

@ -1,13 +1,13 @@
<div [class.selection-enabled]="selectionEnabled" class="header-item"> <div [class.selection-enabled]="selectionEnabled" class="header-item">
<iqser-round-checkbox <iqser-round-checkbox
(click)="screenStateService.selectEntities()" (click)="entitiesService.selectAll()"
*ngIf="selectionEnabled" *ngIf="selectionEnabled"
[active]="screenStateService.areAllEntitiesSelected$ | async" [active]="entitiesService.areAllSelected$ | async"
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async" [indeterminate]="entitiesService.notAllSelected$ | async"
></iqser-round-checkbox> ></iqser-round-checkbox>
<span class="all-caps-label"> <span class="all-caps-label">
{{ tableHeaderLabel | translate: { length: (screenStateService.displayedLength$ | async) } }} {{ tableHeaderLabel | translate: { length: (entitiesService.displayedLength$ | async) } }}
</span> </span>
<ng-container [ngTemplateOutlet]="bulkActions"></ng-container> <ng-container [ngTemplateOutlet]="bulkActions"></ng-container>

View File

@ -1,6 +1,5 @@
import { ChangeDetectionStrategy, Component, Input, TemplateRef } from '@angular/core'; import { ChangeDetectionStrategy, Component, Input, TemplateRef } from '@angular/core';
import { ScreenStateService } from '@shared/services/screen-state.service'; import { EntitiesService, Required, TableColumnConfig } from '@iqser/common-ui';
import { TableColumnConfig } from '@iqser/common-ui';
@Component({ @Component({
selector: 'redaction-table-header', selector: 'redaction-table-header',
@ -9,11 +8,11 @@ import { TableColumnConfig } from '@iqser/common-ui';
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class TableHeaderComponent<T extends object> { export class TableHeaderComponent<T extends object> {
@Input() tableHeaderLabel: string; @Input() @Required() tableHeaderLabel: string;
@Input() tableColumnConfigs: TableColumnConfig<T>[]; @Input() @Required() tableColumnConfigs: TableColumnConfig<T>[];
@Input() hasEmptyColumn = false; @Input() hasEmptyColumn = false;
@Input() selectionEnabled = false; @Input() selectionEnabled = false;
@Input() bulkActions: TemplateRef<any>; @Input() bulkActions: TemplateRef<any>;
constructor(readonly screenStateService: ScreenStateService<T>) {} constructor(readonly entitiesService: EntitiesService<T>) {}
} }

View File

@ -1,133 +0,0 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, combineLatest, Observable, pipe } from 'rxjs';
import { distinctUntilChanged, map, tap } from 'rxjs/operators';
import { FilterService, getFilteredEntities, SearchService } from '@iqser/common-ui';
const toLengthValue = (entities: unknown[]) => entities?.length ?? 0;
const getLength = pipe(map(toLengthValue), distinctUntilChanged());
@Injectable()
export class ScreenStateService<T extends object> {
private readonly _allEntities$ = new BehaviorSubject<T[]>([]);
readonly allEntities$ = this._allEntities$.asObservable();
readonly allEntitiesLength$ = this._allEntities$.pipe(getLength);
private readonly _displayedEntities$ = new BehaviorSubject<T[]>([]);
readonly displayedEntities$ = this._getDisplayedEntities$;
readonly displayedLength$ = this._displayedEntities$.pipe(getLength);
private readonly _selectedEntities$ = new BehaviorSubject<T[]>([]);
readonly selectedEntities$ = this._selectedEntities$.asObservable();
readonly selectedLength$ = this._selectedEntities$.pipe(getLength);
readonly noData$ = this._noData$;
readonly areAllEntitiesSelected$ = this._areAllEntitiesSelected$;
readonly areSomeEntitiesSelected$ = this._areSomeEntitiesSelected$;
readonly notAllEntitiesSelected$ = this._notAllEntitiesSelected$;
constructor(private readonly _filterService: FilterService, private readonly _searchService: SearchService<T>) {
// setInterval(() => {
// console.log('All entities subs: ', this._allEntities$.observers);
// console.log('Displayed entities subs: ', this._displayedEntities$.observers);
// console.log('Selected entities subs: ', this._selectedEntities$.observers);
// }, 10000);
}
get allEntities(): T[] {
return Object.values(this._allEntities$.getValue());
}
get selectedEntities(): T[] {
return Object.values(this._selectedEntities$.getValue());
}
get displayedEntities(): T[] {
return Object.values(this._displayedEntities$.getValue());
}
get _getDisplayedEntities$(): Observable<T[]> {
const filterGroups$ = this._filterService.filterGroups$;
const searchValue$ = this._searchService.valueChanges$;
return combineLatest([this.allEntities$, filterGroups$, searchValue$]).pipe(
map(([entities, filterGroups]) => getFilteredEntities(entities, filterGroups)),
map(entities => this._searchService.searchIn(entities)),
tap(entities => this._displayedEntities$.next(entities))
);
}
private get _areAllEntitiesSelected$(): Observable<boolean> {
return combineLatest([this.displayedLength$, this.selectedLength$]).pipe(
map(([displayedLength, selectedLength]) => displayedLength && displayedLength === selectedLength),
distinctUntilChanged()
);
}
private get _areSomeEntitiesSelected$(): Observable<boolean> {
return this.selectedLength$.pipe(
map(value => !!value),
distinctUntilChanged()
);
}
private get _notAllEntitiesSelected$(): Observable<boolean> {
return combineLatest([this.areAllEntitiesSelected$, this.areSomeEntitiesSelected$]).pipe(
map(([allEntitiesAreSelected, someEntitiesAreSelected]) => !allEntitiesAreSelected && someEntitiesAreSelected),
distinctUntilChanged()
);
}
private get _noData$(): Observable<boolean> {
return this.allEntitiesLength$.pipe(
map(length => length === 0),
distinctUntilChanged()
);
}
private get _allEntitiesSelected() {
return this.displayedEntities.length !== 0 && this.displayedEntities.length === this.selectedEntities.length;
}
setEntities(newEntities: T[]): void {
this._allEntities$.next(newEntities);
}
setSelectedEntities(newEntities: T[]): void {
this._selectedEntities$.next(newEntities);
}
isSelected(entity: T): boolean {
return this.selectedEntities.indexOf(entity) !== -1;
}
selectEntities(entities?: T[]): void {
if (entities?.length > 0) {
return entities.forEach(entity => this._selectOne(entity));
}
return this._selectAll();
}
updateSelection(): void {
const items = this.displayedEntities.filter(item => this.selectedEntities.includes(item));
this.setSelectedEntities(items);
}
logCurrentState(): void {
console.log('Entities', this.allEntities);
console.log('Displayed', this.displayedEntities);
console.log('Selected', this.selectedEntities);
}
private _selectOne(entity: T): void {
const currentEntityIdx = this.selectedEntities.indexOf(entity);
if (currentEntityIdx === -1) {
return this.setSelectedEntities([...this.selectedEntities, entity]);
}
this.setSelectedEntities(this.selectedEntities.filter((el, idx) => idx !== currentEntityIdx));
}
private _selectAll(): void {
if (this._allEntitiesSelected) return this.setSelectedEntities([]);
this.setSelectedEntities(this.displayedEntities);
}
}