From 301616fb062dfd6cb9e7ed0c11feb215b1bd128c Mon Sep 17 00:00:00 2001 From: Nicoleta Panaghiu Date: Wed, 20 Nov 2024 18:11:48 +0200 Subject: [PATCH] RED-10498 - added the locked rules indicator; implemented the reset. --- .../guards/dossier-template-exists.guard.ts | 3 ++ .../dossier-template-details.component.html | 10 ++++++ .../dossier-template-details.component.scss | 8 +++++ .../dossier-template-details.component.ts | 25 +++++++++++++-- .../modules/admin/services/rules.service.ts | 32 ++++++++++++++++--- apps/red-ui/src/assets/i18n/redact/de.json | 5 +++ apps/red-ui/src/assets/i18n/redact/en.json | 5 +++ apps/red-ui/src/assets/i18n/scm/de.json | 21 +++++++----- apps/red-ui/src/assets/i18n/scm/en.json | 5 +++ libs/red-domain/src/lib/shared/index.ts | 1 + libs/red-domain/src/lib/shared/rules.model.ts | 23 +++++++++++++ libs/red-domain/src/lib/shared/rules.ts | 6 +++- 12 files changed, 128 insertions(+), 16 deletions(-) create mode 100644 libs/red-domain/src/lib/shared/rules.model.ts diff --git a/apps/red-ui/src/app/guards/dossier-template-exists.guard.ts b/apps/red-ui/src/app/guards/dossier-template-exists.guard.ts index 0ad5ad5c3..6e751efa1 100644 --- a/apps/red-ui/src/app/guards/dossier-template-exists.guard.ts +++ b/apps/red-ui/src/app/guards/dossier-template-exists.guard.ts @@ -12,6 +12,7 @@ import { DefaultColorsService } from '@services/entity-services/default-colors.s import { WatermarkService } from '@services/entity-services/watermark.service'; import { FileAttributesService } from '@services/entity-services/file-attributes.service'; import { getConfig } from '@iqser/common-ui'; +import { RulesService } from '../modules/admin/services/rules.service'; export function templateExistsWhenEnteringAdmin(): CanActivateFn { return async function (route: ActivatedRouteSnapshot): Promise { @@ -21,12 +22,14 @@ export function templateExistsWhenEnteringAdmin(): CanActivateFn { const defaultColorsService = inject(DefaultColorsService); const watermarksService = inject(WatermarkService); const router = inject(Router); + const rulesService = inject(RulesService); const isDocumine = getConfig().IS_DOCUMINE; const dossierTemplate = inject(DossierTemplateStatsService).get(dossierTemplateId); await firstValueFrom(fileAttributesService.loadFileAttributesConfig(dossierTemplateId)); await firstValueFrom(dictionaryService.loadDictionaryDataForDossierTemplate(dossierTemplateId)); await firstValueFrom(defaultColorsService.loadForDossierTemplate(dossierTemplateId)); + await firstValueFrom(rulesService.getFor(dossierTemplateId)); if (!isDocumine) { await firstValueFrom(watermarksService.loadForDossierTemplate(dossierTemplateId)); } diff --git a/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.html b/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.html index d8fa1b64c..2ef1b2e8c 100644 --- a/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.html @@ -34,6 +34,16 @@ +
+ + {{ 'dossier-template-info-screen.rules-reset.label' | translate }} +
+
{{ 'dossier-template-info-screen.entries' | translate: { count: ctx.stats.numberOfEntries } }} diff --git a/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.scss b/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.scss index dd00e21c8..eda21743e 100644 --- a/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.scss +++ b/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.scss @@ -18,3 +18,11 @@ padding-right: 24px; margin-right: 24px; } + +.error { + color: var(--iqser-primary); +} + +.action-icon { + cursor: pointer; +} diff --git a/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.ts b/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.ts index a6dab16e7..49c904e80 100644 --- a/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-details/dossier-template-details.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, computed, Input, OnInit } from '@angular/core'; import { ContextComponent } from '@iqser/common-ui/lib/utils'; import { type DossierTemplate, type DossierTemplateStats } from '@red/domain'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; @@ -9,6 +9,11 @@ import { MatIcon } from '@angular/material/icon'; import { TranslateModule } from '@ngx-translate/core'; import { InitialsAvatarComponent } from '@common-ui/users'; import { DatePipe } from '@shared/pipes/date.pipe'; +import { RulesService } from '../../../services/rules.service'; +import { Toaster } from '@iqser/common-ui'; +import { MatTooltip } from '@angular/material/tooltip'; +import { firstValueFrom } from 'rxjs'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; interface Context { readonly dossierTemplate: DossierTemplate; @@ -20,16 +25,20 @@ interface Context { templateUrl: './dossier-template-details.component.html', styleUrls: ['./dossier-template-details.component.scss'], standalone: true, - imports: [NgIf, AsyncPipe, MatIcon, TranslateModule, DatePipe, InitialsAvatarComponent], + imports: [NgIf, AsyncPipe, MatIcon, TranslateModule, DatePipe, InitialsAvatarComponent, MatTooltip], }) export class DossierTemplateDetailsComponent extends ContextComponent implements OnInit { readonly translations = dossierTemplateStatusTranslations; - @Input({ required: true }) dossierTemplateId: string; + readonly areRulesLocked = computed(() => { + return this._rulesService.currentTemplateRules().timeoutDetected; + }); constructor( private readonly _dossierTemplatesService: DossierTemplatesService, private readonly _dossierTemplateStatsService: DossierTemplateStatsService, + private readonly _rulesService: RulesService, + private readonly _toaster: Toaster, ) { super(); } @@ -40,4 +49,14 @@ export class DossierTemplateDetailsComponent extends ContextComponent i stats: this._dossierTemplateStatsService.watch$(this.dossierTemplateId), }); } + + async resetRules() { + try { + await firstValueFrom(this._rulesService.reset(this.dossierTemplateId)); + this._toaster.success(_('dossier-template-info-screen.rules-reset.success')); + await firstValueFrom(this._rulesService.getFor(this.dossierTemplateId)); + } catch (error) { + this._toaster.rawError(error.error.message); + } + } } diff --git a/apps/red-ui/src/app/modules/admin/services/rules.service.ts b/apps/red-ui/src/app/modules/admin/services/rules.service.ts index 01b5b0886..74eaa92cf 100644 --- a/apps/red-ui/src/app/modules/admin/services/rules.service.ts +++ b/apps/red-ui/src/app/modules/admin/services/rules.service.ts @@ -1,9 +1,25 @@ import { Injectable } from '@angular/core'; -import { GenericService } from '@iqser/common-ui'; -import { IRules } from '@red/domain'; +import { EntitiesService, QueryParam } from '@iqser/common-ui'; +import { IRules, Rules } from '@red/domain'; +import { map, Observable, tap } from 'rxjs'; +import { List } from '@common-ui/utils'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { distinctUntilChanged, filter } from 'rxjs/operators'; -@Injectable() -export class RulesService extends GenericService { +@Injectable({ providedIn: 'root' }) +export class RulesService extends EntitiesService { + readonly currentTemplateRules = toSignal( + this.all$.pipe( + filter(all => !!all.length), + map(rules => rules[0]), + distinctUntilChanged( + (prev, curr) => + prev.rules === curr.rules && + prev.timeoutDetected === curr.timeoutDetected && + prev.dossierTemplateId === curr.dossierTemplateId, + ), + ), + ); protected readonly _defaultModelPath = 'rules'; download(dossierTemplateId: string, ruleFileType: IRules['ruleFileType'] = 'ENTITY') { @@ -13,4 +29,12 @@ export class RulesService extends GenericService { uploadRules(body: IRules) { return this._post({ ...body, ruleFileType: body.ruleFileType ?? 'ENTITY' }); } + + getFor(entityId: string, queryParams?: List): Observable { + return super.getFor(entityId, queryParams).pipe(tap(rules => this.setEntities([rules as Rules]))); + } + + reset(dossierTemplateId: string, ruleFileType: IRules['ruleFileType'] = 'ENTITY') { + return this._put(null, `${this._defaultModelPath}/${dossierTemplateId}/${ruleFileType}/reset`); + } } diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index 0408fc607..2f884a217 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -1069,6 +1069,11 @@ "entities": "{count} {count, plural, one{Entität} other{Entitäten}}", "entries": "{count} {count, plural, one{Eintrag} other{Einträge}}", "modified-on": "Geändert am: {date}", + "rules-reset": { + "label": "Regeln gesperrt", + "success": "Die Regeln der Dossier-Vorlage wurden erfolgreich zurückgesetzt.", + "tooltip": "Klicken Sie hier, um die Regeln zurückzusetzen" + }, "title": "Dossier-Vorlage bearbeiten", "valid-from": "Gültig ab: {date}", "valid-to": "Gültig bis: {Datum}" diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index f4685adcd..33c00275e 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -1069,6 +1069,11 @@ "entities": "{count} {count, plural, one{entity} other{entities}}", "entries": "{count} {count, plural, one{entry} other{entries}}", "modified-on": "Modified on: {date}", + "rules-reset": { + "label": "Rules locked", + "success": "Dossier template rules successfully reset.", + "tooltip": "Click to reset rules" + }, "title": "Edit dossier template", "valid-from": "Valid from: {date}", "valid-to": "Valid to: {date}" diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index c2acb53cc..208af7127 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -1064,14 +1064,19 @@ } }, "dossier-template-info-screen": { - "created-by": "Created by", - "created-on": "Created on: {date}", - "entities": "{count} {count, plural, one{entity} other{entities}}", - "entries": "{count} {count, plural, one{entry} other{entries}}", - "modified-on": "Modified on: {date}", - "title": "Edit dossier template", - "valid-from": "Valid from: {date}", - "valid-to": "Valid to: {date}" + "created-by": "Ersteller", + "created-on": "Erstellt am {date}", + "entities": "{count} {count, plural, one{Entität} other{Entitäten}}", + "entries": "{count} {count, plural, one{Eintrag} other{Einträge}}", + "modified-on": "Geändert am {date}", + "rules-reset": { + "label": "Regeln gesperrt", + "success": "Die Regeln der Dossier-Vorlage wurden erfolgreich zurückgesetzt.", + "tooltip": "Klicken Sie hier, um die Regeln zurückzusetzen" + }, + "title": "Dossier-Vorlage bearbeiten", + "valid-from": "Gültig ab: {date}", + "valid-to": "Gültig bis: {date}" }, "dossier-template-stats": { "active-dossiers": "Active {count, plural, one{dossier} other{dossiers}}", diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 765d4015c..3d38b1eee 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -1069,6 +1069,11 @@ "entities": "{count} {count, plural, one{entity} other{entities}}", "entries": "{count} {count, plural, one{entry} other{entries}}", "modified-on": "Modified on: {date}", + "rules-reset": { + "label": "Rules locked", + "success": "Dossier template rules successfully reset.", + "tooltip": "Click to reset rules" + }, "title": "Edit dossier template", "valid-from": "Valid from: {date}", "valid-to": "Valid to: {date}" diff --git a/libs/red-domain/src/lib/shared/index.ts b/libs/red-domain/src/lib/shared/index.ts index 8406e4be7..7c5c49665 100644 --- a/libs/red-domain/src/lib/shared/index.ts +++ b/libs/red-domain/src/lib/shared/index.ts @@ -13,3 +13,4 @@ export * from './app-config'; export * from './system-preferences'; export * from './component-rules'; export * from './editor.types'; +export * from './rules.model'; diff --git a/libs/red-domain/src/lib/shared/rules.model.ts b/libs/red-domain/src/lib/shared/rules.model.ts new file mode 100644 index 000000000..85b7c2d05 --- /dev/null +++ b/libs/red-domain/src/lib/shared/rules.model.ts @@ -0,0 +1,23 @@ +import { IRules } from '@red/domain'; +import { Entity } from '@iqser/common-ui'; + +export class Rules extends Entity implements IRules { + readonly id: string; + readonly routerLink: string; + readonly searchKey: string; + readonly dossierTemplateId: string; + readonly ruleFileType?: 'ENTITY' | 'COMPONENT'; + readonly rules?: string; + readonly dryRun?: boolean; + readonly timeoutDetected?: boolean; + + constructor(rules: IRules) { + super(rules); + this.id = rules.dossierTemplateId; + this.dossierTemplateId = rules.dossierTemplateId; + this.ruleFileType = rules.ruleFileType; + this.rules = rules.rules; + this.dryRun = rules.dryRun; + this.timeoutDetected = rules.timeoutDetected; + } +} diff --git a/libs/red-domain/src/lib/shared/rules.ts b/libs/red-domain/src/lib/shared/rules.ts index f6667e65b..431bb3427 100644 --- a/libs/red-domain/src/lib/shared/rules.ts +++ b/libs/red-domain/src/lib/shared/rules.ts @@ -5,7 +5,7 @@ export interface IRules { /** * The DossierTemplate ID for these rules */ - dossierTemplateId?: string; + dossierTemplateId: string; /** * The file type to be retrieved/saved under, defaults to ENTITY */ @@ -18,4 +18,8 @@ export interface IRules { * Request param for rules validation, without updating them */ dryRun?: boolean; + /** + * Flag which indicates whether the dossier template rules have been locked due to a timeout + */ + timeoutDetected?: boolean; }