Preview dossier attributes in overview
This commit is contained in:
parent
95edb70dea
commit
427b0a9402
3
apps/red-ui/src/app/models/dossier-attributes.model.ts
Normal file
3
apps/red-ui/src/app/models/dossier-attributes.model.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { DossierAttributeConfig } from '@redaction/red-ui-http';
|
||||||
|
|
||||||
|
export type DossierAttributeWithValue = DossierAttributeConfig & { value: any };
|
||||||
@ -1,12 +1,13 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { DossierAttributeConfig, DossierAttributesControllerService, FileAttributeConfig } from '@redaction/red-ui-http';
|
import { DossierAttributeConfig, FileAttributeConfig } from '@redaction/red-ui-http';
|
||||||
import { AppStateService } from '@state/app-state.service';
|
import { AppStateService } from '@state/app-state.service';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { LoadingService } from '@services/loading.service';
|
import { LoadingService } from '@services/loading.service';
|
||||||
import { ErrorMessageService } from '@services/error-message.service';
|
import { ErrorMessageService } from '@services/error-message.service';
|
||||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||||
import { HttpErrorResponse } from '@angular/common/http';
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
|
import { DossierAttributesService } from '@shared/services/controller-wrappers/dossier-attributes.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-add-edit-dossier-attribute-dialog',
|
selector: 'redaction-add-edit-dossier-attribute-dialog',
|
||||||
@ -28,7 +29,7 @@ export class AddEditDossierAttributeDialogComponent {
|
|||||||
private readonly _appStateService: AppStateService,
|
private readonly _appStateService: AppStateService,
|
||||||
private readonly _formBuilder: FormBuilder,
|
private readonly _formBuilder: FormBuilder,
|
||||||
private readonly _loadingService: LoadingService,
|
private readonly _loadingService: LoadingService,
|
||||||
private readonly _dossierAttributesService: DossierAttributesControllerService,
|
private readonly _dossierAttributesService: DossierAttributesService,
|
||||||
private readonly _errorMessageService: ErrorMessageService,
|
private readonly _errorMessageService: ErrorMessageService,
|
||||||
private readonly _notificationService: NotificationService,
|
private readonly _notificationService: NotificationService,
|
||||||
public dialogRef: MatDialogRef<AddEditDossierAttributeDialogComponent>,
|
public dialogRef: MatDialogRef<AddEditDossierAttributeDialogComponent>,
|
||||||
@ -71,20 +72,18 @@ export class AddEditDossierAttributeDialogComponent {
|
|||||||
...this.dossierAttributeForm.getRawValue()
|
...this.dossierAttributeForm.getRawValue()
|
||||||
};
|
};
|
||||||
|
|
||||||
this._dossierAttributesService
|
this._dossierAttributesService.addOrUpdateConfig(attribute).subscribe(
|
||||||
.addOrUpdateDossierAttributesConfig(attribute, this._appStateService.activeDossierTemplateId)
|
() => {
|
||||||
.subscribe(
|
this.dialogRef.close(true);
|
||||||
() => {
|
},
|
||||||
this.dialogRef.close(true);
|
(err: HttpErrorResponse) => {
|
||||||
},
|
this._loadingService.stop();
|
||||||
(err: HttpErrorResponse) => {
|
this._notificationService.showToastNotification(
|
||||||
this._loadingService.stop();
|
this._errorMessageService.getMessage(err, 'add-edit-dossier-attribute.error.generic'),
|
||||||
this._notificationService.showToastNotification(
|
null,
|
||||||
this._errorMessageService.getMessage(err, 'add-edit-dossier-attribute.error.generic'),
|
NotificationType.ERROR
|
||||||
null,
|
);
|
||||||
NotificationType.ERROR
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Component, Injector, OnInit } from '@angular/core';
|
import { Component, Injector, OnInit } from '@angular/core';
|
||||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||||
import { DossierAttributeConfig, DossierAttributesControllerService } from '@redaction/red-ui-http';
|
import { DossierAttributeConfig } from '@redaction/red-ui-http';
|
||||||
import { AppStateService } from '@state/app-state.service';
|
import { AppStateService } from '@state/app-state.service';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||||
@ -10,6 +10,7 @@ import { FilterService } from '@shared/services/filter.service';
|
|||||||
import { SearchService } from '@shared/services/search.service';
|
import { SearchService } from '@shared/services/search.service';
|
||||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
|
import { DossierAttributesService } from '@shared/services/controller-wrappers/dossier-attributes.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './dossier-attributes-listing-screen.component.html',
|
templateUrl: './dossier-attributes-listing-screen.component.html',
|
||||||
@ -23,7 +24,7 @@ export class DossierAttributesListingScreenComponent extends BaseListingComponen
|
|||||||
private readonly _activatedRoute: ActivatedRoute,
|
private readonly _activatedRoute: ActivatedRoute,
|
||||||
private readonly _dialogService: AdminDialogService,
|
private readonly _dialogService: AdminDialogService,
|
||||||
private readonly _loadingService: LoadingService,
|
private readonly _loadingService: LoadingService,
|
||||||
private readonly _dossierAttributesService: DossierAttributesControllerService,
|
private readonly _dossierAttributesService: DossierAttributesService,
|
||||||
readonly permissionsService: PermissionsService
|
readonly permissionsService: PermissionsService
|
||||||
) {
|
) {
|
||||||
super(_injector);
|
super(_injector);
|
||||||
@ -41,9 +42,7 @@ export class DossierAttributesListingScreenComponent extends BaseListingComponen
|
|||||||
this._dialogService.openDialog('confirm', $event, null, async () => {
|
this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
const ids = dossierAttribute ? [dossierAttribute.id] : this._screenStateService.selectedEntitiesIds;
|
const ids = dossierAttribute ? [dossierAttribute.id] : this._screenStateService.selectedEntitiesIds;
|
||||||
await this._dossierAttributesService
|
await this._dossierAttributesService.deleteConfigs(ids);
|
||||||
.deleteDossierAttributesConfig(ids, this._appStateService.activeDossierTemplateId)
|
|
||||||
.toPromise();
|
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -61,10 +60,8 @@ export class DossierAttributesListingScreenComponent extends BaseListingComponen
|
|||||||
|
|
||||||
private async _loadData() {
|
private async _loadData() {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
const response = await this._dossierAttributesService
|
const attributes = await this._dossierAttributesService.getConfig();
|
||||||
.getDossierAttributesConfig(this._appStateService.activeDossierTemplateId)
|
this._screenStateService.setEntities(attributes);
|
||||||
.toPromise();
|
|
||||||
this._screenStateService.setEntities(response?.dossierAttributeConfigs || []);
|
|
||||||
this.filterService.filterEntities();
|
this.filterService.filterEntities();
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,66 @@
|
|||||||
|
<div>
|
||||||
|
<mat-icon svgIcon="red:document"></mat-icon>
|
||||||
|
<span>{{ 'dossier-overview.dossier-details.stats.documents' | translate: { count: activeDossier.files.length } }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<mat-icon svgIcon="red:user"></mat-icon>
|
||||||
|
<span>{{ 'dossier-overview.dossier-details.stats.people' | translate: { count: activeDossier.memberCount } }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<mat-icon svgIcon="red:pages"></mat-icon>
|
||||||
|
<span>{{
|
||||||
|
'dossier-overview.dossier-details.stats.analysed-pages' | translate: { count: activeDossier.totalNumberOfPages | number }
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<mat-icon svgIcon="red:calendar"></mat-icon>
|
||||||
|
<span
|
||||||
|
>{{
|
||||||
|
'dossier-overview.dossier-details.stats.created-on'
|
||||||
|
| translate
|
||||||
|
: {
|
||||||
|
date: activeDossier.dossier.date | date: 'd MMM. yyyy'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="activeDossier.dossier.dueDate">
|
||||||
|
<mat-icon svgIcon="red:lightning"></mat-icon>
|
||||||
|
<span>{{
|
||||||
|
'dossier-overview.dossier-details.stats.due-date'
|
||||||
|
| translate
|
||||||
|
: {
|
||||||
|
date: activeDossier.dossier.dueDate | date: 'd MMM. yyyy'
|
||||||
|
}
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<mat-icon svgIcon="red:template"></mat-icon>
|
||||||
|
<span>{{ dossierTemplate?.name }} </span>
|
||||||
|
</div>
|
||||||
|
<div (click)="openDossierDictionaryDialog.emit()" *ngIf="activeDossier.type" class="link-property">
|
||||||
|
<mat-icon svgIcon="red:dictionary"></mat-icon>
|
||||||
|
<span>{{ 'dossier-overview.dossier-details.dictionary' | translate }} </span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="dossierAttributes?.length">
|
||||||
|
<div (click)="attributesExpanded = true" *ngIf="!attributesExpanded" class="all-caps-label show-attributes">
|
||||||
|
{{ 'dossier-overview.dossier-details.attributes.expand' | translate: { count: dossierAttributes.length } }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="attributesExpanded">
|
||||||
|
<div (click)="openEditDossierAttributesDialog()" *ngFor="let attr of dossierAttributes" class="link-property">
|
||||||
|
<mat-icon svgIcon="red:attribute"></mat-icon>
|
||||||
|
<span *ngIf="!attr.value"> {{ attr.label + ': -' }}</span>
|
||||||
|
<span *ngIf="attr.value && attr.type === 'DATE'"> {{ attr.label + ': ' + (attr.value | date: 'd MMM. yyyy') }}</span>
|
||||||
|
<span *ngIf="attr.value && attr.type === 'IMAGE'">
|
||||||
|
{{ attr.label + ': ' + ('dossier-overview.dossier-details.attributes.image-uploaded' | translate) }}</span
|
||||||
|
>
|
||||||
|
<span *ngIf="attr.value && (attr.type === 'TEXT' || attr.type === 'NUMBER')"> {{ attr.label + ': ' + attr.value }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div (click)="attributesExpanded = false" class="all-caps-label hide-attributes">
|
||||||
|
{{ 'dossier-overview.dossier-details.attributes.show-less' | translate }}
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
@import '../../../../../assets/styles/red-variables';
|
||||||
|
@import '../../../../../assets/styles/red-components';
|
||||||
|
@import '../../../../../assets/styles/red-text-styles';
|
||||||
|
|
||||||
|
:host {
|
||||||
|
@extend .stats-subtitle;
|
||||||
|
@extend .small-label;
|
||||||
|
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
margin-right: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 0 8px;
|
||||||
|
margin-left: -8px;
|
||||||
|
|
||||||
|
&.link-property {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $grey-6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-attributes,
|
||||||
|
.hide-attributes {
|
||||||
|
margin-top: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-attributes::before {
|
||||||
|
content: '+';
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide-attributes::before {
|
||||||
|
content: '-';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
import { DossierAttributeWithValue } from '@models/dossier-attributes.model';
|
||||||
|
import { AppStateService } from '@state/app-state.service';
|
||||||
|
import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||||
|
import { DossierTemplateModel } from '@redaction/red-ui-http';
|
||||||
|
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'redaction-dossier-details-stats',
|
||||||
|
templateUrl: './dossier-details-stats.component.html',
|
||||||
|
styleUrls: ['./dossier-details-stats.component.scss']
|
||||||
|
})
|
||||||
|
export class DossierDetailsStatsComponent {
|
||||||
|
attributesExpanded = false;
|
||||||
|
@Input() dossierAttributes: DossierAttributeWithValue[];
|
||||||
|
@Output() openDossierDictionaryDialog = new EventEmitter();
|
||||||
|
|
||||||
|
constructor(private readonly _appStateService: AppStateService, private readonly _dialogService: DossiersDialogService) {}
|
||||||
|
|
||||||
|
get activeDossier(): DossierWrapper {
|
||||||
|
return this._appStateService.activeDossier;
|
||||||
|
}
|
||||||
|
|
||||||
|
get dossierTemplate(): DossierTemplateModel {
|
||||||
|
return this._appStateService.getDossierTemplateById(this.activeDossier.dossierTemplateId);
|
||||||
|
}
|
||||||
|
|
||||||
|
openEditDossierAttributesDialog() {
|
||||||
|
this._dialogService.openDialog('editDossier', null, {
|
||||||
|
dossierWrapper: this.activeDossier,
|
||||||
|
section: 'dossier-attributes'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,21 +6,14 @@
|
|||||||
|
|
||||||
<div class="header-wrapper mt-8">
|
<div class="header-wrapper mt-8">
|
||||||
<div class="heading-xl flex-1">{{ appStateService.activeDossier.dossier.dossierName }}</div>
|
<div class="heading-xl flex-1">{{ appStateService.activeDossier.dossier.dossierName }}</div>
|
||||||
<ng-container
|
<ng-container *ngTemplateOutlet="collapsible; context: { action: 'collapse' }"></ng-container>
|
||||||
*ngTemplateOutlet="collapsible; context: { action: 'collapse' }"
|
|
||||||
></ng-container>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-24">
|
<div class="mt-24">
|
||||||
<div class="all-caps-label" translate="dossier-details.owner"></div>
|
<div class="all-caps-label" translate="dossier-details.owner"></div>
|
||||||
<div class="mt-12 d-flex">
|
<div class="mt-12 d-flex">
|
||||||
<ng-container *ngIf="!editingOwner; else editOwner">
|
<ng-container *ngIf="!editingOwner; else editOwner">
|
||||||
<redaction-initials-avatar
|
<redaction-initials-avatar [userId]="owner.userId" [withName]="true" color="gray" size="large"></redaction-initials-avatar>
|
||||||
[userId]="owner.userId"
|
|
||||||
[withName]="true"
|
|
||||||
color="gray"
|
|
||||||
size="large"
|
|
||||||
></redaction-initials-avatar>
|
|
||||||
|
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
(action)="editingOwner = true"
|
(action)="editingOwner = true"
|
||||||
@ -65,73 +58,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div [class.mt-24]="!hasFiles" class="pb-32 small-label stats-subtitle">
|
<div [class.mt-24]="!hasFiles" class="pb-32">
|
||||||
<div>
|
<redaction-dossier-details-stats
|
||||||
<mat-icon svgIcon="red:document"></mat-icon>
|
(openDossierDictionaryDialog)="openDossierDictionaryDialog.emit()"
|
||||||
<span>{{
|
[dossierAttributes]="dossierAttributes"
|
||||||
'dossier-overview.dossier-details.stats.documents'
|
></redaction-dossier-details-stats>
|
||||||
| translate: { count: appStateService.activeDossier.files.length }
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<mat-icon svgIcon="red:user"></mat-icon>
|
|
||||||
<span>{{
|
|
||||||
'dossier-overview.dossier-details.stats.people'
|
|
||||||
| translate: { count: appStateService.activeDossier.memberCount }
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<mat-icon svgIcon="red:pages"></mat-icon>
|
|
||||||
<span>{{
|
|
||||||
'dossier-overview.dossier-details.stats.analysed-pages'
|
|
||||||
| translate
|
|
||||||
: { count: appStateService.activeDossier.totalNumberOfPages | number }
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<mat-icon svgIcon="red:calendar"></mat-icon>
|
|
||||||
<span
|
|
||||||
>{{
|
|
||||||
'dossier-overview.dossier-details.stats.created-on'
|
|
||||||
| translate
|
|
||||||
: {
|
|
||||||
date:
|
|
||||||
appStateService.activeDossier.dossier.date
|
|
||||||
| date: 'd MMM. yyyy'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="appStateService.activeDossier.dossier.dueDate">
|
|
||||||
<mat-icon svgIcon="red:lightning"></mat-icon>
|
|
||||||
<span>{{
|
|
||||||
'dossier-overview.dossier-details.stats.due-date'
|
|
||||||
| translate
|
|
||||||
: {
|
|
||||||
date:
|
|
||||||
appStateService.activeDossier.dossier.dueDate
|
|
||||||
| date: 'd MMM. yyyy'
|
|
||||||
}
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<mat-icon svgIcon="red:template"></mat-icon>
|
|
||||||
<span
|
|
||||||
>{{
|
|
||||||
appStateService.getDossierTemplateById(
|
|
||||||
appStateService.activeDossier.dossierTemplateId
|
|
||||||
)?.name
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
(click)="openDossierDictionaryDialog.emit()"
|
|
||||||
*ngIf="appStateService.activeDossier.type"
|
|
||||||
class="pointer"
|
|
||||||
>
|
|
||||||
<mat-icon svgIcon="red:dictionary"></mat-icon>
|
|
||||||
<span>{{ 'dossier-overview.dossier-details.dictionary' | translate }} </span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="!!appStateService.activeDossier.dossier.description" class="pb-32">
|
<div *ngIf="!!appStateService.activeDossier.dossier.description" class="pb-32">
|
||||||
|
|||||||
@ -42,15 +42,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-subtitle {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mt-12 {
|
.mt-12 {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectorRef, Component, EventEmitter, OnInit, Output } from '@angular/core';
|
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
import { AppStateService } from '@state/app-state.service';
|
import { AppStateService } from '@state/app-state.service';
|
||||||
import { groupBy } from '@utils/functions';
|
import { groupBy } from '@utils/functions';
|
||||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||||
@ -10,6 +10,7 @@ import { User } from '@redaction/red-ui-http';
|
|||||||
import { NotificationService } from '@services/notification.service';
|
import { NotificationService } from '@services/notification.service';
|
||||||
import { FilterService } from '@shared/services/filter.service';
|
import { FilterService } from '@shared/services/filter.service';
|
||||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||||
|
import { DossierAttributeWithValue } from '@models/dossier-attributes.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-dossier-details',
|
selector: 'redaction-dossier-details',
|
||||||
@ -20,6 +21,7 @@ export class DossierDetailsComponent implements OnInit {
|
|||||||
documentsChartData: DoughnutChartConfig[] = [];
|
documentsChartData: DoughnutChartConfig[] = [];
|
||||||
owner: User;
|
owner: User;
|
||||||
editingOwner = false;
|
editingOwner = false;
|
||||||
|
@Input() dossierAttributes: DossierAttributeWithValue[];
|
||||||
@Output() openAssignDossierMembersDialog = new EventEmitter();
|
@Output() openAssignDossierMembersDialog = new EventEmitter();
|
||||||
@Output() openDossierDictionaryDialog = new EventEmitter();
|
@Output() openDossierDictionaryDialog = new EventEmitter();
|
||||||
@Output() toggleCollapse = new EventEmitter();
|
@Output() toggleCollapse = new EventEmitter();
|
||||||
|
|||||||
@ -3,12 +3,11 @@ import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
|
|||||||
import { DossierWrapper } from '@state/model/dossier.wrapper';
|
import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||||
import { AppStateService } from '@state/app-state.service';
|
import { AppStateService } from '@state/app-state.service';
|
||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
import { DossierAttributeConfig, DossierAttributesControllerService } from '@redaction/red-ui-http';
|
|
||||||
import { LoadingService } from '@services/loading.service';
|
import { LoadingService } from '@services/loading.service';
|
||||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
|
import { DossierAttributeWithValue } from '@models/dossier-attributes.model';
|
||||||
type DossierAttributeWithValue = DossierAttributeConfig & { value: any };
|
import { DossierAttributesService } from '@shared/services/controller-wrappers/dossier-attributes.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-edit-dossier-attributes',
|
selector: 'redaction-edit-dossier-attributes',
|
||||||
@ -20,7 +19,7 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa
|
|||||||
@Output() updateDossier = new EventEmitter<any>();
|
@Output() updateDossier = new EventEmitter<any>();
|
||||||
customAttributes: DossierAttributeWithValue[] = [];
|
customAttributes: DossierAttributeWithValue[] = [];
|
||||||
imageAttributes: DossierAttributeWithValue[] = [];
|
imageAttributes: DossierAttributeWithValue[] = [];
|
||||||
attributesMapping: DossierAttributeWithValue[] = [];
|
attributes: DossierAttributeWithValue[] = [];
|
||||||
|
|
||||||
attributesForm: FormGroup;
|
attributesForm: FormGroup;
|
||||||
@ViewChildren('fileInput') private _fileInputs: QueryList<ElementRef>;
|
@ViewChildren('fileInput') private _fileInputs: QueryList<ElementRef>;
|
||||||
@ -28,13 +27,13 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly _appStateService: AppStateService,
|
private readonly _appStateService: AppStateService,
|
||||||
private readonly _permissionsService: PermissionsService,
|
private readonly _permissionsService: PermissionsService,
|
||||||
private readonly _dossierAttributesService: DossierAttributesControllerService,
|
private readonly _dossierAttributesService: DossierAttributesService,
|
||||||
private readonly _loadingService: LoadingService,
|
private readonly _loadingService: LoadingService,
|
||||||
private readonly _formBuilder: FormBuilder
|
private readonly _formBuilder: FormBuilder
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
get changed() {
|
get changed() {
|
||||||
for (const attr of this.attributesMapping) {
|
for (const attr of this.attributes) {
|
||||||
if (this.isDate(attr)) {
|
if (this.isDate(attr)) {
|
||||||
if (!moment(attr.value).isSame(moment(this.currentAttrValue(attr)))) {
|
if (!moment(attr.value).isSame(moment(this.currentAttrValue(attr)))) {
|
||||||
return true;
|
return true;
|
||||||
@ -60,11 +59,11 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa
|
|||||||
|
|
||||||
async save() {
|
async save() {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
const dossierAttributeList = this.attributesMapping.map(attr => ({
|
const dossierAttributeList = this.attributes.map(attr => ({
|
||||||
dossierAttributeId: attr.id,
|
dossierAttributeId: attr.id,
|
||||||
value: this.currentAttrValue(attr)
|
value: this.currentAttrValue(attr)
|
||||||
}));
|
}));
|
||||||
await this._dossierAttributesService.setDossierAttributes({ dossierAttributeList }, this.dossierWrapper.dossierId).toPromise();
|
await this._dossierAttributesService.setValues(this.dossierWrapper, dossierAttributeList);
|
||||||
await this._loadAttributes();
|
await this._loadAttributes();
|
||||||
this.updateDossier.emit();
|
this.updateDossier.emit();
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
@ -130,22 +129,14 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _loadAttributes() {
|
private async _loadAttributes() {
|
||||||
const attributes = await this._dossierAttributesService.getDossierAttributes(this.dossierWrapper.dossierId).toPromise();
|
this.attributes = await this._dossierAttributesService.getValues(this.dossierWrapper);
|
||||||
const attributesConfig = await this._dossierAttributesService
|
this.customAttributes = this.attributes.filter(attr => !this.isImage(attr));
|
||||||
.getDossierAttributesConfig(this.dossierWrapper.dossierTemplateId)
|
this.imageAttributes = this.attributes.filter(attr => this.isImage(attr));
|
||||||
.toPromise();
|
|
||||||
this.attributesMapping = attributesConfig.dossierAttributeConfigs.map(config => ({
|
|
||||||
...config,
|
|
||||||
value: attributes.dossierAttributeList.find(attr => attr.dossierAttributeId === config.id)?.value
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.customAttributes = this.attributesMapping.filter(attr => !this.isImage(attr));
|
|
||||||
this.imageAttributes = this.attributesMapping.filter(attr => this.isImage(attr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _initForm() {
|
private _initForm() {
|
||||||
const controlsConfig = {};
|
const controlsConfig = {};
|
||||||
for (const attribute of this.attributesMapping) {
|
for (const attribute of this.attributes) {
|
||||||
controlsConfig[attribute.id] = attribute.value;
|
controlsConfig[attribute.id] = attribute.value;
|
||||||
}
|
}
|
||||||
this.attributesForm = this._formBuilder.group(controlsConfig);
|
this.attributesForm = this._formBuilder.group(controlsConfig);
|
||||||
|
|||||||
@ -48,6 +48,7 @@ import { PageExclusionComponent } from './components/page-exclusion/page-exclusi
|
|||||||
import { RecategorizeImageDialogComponent } from './dialogs/recategorize-image-dialog/recategorize-image-dialog.component';
|
import { RecategorizeImageDialogComponent } from './dialogs/recategorize-image-dialog/recategorize-image-dialog.component';
|
||||||
import { EditDossierAttributesComponent } from './dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component';
|
import { EditDossierAttributesComponent } from './dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component';
|
||||||
import { DossiersService } from './services/dossiers.service';
|
import { DossiersService } from './services/dossiers.service';
|
||||||
|
import { DossierDetailsStatsComponent } from './components/dossier-details-stats/dossier-details-stats.component';
|
||||||
|
|
||||||
const screens = [DossierListingScreenComponent, DossierOverviewScreenComponent, FilePreviewScreenComponent];
|
const screens = [DossierListingScreenComponent, DossierOverviewScreenComponent, FilePreviewScreenComponent];
|
||||||
|
|
||||||
@ -88,6 +89,7 @@ const components = [
|
|||||||
TeamMembersManagerComponent,
|
TeamMembersManagerComponent,
|
||||||
ScrollButtonComponent,
|
ScrollButtonComponent,
|
||||||
PageExclusionComponent,
|
PageExclusionComponent,
|
||||||
|
DossierDetailsStatsComponent,
|
||||||
|
|
||||||
...screens,
|
...screens,
|
||||||
...dialogs
|
...dialogs
|
||||||
|
|||||||
@ -230,6 +230,7 @@
|
|||||||
(openAssignDossierMembersDialog)="openAssignDossierMembersDialog()"
|
(openAssignDossierMembersDialog)="openAssignDossierMembersDialog()"
|
||||||
(openDossierDictionaryDialog)="openDossierDictionaryDialog()"
|
(openDossierDictionaryDialog)="openDossierDictionaryDialog()"
|
||||||
(toggleCollapse)="toggleCollapsedDetails()"
|
(toggleCollapse)="toggleCollapsedDetails()"
|
||||||
|
[dossierAttributes]="dossierAttributes"
|
||||||
></redaction-dossier-details>
|
></redaction-dossier-details>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -23,14 +23,16 @@ import { DossierWrapper } from '@state/model/dossier.wrapper';
|
|||||||
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
|
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
|
||||||
import { annotationFilterChecker, keyChecker } from '@shared/components/filters/popup-filter/utils/filter-utils';
|
import { annotationFilterChecker, keyChecker } from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||||
import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model';
|
import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model';
|
||||||
import { AppConfigKey, AppConfigService } from '../../../app-config/app-config.service';
|
import { AppConfigKey, AppConfigService } from '@app-config/app-config.service';
|
||||||
import { FilterConfig } from '@shared/components/page-header/models/filter-config.model';
|
|
||||||
import { ActionConfig } from '@shared/components/page-header/models/action-config.model';
|
import { ActionConfig } from '@shared/components/page-header/models/action-config.model';
|
||||||
import { FilterService } from '@shared/services/filter.service';
|
import { FilterService } from '@shared/services/filter.service';
|
||||||
import { SearchService } from '@shared/services/search.service';
|
import { SearchService } from '@shared/services/search.service';
|
||||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||||
import { ScreenNames, SortingService } from '@services/sorting.service';
|
import { ScreenNames, SortingService } from '@services/sorting.service';
|
||||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
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';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './dossier-overview-screen.component.html',
|
templateUrl: './dossier-overview-screen.component.html',
|
||||||
@ -43,9 +45,8 @@ export class DossierOverviewScreenComponent
|
|||||||
{
|
{
|
||||||
collapsedDetails = false;
|
collapsedDetails = false;
|
||||||
readonly itemSize = 80;
|
readonly itemSize = 80;
|
||||||
filterConfigs: FilterConfig[];
|
|
||||||
actionConfigs: ActionConfig[];
|
actionConfigs: ActionConfig[];
|
||||||
|
dossierAttributes: DossierAttributeWithValue[] = [];
|
||||||
@ViewChild(DossierDetailsComponent, { static: false })
|
@ViewChild(DossierDetailsComponent, { static: false })
|
||||||
private readonly _dossierDetailsComponent: DossierDetailsComponent;
|
private readonly _dossierDetailsComponent: DossierDetailsComponent;
|
||||||
private _filesAutoUpdateTimer: Subscription;
|
private _filesAutoUpdateTimer: Subscription;
|
||||||
@ -53,7 +54,6 @@ export class DossierOverviewScreenComponent
|
|||||||
private _fileChangedSub: Subscription;
|
private _fileChangedSub: Subscription;
|
||||||
private _lastScrollPosition: number;
|
private _lastScrollPosition: number;
|
||||||
private _lastOpenedFileId = '';
|
private _lastOpenedFileId = '';
|
||||||
|
|
||||||
@ViewChild('needsWorkTemplate', { read: TemplateRef, static: true })
|
@ViewChild('needsWorkTemplate', { read: TemplateRef, static: true })
|
||||||
private readonly _needsWorkTemplate: TemplateRef<any>;
|
private readonly _needsWorkTemplate: TemplateRef<any>;
|
||||||
@ViewChild('fileInput') private _fileInput: ElementRef;
|
@ViewChild('fileInput') private _fileInput: ElementRef;
|
||||||
@ -72,6 +72,8 @@ export class DossierOverviewScreenComponent
|
|||||||
private readonly _userPreferenceControllerService: UserPreferenceControllerService,
|
private readonly _userPreferenceControllerService: UserPreferenceControllerService,
|
||||||
private readonly _appConfigService: AppConfigService,
|
private readonly _appConfigService: AppConfigService,
|
||||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private readonly _loadingService: LoadingService,
|
||||||
|
private readonly _dossierAttributesService: DossierAttributesService,
|
||||||
protected readonly _injector: Injector
|
protected readonly _injector: Injector
|
||||||
) {
|
) {
|
||||||
super(_injector);
|
super(_injector);
|
||||||
@ -101,15 +103,7 @@ export class DossierOverviewScreenComponent
|
|||||||
return this._lastOpenedFileId === fileStatus.fileId;
|
return this._lastOpenedFileId === fileStatus.fileId;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
async ngOnInit() {
|
||||||
this._userPreferenceControllerService.getAllUserAttributes().subscribe(attributes => {
|
|
||||||
if (attributes === null || attributes === undefined) return;
|
|
||||||
const key = 'Dossier-Recent-' + this.activeDossier.dossierId;
|
|
||||||
if (attributes[key]?.length > 0) {
|
|
||||||
this._lastOpenedFileId = attributes[key][0];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this._fileDropOverlayService.initFileDropHandling();
|
this._fileDropOverlayService.initFileDropHandling();
|
||||||
|
|
||||||
this.calculateData();
|
this.calculateData();
|
||||||
@ -134,6 +128,19 @@ export class DossierOverviewScreenComponent
|
|||||||
this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top');
|
this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
@ -143,9 +150,9 @@ export class DossierOverviewScreenComponent
|
|||||||
this._routerEventsScrollPositionSub.unsubscribe();
|
this._routerEventsScrollPositionSub.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnAttach() {
|
async ngOnAttach() {
|
||||||
this._loadEntitiesFromState();
|
this._loadEntitiesFromState();
|
||||||
this.ngOnInit();
|
await this.ngOnInit();
|
||||||
this.scrollViewport.scrollTo({ top: this._lastScrollPosition });
|
this.scrollViewport.scrollTo({ top: this._lastScrollPosition });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export class DossiersDialogService extends DialogService<DialogType> {
|
|||||||
},
|
},
|
||||||
editDossier: {
|
editDossier: {
|
||||||
component: EditDossierDialogComponent,
|
component: EditDossierDialogComponent,
|
||||||
dialogConfig: { ...this._largeConfig, autoFocus: true }
|
dialogConfig: { ...this._largeConfig }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,57 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import {
|
||||||
|
DossierAttributeConfig,
|
||||||
|
DossierAttributeReq,
|
||||||
|
DossierAttributesControllerService,
|
||||||
|
DossierAttributesRes
|
||||||
|
} from '@redaction/red-ui-http';
|
||||||
|
import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||||
|
import { DossierAttributeWithValue } from '@models/dossier-attributes.model';
|
||||||
|
import { AppStateService } from '@state/app-state.service';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class DossierAttributesService {
|
||||||
|
constructor(
|
||||||
|
private readonly _dossierAttributesControllerService: DossierAttributesControllerService,
|
||||||
|
private readonly _appStateService: AppStateService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async getValues(dossierWrapper: DossierWrapper): Promise<DossierAttributeWithValue[]> {
|
||||||
|
const attributes = await this._dossierAttributesControllerService.getDossierAttributes(dossierWrapper.dossierId).toPromise();
|
||||||
|
const attributesConfig = await this._dossierAttributesControllerService
|
||||||
|
.getDossierAttributesConfig(dossierWrapper.dossierTemplateId)
|
||||||
|
.toPromise();
|
||||||
|
|
||||||
|
return attributesConfig.dossierAttributeConfigs.map(config => ({
|
||||||
|
...config,
|
||||||
|
value: attributes.dossierAttributeList.find(attr => attr.dossierAttributeId === config.id)?.value
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
setValues(dossierWrapper: DossierWrapper, dossierAttributeList: DossierAttributeReq[]): Promise<DossierAttributesRes> {
|
||||||
|
return this._dossierAttributesControllerService
|
||||||
|
.setDossierAttributes({ dossierAttributeList }, dossierWrapper.dossierId)
|
||||||
|
.toPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteConfigs(ids: string[], dossierTemplateId = this._appStateService.activeDossierTemplateId): Promise<void> {
|
||||||
|
return this._dossierAttributesControllerService.deleteDossierAttributesConfig(ids, dossierTemplateId).toPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getConfig(dossierTemplateId = this._appStateService.activeDossierTemplateId): Promise<DossierAttributeConfig[]> {
|
||||||
|
return (
|
||||||
|
(await this._dossierAttributesControllerService.getDossierAttributesConfig(dossierTemplateId).toPromise())
|
||||||
|
?.dossierAttributeConfigs || []
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
addOrUpdateConfig(
|
||||||
|
attribute: DossierAttributeConfig,
|
||||||
|
dossierTemplateId = this._appStateService.activeDossierTemplateId
|
||||||
|
): Observable<DossierAttributeConfig> {
|
||||||
|
return this._dossierAttributesControllerService.addOrUpdateDossierAttributesConfig(attribute, dossierTemplateId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -40,13 +40,7 @@ import { InputWithActionComponent } from '@shared/components/input-with-action/i
|
|||||||
import { PageHeaderComponent } from './components/page-header/page-header.component';
|
import { PageHeaderComponent } from './components/page-header/page-header.component';
|
||||||
import { DatePipe } from '@shared/pipes/date.pipe';
|
import { DatePipe } from '@shared/pipes/date.pipe';
|
||||||
|
|
||||||
const buttons = [
|
const buttons = [ChevronButtonComponent, CircleButtonComponent, FileDownloadBtnComponent, IconButtonComponent, UserButtonComponent];
|
||||||
ChevronButtonComponent,
|
|
||||||
CircleButtonComponent,
|
|
||||||
FileDownloadBtnComponent,
|
|
||||||
IconButtonComponent,
|
|
||||||
UserButtonComponent
|
|
||||||
];
|
|
||||||
|
|
||||||
const components = [
|
const components = [
|
||||||
FullPageLoadingIndicatorComponent,
|
FullPageLoadingIndicatorComponent,
|
||||||
@ -74,22 +68,9 @@ const components = [
|
|||||||
...buttons
|
...buttons
|
||||||
];
|
];
|
||||||
|
|
||||||
const utils = [
|
const utils = [HumanizePipe, DatePipe, SyncWidthDirective, HasScrollbarDirective, NavigateLastDossiersScreenDirective];
|
||||||
HumanizePipe,
|
|
||||||
DatePipe,
|
|
||||||
SyncWidthDirective,
|
|
||||||
HasScrollbarDirective,
|
|
||||||
NavigateLastDossiersScreenDirective
|
|
||||||
];
|
|
||||||
|
|
||||||
const modules = [
|
const modules = [MatConfigModule, TranslateModule, ScrollingModule, IconsModule, FormsModule, ReactiveFormsModule];
|
||||||
MatConfigModule,
|
|
||||||
TranslateModule,
|
|
||||||
ScrollingModule,
|
|
||||||
IconsModule,
|
|
||||||
FormsModule,
|
|
||||||
ReactiveFormsModule
|
|
||||||
];
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [...components, ...utils],
|
declarations: [...components, ...utils],
|
||||||
|
|||||||
@ -657,6 +657,11 @@
|
|||||||
"action": "Delete File"
|
"action": "Delete File"
|
||||||
},
|
},
|
||||||
"dossier-details": {
|
"dossier-details": {
|
||||||
|
"attributes": {
|
||||||
|
"image-uploaded": "Image uploaded",
|
||||||
|
"expand": "{{count}} custom attributes",
|
||||||
|
"show-less": "show less"
|
||||||
|
},
|
||||||
"charts": {
|
"charts": {
|
||||||
"documents-in-dossier": "Documents in Dossier"
|
"documents-in-dossier": "Documents in Dossier"
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user