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

View File

@ -41,13 +41,13 @@ export class DownloadsListScreenComponent extends BaseListingComponent<DownloadS
}
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._loadData();
}
private async _loadData() {
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">
<iqser-round-checkbox
(click)="toggleSelectAll()"
[active]="screenStateService.areAllEntitiesSelected$ | async"
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async"
[active]="entitiesService.areAllSelected$ | async"
[indeterminate]="entitiesService.notAllSelected$ | async"
></iqser-round-checkbox>
<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>
<ng-container *ngIf="screenStateService.areSomeEntitiesSelected$ | async">
<ng-container *ngIf="entitiesService.areSomeSelected$ | async">
<iqser-circle-button
[matMenuTriggerFor]="readOnlyMenu"
[tooltip]="'file-attributes-csv-import.table-header.actions.read-only' | translate"
@ -76,7 +76,7 @@
</div>
<redaction-empty-state
*ngIf="screenStateService.noData$ | async"
*ngIf="entitiesService.noData$ | async"
[text]="'file-attributes-csv-import.no-data.title' | translate"
icon="red:attribute"
></redaction-empty-state>

View File

@ -12,37 +12,40 @@ import { fileAttributeTypesTranslations } from '../../../translations/file-attri
providers: [...DefaultListingServices]
})
export class ActiveFieldsListingComponent extends BaseListingComponent<Field> implements OnChanges {
protected readonly _primaryKey = 'csvColumn';
readonly circleButtonTypes = CircleButtonTypes;
readonly translations = fileAttributeTypesTranslations;
readonly typeOptions = [
FileAttributeConfig.TypeEnum.TEXT,
FileAttributeConfig.TypeEnum.NUMBER,
FileAttributeConfig.TypeEnum.DATE
] as const;
@Input() entities: Field[];
@Output() entitiesChange = new EventEmitter<Field[]>();
@Output() setHoveredColumn = new EventEmitter<string>();
@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) {
super(_injector);
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.entities) {
this.screenStateService.setEntities(this.entities);
this.screenStateService.updateSelection();
this.entitiesService.setEntities(this.entities);
this.entitiesService.updateSelection();
}
}
deactivateSelection() {
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.screenStateService.setSelectedEntities([]);
this.entitiesService.setSelected([]);
}
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;
}
}

View File

@ -93,7 +93,7 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
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 = [];
for (const entity of this.allEntities) {

View File

@ -22,7 +22,7 @@
<div class="content-container">
<div class="header-item">
<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>
</div>

View File

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

View File

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

View File

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

View File

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

View File

@ -41,7 +41,7 @@ export class DossierAttributesListingScreenComponent extends BaseListingComponen
openConfirmDeleteAttributeDialog($event: MouseEvent, dossierAttribute?: DossierAttributeConfig) {
this._dialogService.openDialog('confirm', $event, null, async () => {
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._loadData();
});
@ -61,7 +61,7 @@ export class DossierAttributesListingScreenComponent extends BaseListingComponen
private async _loadData() {
this._loadingService.start();
const attributes = await this._dossierAttributesService.getConfig();
this.screenStateService.setEntities(attributes);
this.entitiesService.setEntities(attributes);
this._loadingService.stop();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -36,17 +36,17 @@
<div class="header-item">
<iqser-round-checkbox
(click)="toggleSelectAll()"
[active]="screenStateService.areAllEntitiesSelected$ | async"
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async"
[active]="entitiesService.areAllSelected$ | async"
[indeterminate]="entitiesService.notAllSelected$ | async"
></iqser-round-checkbox>
<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>
<iqser-circle-button
(action)="bulkDelete()"
*ngIf="screenStateService.areSomeEntitiesSelected$ | async"
*ngIf="entitiesService.areSomeSelected$ | async"
[disabled]="(canDeleteSelected$ | async) === false"
[tooltip]="
(canDeleteSelected$ | async)

View File

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

View File

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

View File

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

View File

@ -27,6 +27,7 @@ import {
dossierStatusChecker,
dossierTemplateChecker
} 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';
@ -81,6 +82,7 @@ export class DossierListingScreenComponent
protected readonly _injector: Injector,
private readonly _userService: UserService,
readonly changeDetectorRef: ChangeDetectorRef,
readonly permissionsService: PermissionsService,
private readonly _appStateService: AppStateService,
private readonly _translateService: TranslateService,
private readonly _dialogService: DossiersDialogService,
@ -97,11 +99,11 @@ export class DossierListingScreenComponent
}
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 {
return this.screenStateService.allEntities.length - this._activeDossiersCount;
return this.entitiesService.all.length - this._activeDossiersCount;
}
ngOnInit(): void {
@ -176,7 +178,7 @@ export class DossierListingScreenComponent
}
private _loadEntitiesFromState() {
this.screenStateService.setEntities(this._appStateService.allDossiers);
this.entitiesService.setEntities(this._appStateService.allDossiers);
}
private _computeAllFilters() {
@ -185,7 +187,7 @@ export class DossierListingScreenComponent
const allDistinctNeedsWork = new Set<string>();
const allDistinctDossierTemplates = new Set<string>();
this.screenStateService?.allEntities?.forEach(entry => {
this.entitiesService?.all?.forEach(entry => {
// all people
entry.dossier.memberIds.forEach(f => allDistinctPeople.add(f));
// Needs work

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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