remove unused methods, add AutoUnsubscribeComponent
This commit is contained in:
parent
cb3cd4db11
commit
6932fa6b30
@ -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) {
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
></redaction-round-checkbox>
|
||||
</div>
|
||||
<span class="all-caps-label">
|
||||
{{ 'file-attributes-csv-import.table-header.title' | translate: { length: allEntities.length } }}
|
||||
{{ 'file-attributes-csv-import.table-header.title' | translate: { length: (allEntities$ | async)?.length } }}
|
||||
</span>
|
||||
|
||||
<ng-container *ngIf="areSomeEntitiesSelected$ | async">
|
||||
|
||||
@ -23,38 +23,36 @@ export class ActiveFieldsListingComponent extends BaseListingComponent<Field> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,37 +4,25 @@
|
||||
<div class="dialog-content">
|
||||
<div class="sub-header">
|
||||
<div class="left">
|
||||
<div class="info">
|
||||
<span translate="file-attributes-csv-import.file"> </span> {{ csvFile.name }}
|
||||
</div>
|
||||
<div class="info"><span translate="file-attributes-csv-import.file"> </span> {{ csvFile.name }}</div>
|
||||
<div class="large-label">
|
||||
{{
|
||||
'file-attributes-csv-import.total-rows'
|
||||
| translate: { rows: parseResult?.data?.length }
|
||||
}}
|
||||
{{ 'file-attributes-csv-import.total-rows' | translate: { rows: parseResult?.data?.length } }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<form (submit)="changedParseConfig && readFile()" [formGroup]="baseConfigForm">
|
||||
<div class="red-input-group required w-250">
|
||||
<mat-form-field floatLabel="always">
|
||||
<mat-label>{{
|
||||
'file-attributes-csv-import.key-column' | translate
|
||||
}}</mat-label>
|
||||
<mat-label>{{ 'file-attributes-csv-import.key-column' | translate }}</mat-label>
|
||||
<input
|
||||
[matAutocomplete]="auto"
|
||||
[placeholder]="
|
||||
'file-attributes-csv-import.key-column-placeholder' | translate
|
||||
"
|
||||
[placeholder]="'file-attributes-csv-import.key-column-placeholder' | translate"
|
||||
formControlName="filenameMappingColumnHeaderName"
|
||||
matInput
|
||||
type="text"
|
||||
/>
|
||||
<mat-autocomplete #auto="matAutocomplete" autoActiveFirstOption>
|
||||
<mat-option
|
||||
*ngFor="let field of filteredKeyOptions | async"
|
||||
[value]="field"
|
||||
>
|
||||
<mat-option *ngFor="let field of filteredKeyOptions | async" [value]="field">
|
||||
{{ field }}
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
@ -44,9 +32,7 @@
|
||||
<div class="red-input-group required w-110">
|
||||
<label translate="file-attributes-csv-import.delimiter"></label>
|
||||
<input
|
||||
[placeholder]="
|
||||
'file-attributes-csv-import.delimiter-placeholder' | translate
|
||||
"
|
||||
[placeholder]="'file-attributes-csv-import.delimiter-placeholder' | translate"
|
||||
formControlName="delimiter"
|
||||
name="delimiter"
|
||||
type="text"
|
||||
@ -56,9 +42,7 @@
|
||||
<div class="red-input-group required w-160">
|
||||
<label translate="file-attributes-csv-import.encoding"></label>
|
||||
<input
|
||||
[placeholder]="
|
||||
'file-attributes-csv-import.encoding-placeholder' | translate
|
||||
"
|
||||
[placeholder]="'file-attributes-csv-import.encoding-placeholder' | translate"
|
||||
formControlName="encoding"
|
||||
name="encoding"
|
||||
type="text"
|
||||
@ -78,12 +62,10 @@
|
||||
<div class="csv-part-header">
|
||||
<div>
|
||||
<span class="all-caps-label">{{
|
||||
'file-attributes-csv-import.available'
|
||||
| translate: { value: parseResult?.meta?.fields.length }
|
||||
'file-attributes-csv-import.available' | translate: { value: parseResult?.meta?.fields.length }
|
||||
}}</span>
|
||||
<span class="all-caps-label">{{
|
||||
'file-attributes-csv-import.selected'
|
||||
| translate: { value: activeFields.length }
|
||||
'file-attributes-csv-import.selected' | translate: { value: activeFields.length }
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="actions">
|
||||
@ -108,7 +90,7 @@
|
||||
</div>
|
||||
<div *ngIf="isSearchOpen" class="search-input-container">
|
||||
<redaction-input-with-action
|
||||
[form]="searchForm"
|
||||
[form]="searchService.searchForm"
|
||||
placeholder="file-attributes-csv-import.search.placeholder"
|
||||
type="search"
|
||||
width="full"
|
||||
@ -127,12 +109,8 @@
|
||||
{{ field.csvColumn }}
|
||||
</div>
|
||||
<div class="secondary">
|
||||
<div class="entry-count small-label">
|
||||
{{ getEntries(field.csvColumn) }} entries
|
||||
</div>
|
||||
<div class="sample small-label">
|
||||
Sample: {{ getSample(field.csvColumn) }}
|
||||
</div>
|
||||
<div class="entry-count small-label">{{ getEntries(field.csvColumn) }} entries</div>
|
||||
<div class="sample small-label">Sample: {{ getSample(field.csvColumn) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -146,10 +124,7 @@
|
||||
>
|
||||
<div class="csv-part-header">
|
||||
<div class="all-caps-label">
|
||||
{{
|
||||
'file-attributes-csv-import.csv-column' +
|
||||
(previewExpanded ? '' : '-preview') | translate
|
||||
}}
|
||||
{{ 'file-attributes-csv-import.csv-column' + (previewExpanded ? '' : '-preview') | translate }}
|
||||
</div>
|
||||
<redaction-circle-button
|
||||
(click)="previewExpanded = !previewExpanded"
|
||||
@ -157,16 +132,9 @@
|
||||
></redaction-circle-button>
|
||||
</div>
|
||||
<div [class.hidden]="!previewExpanded" class="csv-part-content">
|
||||
<div
|
||||
*ngIf="!hoveredColumn"
|
||||
class="no-column-data"
|
||||
translate="file-attributes-csv-import.no-hovered-column"
|
||||
></div>
|
||||
<div *ngIf="!hoveredColumn" class="no-column-data" translate="file-attributes-csv-import.no-hovered-column"></div>
|
||||
<div *ngIf="hoveredColumn && !columnSample.length" class="no-column-data">
|
||||
{{
|
||||
'file-attributes-csv-import.no-sample-data-for'
|
||||
| translate: { column: hoveredColumn }
|
||||
}}
|
||||
{{ 'file-attributes-csv-import.no-sample-data-for' | translate: { column: hoveredColumn } }}
|
||||
</div>
|
||||
<div *ngFor="let row of columnSample">
|
||||
{{ row }}
|
||||
@ -184,12 +152,7 @@
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button
|
||||
(click)="save()"
|
||||
[disabled]="changedParseConfig || baseConfigForm.invalid"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
>
|
||||
<button (click)="save()" [disabled]="changedParseConfig || baseConfigForm.invalid" color="primary" mat-flat-button>
|
||||
{{ 'file-attributes-csv-import.save.label' | translate }}
|
||||
</button>
|
||||
|
||||
@ -198,9 +161,5 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<redaction-circle-button
|
||||
class="dialog-close"
|
||||
icon="red:close"
|
||||
mat-dialog-close
|
||||
></redaction-circle-button>
|
||||
<redaction-circle-button class="dialog-close" icon="red:close" mat-dialog-close></redaction-circle-button>
|
||||
</section>
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -25,17 +25,12 @@
|
||||
<redaction-round-checkbox
|
||||
(click)="toggleSelectAll()"
|
||||
[active]="areAllEntitiesSelected"
|
||||
[indeterminate]="
|
||||
(areSomeEntitiesSelected$ | async) && !areAllEntitiesSelected
|
||||
"
|
||||
[indeterminate]="(areSomeEntitiesSelected$ | async) && !areAllEntitiesSelected"
|
||||
></redaction-round-checkbox>
|
||||
</div>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{
|
||||
'dictionary-listing.table-header.title'
|
||||
| translate: { length: (displayedEntities$ | async)?.length }
|
||||
}}
|
||||
{{ 'dictionary-listing.table-header.title' | translate: { length: (displayedEntities$ | async)?.length } }}
|
||||
</span>
|
||||
|
||||
<redaction-circle-button
|
||||
@ -48,7 +43,7 @@
|
||||
|
||||
<div class="attributes-actions-container">
|
||||
<redaction-input-with-action
|
||||
[form]="searchForm"
|
||||
[form]="searchService.searchForm"
|
||||
placeholder="dictionary-listing.search"
|
||||
type="search"
|
||||
></redaction-input-with-action>
|
||||
@ -64,11 +59,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
[class.no-data]="!allEntities.length"
|
||||
class="table-header"
|
||||
redactionSyncWidth="table-item"
|
||||
>
|
||||
<div [class.no-data]="(allEntities$ | async)?.length === 0" class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
@ -98,39 +89,30 @@
|
||||
|
||||
<redaction-empty-state
|
||||
(action)="openAddEditDictionaryDialog()"
|
||||
*ngIf="!allEntities.length"
|
||||
*ngIf="(allEntities$ | async)?.length === 0"
|
||||
[showButton]="permissionsService.isAdmin()"
|
||||
icon="red:dictionary"
|
||||
screen="dictionary-listing"
|
||||
></redaction-empty-state>
|
||||
|
||||
<redaction-empty-state
|
||||
*ngIf="allEntities.length && (displayedEntities$ | async)?.length === 0"
|
||||
*ngIf="(allEntities$ | async)?.length && (displayedEntities$ | async)?.length === 0"
|
||||
screen="dictionary-listing"
|
||||
type="no-match"
|
||||
></redaction-empty-state>
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="80" redactionHasScrollbar>
|
||||
<div
|
||||
*cdkVirtualFor="
|
||||
let dict of displayedEntities$
|
||||
| async
|
||||
| sortBy: sortingOption.order:sortingOption.column
|
||||
"
|
||||
*cdkVirtualFor="let dict of displayedEntities$ | async | sortBy: sortingOption.order:sortingOption.column"
|
||||
[routerLink]="[dict.type]"
|
||||
class="table-item pointer"
|
||||
>
|
||||
<div (click)="toggleEntitySelected($event, dict)" class="selection-column">
|
||||
<redaction-round-checkbox
|
||||
[active]="isSelected(dict)"
|
||||
></redaction-round-checkbox>
|
||||
<redaction-round-checkbox [active]="isSelected(dict)"></redaction-round-checkbox>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div
|
||||
[ngStyle]="{ 'background-color': dict.hexColor }"
|
||||
class="color-square"
|
||||
></div>
|
||||
<div [ngStyle]="{ 'background-color': dict.hexColor }" class="color-square"></div>
|
||||
<div class="dict-name">
|
||||
<div class="table-item-title heading">
|
||||
{{ dict.label }}
|
||||
@ -153,16 +135,13 @@
|
||||
</div>
|
||||
|
||||
<div class="center">
|
||||
<redaction-annotation-icon
|
||||
[dictType]="dict"
|
||||
[type]="dict.hint ? 'circle' : 'square'"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon [dictType]="dict" [type]="dict.hint ? 'circle' : 'square'"></redaction-annotation-icon>
|
||||
</div>
|
||||
|
||||
<div class="actions-container">
|
||||
<div *ngIf="permissionsService.isAdmin()" class="action-buttons">
|
||||
<redaction-circle-button
|
||||
(action)="openDeleteDictionariesDialog($event, [dict.type])"
|
||||
(action)="openDeleteDictionariesDialog($event, [dict])"
|
||||
icon="red:trash"
|
||||
tooltip="dictionary-listing.action.delete"
|
||||
type="dark-bg"
|
||||
@ -183,7 +162,7 @@
|
||||
|
||||
<div class="right-container" redactionHasScrollbar>
|
||||
<redaction-simple-doughnut-chart
|
||||
*ngIf="allEntities.length"
|
||||
*ngIf="(allEntities$ | async)?.length"
|
||||
[config]="chartData"
|
||||
[counterText]="'dictionary-listing.stats.charts.entries' | translate"
|
||||
[radius]="82"
|
||||
|
||||
@ -43,9 +43,8 @@ export class DictionaryListingScreenComponent extends BaseListingComponent<TypeV
|
||||
) {
|
||||
super(_injector);
|
||||
_loadingService.start();
|
||||
this._sortingService.setScreenName(ScreenNames.DOSSIER_LISTING);
|
||||
this._searchService.setSearchKey('label');
|
||||
this._screenStateService.setIdKey('type');
|
||||
this.sortingService.setScreenName(ScreenNames.DOSSIER_LISTING);
|
||||
this.searchService.setSearchKey('label');
|
||||
_appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId);
|
||||
}
|
||||
|
||||
@ -53,11 +52,16 @@ export class DictionaryListingScreenComponent extends BaseListingComponent<TypeV
|
||||
this._loadDictionaryData();
|
||||
}
|
||||
|
||||
openDeleteDictionariesDialog($event?: MouseEvent, types = this._screenStateService.selectedEntitiesIds) {
|
||||
openDeleteDictionariesDialog($event?: MouseEvent, types = this.screenStateService.selectedEntities) {
|
||||
this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||
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<TypeV
|
||||
const entities = Object.values(appStateDictionaryData).filter(d => !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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
<div class="attributes-actions-container">
|
||||
<redaction-input-with-action
|
||||
[form]="searchForm"
|
||||
[form]="searchService.searchForm"
|
||||
placeholder="dossier-attributes-listing.search"
|
||||
type="search"
|
||||
></redaction-input-with-action>
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
<div class="actions flex-1">
|
||||
<redaction-input-with-action
|
||||
[form]="searchForm"
|
||||
[form]="searchService.searchForm"
|
||||
placeholder="dossier-templates-listing.search"
|
||||
type="search"
|
||||
></redaction-input-with-action>
|
||||
@ -58,7 +58,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div [class.no-data]="noData" class="table-header" redactionSyncWidth="table-item">
|
||||
<div [class.no-data]="(allEntities$ | async)?.length === 0" class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
|
||||
@ -29,9 +29,8 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent
|
||||
readonly userPreferenceService: UserPreferenceService
|
||||
) {
|
||||
super(_injector);
|
||||
this._sortingService.setScreenName(ScreenNames.DOSSIER_TEMPLATES_LISTING);
|
||||
this._searchService.setSearchKey('name');
|
||||
this._screenStateService.setIdKey('dossierTemplateId');
|
||||
this.sortingService.setScreenName(ScreenNames.DOSSIER_TEMPLATES_LISTING);
|
||||
this.searchService.setSearchKey('name');
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
@ -41,8 +40,10 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent
|
||||
openDeleteTemplatesDialog($event?: MouseEvent) {
|
||||
return this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||
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)
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
|
||||
<div class="attributes-actions-container">
|
||||
<redaction-input-with-action
|
||||
[form]="searchForm"
|
||||
[form]="searchService.searchForm"
|
||||
placeholder="file-attributes-listing.search"
|
||||
type="search"
|
||||
></redaction-input-with-action>
|
||||
|
||||
@ -31,9 +31,8 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
|
||||
protected readonly _injector: Injector
|
||||
) {
|
||||
super(_injector);
|
||||
this._sortingService.setScreenName(ScreenNames.FILE_ATTRIBUTES_LISTING);
|
||||
this._searchService.setSearchKey('label');
|
||||
this._screenStateService.setIdKey('id');
|
||||
this.sortingService.setScreenName(ScreenNames.FILE_ATTRIBUTES_LISTING);
|
||||
this.searchService.setSearchKey('label');
|
||||
_appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId);
|
||||
}
|
||||
|
||||
@ -65,7 +64,10 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
|
||||
.toPromise();
|
||||
} else {
|
||||
await this._fileAttributesService
|
||||
.deleteFileAttributes(this._screenStateService.selectedEntitiesIds, this._appStateService.activeDossierTemplateId)
|
||||
.deleteFileAttributes(
|
||||
this.screenStateService.selectedEntities.map(f => f.id),
|
||||
this._appStateService.activeDossierTemplateId
|
||||
)
|
||||
.toPromise();
|
||||
}
|
||||
await this._loadData();
|
||||
@ -95,7 +97,7 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
|
||||
.getFileAttributesConfiguration(this._appStateService.activeDossierTemplateId)
|
||||
.toPromise();
|
||||
this._existingConfiguration = response;
|
||||
this._screenStateService.setEntities(response?.fileAttributeConfigs || []);
|
||||
this.screenStateService.setEntities(response?.fileAttributeConfigs || []);
|
||||
} catch (e) {
|
||||
} finally {
|
||||
this.filterService.filterEntities();
|
||||
|
||||
@ -44,9 +44,7 @@ export class RulesScreenComponent extends ComponentHasChanges {
|
||||
private readonly _activatedRoute: ActivatedRoute
|
||||
) {
|
||||
super(_translateService);
|
||||
this._appStateService.activateDossierTemplate(
|
||||
_activatedRoute.snapshot.params.dossierTemplateId
|
||||
);
|
||||
this._appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId);
|
||||
this._initialize();
|
||||
}
|
||||
|
||||
@ -78,9 +76,7 @@ export class RulesScreenComponent extends ComponentHasChanges {
|
||||
|
||||
@debounce()
|
||||
codeEditorTextChanged() {
|
||||
const newDecorations = this.currentLines
|
||||
.filter(entry => 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -32,8 +32,7 @@ export class TrashScreenComponent extends BaseListingComponent<Dossier> 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<void> {
|
||||
@ -46,7 +45,7 @@ export class TrashScreenComponent extends BaseListingComponent<Dossier> implemen
|
||||
}
|
||||
|
||||
async loadDossierTemplatesData(): Promise<void> {
|
||||
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<Dossier> 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<Dossier> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
<div class="actions">
|
||||
<redaction-input-with-action
|
||||
[form]="searchForm"
|
||||
[form]="searchService.searchForm"
|
||||
placeholder="user-listing.search"
|
||||
type="search"
|
||||
></redaction-input-with-action>
|
||||
@ -38,28 +38,19 @@
|
||||
<redaction-round-checkbox
|
||||
(click)="toggleSelectAll()"
|
||||
[active]="areAllEntitiesSelected"
|
||||
[indeterminate]="
|
||||
(areSomeEntitiesSelected$ | async) && !areAllEntitiesSelected
|
||||
"
|
||||
[indeterminate]="(areSomeEntitiesSelected$ | async) && !areAllEntitiesSelected"
|
||||
></redaction-round-checkbox>
|
||||
</div>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{
|
||||
'user-listing.table-header.title'
|
||||
| translate: { length: (displayedEntities$ | async)?.length }
|
||||
}}
|
||||
{{ 'user-listing.table-header.title' | translate: { length: (displayedEntities$ | async)?.length } }}
|
||||
</span>
|
||||
|
||||
<redaction-circle-button
|
||||
(action)="bulkDelete()"
|
||||
*ngIf="areSomeEntitiesSelected$ | async"
|
||||
[disabled]="(canDeleteSelected$ | async) === false"
|
||||
[tooltip]="
|
||||
(canDeleteSelected$ | async)
|
||||
? 'user-listing.bulk.delete'
|
||||
: 'user-listing.bulk.delete-disabled'
|
||||
"
|
||||
[tooltip]="(canDeleteSelected$ | async) ? 'user-listing.bulk.delete' : 'user-listing.bulk.delete-disabled'"
|
||||
icon="red:trash"
|
||||
tooltipPosition="after"
|
||||
type="dark-bg"
|
||||
@ -69,22 +60,13 @@
|
||||
<div class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
label="user-listing.table-col-names.name"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name label="user-listing.table-col-names.name"></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
label="user-listing.table-col-names.email"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name label="user-listing.table-col-names.email"></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
class="flex-center"
|
||||
label="user-listing.table-col-names.active"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name class="flex-center" label="user-listing.table-col-names.active"></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
label="user-listing.table-col-names.roles"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name label="user-listing.table-col-names.roles"></redaction-table-col-name>
|
||||
|
||||
<div></div>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
@ -98,14 +80,9 @@
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="80" redactionHasScrollbar>
|
||||
<!-- Table lines -->
|
||||
<div
|
||||
*cdkVirtualFor="let user of displayedEntities$ | async; trackBy: trackById"
|
||||
class="table-item"
|
||||
>
|
||||
<div *cdkVirtualFor="let user of displayedEntities$ | async; trackBy: trackById" class="table-item">
|
||||
<div (click)="toggleEntitySelected($event, user)" class="selection-column">
|
||||
<redaction-round-checkbox
|
||||
[active]="isSelected(user)"
|
||||
></redaction-round-checkbox>
|
||||
<redaction-round-checkbox [active]="isSelected(user)"></redaction-round-checkbox>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@ -39,12 +39,11 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
|
||||
protected readonly _injector: Injector
|
||||
) {
|
||||
super(_injector);
|
||||
this._screenStateService.setIdKey('userId');
|
||||
}
|
||||
|
||||
get canDeleteSelected$(): Observable<boolean> {
|
||||
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<User> 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<User> 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();
|
||||
|
||||
@ -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<FileStatusWrapper>
|
||||
) {}
|
||||
|
||||
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();
|
||||
});
|
||||
|
||||
@ -38,12 +38,10 @@
|
||||
|
||||
<div *ngIf="hasFiles" class="mt-24">
|
||||
<redaction-simple-doughnut-chart
|
||||
(toggleFilter)="filterService.filterEntities()"
|
||||
[config]="documentsChartData"
|
||||
[filter]="filterService.getFilter$('statusFilters') | async"
|
||||
[radius]="63"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-overview.dossier-details.charts.documents-in-dossier'"
|
||||
[subtitle]="i18nKey + 'charts.documents-in-dossier'"
|
||||
direction="row"
|
||||
></redaction-simple-doughnut-chart>
|
||||
</div>
|
||||
@ -65,9 +63,9 @@
|
||||
></redaction-dossier-details-stats>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!!appStateService.activeDossier.dossier.description" class="pb-32">
|
||||
<div *ngIf="appStateService.activeDossier.dossier.description as description" class="pb-32">
|
||||
<div class="heading" translate="dossier-overview.dossier-details.description"></div>
|
||||
<div class="mt-8">{{ appStateService.activeDossier.dossier.description }}</div>
|
||||
<div class="mt-8">{{ description }}</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -27,7 +27,6 @@
|
||||
<div>
|
||||
<redaction-simple-doughnut-chart
|
||||
[config]="documentsChartData"
|
||||
[filter]="filterService.getFilter$('statusFilters') | async"
|
||||
[radius]="80"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-listing.stats.charts.total-documents'"
|
||||
|
||||
@ -51,12 +51,7 @@ export class TeamMembersManagerComponent implements OnInit {
|
||||
get membersSelectOptions() {
|
||||
const searchQuery = this.searchForm.get('query').value;
|
||||
return this.userService.eligibleUsers
|
||||
.filter(user =>
|
||||
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(
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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<DossierWrapper> implements OnInit, OnDestroy, OnAttach, OnDetach {
|
||||
readonly itemSize = 95;
|
||||
dossiersChartData: DoughnutChartConfig[] = [];
|
||||
documentsChartData: DoughnutChartConfig[] = [];
|
||||
buttonConfigs: ButtonConfig[] = [
|
||||
@ -48,12 +51,7 @@ export class DossierListingScreenComponent extends BaseListingComponent<DossierW
|
||||
}
|
||||
];
|
||||
|
||||
readonly itemSize = 85;
|
||||
|
||||
private _dossierAutoUpdateTimer: Subscription;
|
||||
private _lastScrollPosition: number;
|
||||
private _routerEventsScrollPositionSub: Subscription;
|
||||
private _fileChangedSub: Subscription;
|
||||
|
||||
@ViewChild('needsWorkTemplate', { read: TemplateRef, static: true })
|
||||
private readonly _needsWorkTemplate: TemplateRef<any>;
|
||||
@ -70,65 +68,43 @@ export class DossierListingScreenComponent extends BaseListingComponent<DossierW
|
||||
protected readonly _injector: Injector
|
||||
) {
|
||||
super(_injector);
|
||||
this._sortingService.setScreenName(ScreenNames.DOSSIER_LISTING);
|
||||
this._searchService.setSearchKey('name');
|
||||
this.sortingService.setScreenName(ScreenNames.DOSSIER_LISTING);
|
||||
this.searchService.setSearchKey('name');
|
||||
this._appStateService.reset();
|
||||
this._loadEntitiesFromState();
|
||||
}
|
||||
|
||||
private get _user() {
|
||||
return this._userService.user;
|
||||
}
|
||||
|
||||
private get _activeDossiersCount(): number {
|
||||
return this._screenStateService.entities.filter(p => 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<DossierW
|
||||
});
|
||||
}
|
||||
|
||||
private get _userId() {
|
||||
return this._userService.userId;
|
||||
}
|
||||
|
||||
private get _activeDossiersCount(): number {
|
||||
return this.screenStateService.allEntities.filter(p => 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<DossierW
|
||||
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);
|
||||
}
|
||||
|
||||
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<DossierW
|
||||
const allDistinctNeedsWork = new Set<string>();
|
||||
const allDistinctDossierTemplates = new Set<string>();
|
||||
|
||||
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<DossierW
|
||||
{
|
||||
key: 'my-dossiers',
|
||||
label: myDossiersLabel,
|
||||
checker: (dw: DossierWrapper) => 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)
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@ -49,10 +49,7 @@
|
||||
{{ 'dossier-overview.table-header.title' | translate: { length: (displayedEntities$ | async)?.length || 0 } }}
|
||||
</span>
|
||||
|
||||
<redaction-dossier-overview-bulk-actions
|
||||
(reload)="bulkActionPerformed()"
|
||||
[selectedFileIds]="selectedEntitiesIds$ | async"
|
||||
></redaction-dossier-overview-bulk-actions>
|
||||
<redaction-dossier-overview-bulk-actions (reload)="bulkActionPerformed()"></redaction-dossier-overview-bulk-actions>
|
||||
|
||||
<redaction-quick-filters></redaction-quick-filters>
|
||||
</div>
|
||||
|
||||
@ -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<any>;
|
||||
@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<void> {
|
||||
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<string>();
|
||||
const allDistinctNeedsWork = new Set<string>();
|
||||
|
||||
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 = [
|
||||
{
|
||||
|
||||
@ -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';
|
||||
|
||||
|
||||
@ -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<Dossier> {
|
||||
return this._dossierControllerService.createOrUpdateDossier(dossier).toPromise();
|
||||
}
|
||||
|
||||
delete(dossierId: string): Promise<unknown> {
|
||||
return this._dossierControllerService.deleteDossier(dossierId).toPromise();
|
||||
}
|
||||
|
||||
getAll(): Promise<Dossier[]> {
|
||||
return this._dossierControllerService.getDossiers().toPromise();
|
||||
}
|
||||
|
||||
getDeleted(): Promise<Dossier[]> {
|
||||
return this._dossierControllerService.getDeletedDossiers().toPromise();
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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<T> {
|
||||
export abstract class BaseListingComponent<T> extends AutoUnsubscribeComponent implements OnDestroy {
|
||||
@ViewChild(CdkVirtualScrollViewport)
|
||||
readonly scrollViewport: CdkVirtualScrollViewport;
|
||||
|
||||
readonly filterService: FilterService<T>;
|
||||
protected readonly _sortingService: SortingService;
|
||||
protected readonly _searchService: SearchService<T>;
|
||||
protected readonly _screenStateService: ScreenStateService<T>;
|
||||
readonly sortingService: SortingService;
|
||||
readonly searchService: SearchService<T>;
|
||||
readonly screenStateService: ScreenStateService<T>;
|
||||
|
||||
protected constructor(protected readonly _injector: Injector) {
|
||||
super();
|
||||
this.filterService = this._injector.get<FilterService<T>>(FilterService);
|
||||
this._sortingService = this._injector.get<SortingService>(SortingService);
|
||||
this._searchService = this._injector.get<SearchService<T>>(SearchService);
|
||||
this._screenStateService = this._injector.get<ScreenStateService<T>>(ScreenStateService);
|
||||
this.sortingService = this._injector.get<SortingService>(SortingService);
|
||||
this.searchService = this._injector.get<SearchService<T>>(SearchService);
|
||||
this.screenStateService = this._injector.get<ScreenStateService<T>>(ScreenStateService);
|
||||
}
|
||||
|
||||
get selectedEntitiesIds$(): Observable<string[]> {
|
||||
return this._screenStateService.selectedEntitiesIds$;
|
||||
ngOnDestroy(): void {
|
||||
super.ngOnDestroy();
|
||||
}
|
||||
|
||||
get selectedEntities$(): Observable<T[]> {
|
||||
return this.screenStateService.selectedEntities$;
|
||||
}
|
||||
|
||||
get displayedEntities$(): Observable<T[]> {
|
||||
return this._screenStateService.displayedEntities$;
|
||||
return this.screenStateService.displayedEntities$;
|
||||
}
|
||||
|
||||
get allEntities$(): Observable<T[]> {
|
||||
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<boolean> {
|
||||
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<T> {
|
||||
return this.allEntities.length === 0;
|
||||
}
|
||||
|
||||
getFilter$(slug: string): Observable<FilterModel[]> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
>
|
||||
<g *ngFor="let value of config; let i = index">
|
||||
<circle
|
||||
*ngIf="exists(i)"
|
||||
*ngIf="!!chartData[i]"
|
||||
[attr.stroke]="value.color.includes('#') ? value.color : ''"
|
||||
[class]="value.color"
|
||||
attr.cx="{{ cx }}"
|
||||
@ -23,10 +23,7 @@
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<div
|
||||
[style]="'height: ' + size + 'px; width: ' + size + 'px; padding: ' + strokeWidth + 'px;'"
|
||||
class="text-container"
|
||||
>
|
||||
<div [style]="'height: ' + size + 'px; width: ' + size + 'px; padding: ' + strokeWidth + 'px;'" class="text-container">
|
||||
<div class="heading-xl">{{ displayedDataTotal }}</div>
|
||||
<div class="mt-5">{{ subtitle | translate }}</div>
|
||||
</div>
|
||||
@ -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"
|
||||
>
|
||||
<redaction-status-bar
|
||||
[config]="[
|
||||
@ -45,10 +42,7 @@
|
||||
length: val.value,
|
||||
color: val.color,
|
||||
label: getLabel(val),
|
||||
cssClass:
|
||||
val.color === 'PROCESSING' || val.color === 'OCR_PROCESSING'
|
||||
? 'loading'
|
||||
: ''
|
||||
cssClass: val.color === 'PROCESSING' || val.color === 'OCR_PROCESSING' ? 'loading' : ''
|
||||
}
|
||||
]"
|
||||
[small]="true"
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { Color } from '@utils/types';
|
||||
import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model';
|
||||
import { FilterService } from '@shared/services/filter.service';
|
||||
|
||||
export interface DoughnutChartConfig {
|
||||
@ -22,11 +21,8 @@ export class SimpleDoughnutChartComponent<T> 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<string>();
|
||||
|
||||
chartData: any[] = [];
|
||||
perimeter: number;
|
||||
@ -36,11 +32,11 @@ export class SimpleDoughnutChartComponent<T> implements OnChanges {
|
||||
|
||||
constructor(readonly filterService: FilterService<T>) {}
|
||||
|
||||
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<T> 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];
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<T> {
|
||||
}
|
||||
|
||||
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<T> {
|
||||
}
|
||||
|
||||
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)], []);
|
||||
}
|
||||
|
||||
@ -4,23 +4,21 @@ import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
|
||||
@Injectable()
|
||||
export class ScreenStateService<T> {
|
||||
entities$ = new BehaviorSubject<T[]>([]);
|
||||
allEntities$ = new BehaviorSubject<T[]>([]);
|
||||
filteredEntities$ = new BehaviorSubject<T[]>([]);
|
||||
displayedEntities$ = new BehaviorSubject<T[]>([]);
|
||||
selectedEntitiesIds$ = new BehaviorSubject<string[]>([]);
|
||||
selectedEntities$ = new BehaviorSubject<T[]>([]);
|
||||
|
||||
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<T> {
|
||||
}
|
||||
|
||||
map<K>(func: (state: T[]) => K): Observable<K> {
|
||||
return this.entities$.asObservable().pipe(
|
||||
return this.allEntities$.asObservable().pipe(
|
||||
map((state: T[]) => func(state)),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
}
|
||||
|
||||
setEntities(newEntities: Partial<T[]>): void {
|
||||
this.entities$.next(newEntities);
|
||||
this.allEntities$.next(newEntities);
|
||||
}
|
||||
|
||||
setFilteredEntities(newEntities: Partial<T[]>): void {
|
||||
this.filteredEntities$.next(newEntities);
|
||||
}
|
||||
|
||||
setSelectedEntitiesIds(newEntities: Partial<string[]>): void {
|
||||
this.selectedEntitiesIds$.next(newEntities);
|
||||
setSelectedEntities(newEntities: Partial<T[]>): void {
|
||||
this.selectedEntities$.next(newEntities);
|
||||
}
|
||||
|
||||
setDisplayedEntities(newEntities: Partial<T[]>): 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<boolean> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,10 +12,7 @@ export class SearchService<T> {
|
||||
query: ['']
|
||||
});
|
||||
|
||||
constructor(
|
||||
private readonly _screenStateService: ScreenStateService<T>,
|
||||
private readonly _formBuilder: FormBuilder
|
||||
) {
|
||||
constructor(private readonly _screenStateService: ScreenStateService<T>, private readonly _formBuilder: FormBuilder) {
|
||||
this.searchForm.valueChanges.subscribe(() => this.executeSearch());
|
||||
}
|
||||
|
||||
@ -26,17 +23,14 @@ export class SearchService<T> {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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<void> {
|
||||
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<string>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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]
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user