diff --git a/apps/red-ui/src/app/modules/admin/admin.module.ts b/apps/red-ui/src/app/modules/admin/admin.module.ts index 10c37878c..f4087d8b1 100644 --- a/apps/red-ui/src/app/modules/admin/admin.module.ts +++ b/apps/red-ui/src/app/modules/admin/admin.module.ts @@ -49,6 +49,7 @@ import { BaseDossierTemplateScreenComponent } from './base-dossier-templates-scr import { DossierStatesListingScreenComponent } from './screens/dossier-states-listing/dossier-states-listing-screen.component'; import { AddEditDossierStateDialogComponent } from './dialogs/add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component'; import { A11yModule } from '@angular/cdk/a11y'; +import { ConfirmDeleteDossierStateDialogComponent } from './dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component'; const dialogs = [ AddEditDossierTemplateDialogComponent, @@ -98,7 +99,12 @@ const components = [ ]; @NgModule({ - declarations: [...components, DossierStatesListingScreenComponent, AddEditDossierStateDialogComponent], + declarations: [ + ...components, + DossierStatesListingScreenComponent, + AddEditDossierStateDialogComponent, + ConfirmDeleteDossierStateDialogComponent, + ], providers: [AdminDialogService, AuditService, DigitalSignatureService, LicenseReportService, RulesService, SmtpConfigService], imports: [ CommonModule, diff --git a/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component.html b/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component.html new file mode 100644 index 000000000..ff36577ae --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component.html @@ -0,0 +1,39 @@ + + + {{ 'confirm-delete-dossier-state.title' | translate }} + + + + {{ 'confirm-delete-dossier-state.warning' | translate: translateArgs }} + + {{ 'confirm-delete-dossier-state.suggestion' | translate }} + + + + + + + + {{ state.name }} + + + + + + + + + + {{ 'confirm-delete-dossier-state.delete-only' | translate }} + + + {{ 'confirm-delete-dossier-state.delete-replace' | translate }} + + + + + + diff --git a/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component.scss b/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component.scss new file mode 100644 index 000000000..616e7b39c --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component.scss @@ -0,0 +1,16 @@ +@use 'variables'; + +.replacement-suggestion { + font-size: 13px; + line-height: 18px; + color: variables.$grey-1; + margin-bottom: 24px; +} + +.dialog-header { + color: variables.$primary; +} + +.heading { + margin-bottom: 8px; +} diff --git a/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component.ts new file mode 100644 index 000000000..d80ece9ad --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component.ts @@ -0,0 +1,46 @@ +import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; +import { IDossierState } from '../../../../../../../../libs/red-domain/src/lib/dossier-state'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { FormBuilder, FormGroup } from '@angular/forms'; + +interface DialogData { + toBeDeletedState: IDossierState; + otherStates: IDossierState[]; + dossierCount: number; +} + +@Component({ + selector: 'redaction-confirm-delete-dossier-state-dialog', + templateUrl: './confirm-delete-dossier-state-dialog.component.html', + styleUrls: ['./confirm-delete-dossier-state-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ConfirmDeleteDossierStateDialogComponent { + readonly form: FormGroup; + + constructor( + private readonly _formBuilder: FormBuilder, + readonly dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: DialogData, + ) { + this.form = this._getForm(); + console.log(data); + } + + private _getForm(): FormGroup { + return this._formBuilder.group({ + replaceDossierStatusId: [null], + }); + } + + get translateArgs() { + return { + name: this.data.toBeDeletedState.name, + count: this.data.dossierCount, + }; + } + + get replaceDossierStatusId(): string { + return this.form.get('replaceDossierStatusId').value; + } +} diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen.component.html index 74fd22735..045a9d075 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen.component.html @@ -72,6 +72,12 @@ [type]="circleButtonTypes.dark" icon="iqser:edit" > + diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen.component.ts index 6aaa067f9..d3230e1e0 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen.component.ts @@ -6,6 +6,7 @@ import { ListingComponent, LoadingService, TableColumnConfig, + Toaster, } from '../../../../../../../../libs/common-ui/src'; import { DossierState, IDossierState } from '../../../../../../../../libs/red-domain/src/lib/dossier-state'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -16,6 +17,7 @@ import { DossierTemplatesService } from '../../../../services/entity-services/do import { AdminDialogService } from '../../services/admin-dialog.service'; import { UserService } from '../../../../services/user.service'; import { AppStateService } from '../../../../state/app-state.service'; +import { HttpStatusCode } from '@angular/common/http'; @Component({ templateUrl: './dossier-states-listing-screen.component.html', @@ -45,6 +47,7 @@ export class DossierStatesListingScreenComponent extends ListingComponent { - await firstValueFrom(this._dossierStateService.setDossierState(newValue)); - await this._appStateService.refreshDossierTemplate(this._dossierTemplatesService.activeDossierTemplateId); + await this._createNewDossierStateAndRefreshView(newValue); + }); + } + + openConfirmDeleteStateDialog($event: MouseEvent, dossierState: IDossierState) { + const templateId = this._dossierTemplatesService.activeDossierTemplateId; + const data = { + toBeDeletedState: dossierState, + otherStates: this.entitiesService.all.filter(state => state.dossierStatusId !== dossierState.dossierStatusId), + dossierCount: this._getDossiersWithStateAndTemplateCount(dossierState.dossierStatusId, templateId), + }; + this._dialogService.openDialog('deleteDossierState', $event, data, async (value: string | true) => { + if (value) { + if (value === true) { + console.log('asteptam'); + } else { + await firstValueFrom(this._dossierStateService.deleteAndReplace(dossierState.dossierStatusId, value)); + } + } + + await this._appStateService.refreshDossierTemplate(templateId); await this._loadData(); }); } + private async _createNewDossierStateAndRefreshView(newValue: IDossierState): Promise { + await firstValueFrom(this._dossierStateService.setDossierState(newValue)).catch(error => { + if (error.status === HttpStatusCode.Conflict) { + this._toaster.error(_('dossier-states-listing.error.conflict')); + } else { + this._toaster.error(_('dossier-states-listing.error.generic')); + } + }); + await this._appStateService.refreshDossierTemplate(this._dossierTemplatesService.activeDossierTemplateId); + await this._loadData(); + } + private async _loadData() { this._loadingService.start(); try { const templateId = this._dossierTemplatesService.activeDossierTemplateId; - const dossierStates = await firstValueFrom(this._dossierStateService.loadAll(`dossier-status/dossier-template/${templateId}`)); - const dossiers = this._dossiersService.all; + const dossierStates = await firstValueFrom(this._dossierStateService.loadAllForTemplate(templateId)); dossierStates.forEach(state => { - state.dossierCount = dossiers.filter( - dossier => dossier.dossierStatusId === state.dossierStatusId && dossier.dossierTemplateId === templateId, - ).length; + state.dossierCount = this._getDossiersWithStateAndTemplateCount(state.dossierStatusId, templateId); }); this.entitiesService.setEntities(dossierStates || []); } catch (e) {} this._loadingService.stop(); } + + private _getDossiersWithStateAndTemplateCount(dossierStatusId: string, templateId: string) { + const dossiers = this._dossiersService.all; + return dossiers.filter(dossier => dossier.dossierStatusId === dossierStatusId && dossier.dossierTemplateId === templateId).length; + } } diff --git a/apps/red-ui/src/app/modules/admin/services/admin-dialog.service.ts b/apps/red-ui/src/app/modules/admin/services/admin-dialog.service.ts index ff3c3fb67..31d5dab3c 100644 --- a/apps/red-ui/src/app/modules/admin/services/admin-dialog.service.ts +++ b/apps/red-ui/src/app/modules/admin/services/admin-dialog.service.ts @@ -14,6 +14,7 @@ import { ConfirmationDialogComponent, DialogConfig, DialogService, largeDialogCo import { UploadDictionaryDialogComponent } from '../dialogs/upload-dictionary-dialog/upload-dictionary-dialog.component'; import { FileAttributesConfigurationsDialogComponent } from '../dialogs/file-attributes-configurations-dialog/file-attributes-configurations-dialog.component'; import { AddEditDossierStateDialogComponent } from '../dialogs/add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component'; +import { ConfirmDeleteDossierStateDialogComponent } from '../dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component'; type DialogType = | 'confirm' @@ -30,7 +31,8 @@ type DialogType = | 'addEditDossierAttribute' | 'addEditJustification' | 'uploadDictionary' - | 'addEditDossierState'; + | 'addEditDossierState' + | 'deleteDossierState'; @Injectable() export class AdminDialogService extends DialogService { @@ -88,6 +90,9 @@ export class AdminDialogService extends DialogService { addEditDossierState: { component: AddEditDossierStateDialogComponent, }, + deleteDossierState: { + component: ConfirmDeleteDossierStateDialogComponent, + }, }; constructor(protected readonly _dialog: MatDialog) { diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-status/dossiers-listing-status.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-status/dossiers-listing-status.component.html new file mode 100644 index 000000000..8bc358801 --- /dev/null +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-status/dossiers-listing-status.component.html @@ -0,0 +1,4 @@ + + {{ dossierState.name }} + + diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-status/dossiers-listing-status.component.scss b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-status/dossiers-listing-status.component.scss new file mode 100644 index 000000000..0c4471d56 --- /dev/null +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-status/dossiers-listing-status.component.scss @@ -0,0 +1,19 @@ +@use 'variables'; + +.dossier-status-container { + justify-content: flex-end; + width: 100%; +} + +.dossier-status-chip { + width: 12px; + height: 6px; + border-radius: 6px; + margin-left: 8px; +} + +.dossier-status-text { + font-size: 13px; + line-height: 16px; + color: variables.$grey-1; +} diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-status/dossiers-listing-status.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-status/dossiers-listing-status.component.ts new file mode 100644 index 000000000..4ec6e70d2 --- /dev/null +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-status/dossiers-listing-status.component.ts @@ -0,0 +1,12 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { DossierState } from '../../../../../../../../../../libs/red-domain/src/lib/dossier-state'; + +@Component({ + selector: 'redaction-dossiers-listing-status', + templateUrl: './dossiers-listing-status.component.html', + styleUrls: ['./dossiers-listing-status.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DossiersListingStatusComponent { + @Input() dossierState: DossierState; +} diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.html index fcff19968..9a8bc9a43 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.html @@ -14,4 +14,8 @@ + + + + diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.ts index d1e991d3c..b6c66da48 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.ts @@ -1,8 +1,10 @@ -import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnChanges, OnInit } from '@angular/core'; import { Dossier, DossierStats } from '@red/domain'; import { DossierStatsService } from '@services/entity-services/dossier-stats.service'; -import { BehaviorSubject, Observable } from 'rxjs'; +import { BehaviorSubject, firstValueFrom, Observable } from 'rxjs'; import { switchMap } from 'rxjs/operators'; +import { DossierStateService } from '../../../../../../services/entity-services/dossier-state.service'; +import { DossierState } from '../../../../../../../../../../libs/red-domain/src/lib/dossier-state'; @Component({ selector: 'redaction-table-item [dossier]', @@ -10,13 +12,14 @@ import { switchMap } from 'rxjs/operators'; styleUrls: ['./table-item.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class TableItemComponent implements OnChanges { +export class TableItemComponent implements OnChanges, OnInit { @Input() dossier!: Dossier; + states: DossierState[]; readonly stats$: Observable; private readonly _ngOnChanges$ = new BehaviorSubject(undefined); - constructor(readonly dossierStatsService: DossierStatsService) { + constructor(readonly dossierStatsService: DossierStatsService, readonly dossierStateService: DossierStateService) { this.stats$ = this._ngOnChanges$.pipe(switchMap(dossierId => this.dossierStatsService.watch$(dossierId))); } @@ -25,4 +28,9 @@ export class TableItemComponent implements OnChanges { this._ngOnChanges$.next(this.dossier.dossierId); } } + + async ngOnInit(): Promise { + this.states = await firstValueFrom(this.dossierStateService.loadAllForTemplate('b3413395-8511-4a45-b0eb-b103012b4d8a')); + console.log(this.states); + } } diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/config.service.ts b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/config.service.ts index ce0711162..66fdedebd 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/config.service.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/config.service.ts @@ -26,7 +26,8 @@ export class ConfigService { { label: _('dossier-listing.table-col-names.name'), sortByKey: 'searchKey', width: '2fr' }, { label: _('dossier-listing.table-col-names.needs-work') }, { label: _('dossier-listing.table-col-names.owner'), class: 'user-column' }, - { label: _('dossier-listing.table-col-names.status'), class: 'flex-end', width: 'auto' }, + { label: _('dossier-listing.table-col-names.documents-status'), class: 'flex-end', width: 'auto' }, + { label: _('dossier-listing.table-col-names.dossier-status'), class: 'flex-end' }, ]; } diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/dossiers-listing.module.ts b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/dossiers-listing.module.ts index f04907531..01490f1bd 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/dossiers-listing.module.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/dossiers-listing.module.ts @@ -12,6 +12,7 @@ import { ConfigService } from './config.service'; import { TableItemComponent } from './components/table-item/table-item.component'; import { SharedDossiersModule } from '../../shared/shared-dossiers.module'; import { DossierWorkloadColumnComponent } from './components/dossier-workload-column/dossier-workload-column.component'; +import { DossiersListingStatusComponent } from './components/dossiers-listing-status/dossiers-listing-status.component'; const routes: Routes = [ { @@ -30,6 +31,7 @@ const routes: Routes = [ DossiersListingDossierNameComponent, DossierWorkloadColumnComponent, TableItemComponent, + DossiersListingStatusComponent, ], providers: [ConfigService], imports: [RouterModule.forChild(routes), CommonModule, SharedModule, SharedDossiersModule, IqserIconsModule, TranslateModule], diff --git a/apps/red-ui/src/app/services/entity-services/dossier-state.service.ts b/apps/red-ui/src/app/services/entity-services/dossier-state.service.ts index d3be59e74..b5d3f8608 100644 --- a/apps/red-ui/src/app/services/entity-services/dossier-state.service.ts +++ b/apps/red-ui/src/app/services/entity-services/dossier-state.service.ts @@ -1,6 +1,7 @@ import { Injectable, Injector } from '@angular/core'; import { EntitiesService, RequiredParam, Validate } from '../../../../../../libs/common-ui/src'; import { DossierState, IDossierState } from '../../../../../../libs/red-domain/src/lib/dossier-state'; +import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root', @@ -14,4 +15,20 @@ export class DossierStateService extends EntitiesService(body, this._defaultModelPath); } + + @Validate() + loadAllForTemplate(@RequiredParam() templateId: string) { + return this.loadAll(`${this._defaultModelPath}/dossier-template/${templateId}`); + } + + @Validate() + deleteAndReplace(@RequiredParam() dossierStatusId: string, @RequiredParam() replaceDossierStatusId: string) { + const url = `${this._defaultModelPath}/${dossierStatusId}?replaceDossierStatusId=${replaceDossierStatusId}`; + return this.delete({}, url); + } + + @Validate() + getById(@RequiredParam() id: string): Observable { + return this._getOne([id]); + } } diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 993a08598..42a3ce3ff 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -421,6 +421,18 @@ "toast-error": "Please confirm that you understand the ramifications of your action!", "warning": "Warning: this cannot be undone!" }, + "confirm-delete-dossier-state": { + "title": "Delete Dossier Status", + "warning": "The {name} status is assigned to {count} Dossiers.", + "suggestion": "Would you like to replace the states of the Dossiers with another status?", + "form": { + "status": "Replace Status", + "status-placeholder": "Choose another status" + }, + "delete-only": "Delete Only", + "delete-replace": "Delete and Replace", + "cancel": "Cancel" + }, "confirm-delete-users": { "cancel": "Keep {usersCount, plural, one{User} other{Users}}", "delete": "Delete {usersCount, plural, one{User} other{Users}}", @@ -628,6 +640,10 @@ "delete": "Delete Status", "edit": "Edit Status" }, + "error": { + "conflict": "Dossier State with this name already exists!", + "generic": "Failed to add Dossier State" + }, "search": "Search...", "table-col-names": { "name": "Name", @@ -732,7 +748,8 @@ "name": "Name", "needs-work": "Workload", "owner": "Owner", - "status": "Status" + "documents-status": "Documents Status", + "dossier-status": "Dossier Status" }, "table-header": { "title": "{length} active {length, plural, one{Dossier} other{Dossiers}}"