diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts index de57e29c3..713f365da 100644 --- a/apps/red-ui/src/app/app-routing.module.ts +++ b/apps/red-ui/src/app/app-routing.module.ts @@ -16,7 +16,7 @@ import { CompositeRouteGuard, DEFAULT_REDIRECT_KEY, IqserPermissionsGuard, Iqser import { TenantSelectComponent } from '@iqser/common-ui/lib/tenants'; import { doesNotHaveAnyRole, hasAnyRole, IqserAuthGuard } from '@iqser/common-ui/lib/users'; import { CustomRouteReuseStrategy } from '@iqser/common-ui/lib/utils'; -import { ARCHIVE_ROUTE, BreadcrumbTypes, DOSSIER_ID, DOSSIER_TEMPLATE_ID, DOSSIERS_ARCHIVE, DOSSIERS_ROUTE, FILE_ID } from '@red/domain'; +import { ARCHIVE_ROUTE, BreadcrumbTypes, DOSSIER_ID, DOSSIER_TEMPLATE_ID, DOSSIERS_ROUTE, FILE_ID } from '@red/domain'; import { RedRoleGuard } from '@users/red-role.guard'; import { Roles } from '@users/roles'; import { mainGuard } from '@utils/main.guard'; @@ -81,7 +81,6 @@ const dossierTemplateIdRoutes: IqserRoutes = [ canActivate: [CompositeRouteGuard, loadArchivedDossiersGuard()], data: { routeGuards: [FeaturesGuard], - features: [DOSSIERS_ARCHIVE], }, }, { diff --git a/apps/red-ui/src/app/components/base-screen/base-screen.component.ts b/apps/red-ui/src/app/components/base-screen/base-screen.component.ts index d0b3e4df2..a5c674642 100644 --- a/apps/red-ui/src/app/components/base-screen/base-screen.component.ts +++ b/apps/red-ui/src/app/components/base-screen/base-screen.component.ts @@ -8,8 +8,7 @@ import { SpotlightSearchAction } from '@components/spotlight-search/spotlight-se import { filter, map, startWith } from 'rxjs/operators'; import { getConfig, IqserPermissionsService } from '@iqser/common-ui'; import { BreadcrumbsService } from '@services/breadcrumbs.service'; -import { FeaturesService } from '@services/features.service'; -import { ARCHIVE_ROUTE, DOSSIERS_ARCHIVE, DOSSIERS_ROUTE } from '@red/domain'; +import { ARCHIVE_ROUTE, DOSSIERS_ROUTE } from '@red/domain'; import { Roles } from '@users/roles'; import { REDDocumentViewer } from '../../modules/pdf-viewer/services/document-viewer.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @@ -36,7 +35,6 @@ export class BaseScreenComponent { { text: this._translateService.instant('search.active-dossiers'), icon: 'red:enter', - hide: () => !this._featuresService.isEnabled(DOSSIERS_ARCHIVE), action: (query): void => this.#search(query, [], true), }, { @@ -58,7 +56,6 @@ export class BaseScreenComponent { private readonly _router: Router, activatedRoute: ActivatedRoute, private readonly _translateService: TranslateService, - private readonly _featuresService: FeaturesService, readonly permissionsService: IqserPermissionsService, readonly userService: UserService, readonly userPreferenceService: UserPreferenceService, diff --git a/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts b/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts index aa0830d0c..be5b01235 100644 --- a/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts +++ b/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts @@ -1,6 +1,6 @@ import { AnnotationPermissions } from '@models/file/annotation.permissions'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { Dictionary, LogEntryEngines, SuperTypes } from '@red/domain'; +import { Dictionary, SuperTypes } from '@red/domain'; export const canUndo = (annotation: AnnotationWrapper, isApprover: boolean) => !isApprover && annotation.pending; @@ -16,7 +16,11 @@ export const canForceRedaction = (annotation: AnnotationWrapper, canAddRedaction export const canAcceptRecommendation = (annotation: AnnotationWrapper) => annotation.isRecommendation && !annotation.pending; export const canMarkAsFalsePositive = (annotation: AnnotationWrapper, annotationEntity: Dictionary) => - annotation.canBeMarkedAsFalsePositive && !annotation.hasBeenResizedLocally && annotationEntity?.hasDictionary; + annotation.canBeMarkedAsFalsePositive && + !annotation.hasBeenResizedLocally && + !annotation.isRemovedLocally && + !annotation.hasBeenForcedRedaction && + annotationEntity?.hasDictionary; export const canRemoveOnlyHere = (annotation: AnnotationWrapper, canAddRedaction: boolean, autoAnalysisDisabled: boolean) => canAddRedaction && diff --git a/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.html b/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.html index ad1f6dd44..b6cfb0efd 100644 --- a/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.html +++ b/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.html @@ -11,12 +11,6 @@ -
- - {{ 'preferences-screen.form.open-structured-view-by-default' | translate }} - -
-
@@ -37,6 +31,11 @@ {{ 'preferences-screen.form.help-mode-dialog' | translate }}
+
+ + {{ 'preferences-screen.form.overwrite-file-option' | translate }} + +
diff --git a/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.ts b/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.ts index 269fe712f..36b1edc02 100644 --- a/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.ts +++ b/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; import { @@ -23,11 +23,11 @@ import { MatCheckbox } from '@angular/material/checkbox'; interface PreferencesForm { // preferences autoExpandFiltersOnActions: boolean; - openScmDialogByDefault: boolean; tableExtractionType: string; // warnings preferences loadAllAnnotationsWarning: boolean; helpModeDialog: boolean; + overwriteFileOption: boolean; [k: string]: any; } @@ -58,6 +58,12 @@ const Screens = { ], }) export class PreferencesComponent extends BaseFormComponent implements OnInit { + readonly #formBuilder = inject(FormBuilder); + readonly #permissionsService = inject(IqserPermissionsService); + readonly #changeRef = inject(ChangeDetectorRef); + readonly #loadingService = inject(LoadingService); + readonly #userPreferenceService = inject(UserPreferenceService); + readonly form: FormGroup>; readonly currentScreen: Screen; readonly screens = Screens; @@ -66,81 +72,87 @@ export class PreferencesComponent extends BaseFormComponent implements OnInit { readonly config = getConfig(); readonly isIqserDevMode = isIqserDevMode(); - constructor( - route: ActivatedRoute, - readonly userPreferenceService: UserPreferenceService, - private readonly _formBuilder: FormBuilder, - private readonly _permissionsService: IqserPermissionsService, - private readonly _changeRef: ChangeDetectorRef, - private readonly _loadingService: LoadingService, - ) { + get #isOverwriteFileOptionActive() { + return !(this.#userPreferenceService.getOverwriteFileOption() === 'undefined'); + } + + constructor(route: ActivatedRoute) { super(); - this.form = this._formBuilder.group({ + this.form = this.#formBuilder.group({ // preferences - autoExpandFiltersOnActions: [this.userPreferenceService.getAutoExpandFiltersOnActions()], - openScmDialogByDefault: [this.userPreferenceService.getOpenScmDialogByDefault()], - tableExtractionType: [this.userPreferenceService.getTableExtractionType()], + autoExpandFiltersOnActions: [this.#userPreferenceService.getAutoExpandFiltersOnActions()], + tableExtractionType: [this.#userPreferenceService.getTableExtractionType()], // warnings preferences - loadAllAnnotationsWarning: [this.userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning)], - helpModeDialog: [this.userPreferenceService.getBool(KEYS.helpModeDialog)], + loadAllAnnotationsWarning: [this.#userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning)], + helpModeDialog: [this.#userPreferenceService.getBool(KEYS.helpModeDialog)], + overwriteFileOption: [this.#isOverwriteFileOptionActive], }); - if (!this._permissionsService.has(Roles.managePreferences)) { + if (!this.#permissionsService.has(Roles.managePreferences)) { this.form.disable(); } - if (!this._permissionsService.has(Roles.getTables)) { + if (!this.#permissionsService.has(Roles.getTables)) { this.form.controls.tableExtractionType.disable(); } + if (!this.#isOverwriteFileOptionActive) { + this.form.controls.overwriteFileOption.disable(); + } + this.initialFormValue = this.form.getRawValue(); this.currentScreen = route.snapshot.data.screen; } ngOnInit() { - this._loadingService.stop(); + this.#loadingService.stop(); } async save(): Promise { - if (this.form.controls.autoExpandFiltersOnActions.value !== this.userPreferenceService.getAutoExpandFiltersOnActions()) { - await this.userPreferenceService.toggleAutoExpandFiltersOnActions(); - } - if (this.form.controls.openScmDialogByDefault.value !== this.userPreferenceService.getOpenScmDialogByDefault()) { - await this.userPreferenceService.toggleOpenScmDialogByDefault(); + if (this.form.controls.autoExpandFiltersOnActions.value !== this.#userPreferenceService.getAutoExpandFiltersOnActions()) { + await this.#userPreferenceService.toggleAutoExpandFiltersOnActions(); } - if (this.form.controls.tableExtractionType.value !== this.userPreferenceService.getTableExtractionType()) { - await this.userPreferenceService.save(PreferencesKeys.tableExtractionType, this.form.controls.tableExtractionType.value); + if (this.form.controls.tableExtractionType.value !== this.#userPreferenceService.getTableExtractionType()) { + await this.#userPreferenceService.save(PreferencesKeys.tableExtractionType, this.form.controls.tableExtractionType.value); } if ( this.form.controls.loadAllAnnotationsWarning.value !== - this.userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning) + this.#userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning) ) { - await this.userPreferenceService.save( + await this.#userPreferenceService.save( PreferencesKeys.loadAllAnnotationsWarning, String(this.form.controls.loadAllAnnotationsWarning.value), ); } - if (this.form.controls.helpModeDialog.value !== this.userPreferenceService.getBool(KEYS.helpModeDialog)) { - await this.userPreferenceService.save(KEYS.helpModeDialog, String(this.form.controls.helpModeDialog.value)); + if (this.form.controls.helpModeDialog.value !== this.#userPreferenceService.getBool(KEYS.helpModeDialog)) { + await this.#userPreferenceService.save(KEYS.helpModeDialog, String(this.form.controls.helpModeDialog.value)); } - await this.userPreferenceService.reload(); + if (this.form.controls.overwriteFileOption.enabled && !this.form.controls.overwriteFileOption.value) { + await this.#userPreferenceService.saveOverwriteFileOption('undefined'); + } + + await this.#userPreferenceService.reload(); this.#patchValues(); this.initialFormValue = this.form.getRawValue(); - this._changeRef.markForCheck(); + this.#changeRef.markForCheck(); } #patchValues() { this.form.patchValue({ - autoExpandFiltersOnActions: this.userPreferenceService.getAutoExpandFiltersOnActions(), - openScmDialogByDefault: this.userPreferenceService.getOpenScmDialogByDefault(), - tableExtractionType: this.userPreferenceService.getTableExtractionType(), - loadAllAnnotationsWarning: this.userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning), - helpModeDialog: this.userPreferenceService.getBool(KEYS.helpModeDialog), + autoExpandFiltersOnActions: this.#userPreferenceService.getAutoExpandFiltersOnActions(), + tableExtractionType: this.#userPreferenceService.getTableExtractionType(), + loadAllAnnotationsWarning: this.#userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning), + helpModeDialog: this.#userPreferenceService.getBool(KEYS.helpModeDialog), + overwriteFileOption: this.#isOverwriteFileOptionActive, }); + + if (!this.#isOverwriteFileOptionActive) { + this.form.controls.overwriteFileOption.disable(); + } } } diff --git a/apps/red-ui/src/app/modules/admin/dialogs/audit-info-dialog/audit-info-dialog.component.html b/apps/red-ui/src/app/modules/admin/dialogs/audit-info-dialog/audit-info-dialog.component.html index 6b8f9f46d..65ed43f9d 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/audit-info-dialog/audit-info-dialog.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/audit-info-dialog/audit-info-dialog.component.html @@ -6,9 +6,11 @@
Key
Value
- +
{{ entry.key | humanize }}
-
{{ entry.value }}
+
+
{{ entry.value | json }}
+
diff --git a/apps/red-ui/src/app/modules/admin/dialogs/audit-info-dialog/audit-info-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/audit-info-dialog/audit-info-dialog.component.ts index d038df97a..9de2f9c16 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/audit-info-dialog/audit-info-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/audit-info-dialog/audit-info-dialog.component.ts @@ -1,4 +1,4 @@ -import { KeyValue, KeyValuePipe, NgForOf } from '@angular/common'; +import { JsonPipe, KeyValue, KeyValuePipe, NgForOf } from '@angular/common'; import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { BaseDialogComponent, CircleButtonComponent, HumanizePipe } from '@iqser/common-ui'; @@ -17,7 +17,7 @@ type OrderFn = (a: KeyValue, b: KeyValue) => num styleUrls: ['./audit-info-dialog.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, - imports: [TranslateModule, NgForOf, KeyValuePipe, HumanizePipe, CircleButtonComponent], + imports: [TranslateModule, NgForOf, KeyValuePipe, HumanizePipe, CircleButtonComponent, JsonPipe], }) export class AuditInfoDialogComponent extends BaseDialogComponent { constructor( diff --git a/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.html b/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.html index 7f371474f..dbd2a0752 100644 --- a/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.html @@ -19,7 +19,7 @@
-
+
{{ 'component-definitions.columns.position' | translate }}
@@ -27,32 +27,37 @@
- @for (component of componentDefinitions; track component) { -
-
-
- - {{ component.rank }} -
-
{{ component.displayName }}
-
- @if (permissionsService.canEditEntities()) { - - } - +
+ @for (component of componentDefinitions; track component) { +
+
+
+ + {{ component.rank }} +
+
{{ component.displayName }}
+
+ @if (permissionsService.canEditEntities()) { + + } + @if (selectedComponent?.id === component.id) { + + } +
-
- } + } +
@if (selectedComponent) {
diff --git a/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.scss b/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.scss index 80af0380b..54a237251 100644 --- a/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.scss +++ b/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.scss @@ -32,6 +32,10 @@ align-items: center; gap: 5px; + iqser-circle-button { + visibility: hidden; + } + .arrow-right { transform: scale(0.7); } @@ -40,6 +44,7 @@ .content-container { background-color: var(--iqser-grey-6); + height: 100vh; .content-header { display: flex; @@ -58,7 +63,7 @@ .content { display: flex; gap: 20px; - height: 100%; + overflow: hidden; .components-list { flex: 1; @@ -69,8 +74,15 @@ height: 30px; } + .list-content { + overflow-y: auto; + height: calc(100vh - 30px); + outline: none; + } + .list-item { height: 80px; + transition: background 0.3s ease; } .header, @@ -95,6 +107,10 @@ } } } + + .list-item:hover > .item-content > .right-content > iqser-circle-button { + visibility: visible; + } } section { @@ -112,6 +128,9 @@ } .cdk-drag-preview { + .list-item { + transition: background 0.3s ease; + } .item-content { @extend %item-content-style; } diff --git a/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.ts b/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.ts index 31130e284..bf078ecaf 100644 --- a/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/component-definitions/component-definitions.component.ts @@ -1,12 +1,5 @@ import { Component, OnInit, signal } from '@angular/core'; -import { - BaseFormComponent, - CircleButtonComponent, - IconButtonComponent, - IqserDialog, - listingProvidersFactory, - LoadingService, -} from '@iqser/common-ui'; +import { BaseFormComponent, CircleButtonComponent, IconButtonComponent, listingProvidersFactory, LoadingService } from '@iqser/common-ui'; import { ComponentDefinitionsService } from '@services/entity-services/component-definitions.service'; import { firstValueFrom } from 'rxjs'; import { getParam } from '@common-ui/utils'; @@ -50,7 +43,6 @@ export default class ComponentDefinitionsComponent extends BaseFormComponent imp constructor( private readonly _loadingService: LoadingService, private readonly _componentDefinitionsService: ComponentDefinitionsService, - private readonly _dialog: IqserDialog, private readonly _formBuilder: FormBuilder, private readonly _dialogService: AdminDialogService, protected readonly permissionsService: PermissionsService, @@ -96,13 +88,15 @@ export default class ComponentDefinitionsComponent extends BaseFormComponent imp } async drop(event: CdkDragDrop) { - moveItemInArray(this.#componentDefinitions(), event.previousIndex, event.currentIndex); + if (event.isPointerOverContainer) { + moveItemInArray(this.#componentDefinitions(), event.previousIndex, event.currentIndex); - const componentIds = this.#componentDefinitions().map(c => c.id); - const componentDefinitions = await firstValueFrom( - this._componentDefinitionsService.reorderComponentDefinitions(this.#dossierTemplateId, componentIds), - ); - this.#componentDefinitions.set(componentDefinitions); + const componentIds = this.#componentDefinitions().map(c => c.id); + const componentDefinitions = await firstValueFrom( + this._componentDefinitionsService.reorderComponentDefinitions(this.#dossierTemplateId, componentIds), + ); + this.#componentDefinitions.set(componentDefinitions); + } } async deleteComponent(componentId: string) { @@ -119,8 +113,8 @@ export default class ComponentDefinitionsComponent extends BaseFormComponent imp #getForm() { return this._formBuilder.group({ - displayName: [this.selectedComponent.displayName, Validators.required], - description: [this.selectedComponent.description], + displayName: [this.selectedComponent?.displayName, Validators.required], + description: [this.selectedComponent?.description], }); } diff --git a/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.html b/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.html index 9f62ba6d0..8283e05a8 100644 --- a/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.html @@ -29,9 +29,8 @@
diff --git a/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.scss b/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.scss index df17cfe56..9f7a553cc 100644 --- a/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.scss +++ b/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.scss @@ -18,14 +18,8 @@ font-size: 15px; } } - - &.disabled-file-options { - opacity: 0.5; - pointer-events: auto; - max-width: 300px; - - .iqser-input-group { - pointer-events: none; - } - } +} + +.row:last-child { + max-width: 300px; } diff --git a/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.ts b/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.ts index 8c7a41109..e8a628491 100644 --- a/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/component-mappings/add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component.ts @@ -52,7 +52,6 @@ export class AddEditComponentMappingDialogComponent { protected readonly encodingTypeOptions = Object.keys(FileAttributeEncodingTypes); protected readonly translations = fileAttributeEncodingTypesTranslations; - #fileChanged = false; activeFile: File; form!: UntypedFormGroup; @@ -73,13 +72,14 @@ export class AddEditComponentMappingDialogComponent const file = new Blob([fileContent.body as Blob], { type: 'text/csv' }); this.form.get('file').setValue(file); this.initialFormValue = this.form.getRawValue(); + this.#disableEncodingAndDelimiter(); } } changeFile(file: File) { - this.#fileChanged = true; this.form.get('file').setValue(file); this.form.get('fileName').setValue(file?.name); + this.#enableEncodingAndDelimiter(); } save() { @@ -96,7 +96,13 @@ export class AddEditComponentMappingDialogComponent }); } - get disabledFileOptions() { - return this.initialFormValue?.file && !this.#fileChanged; + #disableEncodingAndDelimiter() { + this.form.get('encoding').disable(); + this.form.get('delimiter').disable(); + } + + #enableEncodingAndDelimiter() { + this.form.get('encoding').enable(); + this.form.get('delimiter').enable(); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.html index 5ade8725a..f81f18fb9 100644 --- a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.html @@ -1,6 +1,5 @@
-
-
+
diff --git a/apps/red-ui/src/app/modules/admin/shared/components/admin-side-nav/admin-side-nav.component.ts b/apps/red-ui/src/app/modules/admin/shared/components/admin-side-nav/admin-side-nav.component.ts index e724280e4..6f619125f 100644 --- a/apps/red-ui/src/app/modules/admin/shared/components/admin-side-nav/admin-side-nav.component.ts +++ b/apps/red-ui/src/app/modules/admin/shared/components/admin-side-nav/admin-side-nav.component.ts @@ -96,11 +96,13 @@ export class AdminSideNavComponent implements OnInit { { screen: 'entity-rules', label: _('admin-side-nav.entity-rule-editor'), + helpModeKey: 'rule_editors', show: (this.isIqserDevMode || this.canAccessRulesInDocumine) && this._permissionsService.has(Roles.rules.read), }, { screen: 'component-rules', label: _('admin-side-nav.component-rule-editor'), + helpModeKey: 'rule_editors', show: this.isDocumine && (this.isIqserDevMode || this.canAccessRulesInDocumine) && @@ -109,11 +111,13 @@ export class AdminSideNavComponent implements OnInit { { screen: 'component-mappings', label: _('admin-side-nav.component-mappings'), + helpModeKey: 'component_mappings', show: this.isDocumine, }, { screen: 'components', label: _('admin-side-nav.components'), + helpModeKey: 'components_management', show: this.isDocumine, }, { diff --git a/apps/red-ui/src/app/modules/admin/translations/rules-screen-translations.ts b/apps/red-ui/src/app/modules/admin/translations/rules-screen-translations.ts index 2fb57874c..3c882dcb2 100644 --- a/apps/red-ui/src/app/modules/admin/translations/rules-screen-translations.ts +++ b/apps/red-ui/src/app/modules/admin/translations/rules-screen-translations.ts @@ -5,7 +5,6 @@ export const rulesScreenTranslations: Record<'ENTITY' | 'COMPONENT', Record - + diff --git a/apps/red-ui/src/app/modules/dossiers-listing/screen/dossiers-listing-screen.component.ts b/apps/red-ui/src/app/modules/dossiers-listing/screen/dossiers-listing-screen.component.ts index 9e811cb1c..c59b47b63 100644 --- a/apps/red-ui/src/app/modules/dossiers-listing/screen/dossiers-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossiers-listing/screen/dossiers-listing-screen.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; -import { Dossier, DOSSIER_TEMPLATE_ID, DOSSIERS_ARCHIVE, DossierTemplate } from '@red/domain'; +import { Dossier, DOSSIER_TEMPLATE_ID, DossierTemplate } from '@red/domain'; import { PermissionsService } from '@services/permissions.service'; import { ButtonConfig, @@ -19,7 +19,6 @@ import { UserPreferenceService } from '@users/user-preference.service'; import { SharedDialogService } from '@shared/services/dialog.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { OnAttach } from '@iqser/common-ui/lib/utils'; -import { FeaturesService } from '@services/features.service'; import { DossiersTypeSwitchComponent } from '@shared/components/dossiers-type-switch/dossiers-type-switch.component'; import { TranslateModule } from '@ngx-translate/core'; import { DossiersListingDetailsComponent } from '../components/dossiers-listing-details/dossiers-listing-details.component'; @@ -51,7 +50,6 @@ export class DossiersListingScreenComponent extends ListingComponent im readonly buttonConfigs: ButtonConfig[]; readonly dossierTemplate: DossierTemplate; readonly computeFilters$ = this._activeDossiersService.all$.pipe(tap(() => this._computeAllFilters())); - readonly isArchiveEnabled = this._featuresService.isEnabled(DOSSIERS_ARCHIVE); @ViewChild('needsWorkFilterTemplate', { read: TemplateRef, static: true, @@ -68,7 +66,6 @@ export class DossiersListingScreenComponent extends ListingComponent im private readonly _userPreferenceService: UserPreferenceService, private readonly _loadingService: LoadingService, readonly dossierTemplatesService: DossierTemplatesService, - private readonly _featuresService: FeaturesService, ) { super(); const dossierTemplateId = router.routerState.snapshot.root.firstChild.firstChild.paramMap.get(DOSSIER_TEMPLATE_ID); diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html index 2fcf57392..507ffe447 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html @@ -6,7 +6,7 @@ class="mt-6 mr-10" > -
+
{{ annotation.superTypeLabel | translate }}   diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.scss b/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.scss index 36304a969..76eb01385 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.scss @@ -58,14 +58,17 @@ } } - &:hover, - &.help-mode { + &:hover { background-color: var(--iqser-annotation-hover); ::ng-deep .annotation-actions { display: flex; } } + + &.active { + background-color: var(--iqser-annotation-hover); + } } .hide-comments { diff --git a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html index 92216e66a..39d8bf3d4 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html @@ -12,6 +12,8 @@ @if (hasUpdatedValues) { @@ -26,17 +28,19 @@
-
+
@@ -56,6 +60,7 @@ diff --git a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.scss b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.scss index 3ee2c0515..0246ffeb3 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.scss @@ -29,6 +29,11 @@ iqser-circle-button { visibility: hidden; + + &.help-mode { + visibility: visible; + z-index: 600; + } } .changes-dot { diff --git a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.ts b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.ts index 90dd06fc8..5617d84e0 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.ts @@ -1,9 +1,9 @@ import { CdkDrag, CdkDragDrop, CdkDragHandle, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop'; -import { KeyValuePipe, NgClass, NgForOf, NgIf } from '@angular/common'; +import { AsyncPipe, KeyValuePipe, NgClass, NgForOf, NgIf } from '@angular/common'; import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { MatIcon } from '@angular/material/icon'; -import { CircleButtonComponent, IconButtonComponent, IconButtonTypes, IqserDialog } from '@iqser/common-ui'; +import { CircleButtonComponent, HelpModeService, IconButtonComponent, IconButtonTypes, IqserDialog } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { IComponentLogEntry, IComponentValue } from '@red/domain'; import { RevertValueDialogComponent } from '../../dialogs/docu-mine/revert-value-dialog/revert-value-dialog.component'; @@ -27,6 +27,7 @@ import { FilePreviewStateService } from '../../services/file-preview-state.servi NgForOf, CdkDragHandle, FormsModule, + AsyncPipe, ], }) export class EditableStructuredComponentValueComponent implements OnInit { @@ -43,6 +44,7 @@ export class EditableStructuredComponentValueComponent implements OnInit { selected = false; constructor( + readonly helpModeService: HelpModeService, private readonly _iqserDialog: IqserDialog, private readonly _state: FilePreviewStateService, ) {} diff --git a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.html b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.html index 531d15776..32b509d90 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.html @@ -44,34 +44,9 @@ -
-
- - - {{ listingService.selectedLength$ | async }} selected - - -
- - -
+ @if (!isDocumine) { + + }
@@ -158,11 +133,14 @@
+ @if (isDocumine) { + + } +
- + @@ -254,7 +232,7 @@ + + +
+
+ + + {{ listingService.selectedLength$ | async }} selected + + +
+ + +
+
diff --git a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts index 3bc1ba7b9..a6e0675a4 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts @@ -1,5 +1,16 @@ import { AsyncPipe, NgIf, NgTemplateOutlet } from '@angular/common'; -import { ChangeDetectorRef, Component, computed, effect, ElementRef, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + computed, + effect, + ElementRef, + HostListener, + OnDestroy, + OnInit, + TemplateRef, + viewChild, +} from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { MatIcon } from '@angular/material/icon'; import { MatTooltip } from '@angular/material/tooltip'; @@ -20,7 +31,7 @@ import { AutoUnsubscribe, Debounce, IqserEventTarget } from '@iqser/common-ui/li import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { ListItem } from '@models/file/list-item'; import { TranslateModule } from '@ngx-translate/core'; -import { ComponentLogEntry, WorkflowFileStatuses } from '@red/domain'; +import { WorkflowFileStatuses } from '@red/domain'; import { workloadTranslations } from '@translations/workload-translations'; import { UserPreferenceService } from '@users/user-preference.service'; import { getLocalStorageDataByFileId } from '@utils/local-storage'; @@ -78,8 +89,9 @@ const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; ], }) export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, OnDestroy { - @ViewChild('annotationsElement') private readonly _annotationsElement: ElementRef; - @ViewChild('quickNavigation') private readonly _quickNavigationElement: ElementRef; + private readonly _annotationsElement = viewChild('annotationsElement'); + private readonly _quickNavigationElement = viewChild('quickNavigation'); + readonly multiSelectTemplate = viewChild>('multiSelect'); readonly #isIqserDevMode = this._userPreferenceService.isIqserDevMode; protected readonly iconButtonTypes = IconButtonTypes; protected readonly circleButtonTypes = CircleButtonTypes; @@ -94,6 +106,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On protected displayedPages: number[] = []; protected pagesPanelActive = true; protected enabledFilters = []; + #displayedPagesChanged = false; constructor( readonly filterService: FilterService, @@ -279,18 +292,20 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On } scrollAnnotationsToPage(page: number, mode: 'always' | 'if-needed' = 'if-needed'): void { - if (this._annotationsElement) { - const elements: HTMLElement[] = this._annotationsElement.nativeElement.querySelectorAll(`div[anotation-page-header="${page}"]`); + if (this._annotationsElement()) { + const elements: HTMLElement[] = this._annotationsElement().nativeElement.querySelectorAll( + `div[anotation-page-header="${page}"]`, + ); FileWorkloadComponent._scrollToFirstElement(elements, mode); } } @Debounce() scrollToSelectedAnnotation(): void { - if (this.listingService.selected.length === 0 || !this._annotationsElement) { + if (this.listingService.selected.length === 0 || !this._annotationsElement()) { return; } - const elements: HTMLElement[] = this._annotationsElement.nativeElement.querySelectorAll( + const elements: HTMLElement[] = this._annotationsElement().nativeElement.querySelectorAll( `[annotation-id="${this._firstSelectedAnnotation?.id}"]`, ); FileWorkloadComponent._scrollToFirstElement(elements); @@ -407,7 +422,8 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On ): Map { const onlyPageWithAnnotations = this.viewModeService.onlyPagesWithAnnotations(); if (!primary || primary.length === 0) { - this.displayedPages = onlyPageWithAnnotations ? [] : this.#allPages; + const pages = onlyPageWithAnnotations ? [] : this.#allPages; + this.#setDisplayedPages(pages); return; } @@ -429,15 +445,16 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On this.enabledFilters = this.filterService.enabledFlatFilters; if (this.enabledFilters.some(f => f.id === 'pages-without-annotations')) { if (this.enabledFilters.length === 1 && !onlyPageWithAnnotations) { - this.displayedPages = this.#allPages.filter(page => !pagesThatDisplayAnnotations.includes(page)); + const pages = this.#allPages.filter(page => !pagesThatDisplayAnnotations.includes(page)); + this.#setDisplayedPages(pages); } else { - this.displayedPages = []; + this.#setDisplayedPages([]); } this.displayedAnnotations.clear(); } else if (this.enabledFilters.length || onlyPageWithAnnotations || componentReferenceIds) { - this.displayedPages = pagesThatDisplayAnnotations; + this.#setDisplayedPages(pagesThatDisplayAnnotations); } else { - this.displayedPages = this.#allPages; + this.#setDisplayedPages(this.#allPages); } this.displayedPages.sort((a, b) => a - b); @@ -511,8 +528,8 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On } #scrollQuickNavigationToPage(page: number) { - if (this._quickNavigationElement) { - const elements: HTMLElement[] = this._quickNavigationElement.nativeElement.querySelectorAll(`#quick-nav-page-${page}`); + if (this._quickNavigationElement()) { + const elements: HTMLElement[] = this._quickNavigationElement().nativeElement.querySelectorAll(`#quick-nav-page-${page}`); FileWorkloadComponent._scrollToFirstElement(elements); } } @@ -533,9 +550,25 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On } #scrollToFirstAnnotationPage(annotations: Map[]>) { - if (this.isDocumine && annotations.size && !this.displayedPages.includes(this.pdf.currentPage())) { + if (this.isDocumine && annotations.size && this.#displayedPagesChanged && !this.displayedPages.includes(this.pdf.currentPage())) { const page = annotations.keys().next().value; this.pdf.navigateTo(page); } } + + #setDisplayedPages(newDisplayedPages: number[]) { + if (!this.#samePages(newDisplayedPages)) { + this.displayedPages = newDisplayedPages; + this.#displayedPagesChanged = true; + return; + } + this.#displayedPagesChanged = false; + } + + #samePages(newDisplayedPages: number[]) { + return ( + this.displayedPages.length === newDisplayedPages.length && + this.displayedPages.every((value, index) => value === newDisplayedPages[index]) + ); + } } diff --git a/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.html b/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.html index fff85d262..faa6c3677 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.html @@ -1,9 +1,9 @@
- - + +
-
+
{{ 'component-management.table-header.component' | translate }}
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.html index 47979cbd3..5f142c981 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.html @@ -1,4 +1,4 @@ -
+
@@ -52,6 +52,8 @@
+ +
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.ts index 624e3728e..58745f45b 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.ts @@ -1,6 +1,13 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, ReactiveFormsModule, UntypedFormGroup } from '@angular/forms'; -import { CircleButtonComponent, HasScrollbarDirective, IconButtonComponent, IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui'; +import { + CircleButtonComponent, + HasScrollbarDirective, + HelpButtonComponent, + IconButtonComponent, + IconButtonTypes, + IqserDialogComponent, +} from '@iqser/common-ui'; import { Dictionary, Dossier, SuperTypes } from '@red/domain'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { DictionaryService } from '@services/entity-services/dictionary.service'; @@ -33,6 +40,7 @@ import { MatDialogClose } from '@angular/material/dialog'; IconButtonComponent, CircleButtonComponent, MatDialogClose, + HelpButtonComponent, ], }) export class EditAnnotationDialogComponent diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/remove-annotation-dialog/remove-annotation-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/remove-annotation-dialog/remove-annotation-dialog.component.html index 3d7fe1b1c..42b4689a4 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/remove-annotation-dialog/remove-annotation-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/remove-annotation-dialog/remove-annotation-dialog.component.html @@ -1,4 +1,4 @@ -
+
+
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/remove-annotation-dialog/remove-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/remove-annotation-dialog/remove-annotation-dialog.component.ts index 58ffe7ace..6571d4ecc 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/remove-annotation-dialog/remove-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/remove-annotation-dialog/remove-annotation-dialog.component.ts @@ -6,7 +6,14 @@ import { MatDialogClose } from '@angular/material/dialog'; import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option'; import { DetailsRadioComponent } from '@common-ui/inputs/details-radio/details-radio.component'; import { ReplaceNbspPipe } from '@common-ui/pipes/replace-nbsp.pipe'; -import { CircleButtonComponent, HasScrollbarDirective, IconButtonComponent, IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui'; +import { + CircleButtonComponent, + HasScrollbarDirective, + HelpButtonComponent, + IconButtonComponent, + IconButtonTypes, + IqserDialogComponent, +} from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { getRemoveRedactionOptions } from '../../../utils/dialog-options'; import { RemoveAnnotationData, RemoveAnnotationOption, RemoveAnnotationOptions, RemoveAnnotationResult } from '../../../utils/dialog-types'; @@ -28,6 +35,7 @@ import { RemoveAnnotationData, RemoveAnnotationOption, RemoveAnnotationOptions, CircleButtonComponent, MatDialogClose, NgIf, + HelpButtonComponent, ], }) export class RemoveAnnotationDialogComponent extends IqserDialogComponent< diff --git a/apps/red-ui/src/app/modules/search/search-screen/search-screen.component.ts b/apps/red-ui/src/app/modules/search/search-screen/search-screen.component.ts index 75cb6d922..e5227c862 100644 --- a/apps/red-ui/src/app/modules/search/search-screen/search-screen.component.ts +++ b/apps/red-ui/src/app/modules/search/search-screen/search-screen.component.ts @@ -7,7 +7,7 @@ import { SearchPositions, TableColumnConfig, } from '@iqser/common-ui'; -import { combineLatest, Observable, of } from 'rxjs'; +import { combineLatest, Observable } from 'rxjs'; import { debounceTime, map, startWith, switchMap, tap } from 'rxjs/operators'; import { ActivatedRoute, Router } from '@angular/router'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -16,7 +16,6 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { RouterHistoryService } from '@services/router-history.service'; import { Dossier, - DOSSIERS_ARCHIVE, DossierTemplate, IMatchedDocument, ISearchListItem, @@ -26,7 +25,6 @@ import { } from '@red/domain'; import { FilesMapService } from '@services/files/files-map.service'; import { PlatformSearchService } from '@services/entity-services/platform-search.service'; -import { FeaturesService } from '@services/features.service'; import { DossiersCacheService } from '@services/dossiers/dossiers-cache.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { UserService } from '@users/user.service'; @@ -68,7 +66,6 @@ export default class SearchScreenComponent extends ListingComponent { - const onlyActiveDossiers$ = this.#enabledArchive - ? this.filterService.getSingleFilter('onlyActiveDossiers').pipe(map(f => !!f.checked)) - : of(true); + const onlyActiveDossiers$ = this.filterService.getSingleFilter('onlyActiveDossiers').pipe(map(f => !!f.checked)); const filterGroups$ = this.filterService.filterGroups$; return combineLatest([filterGroups$, onlyActiveDossiers$]).pipe( map(([groups, onlyActive]) => { @@ -225,9 +216,7 @@ export default class SearchScreenComponent extends ListingComponent (); + readonly isDocumine = getConfig().IS_DOCUMINE; analysisForced: boolean; files: File[]; diff --git a/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts index 60c37c090..19a721f98 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts @@ -128,7 +128,7 @@ export class FileActionsComponent implements OnChanges { tooltipClass: 'small', show: this.showDownload, disabled: this.file.processingStatus === ProcessingFileStatuses.ERROR, - helpModeKey: 'download', + helpModeKey: this.#isDocumine ? 'download_document' : 'download', }, { id: 'btn-delete_file', diff --git a/apps/red-ui/src/app/modules/upload-download/services/file-upload.service.ts b/apps/red-ui/src/app/modules/upload-download/services/file-upload.service.ts index c4f82e77a..e8fc4f761 100644 --- a/apps/red-ui/src/app/modules/upload-download/services/file-upload.service.ts +++ b/apps/red-ui/src/app/modules/upload-download/services/file-upload.service.ts @@ -15,6 +15,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { HeadersConfiguration } from '@iqser/common-ui/lib/utils'; import { LicenseService } from '@services/license.service'; import { LicenseFeatures } from '../../admin/screens/license/utils/constants'; +import { UserPreferenceService } from '@users/user-preference.service'; export interface ActiveUpload { subscription: Subscription; @@ -43,6 +44,7 @@ export class FileUploadService extends GenericService impleme private readonly _errorMessageService: ErrorMessageService, private readonly _licenseService: LicenseService, private readonly _toaster: Toaster, + private readonly _userPreferenceService: UserPreferenceService, ) { super(); const fileFetch$ = this.#fetchFiles$.pipe( @@ -76,7 +78,7 @@ export class FileUploadService extends GenericService impleme const maxSizeBytes = maxSizeMB * 1024 * 1024; const dossierFiles = this._filesMapService.get(dossierId); const supportMsOfficeFormats = this._licenseService.getFeature(LicenseFeatures.SUPPORT_MS_OFFICE_FORMATS)?.value as boolean; - let option: OverwriteFileOption = localStorage.getItem('overwriteFileOption') as OverwriteFileOption; + let option: OverwriteFileOption | 'undefined' = this._userPreferenceService.getOverwriteFileOption(); for (let idx = 0; idx < files.length; ++idx) { const file = files[idx]; let currentOption = option; @@ -95,14 +97,14 @@ export class FileUploadService extends GenericService impleme } } } else if (dossierFiles.find(pf => pf.filename === file.file.name)) { - if (!option) { + if (option === 'undefined') { const res = await this._dialogService.openOverwriteFileDialog(file.file.name); if (res.cancel) { return; } if (res.rememberChoice) { - localStorage.setItem('overwriteFileOption', res.option); + await this._userPreferenceService.saveOverwriteFileOption(res.option); } currentOption = res.option; diff --git a/apps/red-ui/src/app/services/dossiers/archived-dossiers.service.ts b/apps/red-ui/src/app/services/dossiers/archived-dossiers.service.ts index bc8e9b2fe..6593826e8 100644 --- a/apps/red-ui/src/app/services/dossiers/archived-dossiers.service.ts +++ b/apps/red-ui/src/app/services/dossiers/archived-dossiers.service.ts @@ -1,12 +1,11 @@ import { inject, Injectable } from '@angular/core'; -import { ARCHIVE_ROUTE, Dossier, DOSSIERS_ARCHIVE, DOSSIERS_ROUTE } from '@red/domain'; +import { ARCHIVE_ROUTE, Dossier, DOSSIERS_ROUTE } from '@red/domain'; import { catchError, switchMap, tap } from 'rxjs/operators'; import { Observable, of } from 'rxjs'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { ActiveDossiersService } from './active-dossiers.service'; import { DossiersService } from './dossiers.service'; import { FilesMapService } from '../files/files-map.service'; -import { FeaturesService } from '../features.service'; import { Router } from '@angular/router'; @Injectable({ providedIn: 'root' }) @@ -15,7 +14,6 @@ export class ArchivedDossiersService extends DossiersService { protected readonly _defaultModelPath = 'archived-dossiers'; readonly #activeDossiersService = inject(ActiveDossiersService); readonly #filesMapService = inject(FilesMapService); - readonly #featuresService = inject(FeaturesService); readonly #router = inject(Router); archive(dossiers: Dossier[]): Observable { @@ -46,7 +44,7 @@ export class ArchivedDossiersService extends DossiersService { } loadAll(): Observable { - return this.#featuresService.isEnabled(DOSSIERS_ARCHIVE) ? super.loadAll() : of([]); + return super.loadAll(); } #removeFromActiveDossiers(archivedDossiersIds: string[]): void { diff --git a/apps/red-ui/src/app/services/entity-services/dossier-states.service.ts b/apps/red-ui/src/app/services/entity-services/dossier-states.service.ts index a10efcb51..be184356c 100644 --- a/apps/red-ui/src/app/services/entity-services/dossier-states.service.ts +++ b/apps/red-ui/src/app/services/entity-services/dossier-states.service.ts @@ -10,21 +10,24 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { mapEach } from '@iqser/common-ui/lib/utils'; const CONFLICT_MSG = _('dossier-states-listing.error.conflict'); -const GENERIC_MSG = _('dossier-states-listing.error.generic'); @Injectable({ providedIn: 'root', }) export class DossierStatesService extends EntitiesService { + protected readonly _defaultModelPath = 'dossier-status'; + protected readonly _entityClass = DossierState; readonly #toaster = inject(Toaster); readonly #dossierTemplatesService = inject(DossierTemplatesService); readonly #dossierStatesMapService = inject(DossierStatesMapService); - protected readonly _defaultModelPath = 'dossier-status'; - protected readonly _entityClass = DossierState; async createOrUpdate(state: IDossierState) { const showToast = (error: HttpErrorResponse) => { - this.#toaster.error(error.status === HttpStatusCode.Conflict ? CONFLICT_MSG : GENERIC_MSG); + if (error.status === HttpStatusCode.Conflict) { + this.#toaster.error(CONFLICT_MSG); + } else { + this.#toaster.rawError(error.error.message); + } return EMPTY; }; diff --git a/apps/red-ui/src/app/services/permissions.service.ts b/apps/red-ui/src/app/services/permissions.service.ts index 69191b669..f1c283543 100644 --- a/apps/red-ui/src/app/services/permissions.service.ts +++ b/apps/red-ui/src/app/services/permissions.service.ts @@ -4,7 +4,6 @@ import { DashboardStats, Dictionary, Dossier, - DOSSIERS_ARCHIVE, DossierTemplate, File, IComment, @@ -13,7 +12,6 @@ import { WorkflowFileStatus, WorkflowFileStatuses, } from '@red/domain'; -import { FeaturesService } from '@services/features.service'; import { FilesMapService } from '@services/files/files-map.service'; import { Roles } from '@users/roles'; import { UserPreferenceService } from '@users/user-preference.service'; @@ -27,7 +25,6 @@ export class PermissionsService { constructor( private readonly _userService: UserService, private readonly _filesMapService: FilesMapService, - private readonly _featuresService: FeaturesService, private readonly _userPreferenceService: UserPreferenceService, private readonly _iqserPermissionsService: IqserPermissionsService, private readonly _dossierTemplatesService: DossierTemplatesService, @@ -290,12 +287,7 @@ export class PermissionsService { } canArchiveDossier(dossier: Dossier): boolean { - return ( - this._iqserPermissionsService.has(Roles.dossiers.archived) && - this._featuresService.isEnabled(DOSSIERS_ARCHIVE) && - dossier.isActive && - this.isOwner(dossier) - ); + return this._iqserPermissionsService.has(Roles.dossiers.archived) && dossier.isActive && this.isOwner(dossier); } canEditDossier(dossier: Dossier): boolean { diff --git a/apps/red-ui/src/app/users/user-preference.service.ts b/apps/red-ui/src/app/users/user-preference.service.ts index 4b05ce78c..dfb18d184 100644 --- a/apps/red-ui/src/app/users/user-preference.service.ts +++ b/apps/red-ui/src/app/users/user-preference.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { IqserUserPreferenceService, ListingMode } from '@iqser/common-ui'; import { SystemDefaultOption, SystemDefaultType } from '../modules/account/utils/dialog-defaults'; import { RedactOrHintOption, RemoveRedactionOption } from '../modules/file-preview/utils/dialog-types'; +import { OverwriteFileOption } from '@red/domain'; export const PreferencesKeys = { dossierRecent: 'Dossier-Recent', @@ -10,7 +11,6 @@ export const PreferencesKeys = { filesListingMode: 'Files-Listing-Mode', autoExpandFiltersOnActions: 'Auto-Expand-Filters-On-Actions', loadAllAnnotationsWarning: 'Load-All-Annotations-Warning', - openScmDialogByDefault: 'Open-Structured-Component-Management-By-Default', tableExtractionType: 'Table-Extraction-Type', addRedactionDefaultOption: 'Add-Redaction-Default', addHintDefaultOption: 'Add-Hint-Default', @@ -22,6 +22,7 @@ export const PreferencesKeys = { removeRedactionDefaultExtraOption: 'Remove-Redaction-Default-Extra', removeRecommendationDefaultExtraOption: 'Remove-Recommendation-Default-Extra', removeHintDefaultExtraOption: 'Remove-Hint-Default-Extra', + rememberOverwriteFileOption: 'Remember-Overwrite-File', } as const; @Injectable({ @@ -65,15 +66,6 @@ export class UserPreferenceService extends IqserUserPreferenceService { await this.save(PreferencesKeys.autoExpandFiltersOnActions, nextValue); } - getOpenScmDialogByDefault(): boolean { - return this._getAttribute(PreferencesKeys.openScmDialogByDefault, 'false') === 'true'; - } - - async toggleOpenScmDialogByDefault(): Promise { - const nextValue = (!this.getOpenScmDialogByDefault()).toString(); - await this.save(PreferencesKeys.openScmDialogByDefault, nextValue); - } - getBool(key: string, defaultValue = 'false') { return this._getAttribute(key, defaultValue) === 'true'; } @@ -179,4 +171,12 @@ export class UserPreferenceService extends IqserUserPreferenceService { async saveRemoveRecommendationDefaultExtraOption(defaultOption: boolean | string): Promise { await this.save(PreferencesKeys.removeRecommendationDefaultExtraOption, defaultOption.toString()); } + + getOverwriteFileOption(): OverwriteFileOption | 'undefined' { + return this._getAttribute(PreferencesKeys.rememberOverwriteFileOption, 'undefined') as OverwriteFileOption | 'undefined'; + } + + async saveOverwriteFileOption(preference: OverwriteFileOption | 'undefined') { + await this.save(PreferencesKeys.rememberOverwriteFileOption, preference); + } } diff --git a/apps/red-ui/src/assets/features/features.json b/apps/red-ui/src/assets/features/features.json index bbcfecc3a..0a8585355 100644 --- a/apps/red-ui/src/assets/features/features.json +++ b/apps/red-ui/src/assets/features/features.json @@ -1,8 +1,3 @@ { - "features": [ - { - "name": "DOSSIERS_ARCHIVE", - "minVersion": "3.3.0" - } - ] + "features": [] } diff --git a/apps/red-ui/src/assets/help-mode/help-mode-keys.json b/apps/red-ui/src/assets/help-mode/help-mode-keys.json index bab5118aa..06209d4b4 100644 --- a/apps/red-ui/src/assets/help-mode/help-mode-keys.json +++ b/apps/red-ui/src/assets/help-mode/help-mode-keys.json @@ -651,6 +651,11 @@ "documentKey": "workload_filter", "overlappingElements": ["USER_MENU", "DOCUMENT_INFO"] }, + { + "elementKey": "filter_annotations", + "documentKey": "filter_annotations", + "overlappingElements": ["USER_MENU", "DOCUMENT_INFO"] + }, { "elementKey": "workload_bulk_selection", "documentKey": "workload_bulk_selection", @@ -692,5 +697,86 @@ { "elementKey": "document_list_view", "documentKey": "document_list" + }, + { + "elementKey": "editor_edit_component", + "documentKey": "editor_edit_component", + "scrollableParentView": "COMPONENTS_VIEW" + }, + { + "elementKey": "edit_component", + "documentKey": "edit_component" + }, + { + "elementKey": "add_component_value", + "documentKey": "add_component_value" + }, + { + "elementKey": "undo_component_change", + "documentKey": "undo_component_change" + }, + { + "elementKey": "change_component_order", + "documentKey": "change_component_order" + }, + { + "elementKey": "remove_component_value", + "documentKey": "remove_component_value" + }, + { + "elementKey": "filter_components", + "documentKey": "filter_components" + }, + { + "elementKey": "annotations_list", + "documentKey": "annotations_list" + }, + { + "elementKey": "components_table", + "documentKey": "components_table" + }, + { + "elementKey": "components_table", + "documentKey": "components_table" + }, + { + "elementKey": "remove_annotation_DIALOG", + "documentKey": "remove_annotation" + }, + { + "elementKey": "edit_annotation_DIALOG", + "documentKey": "edit_annotation" + }, + { + "elementKey": "dossier_download_dossier", + "documentKey": "dossier_download_dossier", + "overlappingElements": ["USER_MENU"] + }, + { + "elementKey": "dossier_download_document", + "documentKey": "dossier_download_document", + "scrollableParentView": "VIRTUAL_SCROLL" + }, + { + "elementKey": "template_download_dossier", + "documentKey": "template_download_dossier", + "scrollableParentView": "VIRTUAL_SCROLL" + }, + { + "elementKey": "editor_download_document", + "documentKey": "editor_download_document", + "overlappingElements": ["USER_MENU"] + }, + { + "elementKey": "rule_editors", + "documentKey": "rule_editors" + }, + { + "elementKey": "component_mappings", + "documentKey": "component_mappings" + }, + { + "elementKey": "components_management", + "documentKey": "components_management" } ] diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index 4a82e785f..5288362b8 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -587,8 +587,7 @@ "success": { "generic": "" }, - "title": "", - "warning-text": "" + "title": "" }, "configurations": "Konfiguration", "confirm-archive-dossier": { @@ -1066,8 +1065,7 @@ "dossier-states": "{count, plural, one{Dossier-Status} other{Dossier-Status}}" }, "error": { - "conflict": "Es gibt bereits einen Dossier-Status mit diesem Namen.", - "generic": "Speichern des Dossier-Status fehlgeschlagen." + "conflict": "Es gibt bereits einen Dossier-Status mit diesem Namen." }, "no-data": { "title": "Es wurde noch kein Dossier-Status angelegt." @@ -1360,7 +1358,6 @@ "generic": "Die Entitätsregeln wurden aktualisiert." }, "title": "Entitätsregeln-Editor", - "warning-text": "Warnung: experimentelle Funktion!", "warnings-found": "{warnings, plural, one{A warning} other{{warnings} warnings}} in Regeln gefunden" }, "error": { @@ -2049,7 +2046,6 @@ "auto-expand-filters-on-action": "Filter ausgehend von meinen Aktionen automatisch anpassen", "help-mode-dialog": "Dialog zur Aktivierung des Hilfemodus", "load-all-annotations-warning": "Warnung bei gleichzeitigem Laden aller Annotationen in der Miniaturansicht", - "open-structured-view-by-default": "Strukturierte Komponentenansicht standardmäßig anzeigen", "table-extraction-type": "Art der Tabellenextraktion" }, "label": "Präferenzen", @@ -2587,4 +2583,4 @@ } }, "yesterday": "Gestern" -} \ No newline at end of file +} diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 44e146a1d..07433cfe7 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -587,8 +587,7 @@ "success": { "generic": "" }, - "title": "", - "warning-text": "" + "title": "" }, "configurations": "Configurations", "confirm-archive-dossier": { @@ -1066,8 +1065,7 @@ "dossier-states": "{count, plural, one{Dossier state} other{Dossier states}}" }, "error": { - "conflict": "Dossier state with this name already exists", - "generic": "Failed to save dossier state." + "conflict": "Dossier state with this name already exists" }, "no-data": { "title": "There are no dossier states." @@ -1351,7 +1349,6 @@ "generic": "Entity rules updated." }, "title": "Entity rule editor", - "warning-text": "Warning: experimental feature!", "warnings-found": "{warnings, plural, one{A warning} other{{warnings} warnings}} found in rules" }, "entity": { @@ -2049,7 +2046,7 @@ "auto-expand-filters-on-action": "Auto-expand filters on my actions", "help-mode-dialog": "Help mode activation dialog", "load-all-annotations-warning": "Warning regarding simultaneous loading of all annotations in thumbnails", - "open-structured-view-by-default": "Display structured component management modal by default", + "overwrite-file-option": "Preferred action when re-uploading of an already existing file", "table-extraction-type": "Table extraction type" }, "label": "Preferences", @@ -2587,4 +2584,4 @@ } }, "yesterday": "Yesterday" -} \ No newline at end of file +} diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index 4f2ce4b2e..3c6b018cc 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -587,8 +587,7 @@ "success": { "generic": "Component rules updated!" }, - "title": "Component rule editor", - "warning-text": "Warning: experimental feature!" + "title": "Component rule editor" }, "configurations": "Einstellungen", "confirm-archive-dossier": { @@ -1066,8 +1065,7 @@ "dossier-states": "{count, plural, one{Dossier state} other{Dossier states}}" }, "error": { - "conflict": "Dossier state with this name already exists!", - "generic": "Failed to save dossier state!" + "conflict": "Dossier state with this name already exists!" }, "no-data": { "title": "There are no dossier states." @@ -1360,7 +1358,6 @@ "generic": "Entity rules updated!" }, "title": "Entity rule editor", - "warning-text": "Warning: experimental feature!", "warnings-found": "{warnings, plural, one{A warning} other{{warnings} warnings}} found in rules" }, "error": { @@ -2049,7 +2046,6 @@ "auto-expand-filters-on-action": "Auto expand filters on my actions", "help-mode-dialog": "Help Mode Dialog", "load-all-annotations-warning": "Warning regarding loading all annotations at once in file preview", - "open-structured-view-by-default": "Display Component View by default when opening a document", "table-extraction-type": "Table extraction type" }, "label": "Preferences", @@ -2587,4 +2583,4 @@ } }, "yesterday": "Gestern" -} \ No newline at end of file +} diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 9eca37841..340aea20c 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -122,7 +122,7 @@ "type": "Attribute type" }, "save": "Save attribute", - "title": "{type, select, edit{Edit {name}} create{Add New} other{}} dossier attribute" + "title": "{type, select, edit{Edit {name}} create{Add new} other{}} dossier attribute" }, "add-edit-dossier-state": { "form": { @@ -178,7 +178,7 @@ "type": "Type" }, "save": "Save attribute", - "title": "{type, select, edit{Edit {name}} create{Add New} other{}} file attribute" + "title": "{type, select, edit{Edit {name}} create{Add new} other{}} file attribute" }, "add-edit-justification": { "actions": { @@ -193,7 +193,7 @@ "reason": "Legal basis", "reason-placeholder": "Enter legal basis" }, - "title": "{type, select, edit{Edit {name}} create{Add New} other{}} justification" + "title": "{type, select, edit{Edit {name}} create{Add new} other{}} justification" }, "add-edit-user": { "actions": { @@ -213,7 +213,7 @@ "reset-password": "Reset password", "role": "Role" }, - "title": "{type, select, edit{Edit} create{Add New} other{}} user" + "title": "{type, select, edit{Edit} create{Add new} other{}} user" }, "add-entity": { "save": "Save entity", @@ -587,8 +587,7 @@ "success": { "generic": "Component rules updated!" }, - "title": "Component rule editor", - "warning-text": "Warning: experimental feature!" + "title": "Component rule editor" }, "configurations": "Configurations", "confirm-archive-dossier": { @@ -1066,8 +1065,7 @@ "dossier-states": "{count, plural, one{Dossier state} other{Dossier states}}" }, "error": { - "conflict": "Dossier state with this name already exists!", - "generic": "Failed to save dossier state!" + "conflict": "Dossier state with this name already exists!" }, "no-data": { "title": "There are no dossier states." @@ -1351,7 +1349,6 @@ "generic": "Entity rules updated!" }, "title": "Entity rule editor", - "warning-text": "Warning: experimental feature!", "warnings-found": "{warnings, plural, one{A warning} other{{warnings} warnings}} found in rules" }, "entity": { @@ -2049,7 +2046,7 @@ "auto-expand-filters-on-action": "Auto expand filters on my actions", "help-mode-dialog": "Help Mode Dialog", "load-all-annotations-warning": "Warning regarding loading all annotations at once in file preview", - "open-structured-view-by-default": "Display Component View by default when opening a document", + "overwrite-file-option": "Preferred action when re-uploading of an already existing file", "table-extraction-type": "Table extraction type" }, "label": "Preferences", @@ -2587,4 +2584,4 @@ } }, "yesterday": "Yesterday" -} \ No newline at end of file +} diff --git a/libs/common-ui b/libs/common-ui index 17943f2e8..0ca5e7e2a 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 17943f2e8dcab28450e9102d6e8b7a0b5f7227db +Subproject commit 0ca5e7e2ad7ca2b788f7234d7a38a3b810d9b31a diff --git a/libs/red-domain/src/lib/dossiers/constants.ts b/libs/red-domain/src/lib/dossiers/constants.ts index 95b78f4fa..4541b260b 100644 --- a/libs/red-domain/src/lib/dossiers/constants.ts +++ b/libs/red-domain/src/lib/dossiers/constants.ts @@ -1,5 +1,4 @@ export const DOSSIER_ID = 'dossierId'; -export const DOSSIERS_ARCHIVE = 'DOSSIERS_ARCHIVE'; export const ARCHIVE_ROUTE = 'archive'; export const DOSSIERS_ROUTE = 'dossiers';