From 6932fa6b30eb2807eb582c956ad5016f28930395 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Wed, 14 Jul 2021 23:12:28 +0300 Subject: [PATCH] remove unused methods, add AutoUnsubscribeComponent --- .../edit-color-dialog.component.ts | 8 +- .../active-fields-listing.component.html | 2 +- .../active-fields-listing.component.ts | 24 ++- ...ttributes-csv-import-dialog.component.html | 75 ++------- ...-attributes-csv-import-dialog.component.ts | 6 +- .../default-colors-screen.component.ts | 4 +- .../dictionary-listing-screen.component.html | 45 ++--- .../dictionary-listing-screen.component.ts | 22 ++- .../digital-signature-screen.component.ts | 21 +-- ...r-attributes-listing-screen.component.html | 2 +- ...ier-attributes-listing-screen.component.ts | 9 +- ...er-templates-listing-screen.component.html | 4 +- ...sier-templates-listing-screen.component.ts | 15 +- ...e-attributes-listing-screen.component.html | 2 +- ...ile-attributes-listing-screen.component.ts | 12 +- .../screens/rules/rules-screen.component.ts | 24 +-- .../smtp-config-screen.component.ts | 38 ++--- .../screens/trash/trash-screen.component.ts | 15 +- .../user-listing-screen.component.html | 43 ++--- .../user-listing-screen.component.ts | 9 +- ...dossier-overview-bulk-actions.component.ts | 42 +++-- .../dossier-details.component.html | 8 +- .../dossier-details.component.ts | 5 +- .../dossier-listing-details.component.html | 1 - .../team-members-manager.component.ts | 14 +- .../add-dossier-dialog.component.ts | 17 +- ...sign-reviewer-approver-dialog.component.ts | 10 +- ...edit-dossier-download-package.component.ts | 2 +- .../edit-dossier-general-info.component.ts | 4 +- .../dossier-listing-screen.component.ts | 90 +++++----- .../dossier-overview-screen.component.html | 5 +- .../dossier-overview-screen.component.ts | 79 +++------ .../file-preview-screen.component.ts | 2 +- .../dossier/services/dossiers.service.ts | 20 ++- .../services/manual-annotation.service.ts | 65 ++------ .../shared/base/auto-unsubscribe.component.ts | 29 ++++ .../shared/base/base-listing.component.ts | 64 ++++--- .../file-download-btn.component.ts | 24 +-- .../simple-doughnut-chart.component.html | 14 +- .../simple-doughnut-chart.component.ts | 48 ++---- .../modules/shared/services/filter.service.ts | 10 +- .../shared/services/screen-state.service.ts | 69 +++----- .../modules/shared/services/search.service.ts | 12 +- .../app/services/user-preference.service.ts | 27 ++- .../red-ui/src/app/state/app-state.service.ts | 157 ++++++++---------- .../src/app/utils/sorters/status-sorter.ts | 2 +- 46 files changed, 466 insertions(+), 734 deletions(-) create mode 100644 apps/red-ui/src/app/modules/shared/base/auto-unsubscribe.component.ts diff --git a/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts index 274d9789f..37ce4623e 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts @@ -47,15 +47,11 @@ export class EditColorDialogComponent { }; try { - await this._dictionaryControllerService - .setColors(colors, this._dossierTemplateId) - .toPromise(); + await this._dictionaryControllerService.setColors(colors, this._dossierTemplateId).toPromise(); this._dialogRef.close(true); this._notificationService.showToastNotification( this._translateService.instant('edit-color-dialog.success', { - color: this._translateService.instant( - 'default-colors-screen.types.' + this.colorKey - ) + color: this._translateService.instant('default-colors-screen.types.' + this.colorKey) }) ); } catch (e) { diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html index a77d8178e..7dc532184 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html @@ -7,7 +7,7 @@ > - {{ 'file-attributes-csv-import.table-header.title' | translate: { length: allEntities.length } }} + {{ 'file-attributes-csv-import.table-header.title' | translate: { length: (allEntities$ | async)?.length } }} diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts index abd4dbd85..e1301401a 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts @@ -23,38 +23,36 @@ export class ActiveFieldsListingComponent extends BaseListingComponent im constructor(protected readonly _injector: Injector) { super(_injector); - this._screenStateService.setIdKey('csvColumn'); } ngOnChanges(changes: SimpleChanges): void { if (changes.entities) { - this._screenStateService.setEntities(this.entities); - this._screenStateService.setDisplayedEntities(this.entities); - this._screenStateService.updateSelection(); + this.screenStateService.setEntities(this.entities); + this.screenStateService.setDisplayedEntities(this.entities); + this.screenStateService.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.screenStateService.setEntities(this.allEntities.filter(field => !this.isSelected(field))); this.entitiesChange.emit(this.allEntities); - this._screenStateService.setSelectedEntitiesIds([]); + this.screenStateService.setSelectedEntities([]); } setAttributeForSelection(attribute: string, value: any) { - for (const csvColumn of this._screenStateService.selectedEntitiesIds) { - this.allEntities.find(f => f.csvColumn === csvColumn)[attribute] = value; + for (const item of this.screenStateService.selectedEntities) { + this.allEntities.find(f => f.csvColumn === item.csvColumn)[attribute] = value; } } togglePrimary(field: Field) { if (field.primaryAttribute) { field.primaryAttribute = false; - } else { - for (const f of this.allEntities) { - f.primaryAttribute = false; - } - field.primaryAttribute = true; + return; } + + for (const f of this.allEntities) f.primaryAttribute = false; + field.primaryAttribute = true; } } diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html index 71d54c5c2..1b5300bfd 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html @@ -4,37 +4,25 @@
-
- {{ csvFile.name }} -
+
{{ csvFile.name }}
- {{ - 'file-attributes-csv-import.total-rows' - | translate: { rows: parseResult?.data?.length } - }} + {{ 'file-attributes-csv-import.total-rows' | translate: { rows: parseResult?.data?.length } }}
- {{ - 'file-attributes-csv-import.key-column' | translate - }} + {{ 'file-attributes-csv-import.key-column' | translate }} - + {{ field }} @@ -44,9 +32,7 @@
{{ - 'file-attributes-csv-import.available' - | translate: { value: parseResult?.meta?.fields.length } + 'file-attributes-csv-import.available' | translate: { value: parseResult?.meta?.fields.length } }} {{ - 'file-attributes-csv-import.selected' - | translate: { value: activeFields.length } + 'file-attributes-csv-import.selected' | translate: { value: activeFields.length } }}
@@ -108,7 +90,7 @@
-
- {{ getEntries(field.csvColumn) }} entries -
-
- Sample: {{ getSample(field.csvColumn) }} -
+
{{ getEntries(field.csvColumn) }} entries
+
Sample: {{ getSample(field.csvColumn) }}
@@ -146,10 +124,7 @@ >
- {{ - 'file-attributes-csv-import.csv-column' + - (previewExpanded ? '' : '-preview') | translate - }} + {{ 'file-attributes-csv-import.csv-column' + (previewExpanded ? '' : '-preview') | translate }}
-
+
- {{ - 'file-attributes-csv-import.no-sample-data-for' - | translate: { column: hoveredColumn } - }} + {{ 'file-attributes-csv-import.no-sample-data-for' | translate: { column: hoveredColumn } }}
{{ row }} @@ -184,12 +152,7 @@
- @@ -198,9 +161,5 @@
- + diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts index e1ea2765e..b09b644ae 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts @@ -26,7 +26,6 @@ export interface Field { } @Component({ - selector: 'redaction-file-attributes-csv-import-dialog', templateUrl: './file-attributes-csv-import-dialog.component.html', styleUrls: ['./file-attributes-csv-import-dialog.component.scss'], providers: [FilterService, SearchService, ScreenStateService, SortingService] @@ -44,7 +43,6 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent keepPreview = false; columnSample = []; initialParseConfig: { delimiter?: string; encoding?: string } = {}; - protected readonly _searchKey = 'csvColumn'; constructor( private readonly _appStateService: AppStateService, @@ -96,8 +94,8 @@ 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._screenStateService.setDisplayedEntities(this.allEntities); + this.screenStateService.setEntities(this.parseResult.meta.fields.map(field => this._buildAttribute(field))); + this.screenStateService.setDisplayedEntities(this.allEntities); this.activeFields = []; for (const entity of this.allEntities) { diff --git a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts index cc63d6124..8b21ef348 100644 --- a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts @@ -35,7 +35,7 @@ export class DefaultColorsScreenComponent protected readonly _injector: Injector ) { super(_injector); - this._sortingService.setScreenName(ScreenNames.DEFAULT_COLORS); + this.sortingService.setScreenName(ScreenNames.DEFAULT_COLORS); _appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId); } @@ -62,7 +62,7 @@ export class DefaultColorsScreenComponent this._loadingService.start(); const data = await this._dictionaryControllerService.getColors(this._appStateService.activeDossierTemplateId).toPromise(); this._colorsObj = data; - this._screenStateService.setEntities( + this.screenStateService.setEntities( Object.keys(data).map(key => ({ key, value: data[key] diff --git a/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html index 13ac5fe9e..b0b8c30a4 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html @@ -25,17 +25,12 @@
- {{ - 'dictionary-listing.table-header.title' - | translate: { length: (displayedEntities$ | async)?.length } - }} + {{ 'dictionary-listing.table-header.title' | translate: { length: (displayedEntities$ | async)?.length } }} @@ -64,11 +59,7 @@
-
+
- +
-
+
{{ dict.label }} @@ -153,16 +135,13 @@
- +
{ this._loadingService.start(); - await this._dictionaryControllerService.deleteTypes(types, this._appStateService.activeDossierTemplateId).toPromise(); - this._screenStateService.setSelectedEntitiesIds([]); + await this._dictionaryControllerService + .deleteTypes( + types.map(t => t.type), + this._appStateService.activeDossierTemplateId + ) + .toPromise(); + this.screenStateService.setSelectedEntities([]); await this._appStateService.loadDictionaryData(); this._loadDictionaryData(false); this._calculateData(); @@ -88,15 +92,15 @@ export class DictionaryListingScreenComponent extends BaseListingComponent !d.virtual); if (!loadEntries) - this._screenStateService.setEntities( + this.screenStateService.setEntities( entities.map(dict => { dict.entries = this.allEntities.find(d => d.type === dict.type)?.entries || []; return dict; }) ); - else this._screenStateService.setEntities(entities); + else this.screenStateService.setEntities(entities); - this._screenStateService.setDisplayedEntities(this.allEntities); + this.screenStateService.setDisplayedEntities(this.allEntities); if (!loadEntries) return; diff --git a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts index 1832c4977..0ebbfb000 100644 --- a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts @@ -29,10 +29,7 @@ export class DigitalSignatureScreenComponent { } get hasDigitalSignatureSet() { - return ( - this.digitalSignatureExists || - !!this.digitalSignatureForm.get('base64EncodedPrivateKey').value - ); + return this.digitalSignatureExists || !!this.digitalSignatureForm.get('base64EncodedPrivateKey').value; } saveDigitalSignature() { @@ -58,17 +55,13 @@ export class DigitalSignatureScreenComponent { error => { if (error.status === 400) { this._notificationService.showToastNotification( - this._translateService.instant( - 'digital-signature-screen.action.certificate-not-valid-error' - ), + this._translateService.instant('digital-signature-screen.action.certificate-not-valid-error'), null, NotificationType.ERROR ); } else { this._notificationService.showToastNotification( - this._translateService.instant( - 'digital-signature-screen.action.save-error' - ), + this._translateService.instant('digital-signature-screen.action.save-error'), null, NotificationType.ERROR ); @@ -82,9 +75,7 @@ export class DigitalSignatureScreenComponent { () => { this.loadDigitalSignatureAndInitializeForm(); this._notificationService.showToastNotification( - this._translateService.instant( - 'digital-signature-screen.action.delete-success' - ), + this._translateService.instant('digital-signature-screen.action.delete-success'), null, NotificationType.SUCCESS ); @@ -139,9 +130,7 @@ export class DigitalSignatureScreenComponent { certificateName: [this.digitalSignature.certificateName, Validators.required], contactInfo: this.digitalSignature.contactInfo, location: this.digitalSignature.location, - keySecret: this.digitalSignatureExists - ? null - : [this.digitalSignature.password, Validators.required], + keySecret: this.digitalSignatureExists ? null : [this.digitalSignature.password, Validators.required], reason: this.digitalSignature.reason, base64EncodedPrivateKey: this.digitalSignatureExists ? null diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.html index 4269a49d2..77c7a7314 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.html @@ -43,7 +43,7 @@
diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts index 63dbde699..5fc724ce7 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts @@ -28,9 +28,8 @@ export class DossierAttributesListingScreenComponent extends BaseListingComponen readonly permissionsService: PermissionsService ) { super(_injector); - this._searchService.setSearchKey('label'); - this._screenStateService.setIdKey('id'); - this._sortingService.setScreenName(ScreenNames.DOSSIER_ATTRIBUTES_LISTING); + this.searchService.setSearchKey('label'); + this.sortingService.setScreenName(ScreenNames.DOSSIER_ATTRIBUTES_LISTING); _appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId); } @@ -41,7 +40,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.selectedEntitiesIds; + const ids = dossierAttribute ? [dossierAttribute.id] : this.screenStateService.selectedEntities.map(item => item.id); await this._dossierAttributesService.deleteConfigs(ids); await this._loadData(); }); @@ -61,7 +60,7 @@ export class DossierAttributesListingScreenComponent extends BaseListingComponen private async _loadData() { this._loadingService.start(); const attributes = await this._dossierAttributesService.getConfig(); - this._screenStateService.setEntities(attributes); + this.screenStateService.setEntities(attributes); this.filterService.filterEntities(); this._loadingService.stop(); } diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.html index a2649fbed..1afdd7a3a 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.html @@ -43,7 +43,7 @@
@@ -58,7 +58,7 @@
-
+
{ this._loadingService.start(); - await this._dossierTemplateControllerService.deleteDossierTemplates(this._screenStateService.selectedEntitiesIds).toPromise(); - this._screenStateService.setSelectedEntitiesIds([]); + await this._dossierTemplateControllerService + .deleteDossierTemplates(this.screenStateService.selectedEntities.map(d => d.dossierTemplateId)) + .toPromise(); + this.screenStateService.setSelectedEntities([]); await this._appStateService.loadAllDossierTemplates(); await this._appStateService.loadDictionaryData(); this.loadDossierTemplatesData(); @@ -52,7 +53,7 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent loadDossierTemplatesData() { this._loadingService.start(); this._appStateService.reset(); - this._screenStateService.setEntities(this._appStateService.dossierTemplates); + this.screenStateService.setEntities(this._appStateService.dossierTemplates); this.filterService.filterEntities(); this._loadDossierTemplateStats(); this._loadingService.stop(); @@ -67,7 +68,7 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent } private _loadDossierTemplateStats() { - this._screenStateService.entities.forEach(rs => { + this.screenStateService.allEntities.forEach(rs => { const dictionaries = this._appStateService.dictionaryData[rs.dossierTemplateId]; if (dictionaries) { rs.dictionariesCount = Object.keys(dictionaries) diff --git a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html index ab90c8b99..599bf6e44 100644 --- a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html @@ -44,7 +44,7 @@
diff --git a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts index f66cf50a0..9a65a16ff 100644 --- a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts @@ -31,9 +31,8 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent f.id), + this._appStateService.activeDossierTemplateId + ) .toPromise(); } await this._loadData(); @@ -95,7 +97,7 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent this._isNew(entry)) - .map(entry => this._makeDecorationFor(entry)); + const newDecorations = this.currentLines.filter(entry => this._isNew(entry)).map(entry => this._makeDecorationFor(entry)); this._decorations = this._codeEditor.deltaDecorations(this._decorations, newDecorations); } @@ -153,14 +149,12 @@ export class RulesScreenComponent extends ComponentHasChanges { } private _initialize() { - this._rulesControllerService - .downloadRules(this._appStateService.activeDossierTemplateId) - .subscribe( - rules => { - this.currentLines = this.initialLines = rules.rules.split('\n'); - this.revert(); - }, - () => (this.processing = false) - ); + this._rulesControllerService.downloadRules(this._appStateService.activeDossierTemplateId).subscribe( + rules => { + this.currentLines = this.initialLines = rules.rules.split('\n'); + this.revert(); + }, + () => (this.processing = false) + ); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.ts index a5d70e5b4..b36206694 100644 --- a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.ts @@ -79,51 +79,37 @@ export class SmtpConfigScreenComponent implements OnInit { async ngOnInit() { await this._loadData(); - this.generalSettings = await this._generalSettingsControllerService - .getGeneralConfigurations() - .toPromise(); + this.generalSettings = await this._generalSettingsControllerService.getGeneralConfigurations().toPromise(); this._initialGeneralSettings = Object.assign({}, this.generalSettings); } async save() { this.viewReady = false; - await this._smtpConfigService - .updateSMTPConfiguration(this.configForm.getRawValue()) - .toPromise(); + await this._smtpConfigService.updateSMTPConfiguration(this.configForm.getRawValue()).toPromise(); this._initialValue = this.configForm.getRawValue(); this.viewReady = true; } async saveGeneralConfig() { this.viewReady = false; - await this._generalSettingsControllerService - .updateGeneralConfigurations(this.generalSettings) - .toPromise(); + await this._generalSettingsControllerService.updateGeneralConfigurations(this.generalSettings).toPromise(); this.viewReady = true; } openAuthConfigDialog(skipDisableOnCancel?: boolean) { - this._dialogService.openDialog( - 'smtpAuthConfig', - null, - this.configForm.getRawValue(), - null, - authConfig => { - if (authConfig) { - this.configForm.patchValue(authConfig); - } else if (!skipDisableOnCancel) { - this.configForm.patchValue({ auth: false }, { emitEvent: false }); - } + this._dialogService.openDialog('smtpAuthConfig', null, this.configForm.getRawValue(), null, authConfig => { + if (authConfig) { + this.configForm.patchValue(authConfig); + } else if (!skipDisableOnCancel) { + this.configForm.patchValue({ auth: false }, { emitEvent: false }); } - ); + }); } async testConnection() { this.viewReady = false; try { - await this._smtpConfigService - .testSMTPConfiguration(this.configForm.getRawValue()) - .toPromise(); + await this._smtpConfigService.testSMTPConfiguration(this.configForm.getRawValue()).toPromise(); this._notificationService.showToastNotification( this._translateService.instant('smtp-config-screen.test.success'), undefined, @@ -142,9 +128,7 @@ export class SmtpConfigScreenComponent implements OnInit { private async _loadData() { try { - this._initialValue = await this._smtpConfigService - .getCurrentSMTPConfiguration() - .toPromise(); + this._initialValue = await this._smtpConfigService.getCurrentSMTPConfiguration().toPromise(); this.configForm.patchValue(this._initialValue, { emitEvent: false }); } catch (e) { } finally { diff --git a/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.ts index 259e0f8b6..b7f469d6c 100644 --- a/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.ts @@ -32,8 +32,7 @@ export class TrashScreenComponent extends BaseListingComponent implemen private readonly _appConfigService: AppConfigService ) { super(_injector); - this._sortingService.setScreenName(ScreenNames.DOSSIER_LISTING); - this._screenStateService.setIdKey('dossierId'); + this.sortingService.setScreenName(ScreenNames.DOSSIER_LISTING); } async ngOnInit(): Promise { @@ -46,7 +45,7 @@ export class TrashScreenComponent extends BaseListingComponent implemen } async loadDossierTemplatesData(): Promise { - this._screenStateService.setEntities(await this._dossiersService.getDeletedDossiers()); + this.screenStateService.setEntities(await this._dossiersService.getDeleted()); } getRestoreDate(softDeletedTime: string): string { @@ -57,11 +56,11 @@ export class TrashScreenComponent extends BaseListingComponent implemen return dossier.dossierId; } - bulkDelete(dossierIds = this._screenStateService.selectedEntitiesIds) { + bulkDelete(dossierIds = this.screenStateService.selectedEntities.map(d => d.dossierId)) { this._loadingService.loadWhile(this._hardDelete(dossierIds)); } - bulkRestore(dossierIds = this._screenStateService.selectedEntitiesIds) { + bulkRestore(dossierIds = this.screenStateService.selectedEntities.map(d => d.dossierId)) { this._loadingService.loadWhile(this._restore(dossierIds)); } @@ -76,9 +75,9 @@ export class TrashScreenComponent extends BaseListingComponent implemen } private _removeFromList(ids: string[]): void { - const entities = this._screenStateService.entities.filter(e => !ids.includes(e.dossierId)); - this._screenStateService.setEntities(entities); - this._screenStateService.setSelectedEntitiesIds([]); + const entities = this.screenStateService.allEntities.filter(e => !ids.includes(e.dossierId)); + this.screenStateService.setEntities(entities); + this.screenStateService.setSelectedEntities([]); this.filterService.filterEntities(); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html index f83253c24..d1b4aca33 100644 --- a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html @@ -9,7 +9,7 @@
@@ -38,28 +38,19 @@
- {{ - 'user-listing.table-header.title' - | translate: { length: (displayedEntities$ | async)?.length } - }} + {{ 'user-listing.table-header.title' | translate: { length: (displayedEntities$ | async)?.length } }}
- + - + - + - +
@@ -98,14 +80,9 @@ -
+
- +
diff --git a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts index 8b7edbee3..e462094ab 100644 --- a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts @@ -39,12 +39,11 @@ export class UserListingScreenComponent extends BaseListingComponent imple protected readonly _injector: Injector ) { super(_injector); - this._screenStateService.setIdKey('userId'); } get canDeleteSelected$(): Observable { - const entities$ = this._screenStateService.selectedEntitiesIds$; - return entities$.pipe(map(all => all.indexOf(this.userService.userId) === -1)); + const entities$ = this.screenStateService.selectedEntities$; + return entities$.pipe(map(all => all.indexOf(this.userService.user) === -1)); } async ngOnInit() { @@ -79,7 +78,7 @@ export class UserListingScreenComponent extends BaseListingComponent imple } bulkDelete() { - this.openDeleteUsersDialog(this._screenStateService.entities.filter(u => this.isSelected(u))); + this.openDeleteUsersDialog(this.screenStateService.allEntities.filter(u => this.isSelected(u))); } trackById(index: number, user: User) { @@ -87,7 +86,7 @@ export class UserListingScreenComponent extends BaseListingComponent imple } private async _loadData() { - this._screenStateService.setEntities(await this._userControllerService.getAllUsers().toPromise()); + this.screenStateService.setEntities(await this._userControllerService.getAllUsers().toPromise()); await this.userService.loadAllUsers(); this.filterService.filterEntities(); this._computeStats(); diff --git a/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts b/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts index 47f2dfe2b..9e3f0584c 100644 --- a/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, Output } from '@angular/core'; import { AppStateService } from '@state/app-state.service'; import { UserService } from '@services/user.service'; import { FileManagementControllerService, ReanalysisControllerService } from '@redaction/red-ui-http'; @@ -8,8 +8,9 @@ import { FileActionService } from '../../services/file-action.service'; import { from, Observable } from 'rxjs'; import { StatusOverlayService } from '@upload-download/services/status-overlay.service'; import { DossiersDialogService } from '../../services/dossiers-dialog.service'; -import { LoadingService } from '@services/loading.service'; -import { ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component'; +import { LoadingService } from '../../../../services/loading.service'; +import { ConfirmationDialogInput } from '../../../shared/dialogs/confirmation-dialog/confirmation-dialog.component'; +import { ScreenStateService } from '../../../shared/services/screen-state.service'; @Component({ selector: 'redaction-dossier-overview-bulk-actions', @@ -17,8 +18,6 @@ import { ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/con styleUrls: ['./dossier-overview-bulk-actions.component.scss'] }) export class DossierOverviewBulkActionsComponent { - @Input() - selectedFileIds: string[]; @Output() reload = new EventEmitter(); @@ -32,7 +31,8 @@ export class DossierOverviewBulkActionsComponent { private readonly _fileActionService: FileActionService, private readonly _statusOverlayService: StatusOverlayService, private readonly _changeDetectorRef: ChangeDetectorRef, - private readonly _loadingService: LoadingService + private readonly _loadingService: LoadingService, + private readonly _screenStateService: ScreenStateService ) {} get dossier() { @@ -40,30 +40,27 @@ export class DossierOverviewBulkActionsComponent { } get selectedFiles(): FileStatusWrapper[] { - return this.selectedFileIds.map(fileId => - this._appStateService.getFileById(this._appStateService.activeDossier.dossier.dossierId, fileId) - ); + return this._screenStateService.selectedEntities; } get areAllFilesSelected() { return ( this._appStateService.activeDossier.files.length !== 0 && - this.selectedFileIds.length === this._appStateService.activeDossier.files.length + this.selectedFiles.length === this._appStateService.activeDossier.files.length ); } get areSomeFilesSelected() { - return this.selectedFileIds.length > 0; + return this.selectedFiles.length > 0; } get allSelectedFilesCanBeAssignedIntoSameState() { if (this.areSomeFilesSelected) { - const selectedFiles = this.selectedFiles; - const allFilesAreUnderReviewOrUnassigned = selectedFiles.reduce( + const allFilesAreUnderReviewOrUnassigned = this.selectedFiles.reduce( (acc, file) => acc && (file.isUnderReview || file.isUnassigned), true ); - const allFilesAreUnderApproval = selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true); + const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true); return allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval; } return false; @@ -139,11 +136,14 @@ export class DossierOverviewBulkActionsComponent { async () => { this._loadingService.start(); await this._fileManagementControllerService - .deleteFiles(this.selectedFileIds, this._appStateService.activeDossierId) + .deleteFiles( + this.selectedFiles.map(item => item.fileId), + this._appStateService.activeDossierId + ) .toPromise(); await this._appStateService.reloadActiveDossierFiles(); this.reload.emit(); - this.selectedFileIds.splice(0, this.selectedFileIds.length); + this._screenStateService.setSelectedEntities([]); this._loadingService.stop(); } ); @@ -153,12 +153,9 @@ export class DossierOverviewBulkActionsComponent { // If more than 1 approver - show dialog and ask who to assign if (this._appStateService.activeDossier.approverIds.length > 1) { this._loadingService.start(); - const files = this.selectedFileIds.map(fileId => - this._appStateService.getFileById(this._appStateService.activeDossierId, fileId) - ); this._dialogService.openAssignFileToUserDialog( - files, + this.selectedFiles, 'approver', () => { this.reload.emit(); @@ -198,11 +195,10 @@ export class DossierOverviewBulkActionsComponent { assign() { this._loadingService.start(); - const files = this.selectedFileIds.map(fileId => this._appStateService.getFileById(this._appStateService.activeDossierId, fileId)); - const mode = files[0].isUnderApproval ? 'approver' : 'reviewer'; + const mode = this.selectedFiles[0].isUnderApproval ? 'approver' : 'reviewer'; - this._dialogService.openAssignFileToUserDialog(files, mode, () => { + this._dialogService.openAssignFileToUserDialog(this.selectedFiles, mode, () => { this.reload.emit(); this._loadingService.stop(); }); diff --git a/apps/red-ui/src/app/modules/dossier/components/dossier-details/dossier-details.component.html b/apps/red-ui/src/app/modules/dossier/components/dossier-details/dossier-details.component.html index da86fc640..95b943ae7 100644 --- a/apps/red-ui/src/app/modules/dossier/components/dossier-details/dossier-details.component.html +++ b/apps/red-ui/src/app/modules/dossier/components/dossier-details/dossier-details.component.html @@ -38,12 +38,10 @@
@@ -65,9 +63,9 @@ >
-
+
-
{{ appStateService.activeDossier.dossier.description }}
+
{{ description }}
diff --git a/apps/red-ui/src/app/modules/dossier/components/dossier-details/dossier-details.component.ts b/apps/red-ui/src/app/modules/dossier/components/dossier-details/dossier-details.component.ts index 3eba24b9d..39de289e9 100644 --- a/apps/red-ui/src/app/modules/dossier/components/dossier-details/dossier-details.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/dossier-details/dossier-details.component.ts @@ -18,6 +18,7 @@ import { DossierAttributeWithValue } from '@models/dossier-attributes.model'; styleUrls: ['./dossier-details.component.scss'] }) export class DossierDetailsComponent implements OnInit { + readonly i18nKey = 'dossier-overview.dossier-details.'; documentsChartData: DoughnutChartConfig[] = []; owner: User; editingOwner = false; @@ -71,7 +72,7 @@ export class DossierDetailsComponent implements OnInit { key: key }); } - this.documentsChartData.sort((a, b) => StatusSorter[a.key] - StatusSorter[b.key]); + this.documentsChartData.sort(StatusSorter.byKey); this.documentsChartData = this.translateChartService.translateStatus(this.documentsChartData); this._changeDetectorRef.detectChanges(); } @@ -80,7 +81,7 @@ export class DossierDetailsComponent implements OnInit { this.owner = typeof user === 'string' ? this._userService.getRedUserById(user) : user; const dw = Object.assign({}, this.appStateService.activeDossier); dw.dossier.ownerId = this.owner.userId; - await this.appStateService.addOrUpdateDossier(dw.dossier); + await this.appStateService.createOrUpdateDossier(dw.dossier); const ownerName = this._userService.getNameForId(this.owner.userId); const dossierName = this.appStateService.activeDossier.name; diff --git a/apps/red-ui/src/app/modules/dossier/components/dossier-listing-details/dossier-listing-details.component.html b/apps/red-ui/src/app/modules/dossier/components/dossier-listing-details/dossier-listing-details.component.html index 1bb665327..6609a95ad 100644 --- a/apps/red-ui/src/app/modules/dossier/components/dossier-listing-details/dossier-listing-details.component.html +++ b/apps/red-ui/src/app/modules/dossier/components/dossier-listing-details/dossier-listing-details.component.html @@ -27,7 +27,6 @@
- this.userService - .getNameForId(user.userId) - .toLowerCase() - .includes(searchQuery.toLowerCase()) - ) + .filter(user => this.userService.getNameForId(user.userId).toLowerCase().includes(searchQuery.toLowerCase())) .filter(user => this.selectedOwnerId !== user.userId) .map(user => user.userId); } @@ -76,10 +71,7 @@ export class TeamMembersManagerComponent implements OnInit { const initialApprovers = this.dossierWrapper.approverIds.sort(); const currentApprovers = this.selectedApproversList.sort(); - return ( - this._compareLists(initialMembers, currentMembers) || - this._compareLists(initialApprovers, currentApprovers) - ); + return this._compareLists(initialMembers, currentMembers) || this._compareLists(initialApprovers, currentApprovers); } isOwner(userId: string): boolean { @@ -96,7 +88,7 @@ export class TeamMembersManagerComponent implements OnInit { dw.dossier.memberIds = memberIds; dw.dossier.approverIds = approverIds; dw.dossier.ownerId = ownerId; - result = await this._appStateService.addOrUpdateDossier(dw.dossier); + result = await this._appStateService.createOrUpdateDossier(dw.dossier); this.save.emit(result); } catch (error) { this._notificationService.showToastNotification( diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts index f00e4e4bb..a0cf0b415 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts @@ -35,10 +35,7 @@ export class AddDossierDialogComponent { }, { validators: control => - control.value.reportTypes?.length > 0 || - control.value.downloadFileTypes?.length > 0 - ? null - : { downloadPackage: true } + control.value.reportTypes?.length > 0 || control.value.downloadFileTypes?.length > 0 ? null : { downloadPackage: true } } ); } @@ -62,14 +59,12 @@ export class AddDossierDialogComponent { async saveDossier() { const dossier: Dossier = this._formToObject(); - const foundDossier = this._appStateService.allDossiers.find( - p => p.dossier.dossierId === dossier.dossierId - ); + const foundDossier = this._appStateService.allDossiers.find(p => p.dossier.dossierId === dossier.dossierId); if (foundDossier) { dossier.memberIds = foundDossier.memberIds; } - const savedDossier = await this._appStateService.addOrUpdateDossier(dossier); + const savedDossier = await this._appStateService.createOrUpdateDossier(dossier); if (savedDossier) { this.dialogRef.close({ dossier: savedDossier }); } @@ -77,7 +72,7 @@ export class AddDossierDialogComponent { async saveDossierAndAddMembers() { const dossier: Dossier = this._formToObject(); - const savedDossier = await this._appStateService.addOrUpdateDossier(dossier); + const savedDossier = await this._appStateService.createOrUpdateDossier(dossier); if (savedDossier) { this.dialogRef.close({ addMembers: true, dossier: savedDossier }); } @@ -85,9 +80,7 @@ export class AddDossierDialogComponent { dossierTemplateChanged(dossierTemplateId) { // get current selected dossierTemplate - const dossierTemplate = this.dossierTemplates.find( - r => r.dossierTemplateId === dossierTemplateId - ); + const dossierTemplate = this.dossierTemplates.find(r => r.dossierTemplateId === dossierTemplateId); if (dossierTemplate) { // update dropdown values this.dossierForm.patchValue( diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts index 362872dd8..0c7390409 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts @@ -111,15 +111,9 @@ export class AssignReviewerApproverDialogComponent { uniqueReviewers.add(file.currentReviewer); } } - let singleUser = - uniqueReviewers.size === 1 - ? uniqueReviewers.values().next().value - : this.userService.userId; + let singleUser = uniqueReviewers.size === 1 ? uniqueReviewers.values().next().value : this.userService.userId; - singleUser = - this.singleUsersSelectOptions.indexOf(singleUser) >= 0 - ? singleUser - : this.singleUsersSelectOptions[0]; + singleUser = this.singleUsersSelectOptions.indexOf(singleUser) >= 0 ? singleUser : this.singleUsersSelectOptions[0]; this.usersForm = this._formBuilder.group({ singleUser: [singleUser, Validators.required] diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts index c00e79dab..b336ede21 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts @@ -71,7 +71,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS downloadFileTypes: this.dossierForm.get('downloadFileTypes').value, reportTypes: this.dossierForm.get('reportTypes').value }; - const updatedDossier = await this._appStateService.addOrUpdateDossier(dossier); + const updatedDossier = await this._appStateService.createOrUpdateDossier(dossier); this.updateDossier.emit(updatedDossier); } diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts index 3435b47be..3fd26d42d 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts @@ -10,7 +10,7 @@ import { PermissionsService } from '@services/permissions.service'; import { Router } from '@angular/router'; import { MatDialogRef } from '@angular/material/dialog'; import { EditDossierDialogComponent } from '../edit-dossier-dialog.component'; -import { NotificationService, NotificationType } from '@services/notification.service'; +import { NotificationService, NotificationType } from '../../../../../services/notification.service'; import { TranslateService } from '@ngx-translate/core'; @Component({ @@ -100,7 +100,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti dueDate: this.hasDueDate ? this.dossierForm.get('dueDate').value : undefined, dossierTemplateId: this.dossierForm.get('dossierTemplateId').value }; - const updatedDossier = await this._appStateService.addOrUpdateDossier(dossier); + const updatedDossier = await this._appStateService.createOrUpdateDossier(dossier); if (updatedDossier) this.updateDossier.emit(updatedDossier); } diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.ts index 2b1720166..a0b321d23 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.ts @@ -7,8 +7,8 @@ import { groupBy } from '@utils/functions'; import { TranslateService } from '@ngx-translate/core'; import { PermissionsService } from '@services/permissions.service'; import { DossierWrapper } from '@state/model/dossier.wrapper'; -import { Subscription, timer } from 'rxjs'; -import { filter, tap } from 'rxjs/operators'; +import { timer } from 'rxjs'; +import { filter } from 'rxjs/operators'; import { TranslateChartService } from '@services/translate-chart.service'; import { RedactionFilterSorter } from '@utils/sorters/redaction-filter-sorter'; import { StatusSorter } from '@utils/sorters/status-sorter'; @@ -30,12 +30,15 @@ import { ScreenStateService } from '@shared/services/screen-state.service'; import { BaseListingComponent } from '@shared/base/base-listing.component'; import { ScreenNames, SortingService } from '@services/sorting.service'; +const isLeavingScreen = event => event instanceof NavigationStart && event.url !== '/main/dossiers'; + @Component({ templateUrl: './dossier-listing-screen.component.html', styleUrls: ['./dossier-listing-screen.component.scss'], providers: [FilterService, SearchService, ScreenStateService, SortingService] }) export class DossierListingScreenComponent extends BaseListingComponent implements OnInit, OnDestroy, OnAttach, OnDetach { + readonly itemSize = 95; dossiersChartData: DoughnutChartConfig[] = []; documentsChartData: DoughnutChartConfig[] = []; buttonConfigs: ButtonConfig[] = [ @@ -48,12 +51,7 @@ export class DossierListingScreenComponent extends BaseListingComponent; @@ -70,65 +68,43 @@ export class DossierListingScreenComponent extends BaseListingComponent p.dossier.status === Dossier.StatusEnum.ACTIVE).length; - } - - private get _inactiveDossiersCount(): number { - return this._screenStateService.entities.length - this._activeDossiersCount; - } - ngOnInit(): void { this.calculateData(); - this._dossierAutoUpdateTimer = timer(0, 10000) - .pipe( - tap(async () => { - await this._appStateService.loadAllDossiers(); - this._loadEntitiesFromState(); - this.calculateData(); - }) - ) - .subscribe(); - - this._fileChangedSub = this._appStateService.fileChanged.subscribe(() => { + this.addSubscription = timer(0, 10000).subscribe(async () => { + await this._appStateService.loadAllDossiers(); + this._loadEntitiesFromState(); this.calculateData(); }); - this._routerEventsScrollPositionSub = this._router.events - .pipe(filter(event => event instanceof NavigationStart)) - .subscribe((event: NavigationStart) => { - if (event.url !== '/main/dossiers') { - this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top'); - } - }); + this.addSubscription = this._appStateService.fileChanged.subscribe(() => { + this.calculateData(); + }); + + this.addSubscription = this._router.events.pipe(filter(isLeavingScreen)).subscribe(() => { + this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top'); + }); } ngOnAttach() { + this.scrollViewport.scrollTo({ top: this._lastScrollPosition }); this._appStateService.reset(); this._loadEntitiesFromState(); this.ngOnInit(); - this.scrollViewport.scrollTo({ top: this._lastScrollPosition }); } - ngOnDetach() { + ngOnDetach(): void { this.ngOnDestroy(); } ngOnDestroy(): void { - this._dossierAutoUpdateTimer.unsubscribe(); - this._routerEventsScrollPositionSub.unsubscribe(); - this._fileChangedSub.unsubscribe(); + super.ngOnDestroy(); } getDossierTemplate(dw: DossierWrapper): DossierTemplateModel { @@ -147,6 +123,18 @@ export class DossierListingScreenComponent extends BaseListingComponent p.dossier.status === Dossier.StatusEnum.ACTIVE).length; + } + + private get _inactiveDossiersCount(): number { + return this.screenStateService.allEntities.length - this._activeDossiersCount; + } + calculateData() { this._computeAllFilters(); @@ -165,12 +153,12 @@ export class DossierListingScreenComponent extends BaseListingComponent StatusSorter[a.key] - StatusSorter[b.key]); + this.documentsChartData.sort(StatusSorter.byKey); this.documentsChartData = this._translateChartService.translateStatus(this.documentsChartData); } private _loadEntitiesFromState() { - this._screenStateService.setEntities(this._appStateService.allDossiers); + this.screenStateService.setEntities(this._appStateService.allDossiers); } private _computeAllFilters() { @@ -179,7 +167,7 @@ export class DossierListingScreenComponent extends BaseListingComponent(); const allDistinctDossierTemplates = new Set(); - this._screenStateService?.entities?.forEach(entry => { + this.screenStateService?.allEntities?.forEach(entry => { // all people entry.dossier.memberIds.forEach(f => allDistinctPeople.add(f)); // Needs work @@ -267,22 +255,22 @@ export class DossierListingScreenComponent extends BaseListingComponent dw.ownerId === this._user.id + checker: (dw: DossierWrapper) => dw.ownerId === this._userId }, { key: 'to-approve', label: this._translateService.instant('dossier-listing.quick-filters.to-approve'), - checker: (dw: DossierWrapper) => dw.approverIds.includes(this._user.id) + checker: (dw: DossierWrapper) => dw.approverIds.includes(this._userId) }, { key: 'to-review', label: this._translateService.instant('dossier-listing.quick-filters.to-review'), - checker: (dw: DossierWrapper) => dw.memberIds.includes(this._user.id) + checker: (dw: DossierWrapper) => dw.memberIds.includes(this._userId) }, { key: 'other', label: this._translateService.instant('dossier-listing.quick-filters.other'), - checker: (dw: DossierWrapper) => !dw.memberIds.includes(this._user.id) + checker: (dw: DossierWrapper) => !dw.memberIds.includes(this._userId) } ]; diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html index a80cc7fc4..e7d1c42b5 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html @@ -49,10 +49,7 @@ {{ 'dossier-overview.table-header.title' | translate: { length: (displayedEntities$ | async)?.length || 0 } }} - +
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts index 3ee41e805..88c1161d3 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts @@ -12,9 +12,8 @@ import { DossierDetailsComponent } from '../../components/dossier-details/dossie import { FileStatusWrapper } from '@models/file/file-status.wrapper'; import { PermissionsService } from '@services/permissions.service'; import { UserService } from '@services/user.service'; -import { FileStatus, UserPreferenceControllerService } from '@redaction/red-ui-http'; -import { Subscription, timer } from 'rxjs'; -import { filter, tap } from 'rxjs/operators'; +import { timer } from 'rxjs'; +import { filter } from 'rxjs/operators'; import { RedactionFilterSorter } from '@utils/sorters/redaction-filter-sorter'; import { StatusSorter } from '@utils/sorters/status-sorter'; import { convertFiles, handleFileDrop } from '@utils/file-drop-utils'; @@ -33,6 +32,7 @@ import { BaseListingComponent } from '@shared/base/base-listing.component'; import { LoadingService } from '@services/loading.service'; import { DossierAttributesService } from '@shared/services/controller-wrappers/dossier-attributes.service'; import { DossierAttributeWithValue } from '@models/dossier-attributes.model'; +import { UserPreferenceService } from '../../../../services/user-preference.service'; @Component({ templateUrl: './dossier-overview-screen.component.html', @@ -49,11 +49,9 @@ export class DossierOverviewScreenComponent dossierAttributes: DossierAttributeWithValue[] = []; @ViewChild(DossierDetailsComponent, { static: false }) private readonly _dossierDetailsComponent: DossierDetailsComponent; - private _filesAutoUpdateTimer: Subscription; - private _routerEventsScrollPositionSub: Subscription; - private _fileChangedSub: Subscription; private _lastScrollPosition: number; - private _lastOpenedFileId = ''; + private _lastOpenedFileKey = 'Dossier-Recent-' + this.activeDossier.dossierId; + @ViewChild('needsWorkTemplate', { read: TemplateRef, static: true }) private readonly _needsWorkTemplate: TemplateRef; @ViewChild('fileInput') private _fileInput: ElementRef; @@ -69,7 +67,7 @@ export class DossierOverviewScreenComponent private readonly _translateService: TranslateService, private readonly _fileDropOverlayService: FileDropOverlayService, private readonly _appStateService: AppStateService, - private readonly _userPreferenceControllerService: UserPreferenceControllerService, + private readonly _userPreferenceService: UserPreferenceService, private readonly _appConfigService: AppConfigService, private readonly _changeDetectorRef: ChangeDetectorRef, private readonly _loadingService: LoadingService, @@ -77,9 +75,8 @@ export class DossierOverviewScreenComponent protected readonly _injector: Injector ) { super(_injector); - this._sortingService.setScreenName(ScreenNames.DOSSIER_OVERVIEW); - this._searchService.setSearchKey('searchField'); - this._screenStateService.setIdKey('fileId'); + this.sortingService.setScreenName(ScreenNames.DOSSIER_OVERVIEW); + this.searchService.setSearchKey('searchField'); this._loadEntitiesFromState(); } @@ -99,30 +96,26 @@ export class DossierOverviewScreenComponent return this.filterService.getFilter('quickFilters')?.values.filter(f => !f.required && f.checked); } - isLastOpenedFile(fileStatus: FileStatusWrapper): boolean { - return this._lastOpenedFileId === fileStatus.fileId; + isLastOpenedFile({ fileId }: FileStatusWrapper): boolean { + return this._userPreferenceService.getLastOpenedFileId(this._lastOpenedFileKey) === fileId; } - async ngOnInit() { + async ngOnInit(): Promise { this._fileDropOverlayService.initFileDropHandling(); this.calculateData(); - this._filesAutoUpdateTimer = timer(0, 7500) - .pipe( - tap(async () => { - await this._appStateService.reloadActiveDossierFilesIfNecessary(); - this._loadEntitiesFromState(); - }) - ) - .subscribe(); + this.addSubscription = timer(0, 7500).subscribe(async () => { + await this._appStateService.reloadActiveDossierFilesIfNecessary(); + this._loadEntitiesFromState(); + }); - this._fileChangedSub = this._appStateService.fileChanged.subscribe(() => { + this.addSubscription = this._appStateService.fileChanged.subscribe(() => { this.calculateData(); }); - this._routerEventsScrollPositionSub = this._router.events - .pipe(filter(events => events instanceof NavigationStart)) + this.addSubscription = this._router.events + .pipe(filter(event => event instanceof NavigationStart)) .subscribe((event: NavigationStart) => { if (!event.url.endsWith(this._appStateService.activeDossierId)) { this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top'); @@ -131,13 +124,6 @@ export class DossierOverviewScreenComponent this._loadingService.start(); - const userAttributes = await this._userPreferenceControllerService.getAllUserAttributes(); - if (userAttributes === null || userAttributes === undefined) return; - const key = 'Dossier-Recent-' + this.activeDossier.dossierId; - if (userAttributes[key]?.length > 0) { - this._lastOpenedFileId = userAttributes[key][0]; - } - this.dossierAttributes = await this._dossierAttributesService.getValues(this.activeDossier); this._loadingService.stop(); @@ -145,9 +131,7 @@ export class DossierOverviewScreenComponent ngOnDestroy(): void { this._fileDropOverlayService.cleanupFileDropHandling(); - this._filesAutoUpdateTimer.unsubscribe(); - this._fileChangedSub.unsubscribe(); - this._routerEventsScrollPositionSub.unsubscribe(); + super.ngOnDestroy(); } async ngOnAttach() { @@ -180,18 +164,8 @@ export class DossierOverviewScreenComponent }); } - isError(fileStatusWrapper: FileStatusWrapper) { - return fileStatusWrapper.status === FileStatus.StatusEnum.ERROR; - } - - isProcessing(fileStatusWrapper: FileStatusWrapper) { - return [FileStatus.StatusEnum.REPROCESS, FileStatus.StatusEnum.FULLREPROCESS, FileStatus.StatusEnum.PROCESSING].includes( - fileStatusWrapper.status - ); - } - reloadDossiers() { - this._appStateService.getFiles(this._appStateService.activeDossier, false).then(() => { + this._appStateService.getFiles(this.activeDossier, false).then(() => { this.calculateData(); }); } @@ -235,7 +209,7 @@ export class DossierOverviewScreenComponent } bulkActionPerformed() { - this._screenStateService.selectedEntitiesIds$.next([]); + this.screenStateService.setSelectedEntities([]); this.reloadDossiers(); } @@ -271,15 +245,12 @@ 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.screenStateService.setEntities(this.activeDossier.files); } private async _uploadFiles(files: FileUploadModel[]) { const fileCount = await this._fileUploadService.uploadFiles(files); - if (fileCount) { - this._statusOverlayService.openUploadStatusOverlay(); - } - // this._changeDetectorRef.detectChanges(); + if (fileCount) this._statusOverlayService.openUploadStatusOverlay(); } private _computeAllFilters() { @@ -290,7 +261,7 @@ export class DossierOverviewScreenComponent const allDistinctAddedDates = new Set(); const allDistinctNeedsWork = new Set(); - this._screenStateService.entities.forEach(file => { + this.screenStateService.allEntities.forEach(file => { allDistinctPeople.add(file.currentReviewer); allDistinctFileStatusWrapper.add(file.status); allDistinctAddedDates.add(moment(file.added).format('DD/MM/YYYY')); @@ -370,7 +341,7 @@ export class DossierOverviewScreenComponent private _createQuickFilters() { let quickFilters = []; - if (this._screenStateService.entities.filter(this.recentlyModifiedChecker).length > 0) { + if (this.screenStateService.allEntities.filter(this.recentlyModifiedChecker).length > 0) { const recentPeriod = this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS); quickFilters = [ { diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts index 7dcf7a362..15c433e57 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts @@ -34,7 +34,7 @@ import { DossiersDialogService } from '../../services/dossiers-dialog.service'; import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy'; import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model'; import { handleFilterDelta, processFilters } from '@shared/components/filters/popup-filter/utils/filter-utils'; -import { LoadingService } from '@services/loading.service'; +import { LoadingService } from '../../../../services/loading.service'; import { stampPDFPage } from '../../../../utils/page-stamper'; import { TranslateService } from '@ngx-translate/core'; diff --git a/apps/red-ui/src/app/modules/dossier/services/dossiers.service.ts b/apps/red-ui/src/app/modules/dossier/services/dossiers.service.ts index df92dfe8f..1379a4b02 100644 --- a/apps/red-ui/src/app/modules/dossier/services/dossiers.service.ts +++ b/apps/red-ui/src/app/modules/dossier/services/dossiers.service.ts @@ -1,11 +1,25 @@ import { Injectable } from '@angular/core'; -import { DossierControllerService } from '@redaction/red-ui-http'; +import { Dossier, DossierControllerService } from '@redaction/red-ui-http'; -@Injectable() +@Injectable({ + providedIn: 'root' +}) export class DossiersService { constructor(private readonly _dossierControllerService: DossierControllerService) {} - getDeletedDossiers() { + createOrUpdate(dossier: Dossier): Promise { + return this._dossierControllerService.createOrUpdateDossier(dossier).toPromise(); + } + + delete(dossierId: string): Promise { + return this._dossierControllerService.deleteDossier(dossierId).toPromise(); + } + + getAll(): Promise { + return this._dossierControllerService.getDossiers().toPromise(); + } + + getDeleted(): Promise { return this._dossierControllerService.getDeletedDossiers().toPromise(); } diff --git a/apps/red-ui/src/app/modules/dossier/services/manual-annotation.service.ts b/apps/red-ui/src/app/modules/dossier/services/manual-annotation.service.ts index 990fd71c5..055e3670d 100644 --- a/apps/red-ui/src/app/modules/dossier/services/manual-annotation.service.ts +++ b/apps/red-ui/src/app/modules/dossier/services/manual-annotation.service.ts @@ -77,12 +77,7 @@ export class ManualAnnotationService { return obs.pipe( tap( () => this._notify(this._getMessage(mode)), - error => - this._notify( - this._getMessage(mode, modifyDictionary, true), - NotificationType.ERROR, - error - ) + error => this._notify(this._getMessage(mode, modifyDictionary, true), NotificationType.ERROR, error) ) ); } @@ -124,9 +119,7 @@ export class ManualAnnotationService { // /manualRedaction/redaction/legalBasisChange // /manualRedaction/request/legalBasis changeLegalBasis(annotationId: string, legalBasis: string, comment?: string) { - const mode: Mode = this._permissionsService.isApprover() - ? 'change-legal-basis' - : 'request-change-legal-basis'; + const mode: Mode = this._permissionsService.isApprover() ? 'change-legal-basis' : 'request-change-legal-basis'; return this._makeRequest(mode, { annotationId, legalBasis, comment }); } @@ -134,9 +127,7 @@ export class ManualAnnotationService { // /manualRedaction/redaction/recategorize // /manualRedaction/request/recategorize recategorizeImage(annotationId: string, type: string, comment: string) { - const mode: Mode = this._permissionsService.isApprover() - ? 'recategorize-image' - : 'request-image-recategorization'; + const mode: Mode = this._permissionsService.isApprover() ? 'recategorize-image' : 'request-image-recategorization'; return this._makeRequest(mode, { annotationId, type, comment }); } @@ -145,21 +136,14 @@ export class ManualAnnotationService { // /manualRedaction/request/add addAnnotation(manualRedactionEntry: AddRedactionRequest) { const mode: Mode = this._permissionsService.isApprover() ? 'add' : 'suggest'; - return this._makeRequest( - mode, - manualRedactionEntry, - null, - manualRedactionEntry.addToDictionary - ); + return this._makeRequest(mode, manualRedactionEntry, null, manualRedactionEntry.addToDictionary); } // this wraps // /manualRedaction/redaction/force // /manualRedaction/request/force forceRedaction(request: ForceRedactionRequest) { - const mode: Mode = this._permissionsService.isApprover() - ? 'force-redaction' - : 'request-force-redaction'; + const mode: Mode = this._permissionsService.isApprover() ? 'force-redaction' : 'request-force-redaction'; return this._makeRequest(mode, request); } @@ -167,21 +151,11 @@ export class ManualAnnotationService { // /manualRedaction/approve approveRequest(annotationId: string, addToDictionary: boolean = false) { // for only here - approve the request - return this._makeRequest( - 'approve', - { addOrRemoveFromDictionary: addToDictionary }, - annotationId, - addToDictionary - ); + return this._makeRequest('approve', { addOrRemoveFromDictionary: addToDictionary }, annotationId, addToDictionary); } undoRequest(annotationWrapper: AnnotationWrapper) { - return this._makeRequest( - 'undo', - annotationWrapper.id, - null, - annotationWrapper.isModifyDictionary - ); + return this._makeRequest('undo', annotationWrapper.id, null, annotationWrapper.isModifyDictionary); } // this wraps @@ -189,21 +163,13 @@ export class ManualAnnotationService { // /manualRedaction/undo declineOrRemoveRequest(annotationWrapper: AnnotationWrapper) { const mode: Mode = this._permissionsService.isApprover() ? 'decline' : 'undo'; - return this._makeRequest( - mode, - annotationWrapper.id, - null, - annotationWrapper.isModifyDictionary - ); + return this._makeRequest(mode, annotationWrapper.id, null, annotationWrapper.isModifyDictionary); } // this wraps // /manualRedaction/redaction/remove/ // /manualRedaction/request/remove/ - removeOrSuggestRemoveAnnotation( - annotationWrapper: AnnotationWrapper, - removeFromDictionary: boolean = false - ) { + removeOrSuggestRemoveAnnotation(annotationWrapper: AnnotationWrapper, removeFromDictionary: boolean = false) { let mode: Mode, body: any, removeDict = false; @@ -258,15 +224,10 @@ export class ManualAnnotationService { } private _notify(key: string, type: NotificationType = NotificationType.SUCCESS, data?: any) { - this._notificationService.showToastNotification( - this._translateService.instant(key, data), - null, - type, - { - positionClass: 'toast-file-preview', - actions: [] - } - ); + this._notificationService.showToastNotification(this._translateService.instant(key, data), null, type, { + positionClass: 'toast-file-preview', + actions: [] + }); } private _getMessage(mode: Mode, modifyDictionary?: boolean, error: boolean = false) { diff --git a/apps/red-ui/src/app/modules/shared/base/auto-unsubscribe.component.ts b/apps/red-ui/src/app/modules/shared/base/auto-unsubscribe.component.ts new file mode 100644 index 000000000..680769e31 --- /dev/null +++ b/apps/red-ui/src/app/modules/shared/base/auto-unsubscribe.component.ts @@ -0,0 +1,29 @@ +import { Component, OnDestroy } from '@angular/core'; +import { Subscription } from 'rxjs'; + +/** + * Inherit this class when you need to subscribe to observables in your components + * + * @remarks You must explicitly call super.ngOnDestroy in you component to unsubscribe + */ +@Component({ template: '' }) +export abstract class AutoUnsubscribeComponent implements OnDestroy { + private _subscriptions = new Subscription(); + + /** + * Call this method when you want to subscribe to an observable + * @param subscription - the new subscription to add to subscriptions array + */ + set addSubscription(subscription: Subscription) { + this._subscriptions.closed = false; + this._subscriptions.add(subscription); + } + + /** + * This method unsubscribes active subscriptions + * Explicitly call this method in your component's ngOnDestroy + */ + ngOnDestroy(): void { + this._subscriptions.unsubscribe(); + } +} diff --git a/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts b/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts index cdb5858b6..7ba2a27aa 100644 --- a/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts +++ b/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts @@ -1,4 +1,4 @@ -import { Component, Injector, ViewChild } from '@angular/core'; +import { Component, Injector, OnDestroy, ViewChild } from '@angular/core'; import { SortingOption, SortingService } from '@services/sorting.service'; import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; import { FilterService } from '../services/filter.service'; @@ -6,58 +6,60 @@ import { SearchService } from '../services/search.service'; import { ScreenStateService } from '../services/screen-state.service'; import { Observable } from 'rxjs'; import { FilterModel } from '../components/filters/popup-filter/model/filter.model'; +import { AutoUnsubscribeComponent } from './auto-unsubscribe.component'; @Component({ template: '' }) -export abstract class BaseListingComponent { +export abstract class BaseListingComponent extends AutoUnsubscribeComponent implements OnDestroy { @ViewChild(CdkVirtualScrollViewport) readonly scrollViewport: CdkVirtualScrollViewport; readonly filterService: FilterService; - protected readonly _sortingService: SortingService; - protected readonly _searchService: SearchService; - protected readonly _screenStateService: ScreenStateService; + readonly sortingService: SortingService; + readonly searchService: SearchService; + readonly screenStateService: ScreenStateService; protected constructor(protected readonly _injector: Injector) { + super(); this.filterService = this._injector.get>(FilterService); - this._sortingService = this._injector.get(SortingService); - this._searchService = this._injector.get>(SearchService); - this._screenStateService = this._injector.get>(ScreenStateService); + this.sortingService = this._injector.get(SortingService); + this.searchService = this._injector.get>(SearchService); + this.screenStateService = this._injector.get>(ScreenStateService); } - get selectedEntitiesIds$(): Observable { - return this._screenStateService.selectedEntitiesIds$; + ngOnDestroy(): void { + super.ngOnDestroy(); + } + + get selectedEntities$(): Observable { + return this.screenStateService.selectedEntities$; } get displayedEntities$(): Observable { - return this._screenStateService.displayedEntities$; + return this.screenStateService.displayedEntities$; } get allEntities$(): Observable { - return this._screenStateService.entities$; + return this.screenStateService.allEntities$; } get displayedEntities(): T[] { - return this._screenStateService.displayedEntities; + return this.screenStateService.displayedEntities; } get allEntities(): T[] { - return this._screenStateService.entities; + return this.screenStateService.allEntities; } get areAllEntitiesSelected() { - return this._screenStateService.areAllEntitiesSelected; + return this.screenStateService.areAllEntitiesSelected; } - get areSomeEntitiesSelected$() { - return this._screenStateService.areSomeEntitiesSelected$; + get areSomeEntitiesSelected$(): Observable { + return this.screenStateService.areSomeEntitiesSelected$; } get sortingOption(): SortingOption { - return this._sortingService.getSortingOption(); - } - - get searchForm() { - return this._searchService.searchForm; + return this.sortingService.getSortingOption(); } get noMatch(): boolean { @@ -68,28 +70,20 @@ export abstract class BaseListingComponent { return this.allEntities.length === 0; } - getFilter$(slug: string): Observable { - return this.filterService.getFilter$(slug); - } - - resetFilters() { - this.filterService.reset(); - } - toggleSort($event) { - this._sortingService.toggleSort($event); + this.sortingService.toggleSort($event); } toggleSelectAll() { - return this._screenStateService.toggleSelectAll(); + return this.screenStateService.toggleSelectAll(); } toggleEntitySelected(event: MouseEvent, entity: T) { event.stopPropagation(); - return this._screenStateService.toggleEntitySelected(entity); + return this.screenStateService.toggleEntitySelected(entity); } - isSelected(entity: T) { - return this._screenStateService.isSelected(entity); + isSelected(entity: T): boolean { + return this.screenStateService.isSelected(entity); } } diff --git a/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts b/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts index e36b401a7..3233c7e4e 100644 --- a/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts @@ -36,25 +36,17 @@ export class FileDownloadBtnComponent { return this._permissionsService.canDownloadFiles(this.file); } - return ( - this.file.length > 0 && - this.file.reduce( - (acc, file) => acc && this._permissionsService.canDownloadFiles(file), - true - ) - ); + return this.file.length > 0 && this.file.reduce((acc, file) => acc && this._permissionsService.canDownloadFiles(file), true); } downloadFiles($event: MouseEvent) { $event.stopPropagation(); - this._fileDownloadService - .downloadFiles(Array.isArray(this.file) ? this.file : [this.file], this.dossier) - .subscribe(() => { - this._notificationService.showToastNotification( - this._translateService.instant('download-status.queued', { - baseUrl: this._baseHref - }) - ); - }); + this._fileDownloadService.downloadFiles(Array.isArray(this.file) ? this.file : [this.file], this.dossier).subscribe(() => { + this._notificationService.showToastNotification( + this._translateService.instant('download-status.queued', { + baseUrl: this._baseHref + }) + ); + }); } } diff --git a/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.html b/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.html index 577055adb..43f9c4c6c 100644 --- a/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.html +++ b/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.html @@ -8,7 +8,7 @@ > -
+
{{ displayedDataTotal }}
{{ subtitle | translate }}
@@ -37,7 +34,7 @@ (click)="selectValue(val.key)" *ngFor="let val of config" [class.active]="filterService.filterChecked$('statusFilters', val.key) | async" - [class.filter-disabled]="!filter" + [class.filter-disabled]="(filterService.getFilter$('statusFilters') | async)?.length === 0" > implements OnChanges { @Input() radius = 85; @Input() strokeWidth = 20; @Input() direction: 'row' | 'column' = 'column'; - @Input() filter: FilterModel[]; @Input() totalType: 'sum' | 'count' = 'sum'; @Input() counterText: string; - @Output() - toggleFilter = new EventEmitter(); chartData: any[] = []; perimeter: number; @@ -36,11 +32,11 @@ export class SimpleDoughnutChartComponent implements OnChanges { constructor(readonly filterService: FilterService) {} - get circumference() { + get circumference(): number { return 2 * Math.PI * this.radius; } - get dataTotal() { + get dataTotal(): number { return this.config.map(v => v.value).reduce((acc, val) => acc + val, 0); } @@ -56,48 +52,34 @@ export class SimpleDoughnutChartComponent implements OnChanges { } calculateChartData() { - const newData = []; let angleOffset = -90; - this.config.forEach(dataVal => { - if (dataVal.value > 0) { - const data = { - degrees: angleOffset - }; - newData.push(data); - angleOffset = this.dataPercentage(dataVal.value) * 360 + angleOffset; - } else { - newData.push(null); - } + this.chartData = this.config.map(dataVal => { + if (dataVal.value === 0) return null; + + const res = { degrees: angleOffset }; + angleOffset = this.dataPercentage(dataVal.value) * 360 + angleOffset; + return res; }); - this.chartData = newData; } - calculateStrokeDashOffset(dataVal) { + calculateStrokeDashOffset(dataVal: number): number { const strokeDiff = this.dataPercentage(dataVal) * this.circumference; return this.circumference - strokeDiff; } - dataPercentage(dataVal) { + dataPercentage(dataVal: number): number { return dataVal / this.dataTotal; } - returnCircleTransformValue(index) { + returnCircleTransformValue(index: number) { return `rotate(${this.chartData[index].degrees}, ${this.cx}, ${this.cy})`; } - getLabel(config: DoughnutChartConfig): string { - return this.totalType === 'sum' - ? `${config.value} ${config.label}` - : `${config.label} (${config.value} ${this.counterText})`; + getLabel({ label, value }: DoughnutChartConfig): string { + return this.totalType === 'sum' ? `${value} ${label}` : `${label} (${value} ${this.counterText})`; } - selectValue(key: string) { + selectValue(key: string): void { this.filterService.toggleFilter('statusFilters', key); - this.filterService.filterEntities(); - this.toggleFilter.emit(key); - } - - exists(index: number) { - return !!this.chartData[index]; } } diff --git a/apps/red-ui/src/app/modules/shared/services/filter.service.ts b/apps/red-ui/src/app/modules/shared/services/filter.service.ts index 172f17ef4..b26f019ef 100644 --- a/apps/red-ui/src/app/modules/shared/services/filter.service.ts +++ b/apps/red-ui/src/app/modules/shared/services/filter.service.ts @@ -1,9 +1,6 @@ import { ChangeDetectorRef, Injectable } from '@angular/core'; import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model'; -import { - getFilteredEntities, - processFilters -} from '@shared/components/filters/popup-filter/utils/filter-utils'; +import { getFilteredEntities, processFilters } from '@shared/components/filters/popup-filter/utils/filter-utils'; import { FilterWrapper } from '@shared/components/filters/popup-filter/model/filter-wrapper.model'; import { ScreenStateService } from '@shared/services/screen-state.service'; import { SearchService } from '@shared/services/search.service'; @@ -48,7 +45,7 @@ export class FilterService { } filterEntities(): void { - const filtered = getFilteredEntities(this._screenStateService.entities, this.filters); + const filtered = getFilteredEntities(this._screenStateService.allEntities, this.filters); this._screenStateService.setFilteredEntities(filtered); this._searchService.executeSearchImmediately(); @@ -98,8 +95,7 @@ export class FilterService { } private _toFlatFilters(entities: FilterWrapper[]): FilterModel[] { - const flatChildren = (filters: FilterModel[]) => - (filters ?? []).reduce((acc, f) => [...acc, ...(f?.filters ?? [])], []); + const flatChildren = (filters: FilterModel[]) => (filters ?? []).reduce((acc, f) => [...acc, ...(f?.filters ?? [])], []); return entities.reduce((acc, f) => [...acc, ...f.values, ...flatChildren(f.values)], []); } diff --git a/apps/red-ui/src/app/modules/shared/services/screen-state.service.ts b/apps/red-ui/src/app/modules/shared/services/screen-state.service.ts index 6c6c0d86d..e8305e8d0 100644 --- a/apps/red-ui/src/app/modules/shared/services/screen-state.service.ts +++ b/apps/red-ui/src/app/modules/shared/services/screen-state.service.ts @@ -4,23 +4,21 @@ import { distinctUntilChanged, map } from 'rxjs/operators'; @Injectable() export class ScreenStateService { - entities$ = new BehaviorSubject([]); + allEntities$ = new BehaviorSubject([]); filteredEntities$ = new BehaviorSubject([]); displayedEntities$ = new BehaviorSubject([]); - selectedEntitiesIds$ = new BehaviorSubject([]); + selectedEntities$ = new BehaviorSubject([]); - private _idKey: string; - - get entities(): T[] { - return Object.values(this.entities$.getValue()); + get allEntities(): T[] { + return Object.values(this.allEntities$.getValue()); } get filteredEntities(): T[] { return Object.values(this.filteredEntities$.getValue()); } - get selectedEntitiesIds(): string[] { - return Object.values(this.selectedEntitiesIds$.getValue()); + get selectedEntities(): T[] { + return Object.values(this.selectedEntities$.getValue()); } get displayedEntities(): T[] { @@ -28,85 +26,62 @@ export class ScreenStateService { } map(func: (state: T[]) => K): Observable { - return this.entities$.asObservable().pipe( + return this.allEntities$.asObservable().pipe( map((state: T[]) => func(state)), distinctUntilChanged() ); } setEntities(newEntities: Partial): void { - this.entities$.next(newEntities); + this.allEntities$.next(newEntities); } setFilteredEntities(newEntities: Partial): void { this.filteredEntities$.next(newEntities); } - setSelectedEntitiesIds(newEntities: Partial): void { - this.selectedEntitiesIds$.next(newEntities); + setSelectedEntities(newEntities: Partial): void { + this.selectedEntities$.next(newEntities); } setDisplayedEntities(newEntities: Partial): void { this.displayedEntities$.next(newEntities); } - setIdKey(value: string): void { - this._idKey = value; - } - get areAllEntitiesSelected(): boolean { - return ( - this.displayedEntities.length !== 0 && - this.selectedEntitiesIds.length === this.displayedEntities.length - ); + return this.displayedEntities.length !== 0 && this.selectedEntities.length === this.displayedEntities.length; } get areSomeEntitiesSelected$(): Observable { - return this.selectedEntitiesIds$.pipe(map(all => all.length > 0)); + return this.selectedEntities$.pipe(map(all => all.length > 0)); } isSelected(entity: T): boolean { - return this.selectedEntitiesIds.indexOf(entity[this._getIdKey]) !== -1; + return this.selectedEntities.indexOf(entity) !== -1; } toggleEntitySelected(entity: T): void { - const currentEntityIdx = this.selectedEntitiesIds.indexOf(entity[this._getIdKey]); + const currentEntityIdx = this.selectedEntities.indexOf(entity); if (currentEntityIdx === -1) { - const currentEntityId = entity[this._getIdKey]; - return this.setSelectedEntitiesIds([...this.selectedEntitiesIds, currentEntityId]); + return this.setSelectedEntities([...this.selectedEntities, entity]); } - - this.setSelectedEntitiesIds( - this.selectedEntitiesIds.filter((el, idx) => idx !== currentEntityIdx) - ); + this.setSelectedEntities(this.selectedEntities.filter((el, idx) => idx !== currentEntityIdx)); } toggleSelectAll(): void { - if (this.areAllEntitiesSelected) return this.setSelectedEntitiesIds([]); - this.setSelectedEntitiesIds(this._displayedEntitiesIds); + if (this.areAllEntitiesSelected) return this.setSelectedEntities([]); + this.setSelectedEntities(this.displayedEntities); } updateSelection(): void { - if (!this._idKey) return; - - const ids = this._displayedEntitiesIds.filter(id => this.selectedEntitiesIds.includes(id)); - this.setSelectedEntitiesIds(ids); + const items = this.displayedEntities.filter(item => this.selectedEntities.includes(item)); + this.setSelectedEntities(items); } logCurrentState(): void { - console.log('Entities', this.entities); + console.log('Entities', this.allEntities); console.log('Displayed', this.displayedEntities); console.log('Filtered', this.filteredEntities); - console.log('Selected', this.selectedEntitiesIds); - } - - private get _displayedEntitiesIds(): string[] { - return this.displayedEntities.map(entity => entity[this._getIdKey]); - } - - private get _getIdKey(): string { - if (!this._idKey) throw new Error('Not implemented'); - - return this._idKey; + console.log('Selected', this.selectedEntities); } } diff --git a/apps/red-ui/src/app/modules/shared/services/search.service.ts b/apps/red-ui/src/app/modules/shared/services/search.service.ts index 49279535a..25a8f19b7 100644 --- a/apps/red-ui/src/app/modules/shared/services/search.service.ts +++ b/apps/red-ui/src/app/modules/shared/services/search.service.ts @@ -12,10 +12,7 @@ export class SearchService { query: [''] }); - constructor( - private readonly _screenStateService: ScreenStateService, - private readonly _formBuilder: FormBuilder - ) { + constructor(private readonly _screenStateService: ScreenStateService, private readonly _formBuilder: FormBuilder) { this.searchForm.valueChanges.subscribe(() => this.executeSearch()); } @@ -26,17 +23,14 @@ export class SearchService { } executeSearchImmediately(): void { - const displayed = - this._screenStateService.filteredEntities || this._screenStateService.entities; + const displayed = this._screenStateService.filteredEntities || this._screenStateService.allEntities; if (!this._searchKey) { return this._screenStateService.setDisplayedEntities(displayed); } this._screenStateService.setDisplayedEntities( - displayed.filter(entity => - this._searchField(entity).toLowerCase().includes(this._searchValue) - ) + displayed.filter(entity => this._searchField(entity).toLowerCase().includes(this._searchValue)) ); this._screenStateService.updateSelection(); } diff --git a/apps/red-ui/src/app/services/user-preference.service.ts b/apps/red-ui/src/app/services/user-preference.service.ts index b77e13d58..e2999f0ce 100644 --- a/apps/red-ui/src/app/services/user-preference.service.ts +++ b/apps/red-ui/src/app/services/user-preference.service.ts @@ -1,15 +1,36 @@ import { Injectable } from '@angular/core'; +import { UserPreferenceControllerService } from '@redaction/red-ui-http'; + +interface UserAttributes { + [p: string]: string[]; +} @Injectable({ providedIn: 'root' }) export class UserPreferenceService { + private _userAttributes: UserAttributes = {}; + + constructor(private readonly _userPreferenceControllerService: UserPreferenceControllerService) { + _userPreferenceControllerService.getAllUserAttributes().subscribe(attributes => { + this._userAttributes = attributes ?? {}; + }); + } + + get userAttributes(): UserAttributes { + return this._userAttributes; + } + get areDevFeaturesEnabled() { const value = sessionStorage.getItem('redaction.enable-dev-features'); - if (value) { - return value === 'true'; + return value ? value === 'true' : false; + } + + getLastOpenedFileId(key: string): string { + if (this.userAttributes[key]?.length > 0) { + return this.userAttributes[key][0]; } - return false; + return ''; } toggleDevFeatures() { diff --git a/apps/red-ui/src/app/state/app-state.service.ts b/apps/red-ui/src/app/state/app-state.service.ts index f8117c4ea..8acaa3a7b 100644 --- a/apps/red-ui/src/app/state/app-state.service.ts +++ b/apps/red-ui/src/app/state/app-state.service.ts @@ -2,7 +2,6 @@ import { EventEmitter, Injectable } from '@angular/core'; import { DictionaryControllerService, Dossier, - DossierControllerService, DossierTemplateControllerService, FileAttributesConfig, FileAttributesControllerService, @@ -21,6 +20,7 @@ import { FileStatusWrapper } from '@models/file/file-status.wrapper'; import { DossierWrapper } from './model/dossier.wrapper'; import { TypeValueWrapper } from '@models/file/type-value.wrapper'; import { DossierTemplateModelWrapper } from '@models/file/dossier-template-model.wrapper'; +import { DossiersService } from '../modules/dossier/services/dossiers.service'; export interface AppState { dossiers: DossierWrapper[]; @@ -46,7 +46,7 @@ export class AppStateService { constructor( private readonly _router: Router, private readonly _userService: UserService, - private readonly _dossierControllerService: DossierControllerService, + private readonly _dossiersService: DossiersService, private readonly _notificationService: NotificationService, private readonly _reanalysisControllerService: ReanalysisControllerService, private readonly _translateService: TranslateService, @@ -65,15 +65,15 @@ export class AppStateService { activeDictionaryType: null }; - this._router.events.subscribe((event: Event) => { + _router.events.subscribe((event: Event) => { if (AppStateService._isFileOverviewRoute(event)) { const url = (event as ResolveStart).url.replace('/main/dossiers/', ''); const [dossierId, , fileId] = url.split(/[/?]/); - this.activateFile(dossierId, fileId); + return this.activateFile(dossierId, fileId); } if (AppStateService._isDossierOverviewRoute(event)) { const dossierId = (event as ResolveStart).url.replace('/main/dossiers/', ''); - this.activateDossier(dossierId); + return this.activateDossier(dossierId); } if (AppStateService._isRandomRoute(event)) { this._appState.activeDossierId = null; @@ -88,11 +88,7 @@ export class AppStateService { } get aggregatedFiles(): FileStatusWrapper[] { - const result: FileStatusWrapper[] = []; - this._appState.dossiers.forEach(p => { - result.push(...p.files); - }); - return result; + return this.allDossiers.reduce((acc, { files }) => [...acc, ...files], []); } get activeDossierTemplateId(): string { @@ -128,7 +124,7 @@ export class AppStateService { } get activeDossier(): DossierWrapper | undefined { - return this._appState.dossiers.find(p => p.dossierId === this.activeDossierId); + return this.allDossiers.find(p => p.dossierId === this.activeDossierId); } get allDossiers(): DossierWrapper[] { @@ -147,18 +143,14 @@ export class AppStateService { return this._appState.activeFileId; } - get totalAnalysedPages() { + get totalAnalysedPages(): number { return this._appState.totalAnalysedPages; } - get totalPeople() { + get totalPeople(): number { return this._appState.totalPeople; } - get totalDocuments() { - return this._appState.totalDocuments; - } - private static _isFileOverviewRoute(event: Event) { return event instanceof ResolveStart && event.url.includes('/main/dossiers/') && event.url.includes('/file/'); } @@ -177,18 +169,15 @@ export class AppStateService { } } - getDictionaryColor(type?: string, dossierTemplateId?: string) { - if (!dossierTemplateId && this.activeDossier) { - dossierTemplateId = this.activeDossier.dossierTemplateId; - } + getDictionaryColor(type?: string, dossierTemplateId = this.activeDossier?.dossierTemplateId) { if (!dossierTemplateId) { - dossierTemplateId = this.dossierTemplates.length > 0 ? this.dossierTemplates[0].dossierTemplateId : undefined; + dossierTemplateId = this.dossierTemplates[0]?.dossierTemplateId; } if (!dossierTemplateId) { return undefined; } const color = this._dictionaryData[dossierTemplateId][type]?.hexColor; - return color ? color : this._dictionaryData[dossierTemplateId]['default'].hexColor; + return color ?? this._dictionaryData[dossierTemplateId]['default'].hexColor; } getDossierTemplateById(id: string): DossierTemplateModelWrapper { @@ -220,20 +209,21 @@ export class AppStateService { } async loadAllDossiers(emitEvents: boolean = true) { - const dossiers = await this._dossierControllerService.getDossiers().toPromise(); - if (dossiers) { - const mappedDossiers = dossiers.map(p => new DossierWrapper(p, this._getExistingFiles(p.dossierId))); - - const fileData = await this._statusControllerService.getFileStatusForDossiers(mappedDossiers.map(p => p.dossierId)).toPromise(); - - for (const dossierId of Object.keys(fileData)) { - const dossier = mappedDossiers.find(p => p.dossierId === dossierId); - this._processFiles(dossier, fileData[dossierId], emitEvents); - } - - this._appState.dossiers = mappedDossiers; - this._computeStats(); + const dossiers = await this._dossiersService.getAll(); + if (!dossiers) { + return; } + + const mappedDossiers = dossiers.map(p => new DossierWrapper(p, this._getExistingFiles(p.dossierId))); + const fileData = await this._statusControllerService.getFileStatusForDossiers(mappedDossiers.map(p => p.dossierId)).toPromise(); + + for (const dossierId of Object.keys(fileData)) { + const dossier = mappedDossiers.find(p => p.dossierId === dossierId); + this._processFiles(dossier, fileData[dossierId], emitEvents); + } + + this._appState.dossiers = mappedDossiers; + this._computeStats(); } async reloadActiveFile() { @@ -246,8 +236,8 @@ export class AppStateService { const activeFileWrapper = new FileStatusWrapper( activeFile, this._userService.getNameForId(activeFile.currentReviewer), - this.activeDossier.dossierTemplateId, - this._appState.fileAttributesConfig[this.activeDossier.dossierTemplateId] + this.activeDossierTemplateId, + this._appState.fileAttributesConfig[this.activeDossierTemplateId] ); this.activeDossier.files = this.activeDossier.files.map(file => file.fileId === activeFileWrapper.fileId ? activeFileWrapper : file @@ -261,32 +251,26 @@ export class AppStateService { return activeFileWrapper; } - async getFiles(dossier?: DossierWrapper, emitEvents: boolean = true) { - if (!dossier) { - dossier = this.activeDossier; - } + async getFiles(dossier: DossierWrapper = this.activeDossier, emitEvents = true) { const files = await this._statusControllerService.getDossierStatus(dossier.dossierId).toPromise(); return this._processFiles(dossier, files, emitEvents); } - async reanalyzeDossier(dossier?: DossierWrapper) { - if (!dossier) { - dossier = this.activeDossier; - } - await this._reanalysisControllerService.reanalyzeDossier(dossier.dossierId).toPromise(); + async reanalyzeDossier({ dossierId }: DossierWrapper = this.activeDossier) { + await this._reanalysisControllerService.reanalyzeDossier(dossierId).toPromise(); } - activateDossier(dossierId: string) { + activateDossier(dossierId: string): void { this._appState.activeFileId = null; this._appState.activeDossierId = dossierId; if (!this.activeDossier) { this._appState.activeDossierId = null; - this._router.navigate(['/main/dossiers']); + this._router.navigate(['/main/dossiers']).then(); return; - } else { - this.updateDossierDictionary(this.activeDossier.dossierTemplateId, dossierId); } + + this.updateDossierDictionary(this.activeDossier.dossierTemplateId, dossierId); } updateDossierDictionary(dossierTemplateId: string, dossierId: string) { @@ -302,7 +286,7 @@ export class AppStateService { } activateFile(dossierId: string, fileId: string) { - if (this._appState.activeDossierId === dossierId && this._appState.activeFileId === fileId) return; + if (this.activeDossierId === dossierId && this.activeFileId === fileId) return; this.activateDossier(dossierId); if (this.activeDossier) { this._appState.activeFileId = fileId; @@ -341,29 +325,25 @@ export class AppStateService { } deleteDossier(dossier: DossierWrapper) { - return this._dossierControllerService - .deleteDossier(dossier.dossierId) - .toPromise() - .then( - () => { - const index = this._appState.dossiers.findIndex(p => p.dossier.dossierId === dossier.dossierId); - this._appState.dossiers.splice(index, 1); - this._appState.dossiers = [...this._appState.dossiers]; - }, - () => { - this._notificationService.showToastNotification( - this._translateService.instant('dossiers.delete.delete-failed', dossier), - null, - NotificationType.ERROR - ); - } - ); + return this._dossiersService.delete(dossier.dossierId).then( + () => { + const index = this.allDossiers.findIndex(p => p.dossierId === dossier.dossierId); + this._appState.dossiers.splice(index, 1); + }, + () => { + this._notificationService.showToastNotification( + this._translateService.instant('dossiers.delete.delete-failed', dossier), + null, + NotificationType.ERROR + ); + } + ); } - async addOrUpdateDossier(dossier: Dossier) { + async createOrUpdateDossier(dossier: Dossier) { try { - const updatedDossier = await this._dossierControllerService.createOrUpdateDossier(dossier).toPromise(); - let foundDossier = this._appState.dossiers.find(p => p.dossier.dossierId === updatedDossier.dossierId); + const updatedDossier = await this._dossiersService.createOrUpdate(dossier); + let foundDossier = this.allDossiers.find(p => p.dossierId === updatedDossier.dossierId); if (foundDossier) { Object.assign((foundDossier.dossier = updatedDossier)); } else { @@ -385,7 +365,7 @@ export class AppStateService { async reloadActiveDossierFiles() { if (this.activeDossierId) { - await this.getFiles(this.activeDossier); + await this.getFiles(); } } @@ -408,7 +388,7 @@ export class AppStateService { } async loadAllDossiersIfNecessary() { - if (!this._appState.dossiers.length) { + if (!this.allDossiers.length) { await this.loadAllDossiers(); } } @@ -642,7 +622,7 @@ export class AppStateService { return [typeObs, colorsObs]; } - async loadDictionaryData() { + async loadDictionaryData(): Promise { const obj = {}; const observables = []; @@ -660,9 +640,9 @@ export class AppStateService { this._dictionaryData = obj; } - private _getExistingFiles(dossierId: string) { - const found = this._appState.dossiers.find(p => p.dossier.dossierId === dossierId); - return found ? found.files : []; + private _getExistingFiles(dossierId: string): FileStatusWrapper[] { + const dossier = this.allDossiers.find(p => p.dossierId === dossierId); + return dossier?.files ?? []; } private _processFiles(dossier: DossierWrapper, files: FileStatus[], emitEvents: boolean = true) { @@ -727,25 +707,18 @@ export class AppStateService { let totalAnalysedPages = 0; let totalDocuments = 0; const totalPeople = new Set(); - this._appState.dossiers.forEach(p => { - totalDocuments += p.files.length; - if (p.dossier.memberIds) { - p.dossier.memberIds.forEach(m => totalPeople.add(m)); + this.allDossiers.forEach(d => { + totalDocuments += d.files.length; + if (d.dossier.memberIds) { + d.dossier.memberIds.forEach(m => totalPeople.add(m)); } - let numberOfPages = 0; - p.files.forEach(f => { - numberOfPages += f.numberOfPages; - }); - p.totalNumberOfPages = numberOfPages; - totalAnalysedPages += numberOfPages; + + d.totalNumberOfPages = d.files.reduce((acc, file) => acc + file.numberOfPages, 0); + totalAnalysedPages += d.totalNumberOfPages; }); this._appState.totalPeople = totalPeople.size; this._appState.totalAnalysedPages = totalAnalysedPages; this._appState.totalDocuments = totalDocuments; - - if (this.activeDossierId && this.activeFileId) { - this.activateFile(this.activeDossierId, this.activeFileId); - } } } diff --git a/apps/red-ui/src/app/utils/sorters/status-sorter.ts b/apps/red-ui/src/app/utils/sorters/status-sorter.ts index d4d2ed8d8..94ec85387 100644 --- a/apps/red-ui/src/app/utils/sorters/status-sorter.ts +++ b/apps/red-ui/src/app/utils/sorters/status-sorter.ts @@ -9,5 +9,5 @@ export const StatusSorter = { UNDER_REVIEW: 15, UNDER_APPROVAL: 20, APPROVED: 25, - byKey: (a: { key: string }, b: { key: string }) => StatusSorter[a.key] - StatusSorter[b.key] + byKey: (a: { key?: string }, b: { key?: string }) => StatusSorter[a.key] - StatusSorter[b.key] };