From 744d18138e7673fed2176ab0ae999fd7411ff914 Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Tue, 4 Jul 2023 17:14:09 +0300 Subject: [PATCH 01/23] RED-6829 - INC15516657: Performance issues --- .../file-workload.component.html | 1 + .../file-workload/file-workload.component.ts | 19 +++++++++++++-- .../file-preview-screen.component.ts | 18 ++++++++++++++- .../file-preview/file-preview.module.ts | 1 - .../file-actions/file-actions.component.ts | 23 +++++++++++++++++-- apps/red-ui/src/app/utils/local-storage.ts | 12 ++++++++++ libs/common-ui | 2 +- 7 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 apps/red-ui/src/app/utils/local-storage.ts 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 56ed7fa4c..771002e53 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 @@ -31,6 +31,7 @@ [attr.help-mode-key]="'workload_in_editor'" [primaryFiltersSlug]="'primaryFilters'" [secondaryFiltersSlug]="'secondaryFilters'" + [fileId]="state.file()?.id" > 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 515b53474..e5a45a15f 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,4 +1,4 @@ -import { ChangeDetectorRef, Component, computed, effect, ElementRef, HostListener, OnDestroy, ViewChild } from '@angular/core'; +import { ChangeDetectorRef, Component, computed, effect, ElementRef, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { AnnotationProcessingService } from '../../services/annotation-processing.service'; import { MatDialog } from '@angular/material/dialog'; @@ -30,6 +30,7 @@ import { REDDocumentViewer } from '../../../pdf-viewer/services/document-viewer. import { SuggestionsService } from '../../services/suggestions.service'; import { ListItem } from '@models/file/list-item'; import { PageRotationService } from '../../../pdf-viewer/services/page-rotation.service'; +import { getLocalStorageDataByFileId } from '@utils/local-storage'; const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape']; const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; @@ -39,7 +40,7 @@ const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; templateUrl: './file-workload.component.html', styleUrls: ['./file-workload.component.scss'], }) -export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy { +export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, OnDestroy { readonly iconButtonTypes = IconButtonTypes; readonly circleButtonTypes = CircleButtonTypes; @@ -115,6 +116,20 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy ); } + ngOnInit(): void { + setTimeout(() => { + const showExcludePages = getLocalStorageDataByFileId(this.state.file()?.id, 'show-exclude-pages') ?? false; + if (showExcludePages) { + this.excludedPagesService.show(); + } + + const showDocumentInfo = getLocalStorageDataByFileId(this.state.file()?.id, 'show-document-info') ?? false; + if (showDocumentInfo) { + this.documentInfoService.show(); + } + }); + } + get activeAnnotations(): AnnotationWrapper[] { return this.displayedAnnotations.get(this.pdf.currentPage()) || []; } diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index 7258e4502..bf975f97f 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -19,6 +19,7 @@ import { CircleButtonTypes, ConfirmOption, ConfirmOptions, + copyLocalStorageFiltersValues, CustomError, Debounce, ErrorService, @@ -41,7 +42,7 @@ import { AnnotationDrawService } from '../pdf-viewer/services/annotation-draw.se import { AnnotationProcessingService } from './services/annotation-processing.service'; import { Dictionary, File, ViewModes } from '@red/domain'; import { PermissionsService } from '@services/permissions.service'; -import { combineLatest, firstValueFrom, of, pairwise } from 'rxjs'; +import { combineLatest, first, firstValueFrom, of, pairwise } from 'rxjs'; import { PreferencesKeys, UserPreferenceService } from '@users/user-preference.service'; import { byId, byPage, download, handleFilterDelta, hasChanges } from '../../utils'; import { FilesService } from '@services/files/files.service'; @@ -336,6 +337,7 @@ export class FilePreviewScreenComponent } this.pdfProxyService.configureElements(); + this.#restoreOldFilters(); document.documentElement.addEventListener('fullscreenchange', this.fullscreenListener); } @@ -822,4 +824,18 @@ export class FilePreviewScreenComponent private _isJapaneseString(text: string) { return text.match(/[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf]/); } + + #restoreOldFilters() { + combineLatest([ + this._filterService.getGroup$('primaryFilters').pipe(first(filterGroup => !!filterGroup?.filters.length)), + this._filterService.getGroup$('secondaryFilters').pipe(first(secondaryFilters => !!secondaryFilters?.filters.length)), + ]).subscribe(([primaryFilters, secondaryFilters]) => { + const localStorageFiltersString = localStorage.getItem('workload-filters') ?? '{}'; + const localStorageFilters = JSON.parse(localStorageFiltersString)[this.fileId]; + if (localStorageFilters) { + copyLocalStorageFiltersValues(primaryFilters.filters, localStorageFilters.primaryFilters); + copyLocalStorageFiltersValues(secondaryFilters.filters, localStorageFilters.secondaryFilters); + } + }); + } } diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts index 4186d8639..3fa7a5773 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts @@ -72,7 +72,6 @@ const routes: IqserRoutes = [ path: '', component: FilePreviewScreenComponent, pathMatch: 'full', - data: { reuse: true }, canDeactivate: [PendingChangesGuard, DocumentUnloadedGuard], }, ]; 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 a9d99b44f..7efcbda12 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 @@ -32,6 +32,7 @@ import { ROTATION_ACTION_BUTTONS } from '../../../pdf-viewer/utils/constants'; import { Roles } from '@users/roles'; import { FileAttributesService } from '@services/entity-services/file-attributes.service'; import { toObservable } from '@angular/core/rxjs-interop'; +import { setLocalStorageDataByFileId } from '@utils/local-storage'; @Component({ selector: 'redaction-file-actions', @@ -160,7 +161,7 @@ export class FileActionsComponent implements OnChanges { { id: 'toggle-document-info-btn', type: ActionTypes.circleBtn, - action: () => this._documentInfoService.toggle(), + action: () => this.#toggleDocumentInfo(), tooltip: _('file-preview.document-info'), ariaExpanded: toObservable(this._documentInfoService?.shown, { injector: this._injector }), icon: 'red:status-info', @@ -169,7 +170,7 @@ export class FileActionsComponent implements OnChanges { { id: 'toggle-exclude-pages-btn', type: ActionTypes.circleBtn, - action: () => this._excludedPagesService.toggle(), + action: () => this.#toggleExcludePages(), tooltip: _('file-preview.exclude-pages'), ariaExpanded: toObservable(this._excludedPagesService?.shown, { injector: this._injector }), showDot: !!this.file.excludedPages?.length, @@ -456,4 +457,22 @@ export class FileActionsComponent implements OnChanges { await this._filesService.setToNew(this.file); this._loadingService.stop(); } + + async #toggleExcludePages() { + this._excludedPagesService.toggle(); + const shown = await this._excludedPagesService.shown(); + setLocalStorageDataByFileId(this.file.id, 'show-exclude-pages', shown); + if (shown) { + setLocalStorageDataByFileId(this.file.id, 'show-document-info', false); + } + } + + async #toggleDocumentInfo() { + this._documentInfoService.toggle(); + const shown = await this._documentInfoService.shown(); + setLocalStorageDataByFileId(this.file.id, 'show-document-info', shown); + if (shown) { + setLocalStorageDataByFileId(this.file.id, 'show-exclude-pages', false); + } + } } diff --git a/apps/red-ui/src/app/utils/local-storage.ts b/apps/red-ui/src/app/utils/local-storage.ts new file mode 100644 index 000000000..0273199c8 --- /dev/null +++ b/apps/red-ui/src/app/utils/local-storage.ts @@ -0,0 +1,12 @@ +export function setLocalStorageDataByFileId(fileId: string, key: string, value: string | number | boolean): void { + let data = localStorage.getItem(key) ?? '{}'; + data = JSON.parse(data); + data[fileId] = value; + localStorage.setItem(key, JSON.stringify(data)); +} + +export function getLocalStorageDataByFileId(fileId: string, key: string): string | number | boolean { + let data = localStorage.getItem(key) ?? '{}'; + data = JSON.parse(data); + return data[fileId]; +} diff --git a/libs/common-ui b/libs/common-ui index 7efa3b7ad..cc8d04065 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 7efa3b7ad2aa442e38308128eb1b4ed99f1febc0 +Subproject commit cc8d040654ab4d3bc1e8e95368a69d495bb3b9b7 From 62bd383b888805c449e7834a48345c32db789f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Wed, 5 Jul 2023 13:54:01 +0300 Subject: [PATCH 02/23] RED-6830: Don't display data for future months in license view --- .../license-storage/license-storage.component.ts | 4 ++-- .../license-usage/license-usage.component.ts | 6 ++++-- .../admin/screens/license/utils/functions.ts | 16 +++++++++++++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/apps/red-ui/src/app/modules/admin/screens/license/components/license-storage/license-storage.component.ts b/apps/red-ui/src/app/modules/admin/screens/license/components/license-storage/license-storage.component.ts index cce4f1eef..e44fe4cf7 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/components/license-storage/license-storage.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/components/license-storage/license-storage.component.ts @@ -6,7 +6,7 @@ import { map, tap } from 'rxjs/operators'; import type { DonutChartConfig, ILicenseReport } from '@red/domain'; import { ChartDataset } from 'chart.js'; import { ChartBlue, ChartGreen, ChartGrey, ChartRed } from '../../utils/constants'; -import { getLabelsFromMonthlyData, getLineConfig } from '../../utils/functions'; +import { getLabelsFromLicense, getLineConfig } from '../../utils/functions'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @Component({ @@ -26,7 +26,7 @@ export class LicenseStorageComponent { }), map(license => ({ datasets: this.#getDatasets(license), - labels: getLabelsFromMonthlyData(license.monthlyData), + labels: getLabelsFromLicense(license), })), ); readonly size = size; diff --git a/apps/red-ui/src/app/modules/admin/screens/license/components/license-usage/license-usage.component.ts b/apps/red-ui/src/app/modules/admin/screens/license/components/license-usage/license-usage.component.ts index 8f1524d3c..0e423a730 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/components/license-usage/license-usage.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/components/license-usage/license-usage.component.ts @@ -5,7 +5,7 @@ import { map } from 'rxjs/operators'; import type { ILicenseReport } from '@red/domain'; import { ChartDataset } from 'chart.js'; import { ChartBlue, ChartGreen, ChartRed } from '../../utils/constants'; -import { getLabelsFromMonthlyData, getLineConfig } from '../../utils/functions'; +import { getLabelsFromLicense, getLineConfig } from '../../utils/functions'; @Component({ selector: 'red-license-usage', @@ -18,7 +18,7 @@ export class LicenseUsageComponent { map(() => this.licenseService.currentLicenseReport), map(license => ({ datasets: this.#getDatasets(license), - labels: getLabelsFromMonthlyData(license.monthlyData), + labels: getLabelsFromLicense(license), })), ); @@ -32,12 +32,14 @@ export class LicenseUsageComponent { #getDatasets(license: ILicenseReport): ChartDataset[] { const monthlyData = license.monthlyData; + return [ { data: monthlyData.flatMap(d => d.numberOfAnalyzedPages), label: 'Pages per Month', type: 'bar', backgroundColor: ChartBlue, + borderColor: ChartBlue, order: 2, }, { diff --git a/apps/red-ui/src/app/modules/admin/screens/license/utils/functions.ts b/apps/red-ui/src/app/modules/admin/screens/license/utils/functions.ts index efbbea5d3..efa5d0aad 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/utils/functions.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/utils/functions.ts @@ -1,7 +1,7 @@ import dayjs, { Dayjs } from 'dayjs'; import { FillTarget } from 'chart.js'; import { hexToRgba } from '@utils/functions'; -import { ILicenseData } from '@red/domain'; +import { ILicenseData, ILicenseReport } from '@red/domain'; import { ComplexFillTarget } from 'chart.js/dist/types'; const monthNames = dayjs.monthsShort(); @@ -30,3 +30,17 @@ export const getLineConfig: ( }); export const getLabelsFromMonthlyData = (monthlyData: ILicenseData[]) => monthlyData.map(data => verboseDate(dayjs(data.startDate))); + +export const getLabelsFromLicense = (license: ILicenseReport) => { + let startMonth = dayjs(license.startDate); + const endMonth = dayjs(license.endDate); + + const result = []; + + while (startMonth.isBefore(endMonth)) { + result.push(verboseDate(startMonth)); + startMonth = startMonth.add(1, 'month'); + } + + return result; +}; From 269bd94cfe0c8bb8f0613803a7a5829632a301e9 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Thu, 6 Jul 2023 13:12:40 +0300 Subject: [PATCH 03/23] RED-6713: update tenants handling --- apps/red-ui/src/app/app-routing.module.ts | 12 ++--- apps/red-ui/src/app/app.module.ts | 2 +- .../base-screen/base-screen.component.ts | 15 +++--- .../notifications/notifications.component.ts | 2 +- .../tenants-menu/tenants-menu.component.html | 6 +-- .../tenants-menu/tenants-menu.component.ts | 30 ++++++------ .../user-menu/user-menu.component.html | 2 +- .../user-menu/user-menu.component.ts | 6 ++- .../guards/dossier-template-exists.guard.ts | 15 +++++- .../src/app/guards/if-logged-in.guard.ts | 47 +++++++++++++++++++ .../modules/account/account-routing.module.ts | 3 +- .../account-side-nav.component.ts | 3 +- .../notifications-screen.component.ts | 4 +- .../preferences/preferences.component.ts | 3 +- .../app/modules/admin/admin-routing.module.ts | 3 +- .../src/app/modules/admin/admin.module.ts | 2 +- .../base-entity-screen.component.ts | 7 +-- .../user-details/user-details.component.ts | 9 ++-- .../screens/audit/audit-screen.component.ts | 8 ++-- .../default-colors-screen.component.ts | 14 ++---- .../digital-signature-screen.component.ts | 3 +- ...ier-attributes-listing-screen.component.ts | 6 +-- ...dossier-states-listing-screen.component.ts | 14 ++---- ...sier-templates-listing-screen.component.ts | 2 +- .../dossier-templates-listing.module.ts | 2 +- .../entities-listing-screen.component.ts | 4 +- .../dictionary/dictionary-screen.component.ts | 10 ++-- .../entity-info/entity-info.component.ts | 6 +-- ...-attributes-csv-import-dialog.component.ts | 3 +- ...ile-attributes-listing-screen.component.ts | 28 +++++------ .../system-preferences-form.component.ts | 29 +++++++----- .../info/dossier-template-info.module.ts | 3 +- .../dossier-template-info-screen.component.ts | 2 +- .../justifications-screen.component.ts | 6 +-- .../table-item/table-item.component.ts | 5 +- .../license-storage.component.ts | 2 +- .../license-screen.component.ts | 3 +- .../permissions-screen.component.ts | 14 ++---- .../reports-screen.component.ts | 8 ++-- .../rules-screen/rules-screen.component.ts | 17 +++---- .../user-listing-screen.component.ts | 2 +- .../watermark-screen.component.ts | 31 ++++-------- .../screens/watermark/watermark.module.ts | 3 +- .../watermarks-listing-screen.component.ts | 6 +-- .../services/digital-signature.service.ts | 3 +- .../admin-side-nav.component.ts | 3 +- .../dossier-template-actions.component.ts | 10 +--- .../src/app/modules/archive/archive.module.ts | 3 +- .../archive/services/config.service.ts | 3 +- .../dashboard-screen.component.ts | 3 +- .../dossier-details.component.ts | 19 +++----- ...ossier-overview-screen-header.component.ts | 5 +- .../workflow-item/workflow-item.component.ts | 6 +-- .../dossier-overview/config.service.ts | 10 ++-- .../dossier-overview.module.ts | 2 +- .../dossier-overview-screen.component.ts | 7 +-- .../dossier-documents-status.component.ts | 3 +- .../dossiers-listing-details.component.ts | 2 +- .../dossiers-listing/config.service.ts | 11 +---- .../dossiers-listing.module.ts | 2 +- .../dossiers-listing-screen.component.ts | 13 ++--- .../annotation-details.component.ts | 8 ++-- .../annotations-list.component.ts | 9 ++-- .../components/comments/comments.component.ts | 8 ++-- .../document-info/document-info.component.ts | 2 +- .../file-workload/file-workload.component.ts | 46 ++++++++---------- .../page-indicator.component.ts | 6 +-- .../components/pages/pages.component.ts | 10 ++-- .../user-management.component.ts | 25 +++++----- .../view-switch/view-switch.component.ts | 3 +- .../file-preview/file-preview-providers.ts | 4 +- .../file-preview-screen.component.ts | 25 ++++------ .../file-preview/file-preview.module.ts | 4 +- .../services/annotation-actions.service.ts | 6 +-- .../services/annotation-processing.service.ts | 2 +- .../services/annotations-listing.service.ts | 4 +- .../services/commenting.service.ts | 2 +- .../services/file-preview-state.service.ts | 8 ++-- .../services/manual-redaction.service.ts | 3 +- .../pdf-annotation-actions.service.ts | 3 +- .../services/pdf-proxy.service.ts | 20 ++++---- .../file-preview/services/skipped.service.ts | 4 +- .../services/suggestions.service.ts | 2 +- .../modules/file-preview/utils/constants.ts | 2 +- .../services/annotation-draw.service.ts | 2 +- .../services/annotation-manager.service.ts | 7 ++- .../services/document-viewer.service.ts | 14 +++--- .../pdf-viewer/services/pdf-viewer.service.ts | 29 +++++------- .../services/readable-redactions.service.ts | 4 +- .../pdf-viewer/services/tooltips.service.ts | 2 +- .../services/viewer-header.service.ts | 7 +-- .../app/modules/pdf-viewer/utils/constants.ts | 3 +- .../app/modules/pdf-viewer/utils/functions.ts | 2 +- .../search-item-template.component.ts | 2 +- .../search-screen/search-screen.component.ts | 14 ++---- .../src/app/modules/search/search.module.ts | 3 +- .../dossiers-listing-actions.component.ts | 3 +- .../file-actions/file-actions.component.ts | 12 ++--- ...sign-reviewer-approver-dialog.component.ts | 3 +- ...edit-dossier-download-package.component.ts | 5 +- .../edit-dossier-dialog.component.ts | 14 ++---- .../edit-dossier-team.component.ts | 12 ++--- .../services/file-assign.service.ts | 3 +- .../shared-dossiers/shared-dossiers.module.ts | 2 +- .../assign-user-dropdown.component.ts | 4 +- .../dictionary-manager.component.ts | 11 ++--- .../donut-chart/donut-chart.component.ts | 12 +++-- .../dossier-name-column.component.ts | 2 +- .../watermark-selector.component.ts | 7 +-- .../dossiers-type-switch.component.ts | 2 +- .../components/editor/editor.component.ts | 12 ++--- .../expandable-file-actions.component.ts | 3 +- .../file-name-column.component.ts | 4 +- .../team-members/team-members.component.ts | 4 +- .../type-filter/type-filter.component.ts | 12 ++--- .../download-dialog.component.ts | 3 +- .../src/app/modules/shared/pipes/date.pipe.ts | 2 +- .../src/app/modules/shared/shared.module.ts | 2 +- .../trash-screen/trash-screen.component.ts | 10 +--- .../src/app/modules/trash/trash.module.ts | 3 +- .../services/file-download.service.ts | 3 +- .../services/file-upload.service.ts | 14 +++--- .../src/app/services/breadcrumbs.service.ts | 4 +- .../dashboard-stats.service.ts | 6 +-- .../dossier-templates.service.ts | 3 +- .../dossiers/dossier-changes.service.ts | 6 +-- .../app/services/dossiers/dossiers.service.ts | 7 +-- .../entity-permissions.service.ts | 6 +-- .../entity-services/default-colors.service.ts | 3 +- .../entity-services/dictionary.service.ts | 3 +- .../dossier-attributes.service.ts | 3 +- .../entity-services/dossier-states.service.ts | 8 ++-- .../file-attributes.service.ts | 7 +-- .../services/entity-services/trash.service.ts | 3 +- .../entity-services/watermark.service.ts | 5 +- .../services/files/file-management.service.ts | 5 +- .../app/services/files/files-map.service.ts | 3 +- .../src/app/services/files/files.service.ts | 3 +- .../files/redaction-import.service.ts | 3 +- .../services/files/viewed-pages.service.ts | 3 +- .../src/app/services/notifications.service.ts | 8 ++-- .../src/app/services/reanalysis.service.ts | 3 +- .../app/services/report-template.service.ts | 3 +- .../annotation-changes-translations.ts | 2 +- .../system-preferences-translations.ts | 2 +- apps/red-ui/src/app/users/red-role.guard.ts | 10 +++- apps/red-ui/src/app/users/user.service.ts | 4 +- apps/red-ui/src/app/utils/csv-utils.ts | 2 +- apps/red-ui/src/app/utils/filter-utils.ts | 2 +- apps/red-ui/src/app/utils/functions.ts | 2 +- apps/red-ui/src/app/utils/main.resolver.ts | 4 +- libs/common-ui | 2 +- .../src/lib/audit/audit.response.ts | 2 +- .../src/lib/dictionaries/dictionary.model.ts | 3 +- .../src/lib/dictionaries/dictionary.ts | 2 +- .../dashboard-stats.model.ts | 3 +- .../lib/dossier-templates/dashboard-stats.ts | 2 +- .../dossier-template.model.ts | 3 +- .../lib/dossier-templates/dossier-template.ts | 2 +- .../src/lib/dossiers/dossier.model.ts | 3 +- .../src/lib/dossiers/dossier.request.ts | 2 +- libs/red-domain/src/lib/dossiers/dossier.ts | 2 +- .../lib/downloads/download-status.model.ts | 3 +- .../src/lib/downloads/download-status.ts | 2 +- .../lib/downloads/prepare-download.request.ts | 2 +- .../lib/downloads/remove-download.request.ts | 2 +- .../src/lib/files/file-upload-result.ts | 2 +- libs/red-domain/src/lib/files/super-types.ts | 2 +- libs/red-domain/src/lib/files/types.ts | 2 +- .../src/lib/geometry/section-grid.ts | 2 +- .../src/lib/geometry/section-rectangle.ts | 2 +- .../src/lib/pages/page-exclusion.request.ts | 2 +- .../redaction-log/add-redaction.request.ts | 2 +- .../src/lib/redaction-log/change.ts | 2 +- .../red-domain/src/lib/redaction-log/types.ts | 2 +- .../src/lib/search/matched-document.ts | 2 +- .../src/lib/search/matched-section.ts | 2 +- .../red-domain/src/lib/search/search-input.ts | 2 +- .../src/lib/search/search-list-item.ts | 3 +- .../src/lib/search/search.request.ts | 2 +- .../src/lib/search/search.response.ts | 2 +- libs/red-domain/src/lib/shared/app-config.ts | 2 +- libs/red-domain/src/lib/shared/pdf.types.ts | 2 +- .../src/lib/trash/trash-dossier.model.ts | 2 +- libs/red-domain/src/lib/trash/trash.item.ts | 2 +- libs/red-domain/src/lib/users/user.model.ts | 3 +- tsconfig.json | 1 + 187 files changed, 600 insertions(+), 567 deletions(-) create mode 100644 apps/red-ui/src/app/guards/if-logged-in.guard.ts diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts index 5eb70338e..16f944ec6 100644 --- a/apps/red-ui/src/app/app-routing.module.ts +++ b/apps/red-ui/src/app/app-routing.module.ts @@ -1,11 +1,8 @@ import { AuthErrorComponent } from '@components/auth-error/auth-error.component'; import { CompositeRouteGuard, - CustomRouteReuseStrategy, DEFAULT_REDIRECT_KEY, - ifLoggedIn, ifNotLoggedIn, - IqserAuthGuard, IqserPermissionsGuard, IqserRoutes, TenantSelectComponent, @@ -27,6 +24,9 @@ import { DossierFilesGuard } from '@guards/dossier-files-guard'; import { WebViewerLoadedGuard } from './modules/pdf-viewer/services/webviewer-loaded.guard'; import { Roles } from '@users/roles'; import { mainResolver } from '@utils/main.resolver'; +import { hasAnyRoleGuard, IqserAuthGuard } from '@iqser/common-ui/lib/users'; +import { CustomRouteReuseStrategy } from '@iqser/common-ui/lib/utils'; +import { ifLoggedIn } from '@guards/if-logged-in.guard'; const dossierTemplateIdRoutes: IqserRoutes = [ { @@ -182,7 +182,7 @@ const mainRoutes: IqserRoutes = [ children: dossierTemplateIdRoutes, canActivate: [CompositeRouteGuard, IqserPermissionsGuard, templateExistsWhenEnteringDossierList()], data: { - routeGuards: [IqserAuthGuard, RedRoleGuard, DossierTemplatesGuard, DashboardGuard], + routeGuards: [IqserAuthGuard, RedRoleGuard], permissions: { allow: [ Roles.any, @@ -220,7 +220,7 @@ const routes: IqserRoutes = [ }, { path: ':tenant/main', - canActivate: [ifLoggedIn], + canActivate: [ifLoggedIn()], component: BaseScreenComponent, resolve: { whateverThisMainRouteNeeds: mainResolver, @@ -230,7 +230,7 @@ const routes: IqserRoutes = [ { path: ':tenant/auth-error', component: AuthErrorComponent, - canActivate: [IqserAuthGuard], + canActivate: [hasAnyRoleGuard()], }, { path: '**', diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index e4d0d0f72..0feb32e33 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -21,7 +21,6 @@ import { IqserListingModule, IqserLoadingModule, IqserTranslateModule, - IqserUsersModule, LanguageService, LogoComponent, MAX_RETRIES_ON_SERVER_ERROR, @@ -71,6 +70,7 @@ import { SkeletonStatsComponent } from '@components/skeleton/skeleton-stats/skel import { UserMenuComponent } from '@components/user-menu/user-menu.component'; import { TenantsMenuComponent } from '@components/tenants-menu/tenants-menu.component'; import { MatDividerModule } from '@angular/material/divider'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; export const appModuleFactory = (config: AppConfig) => { @NgModule({ 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 3961f1bb6..086985221 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 @@ -6,13 +6,14 @@ import { Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; import { SpotlightSearchAction } from '@components/spotlight-search/spotlight-search-action'; import { filter, map, startWith } from 'rxjs/operators'; -import { IqserPermissionsService, List, shareDistinctLast, TenantsService } from '@iqser/common-ui'; +import { IqserPermissionsService, TenantsService } 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 { Roles } from '@users/roles'; import { REDDocumentViewer } from '../../modules/pdf-viewer/services/document-viewer.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { List, shareDistinctLast } from '@iqser/common-ui/lib/utils'; const isNavigationStart = event => event instanceof NavigationStart; const isSearchScreen: (url: string) => boolean = url => url.includes('/search'); @@ -22,6 +23,12 @@ const isSearchScreen: (url: string) => boolean = url => url.includes('/search'); styleUrls: ['./base-screen.component.scss'], }) export class BaseScreenComponent { + readonly #navigationStart$ = this._router.events.pipe( + filter(isNavigationStart), + map((event: NavigationStart) => event.url), + startWith(this._router.url), + shareDistinctLast(), + ); readonly roles = Roles; readonly documentViewer = inject(REDDocumentViewer); readonly currentUser = this.userService.currentUser; @@ -44,12 +51,6 @@ export class BaseScreenComponent { action: (query): void => this.#search(query, []), }, ]; - readonly #navigationStart$ = this._router.events.pipe( - filter(isNavigationStart), - map((event: NavigationStart) => event.url), - startWith(this._router.url), - shareDistinctLast(), - ); readonly isSearchScreen$ = this.#navigationStart$.pipe(map(isSearchScreen)); constructor( diff --git a/apps/red-ui/src/app/components/notifications/notifications.component.ts b/apps/red-ui/src/app/components/notifications/notifications.component.ts index 5d9a56c96..743dcda00 100644 --- a/apps/red-ui/src/app/components/notifications/notifications.component.ts +++ b/apps/red-ui/src/app/components/notifications/notifications.component.ts @@ -4,7 +4,7 @@ import { NotificationsService } from '@services/notifications.service'; import { Notification } from '@red/domain'; import { distinctUntilChanged, map } from 'rxjs/operators'; import { Observable } from 'rxjs'; -import { isToday, shareLast, trackByFactory } from '@iqser/common-ui'; +import { isToday, shareLast, trackByFactory } from '@iqser/common-ui/lib/utils'; import dayjs, { Dayjs } from 'dayjs'; import { TranslateService } from '@ngx-translate/core'; diff --git a/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.html b/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.html index 66bf2b5f3..96ee8315f 100644 --- a/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.html +++ b/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.html @@ -1,11 +1,11 @@
- +
{{ item.key }}
{{ stored.email }} diff --git a/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.ts b/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.ts index c2cd0fc77..7e2a755d0 100644 --- a/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.ts +++ b/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.ts @@ -1,8 +1,9 @@ import { Component, inject } from '@angular/core'; -import { BASE_HREF, getConfig, getCurrentUser, IStoredTenant, KeycloakStatusService, TenantsService } from '@iqser/common-ui'; +import { getConfig, getKeycloakOptions, IStoredTenantId, KeycloakStatusService, TenantsService } from '@iqser/common-ui'; import { User } from '@red/domain'; -import { KeyValue } from '@angular/common'; import { KeycloakService } from 'keycloak-angular'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { BASE_HREF } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'app-tenants-menu', @@ -10,48 +11,49 @@ import { KeycloakService } from 'keycloak-angular'; styleUrls: ['./tenants-menu.component.scss'], }) export class TenantsMenuComponent { - readonly tenantsService = inject(TenantsService); - readonly storedTenants: Map; readonly #baseHref = inject(BASE_HREF); readonly #keycloakService = inject(KeycloakService); readonly #keycloakStatusService = inject(KeycloakStatusService); readonly #currentUser = getCurrentUser(); readonly #config = getConfig(); + readonly tenantsService = inject(TenantsService); + readonly storedTenants: { key: string; value: IStoredTenantId[] }[]; constructor() { this.storedTenants = this.#getStoredTenants(); } - trackBy(_index: number, item: KeyValue) { + trackBy(_index: number, item: { key: string; value: IStoredTenantId[] }) { return item.key; } + // TODO: this should be moved to the keycloak status service async selectTenant(tenantId?: string, email?: string) { - let tenantUrl = tenantId ? '/' + tenantId : '/'; - if (email) { - tenantUrl += '?username=' + email; + if (tenantId && tenantId !== this.tenantsService.activeTenantId) { + await this.#keycloakService.init(getKeycloakOptions(this.#baseHref, this.#config, tenantId)); } - if (tenantId === this.tenantsService.activeTenantId) { + if (tenantId) { const url = this.#keycloakService.getKeycloakInstance().createLoginUrl({ - redirectUri: this.#keycloakStatusService.createLoginUrl(), + redirectUri: this.#keycloakStatusService.createLoginUrl(tenantId), idpHint: this.#config.OAUTH_IDP_HINT, loginHint: email ?? undefined, }); return this.#keycloakService.logout(url); } - window.open(window.location.origin + this.#baseHref + tenantUrl, '_blank'); + return this.#keycloakService.logout(window.location.origin + this.#baseHref); } - #getStoredTenants(): Map { + #getStoredTenants() { const storedTenants = this.tenantsService.getStoredTenants(); const otherTenant = storedTenants.filter(t => { - const isCurrentTenant = t.tenant.tenantId === this.tenantsService.activeTenantId; + const isCurrentTenant = t.tenantId === this.tenantsService.activeTenantId; const isCurrentUser = t.email === this.#currentUser.email || t.email === this.#currentUser.username; return !(isCurrentTenant && isCurrentUser); }); - return otherTenant.groupBy(t => t.tenant.displayName); + const grouped = otherTenant.groupBy(t => t.tenantId); + return [...grouped.keys()].sort((a, b) => a.localeCompare(b)).map(key => ({ key, value: grouped.get(key) })); } } diff --git a/apps/red-ui/src/app/components/user-menu/user-menu.component.html b/apps/red-ui/src/app/components/user-menu/user-menu.component.html index 5bdf0637e..e58926fa9 100644 --- a/apps/red-ui/src/app/components/user-menu/user-menu.component.html +++ b/apps/red-ui/src/app/components/user-menu/user-menu.component.html @@ -5,7 +5,7 @@
- + {{ 'top-bar.navigation-items.my-account.children.select-tenant' | translate }} diff --git a/apps/red-ui/src/app/components/user-menu/user-menu.component.ts b/apps/red-ui/src/app/components/user-menu/user-menu.component.ts index 49690a0ce..f42a374f7 100644 --- a/apps/red-ui/src/app/components/user-menu/user-menu.component.ts +++ b/apps/red-ui/src/app/components/user-menu/user-menu.component.ts @@ -1,9 +1,11 @@ import { Component, inject } from '@angular/core'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { Roles } from '@users/roles'; -import { getCurrentUser, IqserPermissionsService, List, TenantsService } from '@iqser/common-ui'; +import { IqserPermissionsService, TenantsService } from '@iqser/common-ui'; import { User } from '@red/domain'; import { UserService } from '@users/user.service'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { List } from '@iqser/common-ui/lib/utils'; interface MenuItem { readonly id: string; @@ -20,10 +22,10 @@ interface MenuItem { styleUrls: ['./user-menu.component.scss'], }) export class UserMenuComponent { + readonly #permissionsService = inject(IqserPermissionsService); readonly currentUser = getCurrentUser(); readonly tenantsService = inject(TenantsService); readonly userService = inject(UserService); - readonly #permissionsService = inject(IqserPermissionsService); readonly userMenuItems: List = [ { id: 'account', 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 ebd2b36f6..8e49a7fc0 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 @@ -3,6 +3,9 @@ import { ActivatedRouteSnapshot, CanActivateFn, Router } from '@angular/router'; import { DOSSIER_TEMPLATE_ID } from '@red/domain'; import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service'; import { TenantsService } from '@iqser/common-ui'; +import { NGXLogger } from 'ngx-logger'; +import { firstValueFrom } from 'rxjs'; +import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; export function templateExistsWhenEnteringAdmin(): CanActivateFn { return async function (route: ActivatedRouteSnapshot): Promise { @@ -20,10 +23,18 @@ export function templateExistsWhenEnteringAdmin(): CanActivateFn { export function templateExistsWhenEnteringDossierList(): CanActivateFn { return async function (route: ActivatedRouteSnapshot) { const dossierTemplateId: string = route.paramMap.get(DOSSIER_TEMPLATE_ID); + const dashboardStatsService = inject(DashboardStatsService); + const dossierTemplatesService = inject(DossierTemplatesService); + const logger = inject(NGXLogger); + const router = inject(Router); + const tenantsService = inject(TenantsService); - const dossierTemplateStats = inject(DashboardStatsService).find(dossierTemplateId); + await firstValueFrom(dashboardStatsService.loadAll()); + await firstValueFrom(dossierTemplatesService.loadAll()); + const dossierTemplateStats = dashboardStatsService.find(dossierTemplateId); if (!dossierTemplateStats || dossierTemplateStats.isEmpty) { - await inject(Router).navigate([inject(TenantsService).activeTenantId, 'main']); + logger.warn('[ROUTES] Dossier template not found, redirecting to main'); + await router.navigate([tenantsService.activeTenantId, 'main']); return false; } return true; diff --git a/apps/red-ui/src/app/guards/if-logged-in.guard.ts b/apps/red-ui/src/app/guards/if-logged-in.guard.ts new file mode 100644 index 000000000..b7b6707a1 --- /dev/null +++ b/apps/red-ui/src/app/guards/if-logged-in.guard.ts @@ -0,0 +1,47 @@ +import { ActivatedRouteSnapshot, CanActivateFn, Router } from '@angular/router'; +import { inject } from '@angular/core'; +import { NGXLogger } from 'ngx-logger'; +import { keycloakInitializer, KeycloakStatusService, TenantsService } from '@iqser/common-ui'; +import { KeycloakService } from 'keycloak-angular'; +import { UserService } from '@users/user.service'; + +export function ifLoggedIn(): CanActivateFn { + return async (route: ActivatedRouteSnapshot) => { + const logger = inject(NGXLogger); + logger.info('[ROUTES] Check if can activate main'); + + const tenantsService = inject(TenantsService); + const keycloakService = inject(KeycloakService); + const usersService = inject(UserService); + const keycloakStatusService = inject(KeycloakStatusService); + + const keycloakInstance = keycloakService.getKeycloakInstance(); + const tenant = route.paramMap.get('tenant'); + const queryParams = new URLSearchParams(window.location.search); + const username = queryParams.get('username'); + + if (!keycloakInstance) { + if (!tenant) { + logger.error('[ROUTES] No tenant found, something is wrong...'); + return inject(Router).navigate(['/']); + } + + logger.info('[KEYCLOAK] Keycloak init...'); + await keycloakInitializer(tenant); + logger.info('[KEYCLOAK] Keycloak init done!'); + await tenantsService.selectTenant(tenant); + await usersService.initialize(); + } + + const isLoggedIn = await keycloakService.isLoggedIn(); + + if (isLoggedIn) { + logger.info('[ROUTES] Is logged in, continuing'); + return true; + } + + logger.warn('[ROUTES] Redirect to login'); + keycloakStatusService.createLoginUrlAndExecute(username); + return false; + }; +} diff --git a/apps/red-ui/src/app/modules/account/account-routing.module.ts b/apps/red-ui/src/app/modules/account/account-routing.module.ts index 75e216243..086dd3c89 100644 --- a/apps/red-ui/src/app/modules/account/account-routing.module.ts +++ b/apps/red-ui/src/app/modules/account/account-routing.module.ts @@ -1,10 +1,11 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; -import { CompositeRouteGuard, IqserAuthGuard, IqserPermissionsGuard, IqserRoutes } from '@iqser/common-ui'; +import { CompositeRouteGuard, IqserPermissionsGuard, IqserRoutes } from '@iqser/common-ui'; import { RedRoleGuard } from '@users/red-role.guard'; import { BaseAccountScreenComponent } from './base-account-screen/base-account-screen-component'; import { PreferencesComponent } from './screens/preferences/preferences.component'; import { Roles } from '@users/roles'; +import { IqserAuthGuard } from '@iqser/common-ui/lib/users'; const routes: IqserRoutes = [ { path: '', redirectTo: 'user-profile', pathMatch: 'full' }, diff --git a/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.ts b/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.ts index d337c138c..c21b6346c 100644 --- a/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.ts +++ b/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.ts @@ -1,8 +1,9 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { getCurrentUser, IqserPermissionsService } from '@iqser/common-ui'; +import { IqserPermissionsService } from '@iqser/common-ui'; import { Roles } from '@users/roles'; import { User } from '@red/domain'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; interface NavItem { readonly label: string; diff --git a/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.ts b/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.ts index f80144236..1e3a64e7a 100644 --- a/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.ts +++ b/apps/red-ui/src/app/modules/account/screens/notifications/notifications-screen/notifications-screen.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { NotificationPreferencesService } from '../../../services/notification-preferences.service'; -import { BaseFormComponent, getCurrentUser, LoadingService, Toaster } from '@iqser/common-ui'; +import { BaseFormComponent, LoadingService, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { NotificationCategoriesValues, @@ -12,6 +12,7 @@ import { } from '@red/domain'; import { firstValueFrom } from 'rxjs'; import { notificationsSettingsTranslations } from '@translations/notifications-settings-translations'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; @Component({ templateUrl: './notifications-screen.component.html', @@ -24,6 +25,7 @@ export class NotificationsScreenComponent extends BaseFormComponent implements O readonly notificationGroupsValues = NotificationGroupsValues; readonly translations = notificationsSettingsTranslations; readonly currentUser = getCurrentUser(); + constructor( private readonly _toaster: Toaster, private readonly _formBuilder: UntypedFormBuilder, 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 3ecb9c9cf..765aeeeec 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 @@ -2,8 +2,9 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/ import { PreferencesKeys, UserPreferenceService } from '@users/user-preference.service'; import { FormBuilder, FormGroup } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; -import { AsControl, BaseFormComponent, IqserPermissionsService } from '@iqser/common-ui'; +import { BaseFormComponent, IqserPermissionsService } from '@iqser/common-ui'; import { Roles } from '@users/roles'; +import { AsControl } from '@iqser/common-ui/lib/utils'; interface PreferencesForm { // preferences diff --git a/apps/red-ui/src/app/modules/admin/admin-routing.module.ts b/apps/red-ui/src/app/modules/admin/admin-routing.module.ts index 4abb5739d..0f8631355 100644 --- a/apps/red-ui/src/app/modules/admin/admin-routing.module.ts +++ b/apps/red-ui/src/app/modules/admin/admin-routing.module.ts @@ -1,5 +1,5 @@ import { NgModule } from '@angular/core'; -import { CompositeRouteGuard, IqserAuthGuard, IqserPermissionsGuard, IqserRoutes } from '@iqser/common-ui'; +import { CompositeRouteGuard, IqserPermissionsGuard, IqserRoutes } from '@iqser/common-ui'; import { RedRoleGuard } from '@users/red-role.guard'; import { EntitiesListingScreenComponent } from './screens/entities-listing/entities-listing-screen.component'; import { PendingChangesGuard } from '@guards/can-deactivate.guard'; @@ -18,6 +18,7 @@ import { entityExistsGuard } from '@guards/entity-exists-guard.service'; import { BaseEntityScreenComponent } from './base-entity-screen/base-entity-screen.component'; import { PermissionsGuard } from '@guards/permissions-guard'; import { Roles } from '@users/roles'; +import { IqserAuthGuard } from '@iqser/common-ui/lib/users'; const dossierTemplateIdRoutes: IqserRoutes = [ { 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 8ce9a49ac..e38c6febe 100644 --- a/apps/red-ui/src/app/modules/admin/admin.module.ts +++ b/apps/red-ui/src/app/modules/admin/admin.module.ts @@ -49,13 +49,13 @@ import { IqserHelpModeModule, IqserListingModule, IqserUploadFileModule, - IqserUsersModule, RoundCheckboxComponent, TenantPipe, } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { AuditInfoDialogComponent } from './dialogs/audit-info-dialog/audit-info-dialog.component'; import { DossierTemplateActionsComponent } from './shared/components/dossier-template-actions/dossier-template-actions.component'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; const dialogs = [ AddEditCloneDossierTemplateDialogComponent, diff --git a/apps/red-ui/src/app/modules/admin/base-entity-screen/base-entity-screen.component.ts b/apps/red-ui/src/app/modules/admin/base-entity-screen/base-entity-screen.component.ts index 75a70446f..4e5b7e28e 100644 --- a/apps/red-ui/src/app/modules/admin/base-entity-screen/base-entity-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/base-entity-screen/base-entity-screen.component.ts @@ -4,21 +4,22 @@ import { Router } from '@angular/router'; import { firstValueFrom, Observable } from 'rxjs'; import { AdminDialogService } from '../services/admin-dialog.service'; import { DictionaryService } from '@services/entity-services/dictionary.service'; -import { getParam, LoadingService, TenantsService } from '@iqser/common-ui'; +import { LoadingService, TenantsService } from '@iqser/common-ui'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { map } from 'rxjs/operators'; import { PermissionsService } from '@services/permissions.service'; +import { getParam } from '@iqser/common-ui/lib/utils'; @Component({ templateUrl: './base-entity-screen.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) export class BaseEntityScreenComponent { - readonly disabledItems$: Observable; - readonly canDeleteEntity$: Observable; readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly #entityType = getParam(ENTITY_TYPE); + readonly disabledItems$: Observable; + readonly canDeleteEntity$: Observable; constructor( private readonly _router: Router, diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts index 8950b2780..7222506d5 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts @@ -1,13 +1,14 @@ import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { AdminDialogService } from '../../../services/admin-dialog.service'; -import { BaseFormComponent, IProfileUpdateRequest, LoadingService, Toaster } from '@iqser/common-ui'; +import { BaseFormComponent, LoadingService, Toaster } from '@iqser/common-ui'; import { rolesTranslations } from '@translations/roles-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { User } from '@red/domain'; import { UserService } from '@users/user.service'; import { HttpStatusCode } from '@angular/common/http'; import { firstValueFrom } from 'rxjs'; +import { IProfileUpdateRequest } from '@iqser/common-ui/lib/users'; @Component({ selector: 'redaction-user-details', @@ -15,17 +16,15 @@ import { firstValueFrom } from 'rxjs'; styleUrls: ['./user-details.component.scss'], }) export class UserDetailsComponent extends BaseFormComponent implements OnChanges { + /** e.g. a RED_ADMIN is automatically a RED_USER_ADMIN => can't disable RED_USER_ADMIN as long as RED_ADMIN is checked */ + private readonly _ROLE_REQUIREMENTS = { RED_MANAGER: 'RED_USER', RED_ADMIN: 'RED_USER_ADMIN' }; @Input() user: User; @Output() readonly toggleResetPassword = new EventEmitter(); @Output() readonly closeDialog = new EventEmitter(); @Output() readonly cancel = new EventEmitter(); - readonly ROLES = ['RED_USER', 'RED_MANAGER', 'RED_USER_ADMIN', 'RED_ADMIN']; readonly translations = rolesTranslations; - /** e.g. a RED_ADMIN is automatically a RED_USER_ADMIN => can't disable RED_USER_ADMIN as long as RED_ADMIN is checked */ - private readonly _ROLE_REQUIREMENTS = { RED_MANAGER: 'RED_USER', RED_ADMIN: 'RED_USER_ADMIN' }; - constructor( private readonly _formBuilder: UntypedFormBuilder, private readonly _toaster: Toaster, diff --git a/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts index 37973b4da..14f21dce0 100644 --- a/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts @@ -3,7 +3,6 @@ import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { applyIntervalConstraints } from '@utils/date-inputs-utils'; import { CircleButtonTypes, - getCurrentUser, IqserPermissionsService, ListingComponent, listingProvidersFactory, @@ -19,6 +18,7 @@ import { Dayjs } from 'dayjs'; import { RouterHistoryService } from '@services/router-history.service'; import { Roles } from '@users/roles'; import { AdminDialogService } from '../../services/admin-dialog.service'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; const PAGE_SIZE = 50; @@ -28,6 +28,8 @@ const PAGE_SIZE = 50; providers: listingProvidersFactory(AuditScreenComponent), }) export class AuditScreenComponent extends ListingComponent implements OnInit, OnDestroy { + private _previousFrom: Dayjs; + private _previousTo: Dayjs; readonly circleButtonTypes = CircleButtonTypes; readonly ALL_CATEGORIES = 'allCategories'; readonly ALL_USERS = _('audit-screen.all-users'); @@ -37,11 +39,9 @@ export class AuditScreenComponent extends ListingComponent implements OnI readonly permissionsService = inject(IqserPermissionsService); readonly roles = Roles; readonly currentUser = getCurrentUser(); - categories: string[] = []; userIds: Set; logs: IAuditResponse; - readonly tableColumnConfigs: TableColumnConfig[] = [ { label: _('audit-screen.table-col-names.message') }, { label: _('audit-screen.table-col-names.date') }, @@ -49,8 +49,6 @@ export class AuditScreenComponent extends ListingComponent implements OnI { label: _('audit-screen.table-col-names.category') }, ]; readonly tableHeaderLabel = _('audit-screen.table-header.title'); - private _previousFrom: Dayjs; - private _previousTo: Dayjs; constructor( private readonly _formBuilder: UntypedFormBuilder, diff --git a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts index f111beede..6070e9103 100644 --- a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts @@ -1,21 +1,15 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { DefaultColorTypes, DOSSIER_TEMPLATE_ID, User } from '@red/domain'; import { AdminDialogService } from '../../services/admin-dialog.service'; -import { - CircleButtonTypes, - getCurrentUser, - getParam, - IListable, - ListingComponent, - listingProvidersFactory, - TableColumnConfig, -} from '@iqser/common-ui'; +import { CircleButtonTypes, IListable, ListingComponent, listingProvidersFactory, TableColumnConfig } from '@iqser/common-ui'; import { defaultColorsTranslations } from '@translations/default-colors-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { combineLatest } from 'rxjs'; import { map, tap } from 'rxjs/operators'; import { DefaultColorsService } from '@services/entity-services/default-colors.service'; import { Roles } from '@users/roles'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { getParam } from '@iqser/common-ui/lib/utils'; interface ListItem extends IListable { readonly key: string; @@ -29,6 +23,7 @@ interface ListItem extends IListable { providers: listingProvidersFactory(DefaultColorsScreenComponent), }) export class DefaultColorsScreenComponent extends ListingComponent { + readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly circleButtonTypes = CircleButtonTypes; readonly currentUser = getCurrentUser(); readonly roles = Roles; @@ -39,7 +34,6 @@ export class DefaultColorsScreenComponent extends ListingComponent { { label: _('default-colors-screen.table-col-names.color'), class: 'flex-center' }, ]; readonly context$; - readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); constructor(private readonly _dialogService: AdminDialogService, private readonly _defaultColorsService: DefaultColorsService) { super(); diff --git a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts index 9034f49ee..9f866c301 100644 --- a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core'; -import { getCurrentUser, IconButtonTypes, IqserPermissionsService, LoadingService, Toaster } from '@iqser/common-ui'; +import { IconButtonTypes, IqserPermissionsService, LoadingService, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { RouterHistoryService } from '@services/router-history.service'; import { DigitalSignatureService } from '../../services/digital-signature.service'; @@ -9,6 +9,7 @@ import { PkcsSignatureConfigurationComponent } from '../../dialogs/configure-dig import { KmsSignatureConfigurationComponent } from '../../dialogs/configure-digital-signature-dialog/form/kms-signature-configuration/kms-signature-configuration.component'; import { DigitalSignatureOptions, IKmsDigitalSignatureRequest, IPkcsDigitalSignatureRequest, User } from '@red/domain'; import { Roles } from '@users/roles'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; @Component({ selector: 'redaction-digital-signature-screen', diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts index 08396011c..6719b81c9 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts @@ -2,8 +2,6 @@ import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { CircleButtonTypes, defaultDialogConfig, - getCurrentUser, - getParam, IconButtonTypes, ListingComponent, listingProvidersFactory, @@ -21,6 +19,8 @@ import { AddEditDossierAttributeDialogComponent, AddEditDossierAttributeDialogData, } from './add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { getParam } from '@iqser/common-ui/lib/utils'; @Component({ templateUrl: './dossier-attributes-listing-screen.component.html', @@ -31,6 +31,7 @@ import { }), }) export class DossierAttributesListingScreenComponent extends ListingComponent implements OnInit { + readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly iconButtonTypes = IconButtonTypes; readonly circleButtonTypes = CircleButtonTypes; readonly currentUser = getCurrentUser(); @@ -42,7 +43,6 @@ export class DossierAttributesListingScreenComponent extends ListingComponent; readonly canEditDossierAttributes = this.permissionsService.canEditGlobalDossierAttributes(); - readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); constructor( readonly permissionsService: PermissionsService, diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen/dossier-states-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen/dossier-states-listing-screen.component.ts index b830e8473..e4f3b1cda 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen/dossier-states-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-states-listing/dossier-states-listing-screen/dossier-states-listing-screen.component.ts @@ -1,13 +1,5 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; -import { - defaultDialogConfig, - getParam, - IconButtonTypes, - ListingComponent, - listingProvidersFactory, - SortingOrders, - TableColumnConfig, -} from '@iqser/common-ui'; +import { defaultDialogConfig, IconButtonTypes, ListingComponent, listingProvidersFactory, TableColumnConfig } from '@iqser/common-ui'; import { type DonutChartConfig, DOSSIER_TEMPLATE_ID, type DossierState } from '@red/domain'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { firstValueFrom, Observable } from 'rxjs'; @@ -20,6 +12,8 @@ import { AddEditDossierStateDialogComponent, AddEditDossierStateDialogData, } from '../add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component'; +import { SortingOrders } from '@iqser/common-ui/lib/sorting'; +import { getParam } from '@iqser/common-ui/lib/utils'; @Component({ templateUrl: './dossier-states-listing-screen.component.html', @@ -27,6 +21,7 @@ import { providers: listingProvidersFactory(DossierStatesListingScreenComponent), }) export class DossierStatesListingScreenComponent extends ListingComponent implements OnInit, OnDestroy { + readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly iconButtonTypes = IconButtonTypes; readonly tableHeaderLabel = _('dossier-states-listing.table-header.title'); readonly tableColumnConfigs: TableColumnConfig[] = [ @@ -35,7 +30,6 @@ export class DossierStatesListingScreenComponent extends ListingComponent; - readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); constructor( private readonly _dialog: MatDialog, diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing-screen/dossier-templates-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing-screen/dossier-templates-listing-screen.component.ts index 9ac11e170..1b43f9e0d 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing-screen/dossier-templates-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing-screen/dossier-templates-listing-screen.component.ts @@ -4,7 +4,6 @@ import { AdminDialogService } from '../../../services/admin-dialog.service'; import { DossierTemplate, User } from '@red/domain'; import { CircleButtonTypes, - getCurrentUser, IconButtonTypes, IqserPermissionsService, ListingComponent, @@ -17,6 +16,7 @@ import { RouterHistoryService } from '@services/router-history.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { firstValueFrom } from 'rxjs'; import { Roles } from '@users/roles'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; @Component({ templateUrl: './dossier-templates-listing-screen.component.html', diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing.module.ts b/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing.module.ts index 5334b90e3..b0dc3dc8f 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing.module.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing.module.ts @@ -12,10 +12,10 @@ import { IqserHelpModeModule, IqserListingModule, IqserRoutes, - IqserUsersModule, } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { DossierTemplateActionsComponent } from '../../shared/components/dossier-template-actions/dossier-template-actions.component'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; const routes: IqserRoutes = [{ path: '', component: DossierTemplatesListingScreenComponent }]; diff --git a/apps/red-ui/src/app/modules/admin/screens/entities-listing/entities-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/entities-listing/entities-listing-screen.component.ts index ddebcd371..d5c8537a2 100644 --- a/apps/red-ui/src/app/modules/admin/screens/entities-listing/entities-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/entities-listing/entities-listing-screen.component.ts @@ -1,7 +1,6 @@ import { Component } from '@angular/core'; import { CircleButtonTypes, - getParam, IconButtonTypes, ListingComponent, listingProvidersFactory, @@ -17,6 +16,7 @@ import { DossierTemplateStatsService } from '@services/entity-services/dossier-t import { tap } from 'rxjs/operators'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { PermissionsService } from '@services/permissions.service'; +import { getParam } from '@iqser/common-ui/lib/utils'; @Component({ templateUrl: './entities-listing-screen.component.html', @@ -24,6 +24,7 @@ import { PermissionsService } from '@services/permissions.service'; providers: listingProvidersFactory(EntitiesListingScreenComponent), }) export class EntitiesListingScreenComponent extends ListingComponent { + readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly iconButtonTypes = IconButtonTypes; readonly circleButtonTypes = CircleButtonTypes; readonly tableHeaderLabel = _('entities-listing.table-header.title'); @@ -34,7 +35,6 @@ export class EntitiesListingScreenComponent extends ListingComponent { label: _('entities-listing.table-col-names.dictionary-entries') }, ]; readonly templateStats$: Observable; - readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); constructor( private readonly _loadingService: LoadingService, diff --git a/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts index fc7eda515..c7cbd599b 100644 --- a/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts @@ -2,12 +2,14 @@ import { ChangeDetectionStrategy, Component, OnInit, ViewChild } from '@angular/ import { ActivatedRoute } from '@angular/router'; import { DictionaryManagerComponent } from '@shared/components/dictionary-manager/dictionary-manager.component'; import { DictionaryService } from '@services/entity-services/dictionary.service'; -import { getCurrentUser, getParam, IqserPermissionsService, List, LoadingService } from '@iqser/common-ui'; +import { IqserPermissionsService, LoadingService } from '@iqser/common-ui'; import { BehaviorSubject } from 'rxjs'; import { DICTIONARY_TO_ENTRY_TYPE_MAP, DICTIONARY_TYPE_KEY_MAP, DictionaryType, DOSSIER_TEMPLATE_ID, ENTITY_TYPE, User } from '@red/domain'; import { PermissionsService } from '@services/permissions.service'; import { Roles } from '@users/roles'; import { NGXLogger } from 'ngx-logger'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { getParam, List } from '@iqser/common-ui/lib/utils'; @Component({ templateUrl: './dictionary-screen.component.html', @@ -15,15 +17,15 @@ import { NGXLogger } from 'ngx-logger'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class DictionaryScreenComponent implements OnInit { + readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); + @ViewChild('dictionaryManager', { static: false }) + private readonly _dictionaryManager: DictionaryManagerComponent; readonly currentUser = getCurrentUser(); readonly roles = Roles; readonly initialEntries$ = new BehaviorSubject([]); isLeavingPage = false; readonly type: DictionaryType; readonly entityType = getParam(ENTITY_TYPE); - readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); - @ViewChild('dictionaryManager', { static: false }) - private readonly _dictionaryManager: DictionaryManagerComponent; constructor( route: ActivatedRoute, diff --git a/apps/red-ui/src/app/modules/admin/screens/entities/screens/entity-info/entity-info.component.ts b/apps/red-ui/src/app/modules/admin/screens/entities/screens/entity-info/entity-info.component.ts index 8c123a20d..e992f7d9c 100644 --- a/apps/red-ui/src/app/modules/admin/screens/entities/screens/entity-info/entity-info.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/entities/screens/entity-info/entity-info.component.ts @@ -5,9 +5,10 @@ import { ActivatedRoute } from '@angular/router'; import { getCurrentUser } from '@users/user.service'; import { PermissionsService } from '@services/permissions.service'; import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-edit-entity.component'; -import { IconButtonTypes, IqserEventTarget } from '@iqser/common-ui'; +import { IconButtonTypes } from '@iqser/common-ui'; import { Observable } from 'rxjs'; import { Roles } from '@users/roles'; +import { IqserEventTarget } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-entity-info', @@ -16,14 +17,13 @@ import { Roles } from '@users/roles'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class EntityInfoComponent { + @ViewChild(AddEditEntityComponent) private readonly _addEditEntityComponent: AddEditEntityComponent; readonly currentUser = getCurrentUser(); readonly entity$: Observable; readonly dossierTemplateId: string; readonly roles = Roles; readonly iconButtonTypes = IconButtonTypes; - @ViewChild(AddEditEntityComponent) private readonly _addEditEntityComponent: AddEditEntityComponent; - constructor(route: ActivatedRoute, dictionariesMapService: DictionariesMapService, readonly permissionsService: PermissionsService) { this.dossierTemplateId = route.parent.snapshot.paramMap.get(DOSSIER_TEMPLATE_ID); const entityType = route.parent.snapshot.paramMap.get(ENTITY_TYPE); diff --git a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts index 010bdaa8a..19abe8403 100644 --- a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts @@ -4,11 +4,12 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import * as Papa from 'papaparse'; import { firstValueFrom, Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; -import { IconButtonTypes, ListingComponent, listingProvidersFactory, TableColumnConfig, Toaster, trackByFactory } from '@iqser/common-ui'; +import { IconButtonTypes, ListingComponent, listingProvidersFactory, TableColumnConfig, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { FileAttributeConfig, FileAttributeConfigTypes, FileAttributeEncodingTypes, IField, IFileAttributesConfig } from '@red/domain'; import { FileAttributesService } from '@services/entity-services/file-attributes.service'; import { fileAttributeEncodingTypesTranslations } from '@translations/file-attribute-encoding-types-translations'; +import { trackByFactory } from '@iqser/common-ui/lib/utils'; export interface IFileAttributesCSVImportData { readonly csv: File; diff --git a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts index cf2f27b83..32d704f4e 100644 --- a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts @@ -3,8 +3,6 @@ import { AdminDialogService } from '../../services/admin-dialog.service'; import { CircleButtonTypes, defaultDialogConfig, - getCurrentUser, - getParam, IconButtonTypes, largeDialogConfig, ListingComponent, @@ -32,6 +30,8 @@ import { IFileAttributesCSVImportData, } from './file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component'; import { FileAttributesConfigurationsDialogComponent } from './file-attributes-configurations-dialog/file-attributes-configurations-dialog.component'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { getParam } from '@iqser/common-ui/lib/utils'; @Component({ templateUrl: './file-attributes-listing-screen.component.html', @@ -39,6 +39,10 @@ import { FileAttributesConfigurationsDialogComponent } from './file-attributes-c providers: listingProvidersFactory(FileAttributesListingScreenComponent), }) export class FileAttributesListingScreenComponent extends ListingComponent implements OnInit, OnDestroy { + @ViewChild('impactedTemplates') private readonly _impactedTemplatesRef: TemplateRef; + #existingConfiguration: IFileAttributesConfig; + @ViewChild('fileInput') private _fileInput: ElementRef; + readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly iconButtonTypes = IconButtonTypes; readonly circleButtonTypes = CircleButtonTypes; readonly currentUser = getCurrentUser(); @@ -59,18 +63,6 @@ export class FileAttributesListingScreenComponent extends ListingComponent; - #existingConfiguration: IFileAttributesConfig; - @ViewChild('fileInput') private _fileInput: ElementRef; - readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); - - private get _numberOfDisplayedAttrs(): number { - return this.entitiesService.all.filter(attr => attr.displayedInFileList).length; - } - - private get _numberOfFilterableAttrs(): number { - return this.entitiesService.all.filter(attr => attr.filterable).length; - } constructor( readonly permissionsService: PermissionsService, @@ -84,6 +76,14 @@ export class FileAttributesListingScreenComponent extends ListingComponent attr.displayedInFileList).length; + } + + private get _numberOfFilterableAttrs(): number { + return this.entitiesService.all.filter(attr => attr.filterable).length; + } + async ngOnInit() { await this.#loadData(); } diff --git a/apps/red-ui/src/app/modules/admin/screens/general-config/system-preferences-form/system-preferences-form.component.ts b/apps/red-ui/src/app/modules/admin/screens/general-config/system-preferences-form/system-preferences-form.component.ts index 000ac9054..44f01f82a 100644 --- a/apps/red-ui/src/app/modules/admin/screens/general-config/system-preferences-form/system-preferences-form.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/general-config/system-preferences-form/system-preferences-form.component.ts @@ -1,10 +1,11 @@ import { Component } from '@angular/core'; -import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { UntypedFormBuilder, Validators } from '@angular/forms'; import { SystemPreferences } from '@red/domain'; -import { BaseFormComponent, IqserPermissionsService, KeysOf, LoadingService } from '@iqser/common-ui'; +import { BaseFormComponent, IqserPermissionsService, LoadingService } from '@iqser/common-ui'; import { SystemPreferencesService } from '@services/system-preferences.service'; import { systemPreferencesTranslations } from '@translations/system-preferences-translations'; import { Roles } from '@users/roles'; +import { KeysOf } from '@iqser/common-ui/lib/utils'; export type ValueType = 'number' | 'string' | 'boolean'; @@ -13,24 +14,24 @@ export type ValueType = 'number' | 'string' | 'boolean'; templateUrl: './system-preferences-form.component.html', }) export class SystemPreferencesFormComponent extends BaseFormComponent { + #initialConfiguration: SystemPreferences; readonly translations = systemPreferencesTranslations; readonly keys: { name: KeysOf; type: ValueType }[] = [ { name: 'softDeleteCleanupTime', type: 'number' }, { name: 'downloadCleanupNotDownloadFilesHours', type: 'number' }, { name: 'downloadCleanupDownloadFilesHours', type: 'number' }, ]; - private _initialConfiguration: SystemPreferences; constructor( private readonly _loadingService: LoadingService, private readonly _systemPreferencesService: SystemPreferencesService, private readonly _formBuilder: UntypedFormBuilder, - private readonly _permissionsService: IqserPermissionsService, + permissionsService: IqserPermissionsService, ) { super(); - this.form = this._getForm(); - this._loadData(); - if (!_permissionsService.has(Roles.appConfiguration.write)) { + this.form = this.#getForm(); + this.#loadData(); + if (!permissionsService.has(Roles.appConfiguration.write)) { this.form.disable(); } } @@ -38,19 +39,21 @@ export class SystemPreferencesFormComponent extends BaseFormComponent { async save(): Promise { this._loadingService.start(); await this._systemPreferencesService.update(this.form.getRawValue()); - this._loadData(); + this.#loadData(); this._loadingService.stop(); } - private _getForm(): UntypedFormGroup { + #getForm() { const controlsConfig = {}; - this.keys.forEach(key => (controlsConfig[key.name] = [this._systemPreferencesService.values[key.name], Validators.required])); + this.keys.forEach(key => { + controlsConfig[key.name] = [this._systemPreferencesService.values[key.name], Validators.required]; + }); return this._formBuilder.group(controlsConfig); } - private _loadData() { - this._initialConfiguration = this._systemPreferencesService.values; - this.form.patchValue(this._initialConfiguration, { emitEvent: false }); + #loadData() { + this.#initialConfiguration = this._systemPreferencesService.values; + this.form.patchValue(this.#initialConfiguration, { emitEvent: false }); this.initialFormValue = this.form.getRawValue(); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-info.module.ts b/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-info.module.ts index f4ad7c25d..6c2f49351 100644 --- a/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-info.module.ts +++ b/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-info.module.ts @@ -3,8 +3,9 @@ import { CommonModule } from '@angular/common'; import { DossierTemplateInfoScreenComponent } from './info-screen/dossier-template-info-screen.component'; import { RouterModule } from '@angular/router'; import { SharedModule } from '@shared/shared.module'; -import { HasScrollbarDirective, IqserHelpModeModule, IqserUsersModule } from '@iqser/common-ui'; +import { HasScrollbarDirective, IqserHelpModeModule } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; const routes = [{ path: '', component: DossierTemplateInfoScreenComponent }]; diff --git a/apps/red-ui/src/app/modules/admin/screens/info/info-screen/dossier-template-info-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/info/info-screen/dossier-template-info-screen.component.ts index e6d940119..e50143cbe 100644 --- a/apps/red-ui/src/app/modules/admin/screens/info/info-screen/dossier-template-info-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/info/info-screen/dossier-template-info-screen.component.ts @@ -3,7 +3,7 @@ import { DossierTemplatesService } from '@services/dossier-templates/dossier-tem import { DOSSIER_TEMPLATE_ID, type DossierTemplate, type DossierTemplateStats } from '@red/domain'; import { DossierTemplateStatsService } from '@services/entity-services/dossier-template-stats.service'; import { dossierTemplateStatusTranslations } from '@translations/dossier-template-status-translations'; -import { ContextComponent, getParam } from '@iqser/common-ui'; +import { ContextComponent, getParam } from '@iqser/common-ui/lib/utils'; interface Context { readonly dossierTemplate: DossierTemplate; diff --git a/apps/red-ui/src/app/modules/admin/screens/justifications/justifications-screen/justifications-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/justifications/justifications-screen/justifications-screen.component.ts index 59e11f857..3206b2837 100644 --- a/apps/red-ui/src/app/modules/admin/screens/justifications/justifications-screen/justifications-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/justifications/justifications-screen/justifications-screen.component.ts @@ -2,12 +2,10 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { CircleButtonTypes, - getParam, IconButtonTypes, ListingComponent, listingProvidersFactory, LoadingService, - SortingOrders, TableColumnConfig, } from '@iqser/common-ui'; import { DOSSIER_TEMPLATE_ID, Justification } from '@red/domain'; @@ -16,6 +14,8 @@ import { JustificationsDialogService } from '../justifications-dialog.service'; import { UserPreferenceService } from '@users/user-preference.service'; import { firstValueFrom } from 'rxjs'; import { PermissionsService } from '@services/permissions.service'; +import { SortingOrders } from '@iqser/common-ui/lib/sorting'; +import { getParam } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-justifications-screen', @@ -28,6 +28,7 @@ import { PermissionsService } from '@services/permissions.service'; }), }) export class JustificationsScreenComponent extends ListingComponent implements OnInit { + readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly iconButtonTypes = IconButtonTypes; readonly circleButtonTypes = CircleButtonTypes; readonly tableHeaderLabel = _('justifications-listing.table-header'); @@ -37,7 +38,6 @@ export class JustificationsScreenComponent extends ListingComponent implements OnDestroy { + readonly #subscription: Subscription = new Subscription(); readonly roles = Roles; readonly currentUser = getCurrentUser(); readonly translations = permissionsTranslations; @@ -34,7 +29,6 @@ export class PermissionsScreenComponent extends ListingComponent([]); readonly availableTemplates$ = new BehaviorSubject([]); readonly currentUser = getCurrentUser(); readonly roles = Roles; - @ViewChild('fileInput') private readonly _fileInput: ElementRef; - readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); constructor( private readonly _reportTemplateService: ReportTemplateService, diff --git a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.ts index c819bdd82..ef81e18c5 100644 --- a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { PermissionsService } from '@services/permissions.service'; -import { Debounce, getParam, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui'; +import { IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui'; import { saveAs } from 'file-saver'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { RulesService } from '../../../services/rules.service'; @@ -8,6 +8,7 @@ import { firstValueFrom } from 'rxjs'; import { DOSSIER_TEMPLATE_ID } from '@red/domain'; import { EditorThemeService } from '@services/editor-theme.service'; import { ComponentCanDeactivate } from '@guards/can-deactivate.guard'; +import { Debounce, getParam } from '@iqser/common-ui/lib/utils'; import ICodeEditor = monaco.editor.ICodeEditor; import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration; import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions; @@ -18,6 +19,11 @@ import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorCon changeDetection: ChangeDetectionStrategy.OnPush, }) export class RulesScreenComponent implements OnInit, ComponentCanDeactivate { + @ViewChild('fileInput') + private _fileInput: ElementRef; + private _codeEditor: ICodeEditor; + private _decorations: string[] = []; + readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly iconButtonTypes = IconButtonTypes; readonly editorOptions: IStandaloneEditorConstructionOptions = { theme: 'vs', @@ -25,19 +31,10 @@ export class RulesScreenComponent implements OnInit, ComponentCanDeactivate { automaticLayout: true, readOnly: !this.permissionsService.canEditRules(), }; - initialLines: string[] = []; currentLines: string[] = []; - isLeaving = false; - @ViewChild('fileInput') - private _fileInput: ElementRef; - - private _codeEditor: ICodeEditor; - private _decorations: string[] = []; - readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); - constructor( readonly permissionsService: PermissionsService, private readonly _rulesService: RulesService, diff --git a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts index 7ab70f3bf..c002cf300 100644 --- a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts @@ -11,7 +11,6 @@ import { ListingComponent, listingProvidersFactory, LoadingService, - NestedFilter, SearchPositions, TableColumnConfig, } from '@iqser/common-ui'; @@ -22,6 +21,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { userTypeChecker, userTypeFilters } from '../../../../utils'; import { RouterHistoryService } from '@services/router-history.service'; import { Roles } from '@users/roles'; +import { NestedFilter } from '@iqser/common-ui/lib/filtering'; function configToFilter({ key, label }: DonutChartConfig) { return new NestedFilter({ diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts index 4a2f7c1e3..e8e87ef69 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts @@ -2,20 +2,7 @@ import { ChangeDetectorRef, Component, ElementRef, inject, OnInit, ViewChild } f import WebViewer, { WebViewerInstance } from '@pdftron/webviewer'; import { HttpClient } from '@angular/common/http'; import { FormBuilder, FormGroup } from '@angular/forms'; -import { - AsControl, - BASE_HREF_FN, - Debounce, - getConfig, - getCurrentUser, - getParam, - IconButtonTypes, - IqserPermissionsService, - LoadingService, - TenantsService, - Toaster, - trackByFactory, -} from '@iqser/common-ui'; +import { getConfig, IconButtonTypes, IqserPermissionsService, LoadingService, TenantsService, Toaster } from '@iqser/common-ui'; import { AppConfig, DOSSIER_TEMPLATE_ID, @@ -42,6 +29,8 @@ import { Roles } from '@users/roles'; import { environment } from '@environments/environment'; import { tap } from 'rxjs/operators'; import { watermarkTranslations } from '@translations/watermark-translations'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { AsControl, BASE_HREF_FN, Debounce, getParam, trackByFactory } from '@iqser/common-ui/lib/utils'; export const DEFAULT_WATERMARK: Partial = { text: 'Watermark', @@ -72,6 +61,13 @@ interface WatermarkForm { styleUrls: ['./watermark-screen.component.scss'], }) export class WatermarkScreenComponent implements OnInit { + @ViewChild('viewer', { static: true }) private readonly _viewer: ElementRef; + private readonly _convertPath = inject(BASE_HREF_FN); + readonly #loaded$ = new BehaviorSubject(false); + readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); + readonly #watermarkId = Number(getParam(WATERMARK_ID)); + readonly #config = getConfig(); + #watermark: Partial = {}; readonly iconButtonTypes = IconButtonTypes; readonly translations = watermarkTranslations; readonly trackBy = trackByFactory(); @@ -89,13 +85,6 @@ export class WatermarkScreenComponent implements OnInit { readonly watermarkHorizontalAlignments = Object.values(WATERMARK_HORIZONTAL_ALIGNMENTS); readonly watermarkVerticalAlignments = Object.values(WATERMARK_VERTICAL_ALIGNMENTS); currentAlignment: WatermarkAlignment; - @ViewChild('viewer', { static: true }) private readonly _viewer: ElementRef; - private readonly _convertPath = inject(BASE_HREF_FN); - readonly #loaded$ = new BehaviorSubject(false); - readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); - readonly #watermarkId = Number(getParam(WATERMARK_ID)); - readonly #config = getConfig(); - #watermark: Partial = {}; constructor( private readonly _http: HttpClient, diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark.module.ts b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark.module.ts index dc3eabe70..d169929dd 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark.module.ts +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark.module.ts @@ -9,11 +9,9 @@ import { HasScrollbarDirective, IconButtonComponent, IqserAllowDirective, - IqserAuthGuard, IqserHelpModeModule, IqserListingModule, IqserRoutes, - IqserUsersModule, TenantPipe, } from '@iqser/common-ui'; import { RedRoleGuard } from '@users/red-role.guard'; @@ -27,6 +25,7 @@ import { MatSliderModule } from '@angular/material/slider'; import { ColorPickerModule } from 'ngx-color-picker'; import { MatTooltipModule } from '@angular/material/tooltip'; import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { IqserAuthGuard, IqserUsersModule } from '@iqser/common-ui/lib/users'; const routes: IqserRoutes = [ { diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermarks-listing/watermarks-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/watermark/watermarks-listing/watermarks-listing-screen.component.ts index b4590f6ea..8a5602b84 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermarks-listing/watermarks-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermarks-listing/watermarks-listing-screen.component.ts @@ -1,8 +1,6 @@ import { Component } from '@angular/core'; import { CircleButtonTypes, - getCurrentUser, - getParam, IconButtonTypes, IConfirmationDialogData, IqserPermissionsService, @@ -18,6 +16,8 @@ import { WatermarkService } from '@services/entity-services/watermark.service'; import { AdminDialogService } from '../../../services/admin-dialog.service'; import { WatermarksMapService } from '@services/entity-services/watermarks-map.service'; import { Roles } from '@users/roles'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { getParam } from '@iqser/common-ui/lib/utils'; @Component({ templateUrl: './watermarks-listing-screen.component.html', @@ -25,6 +25,7 @@ import { Roles } from '@users/roles'; providers: listingProvidersFactory(WatermarksListingScreenComponent), }) export class WatermarksListingScreenComponent extends ListingComponent { + readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly iconButtonTypes = IconButtonTypes; readonly circleButtonTypes = CircleButtonTypes; readonly currentUser = getCurrentUser(); @@ -37,7 +38,6 @@ export class WatermarksListingScreenComponent extends ListingComponent { 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 8a2fcccea..e755d7e1a 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 @@ -5,9 +5,10 @@ import { adminSideNavTranslations } from '@translations/admin-side-nav-translati import { ActivatedRoute, RouterLink, RouterLinkActive } from '@angular/router'; import { AdminSideNavType, AdminSideNavTypes, DOSSIER_TEMPLATE_ID, ENTITY_TYPE, User, WATERMARK_ID } from '@red/domain'; import { Roles } from '@users/roles'; -import { getCurrentUser, IqserHelpModeModule, IqserPermissionsService, SideNavComponent, TenantPipe } from '@iqser/common-ui'; +import { IqserHelpModeModule, IqserPermissionsService, SideNavComponent, TenantPipe } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { NgForOf, NgIf } from '@angular/common'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; interface NavItem { readonly label: string; diff --git a/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.ts b/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.ts index 021c15f89..4b72cf055 100644 --- a/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.ts +++ b/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.ts @@ -1,19 +1,13 @@ import { Component, Input, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { AdminDialogService } from '../../../services/admin-dialog.service'; -import { - CircleButtonComponent, - CircleButtonTypes, - getCurrentUser, - IqserHelpModeModule, - LoadingService, - TenantsService, -} from '@iqser/common-ui'; +import { CircleButtonComponent, CircleButtonTypes, IqserHelpModeModule, LoadingService, TenantsService } from '@iqser/common-ui'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { firstValueFrom } from 'rxjs'; import { DOSSIER_TEMPLATE_ID, type User } from '@red/domain'; import { NgIf } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; @Component({ selector: 'redaction-dossier-template-actions', diff --git a/apps/red-ui/src/app/modules/archive/archive.module.ts b/apps/red-ui/src/app/modules/archive/archive.module.ts index 32f4c7725..ec6dd7e41 100644 --- a/apps/red-ui/src/app/modules/archive/archive.module.ts +++ b/apps/red-ui/src/app/modules/archive/archive.module.ts @@ -4,10 +4,11 @@ import { ArchivedDossiersScreenComponent } from './screens/archived-dossiers-scr import { ArchiveRoutingModule } from './archive-routing.module'; import { TableItemComponent } from './components/table-item/table-item.component'; import { ConfigService } from './services/config.service'; -import { IqserHelpModeModule, IqserListingModule, IqserUsersModule } from '@iqser/common-ui'; +import { IqserHelpModeModule, IqserListingModule } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { SharedModule } from '@shared/shared.module'; import { SharedDossiersModule } from '../shared-dossiers/shared-dossiers.module'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; @NgModule({ declarations: [TableItemComponent, ArchivedDossiersScreenComponent], diff --git a/apps/red-ui/src/app/modules/archive/services/config.service.ts b/apps/red-ui/src/app/modules/archive/services/config.service.ts index d7b74694a..5655dbf0c 100644 --- a/apps/red-ui/src/app/modules/archive/services/config.service.ts +++ b/apps/red-ui/src/app/modules/archive/services/config.service.ts @@ -1,11 +1,12 @@ import { Injectable } from '@angular/core'; -import { IFilterGroup, keyChecker, NestedFilter, TableColumnConfig } from '@iqser/common-ui'; +import { TableColumnConfig } from '@iqser/common-ui'; import { Dossier, User } from '@red/domain'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { dossierMemberChecker, dossierMemberQuickChecker, dossierOwnerQuickChecker, dossierTemplateChecker } from '@utils/index'; import { UserService } from '@users/user.service'; import { TranslateService } from '@ngx-translate/core'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; +import { IFilterGroup, keyChecker, NestedFilter } from '@iqser/common-ui/lib/filtering'; @Injectable() export class ConfigService { diff --git a/apps/red-ui/src/app/modules/dashboard/dashboard-screen/dashboard-screen.component.ts b/apps/red-ui/src/app/modules/dashboard/dashboard-screen/dashboard-screen.component.ts index 7ebd51e3c..69a16dcee 100644 --- a/apps/red-ui/src/app/modules/dashboard/dashboard-screen/dashboard-screen.component.ts +++ b/apps/red-ui/src/app/modules/dashboard/dashboard-screen/dashboard-screen.component.ts @@ -1,8 +1,9 @@ import { Component, inject, OnInit } from '@angular/core'; import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service'; import { UserPreferenceService } from '@users/user-preference.service'; -import { getCurrentUser, trackByFactory } from '@iqser/common-ui'; +import { trackByFactory } from '@iqser/common-ui/lib/utils'; import { User } from '@red/domain'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; @Component({ templateUrl: './dashboard-screen.component.html', diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts index 4b04618b6..eb401f1d0 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts @@ -13,16 +13,7 @@ import { } from '@red/domain'; import { TranslateChartService } from '@services/translate-chart.service'; import { UserService } from '@users/user.service'; -import { - ContextComponent, - FilterService, - getCurrentUser, - getParam, - INestedFilter, - ProgressBarConfigModel, - shareLast, - Toaster, -} from '@iqser/common-ui'; +import { ProgressBarConfigModel, Toaster } from '@iqser/common-ui'; import { workflowFileStatusTranslations } from '@translations/file-status-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { combineLatestWith, firstValueFrom } from 'rxjs'; @@ -31,6 +22,9 @@ import { map, tap } from 'rxjs/operators'; import { DossiersService } from '@services/dossiers/dossiers.service'; import { FilesMapService } from '@services/files/files-map.service'; import { Roles } from '@users/roles'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { FilterService, INestedFilter } from '@iqser/common-ui/lib/filtering'; +import { ContextComponent, getParam, shareLast } from '@iqser/common-ui/lib/utils'; interface DossierDetailsContext { needsWorkFilters: INestedFilter[] | undefined; @@ -45,17 +39,16 @@ interface DossierDetailsContext { styleUrls: ['./dossier-details.component.scss'], }) export class DossierDetailsComponent extends ContextComponent { + #currentChartSubtitleIndex = 0; + readonly #dossierId = getParam(DOSSIER_ID); @Input() dossierAttributes: DossierAttributeWithValue[]; @Output() readonly toggleCollapse = new EventEmitter(); - editingOwner = false; readonly roles = Roles; readonly currentUser = getCurrentUser(); readonly collapseTooltip = _('dossier-details.collapse'); readonly expandTooltip = _('dossier-details.expand'); chartConfig: DonutChartConfig[] = []; - #currentChartSubtitleIndex = 0; - readonly #dossierId = getParam(DOSSIER_ID); constructor( private readonly _toaster: Toaster, diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts index 138bf667c..41e30706e 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts @@ -3,11 +3,8 @@ import { ActionConfig, CircleButtonTypes, EntitiesService, - List, ListingService, LoadingService, - some, - SortingService, TenantsService, Toaster, } from '@iqser/common-ui'; @@ -22,6 +19,8 @@ import { ConfigService } from '../../config.service'; import { PrimaryFileAttributeService } from '@services/primary-file-attribute.service'; import { Router } from '@angular/router'; import { Roles } from '@users/roles'; +import { SortingService } from '@iqser/common-ui/lib/sorting'; +import { List, some } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-dossier-overview-screen-header [dossier] [upload]', diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.ts index 525ada944..6fe2cb184 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.ts @@ -1,6 +1,7 @@ import { ChangeDetectorRef, Component, ElementRef, Input, OnInit, Optional, ViewChild } from '@angular/core'; import { Dossier, File, IFileAttributeConfig } from '@red/domain'; -import { Debounce, HelpModeService } from '@iqser/common-ui'; +import { HelpModeService } from '@iqser/common-ui'; +import { Debounce } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-workflow-item [file] [dossier] [displayedAttributes]', @@ -8,13 +9,12 @@ import { Debounce, HelpModeService } from '@iqser/common-ui'; styleUrls: ['./workflow-item.component.scss'], }) export class WorkflowItemComponent implements OnInit { + @ViewChild('actionsWrapper', { static: true }) private _actionsWrapper: ElementRef; @Input() file: File; @Input() dossier: Dossier; @Input() displayedAttributes: IFileAttributeConfig[]; width: number; - @ViewChild('actionsWrapper', { static: true }) private _actionsWrapper: ElementRef; - constructor(private readonly _changeRef: ChangeDetectorRef, @Optional() readonly helpModeService: HelpModeService) {} ngOnInit(): void { diff --git a/apps/red-ui/src/app/modules/dossier-overview/config.service.ts b/apps/red-ui/src/app/modules/dossier-overview/config.service.ts index 560b633f6..938b32f30 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/config.service.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/config.service.ts @@ -2,16 +2,9 @@ import { Injectable, TemplateRef } from '@angular/core'; import { ActionConfig, getConfig, - getCurrentUser, - getParam, - IFilterGroup, - INestedFilter, IqserPermissionsService, - keyChecker, - List, ListingMode, ListingModes, - NestedFilter, TableColumnConfig, WorkflowColumn, WorkflowConfig, @@ -46,6 +39,9 @@ import { DictionariesMapService } from '@services/entity-services/dictionaries-m import { UserPreferenceService } from '@users/user-preference.service'; import { DossiersService } from '@services/dossiers/dossiers.service'; import { Roles } from '@users/roles'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { IFilterGroup, INestedFilter, keyChecker, NestedFilter } from '@iqser/common-ui/lib/filtering'; +import { getParam, List } from '@iqser/common-ui/lib/utils'; @Injectable() export class ConfigService { diff --git a/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts b/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts index 230792a1c..dc17c9be2 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts @@ -10,7 +10,6 @@ import { IqserListingModule, IqserLoadingModule, IqserRoutes, - IqserUsersModule, StatusBarComponent, StopPropagationDirective, TenantPipe, @@ -28,6 +27,7 @@ import { DossierOverviewScreenHeaderComponent } from './components/screen-header import { ViewModeSelectionComponent } from './components/view-mode-selection/view-mode-selection.component'; import { FileAttributeComponent } from './components/file-attribute/file-attribute.component'; import { SharedModule } from '@shared/shared.module'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; const routes: IqserRoutes = [ { diff --git a/apps/red-ui/src/app/modules/dossier-overview/screen/dossier-overview-screen.component.ts b/apps/red-ui/src/app/modules/dossier-overview/screen/dossier-overview-screen.component.ts index 4b75aebf2..9563a1cca 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/screen/dossier-overview-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/screen/dossier-overview-screen.component.ts @@ -19,16 +19,11 @@ import { CircleButtonTypes, CustomError, ErrorService, - getParam, IqserPermissionsService, ListingComponent, ListingModes, listingProvidersFactory, LoadingService, - NestedFilter, - OnAttach, - OnDetach, - shareLast, TableColumnConfig, TableComponent, WorkflowConfig, @@ -46,6 +41,8 @@ import { BulkActionsService } from '../services/bulk-actions.service'; import { DossiersService } from '@services/dossiers/dossiers.service'; import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider'; import { Roles } from '@users/roles'; +import { NestedFilter } from '@iqser/common-ui/lib/filtering'; +import { getParam, OnAttach, OnDetach, shareLast } from '@iqser/common-ui/lib/utils'; @Component({ templateUrl: './dossier-overview-screen.component.html', diff --git a/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-documents-status/dossier-documents-status.component.ts b/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-documents-status/dossier-documents-status.component.ts index 6a4e855f7..fc932f3ac 100644 --- a/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-documents-status/dossier-documents-status.component.ts +++ b/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-documents-status/dossier-documents-status.component.ts @@ -1,6 +1,7 @@ import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; import { DossierStats, StatusSorter } from '@red/domain'; -import { List, StatusBarConfig } from '@iqser/common-ui'; +import { StatusBarConfig } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-dossier-documents-status', diff --git a/apps/red-ui/src/app/modules/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.ts b/apps/red-ui/src/app/modules/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.ts index 283137f18..f5acb2e40 100644 --- a/apps/red-ui/src/app/modules/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.ts +++ b/apps/red-ui/src/app/modules/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.ts @@ -4,7 +4,7 @@ import { Observable } from 'rxjs'; import { TranslateChartService } from '@services/translate-chart.service'; import { map } from 'rxjs/operators'; import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service'; -import { getParam } from '@iqser/common-ui'; +import { getParam } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-dossiers-listing-details', diff --git a/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts b/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts index a71840a67..277a5613f 100644 --- a/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts +++ b/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts @@ -1,13 +1,5 @@ import { Injectable, TemplateRef } from '@angular/core'; -import { - ButtonConfig, - IFilterGroup, - INestedFilter, - keyChecker, - NestedFilter, - OverlappingElements, - TableColumnConfig, -} from '@iqser/common-ui'; +import { ButtonConfig, TableColumnConfig } from '@iqser/common-ui'; import { annotationDefaultColorConfig, AnnotationShapeMap, @@ -35,6 +27,7 @@ import { DossierStatesMapService } from '@services/entity-services/dossier-state import { PermissionsService } from '@services/permissions.service'; import { SharedDialogService } from '@shared/services/dialog.service'; import { DefaultColorsService } from '@services/entity-services/default-colors.service'; +import { IFilterGroup, INestedFilter, keyChecker, NestedFilter } from '@iqser/common-ui/lib/filtering'; @Injectable() export class ConfigService { diff --git a/apps/red-ui/src/app/modules/dossiers-listing/dossiers-listing.module.ts b/apps/red-ui/src/app/modules/dossiers-listing/dossiers-listing.module.ts index 5033d8fe1..aec7245db 100644 --- a/apps/red-ui/src/app/modules/dossiers-listing/dossiers-listing.module.ts +++ b/apps/red-ui/src/app/modules/dossiers-listing/dossiers-listing.module.ts @@ -6,7 +6,6 @@ import { IqserHelpModeModule, IqserListingModule, IqserRoutes, - IqserUsersModule, StatusBarComponent, } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; @@ -21,6 +20,7 @@ import { DossierWorkloadColumnComponent } from './components/dossier-workload-co import { DossierDocumentsStatusComponent } from './components/dossier-documents-status/dossier-documents-status.component'; import { DossierFilesGuard } from '@guards/dossier-files-guard'; import { ACTIVE_DOSSIERS_SERVICE } from '../../tokens'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; const routes: IqserRoutes = [ { 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 1ca7f7ddf..32ad8ec0e 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,7 +1,7 @@ import { ChangeDetectionStrategy, Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { Dossier, DOSSIER_TEMPLATE_ID, DossierTemplate } from '@red/domain'; import { PermissionsService } from '@services/permissions.service'; -import { ButtonConfig, ListingComponent, listingProvidersFactory, OnAttach, TableComponent } from '@iqser/common-ui'; +import { ButtonConfig, ListingComponent, listingProvidersFactory, TableComponent } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { ConfigService } from '../config.service'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; @@ -10,6 +10,7 @@ import { Router } from '@angular/router'; 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'; @Component({ templateUrl: './dossiers-listing-screen.component.html', @@ -18,17 +19,17 @@ import { DossierTemplatesService } from '@services/dossier-templates/dossier-tem changeDetection: ChangeDetectionStrategy.OnPush, }) export class DossiersListingScreenComponent extends ListingComponent implements OnInit, OnAttach { - readonly tableColumnConfigs = this._configService.tableConfig; - readonly tableHeaderLabel = _('dossier-listing.table-header.title'); - readonly buttonConfigs: ButtonConfig[]; - readonly dossierTemplate: DossierTemplate; - readonly computeFilters$ = this._activeDossiersService.all$.pipe(tap(() => this._computeAllFilters())); @ViewChild('needsWorkFilterTemplate', { read: TemplateRef, static: true, }) private readonly _needsWorkFilterTemplate: TemplateRef; @ViewChild(TableComponent) private readonly _tableComponent: TableComponent; + readonly tableColumnConfigs = this._configService.tableConfig; + readonly tableHeaderLabel = _('dossier-listing.table-header.title'); + readonly buttonConfigs: ButtonConfig[]; + readonly dossierTemplate: DossierTemplate; + readonly computeFilters$ = this._activeDossiersService.all$.pipe(tap(() => this._computeAllFilters())); constructor( router: Router, diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-details/annotation-details.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotation-details/annotation-details.component.ts index d5266d823..4da630864 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-details/annotation-details.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-details/annotation-details.component.ts @@ -3,9 +3,9 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { TranslateService } from '@ngx-translate/core'; import { annotationChangesTranslations } from '@translations/annotation-changes-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { KeysOf } from '@iqser/common-ui'; import { ListItem } from '@models/file/list-item'; import { MultiSelectService } from '../../services/multi-select.service'; +import { KeysOf } from '@iqser/common-ui/lib/utils'; interface Engine { readonly icon: string; @@ -41,16 +41,14 @@ const changesProperties: KeysOf[] = [ styleUrls: ['./annotation-details.component.scss'], }) export class AnnotationDetailsComponent implements OnChanges { + private readonly _translateService = inject(TranslateService); + private readonly _multiSelectService = inject(MultiSelectService); @Input() annotation: ListItem; isPopoverOpen = false; - engines: Engine[]; changesTooltip: string; noSelection: boolean; - private readonly _translateService = inject(TranslateService); - private readonly _multiSelectService = inject(MultiSelectService); - getChangesTooltip(): string | undefined { const changes = changesProperties.filter(key => this.annotation.item[key]); diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts index bd4a8a323..bf06d514a 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectorRef, Component, computed, ElementRef, EventEmitter, Input, OnChanges, Output } from '@angular/core'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { FilterService, HasScrollbarDirective, IqserEventTarget } from '@iqser/common-ui'; +import { HasScrollbarDirective } from '@iqser/common-ui'; import { MultiSelectService } from '../../services/multi-select.service'; import { AnnotationReferencesService } from '../../services/annotation-references.service'; import { UserPreferenceService } from '@users/user-preference.service'; @@ -9,6 +9,8 @@ import { EarmarkGroup } from '@red/domain'; import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service'; import { AnnotationsListingService } from '../../services/annotations-listing.service'; import { ListItem } from '@models/file/list-item'; +import { FilterService } from '@iqser/common-ui/lib/filtering'; +import { IqserEventTarget } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-annotations-list', @@ -16,15 +18,14 @@ import { ListItem } from '@models/file/list-item'; styleUrls: ['./annotations-list.component.scss'], }) export class AnnotationsListComponent extends HasScrollbarDirective implements OnChanges { - @Input() annotations: ListItem[]; - @Output() readonly pagesPanelActive = new EventEmitter(); - readonly #earmarkGroups = computed(() => { if (this._viewModeService.isEarmarks()) { return this.#getEarmarksGroups(); } return [] as EarmarkGroup[]; }); + @Input() annotations: ListItem[]; + @Output() readonly pagesPanelActive = new EventEmitter(); constructor( protected readonly _elementRef: ElementRef, diff --git a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.ts b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.ts index 617cdea00..578020003 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.ts @@ -2,12 +2,14 @@ import { ChangeDetectorRef, Component, HostBinding, Input, OnInit, ViewChild } f import type { IComment, User } from '@red/domain'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { PermissionsService } from '@services/permissions.service'; -import { ContextComponent, getCurrentUser, InputWithActionComponent, LoadingService, trackByFactory } from '@iqser/common-ui'; +import { InputWithActionComponent, LoadingService } from '@iqser/common-ui'; import { Observable } from 'rxjs'; import { CommentingService } from '../../services/commenting.service'; import { tap } from 'rxjs/operators'; import { FilePreviewStateService } from '../../services/file-preview-state.service'; import { ManualRedactionService } from '../../services/manual-redaction.service'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { ContextComponent, trackByFactory } from '@iqser/common-ui/lib/utils'; interface CommentsContext { hiddenComments: boolean; @@ -19,12 +21,12 @@ interface CommentsContext { styleUrls: ['./comments.component.scss'], }) export class CommentsComponent extends ContextComponent implements OnInit { + @HostBinding('class.hidden') private _hidden = true; + @ViewChild(InputWithActionComponent) private readonly _input: InputWithActionComponent; @Input() annotation: AnnotationWrapper; readonly trackBy = trackByFactory(); readonly currentUser = getCurrentUser(); hiddenComments$: Observable; - @HostBinding('class.hidden') private _hidden = true; - @ViewChild(InputWithActionComponent) private readonly _input: InputWithActionComponent; constructor( readonly permissionsService: PermissionsService, diff --git a/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.ts b/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.ts index 1d9e5ee07..dbe150783 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.ts @@ -6,7 +6,7 @@ import { FilePreviewStateService } from '../../services/file-preview-state.servi import { type FileAttributeConfigType, FileAttributeConfigTypes } from '@red/domain'; import { FilePreviewDialogService } from '../../services/file-preview-dialog.service'; import { FileAttributesService } from '@services/entity-services/file-attributes.service'; -import { ContextComponent } from '@iqser/common-ui'; +import { ContextComponent } from '@iqser/common-ui/lib/utils'; import { toSignal } from '@angular/core/rxjs-interop'; interface FileAttribute { 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 e5a45a15f..8461382d1 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 @@ -3,16 +3,7 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { AnnotationProcessingService } from '../../services/annotation-processing.service'; import { MatDialog } from '@angular/material/dialog'; import scrollIntoView from 'scroll-into-view-if-needed'; -import { - AutoUnsubscribe, - bool, - CircleButtonTypes, - Debounce, - FilterService, - IconButtonTypes, - INestedFilter, - IqserEventTarget, -} from '@iqser/common-ui'; +import { CircleButtonTypes, IconButtonTypes } from '@iqser/common-ui'; import { combineLatest, delay, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { ExcludedPagesService } from '../../services/excluded-pages.service'; @@ -31,6 +22,8 @@ import { SuggestionsService } from '../../services/suggestions.service'; import { ListItem } from '@models/file/list-item'; import { PageRotationService } from '../../../pdf-viewer/services/page-rotation.service'; import { getLocalStorageDataByFileId } from '@utils/local-storage'; +import { FilterService, INestedFilter } from '@iqser/common-ui/lib/filtering'; +import { AutoUnsubscribe, bool, Debounce, IqserEventTarget } from '@iqser/common-ui/lib/utils'; const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape']; const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; @@ -41,9 +34,10 @@ const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; styleUrls: ['./file-workload.component.scss'], }) export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, OnDestroy { + @ViewChild('annotationsElement') private readonly _annotationsElement: ElementRef; + @ViewChild('quickNavigation') private readonly _quickNavigationElement: ElementRef; readonly iconButtonTypes = IconButtonTypes; readonly circleButtonTypes = CircleButtonTypes; - displayedAnnotations = new Map(); displayedPages: number[] = []; pagesPanelActive = true; @@ -52,8 +46,6 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On this.viewModeService.isEarmarks() ? _('file-preview.tabs.highlights.label') : _('file-preview.tabs.annotations.label'), ); readonly currentPageIsExcluded = computed(() => this.state.file().excludedPages.includes(this.pdf.currentPage())); - @ViewChild('annotationsElement') private readonly _annotationsElement: ElementRef; - @ViewChild('quickNavigation') private readonly _quickNavigationElement: ElementRef; constructor( readonly filterService: FilterService, @@ -116,20 +108,6 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On ); } - ngOnInit(): void { - setTimeout(() => { - const showExcludePages = getLocalStorageDataByFileId(this.state.file()?.id, 'show-exclude-pages') ?? false; - if (showExcludePages) { - this.excludedPagesService.show(); - } - - const showDocumentInfo = getLocalStorageDataByFileId(this.state.file()?.id, 'show-document-info') ?? false; - if (showDocumentInfo) { - this.documentInfoService.show(); - } - }); - } - get activeAnnotations(): AnnotationWrapper[] { return this.displayedAnnotations.get(this.pdf.currentPage()) || []; } @@ -170,6 +148,20 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On } } + ngOnInit(): void { + setTimeout(() => { + const showExcludePages = getLocalStorageDataByFileId(this.state.file()?.id, 'show-exclude-pages') ?? false; + if (showExcludePages) { + this.excludedPagesService.show(); + } + + const showDocumentInfo = getLocalStorageDataByFileId(this.state.file()?.id, 'show-document-info') ?? false; + if (showDocumentInfo) { + this.documentInfoService.show(); + } + }); + } + selectAllOnActivePage() { this.listingService.selectAnnotations(this.activeAnnotations); } diff --git a/apps/red-ui/src/app/modules/file-preview/components/page-indicator/page-indicator.component.ts b/apps/red-ui/src/app/modules/file-preview/components/page-indicator/page-indicator.component.ts index 4472986f9..262f9f979 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/page-indicator/page-indicator.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/page-indicator/page-indicator.component.ts @@ -3,12 +3,13 @@ import { PermissionsService } from '@services/permissions.service'; import { ViewedPagesService } from '@services/files/viewed-pages.service'; import { FilePreviewStateService } from '../../services/file-preview-state.service'; import { PageRotationService } from '../../../pdf-viewer/services/page-rotation.service'; -import { ContextComponent, getConfig } from '@iqser/common-ui'; +import { getConfig } from '@iqser/common-ui'; import { map, tap } from 'rxjs/operators'; import { AppConfig, ViewedPage } from '@red/domain'; import { ViewedPagesMapService } from '@services/files/viewed-pages-map.service'; import { pairwise } from 'rxjs'; import { PdfViewer } from '../../../pdf-viewer/services/pdf-viewer.service'; +import { ContextComponent } from '@iqser/common-ui/lib/utils'; interface PageIndicatorContext { isRotated: boolean; @@ -21,14 +22,13 @@ interface PageIndicatorContext { styleUrls: ['./page-indicator.component.scss'], }) export class PageIndicatorComponent extends ContextComponent implements OnChanges, OnInit { + readonly #config = getConfig(); @Input({ required: true }) number: number; @Input() showDottedIcon = false; @Input() activeSelection = false; @Input() read = false; @Output() readonly pageSelected = new EventEmitter(); - pageReadTimeout: number = null; - readonly #config = getConfig(); constructor( private readonly _viewedPagesService: ViewedPagesService, diff --git a/apps/red-ui/src/app/modules/file-preview/components/pages/pages.component.ts b/apps/red-ui/src/app/modules/file-preview/components/pages/pages.component.ts index 287c7db81..b268b15db 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/pages/pages.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/pages/pages.component.ts @@ -1,5 +1,5 @@ import { Component, inject, Input } from '@angular/core'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { PdfViewer } from '../../../pdf-viewer/services/pdf-viewer.service'; import { MultiSelectService } from '../../services/multi-select.service'; import { AnnotationsListingService } from '../../services/annotations-listing.service'; @@ -14,13 +14,13 @@ import { ViewedPage } from '@red/domain'; styleUrls: ['./pages.component.scss'], }) export class PagesComponent { - @Input({ required: true }) pages: List; - @Input({ required: true }) displayedAnnotations: Map; - protected readonly _pdf = inject(PdfViewer); readonly #state = inject(FilePreviewStateService); - readonly viewedPages$ = inject(ViewedPagesMapService).get$(this.#state.fileId); readonly #multiSelectService = inject(MultiSelectService); readonly #listingService = inject(AnnotationsListingService); + protected readonly _pdf = inject(PdfViewer); + @Input({ required: true }) pages: List; + @Input({ required: true }) displayedAnnotations: Map; + readonly viewedPages$ = inject(ViewedPagesMapService).get$(this.#state.fileId); pageSelectedByClick($event: number): void { this._pdf.navigateTo($event); diff --git a/apps/red-ui/src/app/modules/file-preview/components/user-management/user-management.component.ts b/apps/red-ui/src/app/modules/file-preview/components/user-management/user-management.component.ts index b96e5df60..5c04bd120 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/user-management/user-management.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/user-management/user-management.component.ts @@ -1,6 +1,6 @@ import { Component, computed } from '@angular/core'; import { File, User } from '@red/domain'; -import { getCurrentUser, LoadingService, Toaster } from '@iqser/common-ui'; +import { LoadingService, Toaster } from '@iqser/common-ui'; import { PermissionsService } from '@services/permissions.service'; import { workflowFileStatusTranslations } from '@translations/file-status-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -9,6 +9,7 @@ import { FilesService } from '@services/files/files.service'; import { FilePreviewStateService } from '../../services/file-preview-state.service'; import { FileAssignService } from '../../../shared-dossiers/services/file-assign.service'; import { moveElementInArray } from '@utils/functions'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; @Component({ selector: 'redaction-user-management', @@ -16,17 +17,6 @@ import { moveElementInArray } from '@utils/functions'; styleUrls: ['./user-management.component.scss'], }) export class UserManagementComponent { - readonly translations = workflowFileStatusTranslations; - readonly statusBarConfig = computed(() => [{ length: 1, color: this.state.file().workflowStatus }]); - readonly assignTooltip = computed(() => { - const file = this.state.file(); - return file.isUnderApproval - ? _('dossier-overview.assign-approver') - : file.assignee - ? _('file-preview.change-reviewer') - : _('file-preview.assign-reviewer'); - }); - editingReviewer = false; protected readonly _canAssignToSelf = computed(() => this.permissionsService.canAssignToSelf(this.state.file(), this.state.dossier())); protected readonly _canAssignUser = computed(() => this.permissionsService.canAssignUser(this.state.file(), this.state.dossier())); protected readonly _canUnassignUser = computed(() => this.permissionsService.canUnassignUser(this.state.file(), this.state.dossier())); @@ -45,6 +35,17 @@ export class UserManagementComponent { : this.#customSort([...dossier.memberIds, ...unassignUser]); }); protected readonly _currentUserId = getCurrentUser().id; + readonly translations = workflowFileStatusTranslations; + readonly statusBarConfig = computed(() => [{ length: 1, color: this.state.file().workflowStatus }]); + readonly assignTooltip = computed(() => { + const file = this.state.file(); + return file.isUnderApproval + ? _('dossier-overview.assign-approver') + : file.assignee + ? _('file-preview.change-reviewer') + : _('file-preview.assign-reviewer'); + }); + editingReviewer = false; constructor( readonly fileAssignService: FileAssignService, diff --git a/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts b/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts index a79ec3af4..3df651796 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts @@ -3,11 +3,12 @@ import { ViewMode, ViewModes } from '@red/domain'; import { ViewModeService } from '../../services/view-mode.service'; import { FilePreviewStateService } from '../../services/file-preview-state.service'; import { FileDataService } from '../../services/file-data.service'; -import { BASE_HREF, ConfirmOptions, IConfirmationDialogData, Toaster } from '@iqser/common-ui'; +import { ConfirmOptions, IConfirmationDialogData, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { UserPreferenceService } from '@users/user-preference.service'; import { FilePreviewDialogService } from '../../services/file-preview-dialog.service'; import { Roles } from '@users/roles'; +import { BASE_HREF } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-view-switch', diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts index c9a20b8b4..32326378d 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts @@ -7,7 +7,7 @@ import { SkippedService } from './services/skipped.service'; import { AnnotationActionsService } from './services/annotation-actions.service'; import { FilePreviewStateService } from './services/file-preview-state.service'; import { AnnotationReferencesService } from './services/annotation-references.service'; -import { EntitiesService, FilterService, ListingService, SearchService, SortingService } from '@iqser/common-ui'; +import { EntitiesService, ListingService, SearchService } from '@iqser/common-ui'; import { AnnotationProcessingService } from './services/annotation-processing.service'; import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider'; import { FileDataService } from './services/file-data.service'; @@ -15,6 +15,8 @@ import { AnnotationsListingService } from './services/annotations-listing.servic import { StampService } from './services/stamp.service'; import { PdfProxyService } from './services/pdf-proxy.service'; import { PdfAnnotationActionsService } from './services/pdf-annotation-actions.service'; +import { FilterService } from '@iqser/common-ui/lib/filtering'; +import { SortingService } from '@iqser/common-ui/lib/sorting'; export const filePreviewScreenProviders = [ FilterService, diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index bf975f97f..0d29cf9a9 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -13,25 +13,14 @@ import { } from '@angular/core'; import { ActivatedRoute, ActivatedRouteSnapshot, NavigationExtras, Router } from '@angular/router'; import { - AutoUnsubscribe, - Bind, - bool, CircleButtonTypes, ConfirmOption, ConfirmOptions, - copyLocalStorageFiltersValues, CustomError, - Debounce, ErrorService, - FilterService, HelpModeService, IConfirmationDialogData, - List, LoadingService, - NestedFilter, - OnAttach, - OnDetach, - processFilters, TenantsService, Toaster, } from '@iqser/common-ui'; @@ -78,6 +67,8 @@ import { SuggestionsService } from './services/suggestions.service'; import { IqserDialog } from '../../../../../../libs/common-ui/src/lib/dialog/iqser-dialog.service'; import { RedactTextDialogComponent } from './dialogs/redact-text-dialog/redact-text-dialog.component'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; +import { copyLocalStorageFiltersValues, FilterService, NestedFilter, processFilters } from '@iqser/common-ui/lib/filtering'; +import { AutoUnsubscribe, Bind, bool, Debounce, List, OnAttach, OnDetach } from '@iqser/common-ui/lib/utils'; const textActions = [TextPopups.REDACT_TEXT, TextPopups.ADD_HINT, TextPopups.ADD_FALSE_POSITIVE]; @@ -90,18 +81,18 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements AfterViewInit, OnInit, OnDestroy, OnAttach, OnDetach, ComponentCanDeactivate { - readonly circleButtonTypes = CircleButtonTypes; - readonly roles = Roles; - fullScreen = false; - readonly fileId = this.state.fileId; - readonly dossierId = this.state.dossierId; - width: number; @ViewChild('annotationFilterTemplate', { read: TemplateRef, static: false, }) private readonly _filterTemplate: TemplateRef; @ViewChild('actionsWrapper', { static: false }) private readonly _actionsWrapper: ElementRef; + readonly circleButtonTypes = CircleButtonTypes; + readonly roles = Roles; + fullScreen = false; + readonly fileId = this.state.fileId; + readonly dossierId = this.state.dossierId; + width: number; constructor( readonly pdf: PdfViewer, diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts index 3fa7a5773..40509cd5b 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts @@ -12,11 +12,9 @@ import { InputWithActionComponent, IqserAllowDirective, IqserDenyDirective, - IqserFiltersModule, IqserHelpModeModule, IqserRoutes, IqserUploadFileModule, - IqserUsersModule, LogPipe, PreventDefaultDirective, RoundCheckboxComponent, @@ -66,6 +64,8 @@ import { SharedModule } from '@shared/shared.module'; import { SharedDossiersModule } from '../shared-dossiers/shared-dossiers.module'; import { RedactTextDialogComponent } from './dialogs/redact-text-dialog/redact-text-dialog.component'; import { RemoveRedactionDialogComponent } from './dialogs/remove-redaction-dialog/remove-redaction-dialog.component'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; +import { IqserFiltersModule } from '@iqser/common-ui/lib/filtering'; const routes: IqserRoutes = [ { diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts index 53cc5bc78..c49211e79 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts @@ -1,13 +1,12 @@ import { Injectable } from '@angular/core'; import { ManualRedactionService } from './manual-redaction.service'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { firstValueFrom, Observable, of } from 'rxjs'; +import { firstValueFrom, Observable } from 'rxjs'; import { getFirstRelevantTextPart } from '../../../utils'; import { Core } from '@pdftron/webviewer'; import { DictionaryEntryTypes, EarmarkOperation, - IAddRedactionRequest, ILegalBasisChangeRequest, IRecategorizationRequest, IRectangle, @@ -20,7 +19,7 @@ import { AcceptRecommendationDialogComponent, AcceptRecommendationReturnType, } from '../dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component'; -import { defaultDialogConfig, isJustOne, List } from '@iqser/common-ui'; +import { defaultDialogConfig } from '@iqser/common-ui'; import { filter } from 'rxjs/operators'; import { MatDialog } from '@angular/material/dialog'; import { FilePreviewStateService } from './file-preview-state.service'; @@ -38,6 +37,7 @@ import { import { RemoveRedactionOptions } from '../dialogs/remove-redaction-dialog/remove-redaction-options'; import { IqserDialog } from '../../../../../../../libs/common-ui/src/lib/dialog/iqser-dialog.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; +import { isJustOne, List } from '@iqser/common-ui/lib/utils'; @Injectable() export class AnnotationActionsService { diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts index b32c3b2a2..316c5c548 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { SuperTypeSorter } from '../../../utils'; -import { Filter, handleCheckedValue, IFilter, INestedFilter, NestedFilter } from '@iqser/common-ui'; +import { Filter, handleCheckedValue, IFilter, INestedFilter, NestedFilter } from '@iqser/common-ui/lib/filtering'; import { annotationTypesTranslations } from '@translations/annotation-types-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { annotationDefaultColorConfig } from '@red/domain'; diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotations-listing.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotations-listing.service.ts index a33e24c33..fee463b7a 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotations-listing.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotations-listing.service.ts @@ -1,11 +1,13 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { Injectable, OnDestroy } from '@angular/core'; -import { EntitiesService, FilterService, ListingService, SearchService, SortingService } from '@iqser/common-ui'; +import { EntitiesService, ListingService, SearchService } from '@iqser/common-ui'; import { filter, tap } from 'rxjs/operators'; import { MultiSelectService } from './multi-select.service'; import { PdfViewer } from '../../pdf-viewer/services/pdf-viewer.service'; import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service'; import { Subscription } from 'rxjs'; +import { FilterService } from '@iqser/common-ui/lib/filtering'; +import { SortingService } from '@iqser/common-ui/lib/sorting'; @Injectable() export class AnnotationsListingService extends ListingService implements OnDestroy { diff --git a/apps/red-ui/src/app/modules/file-preview/services/commenting.service.ts b/apps/red-ui/src/app/modules/file-preview/services/commenting.service.ts index 90cd0b16d..494cfb796 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/commenting.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/commenting.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; -import { shareDistinctLast } from '@iqser/common-ui'; +import { shareDistinctLast } from '@iqser/common-ui/lib/utils'; @Injectable() export class CommentingService { diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts index a607f1e97..7acc03014 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts @@ -3,7 +3,7 @@ import { firstValueFrom, from, merge, Observable, of, pairwise, Subject, switchM import { Dictionary, Dossier, DOSSIER_ID, DOSSIER_TEMPLATE_ID, File, FILE_ID } from '@red/domain'; import { FilesMapService } from '@services/files/files-map.service'; import { PermissionsService } from '@services/permissions.service'; -import { getParam, LoadingService, wipeCache } from '@iqser/common-ui'; +import { LoadingService, wipeCache } from '@iqser/common-ui'; import { filter, map, startWith, tap, withLatestFrom } from 'rxjs/operators'; import { FileManagementService } from '@services/files/file-management.service'; import { dossiersServiceResolver } from '@services/entity-services/dossiers.service.provider'; @@ -15,6 +15,7 @@ import { DictionariesMapService } from '@services/entity-services/dictionaries-m import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service'; import { toSignal } from '@angular/core/rxjs-interop'; import { ViewModeService } from './view-mode.service'; +import { getParam } from '@iqser/common-ui/lib/utils'; const ONE_MEGABYTE = 1024 * 1024; @@ -31,6 +32,8 @@ function isDownload(event: HttpEvent): event is HttpProgressEvent { @Injectable() export class FilePreviewStateService { + readonly #reloadBlob$ = new Subject(); + readonly #dossierFileChange: Signal; readonly file$: Observable; readonly file: Signal; readonly dossier: Signal; @@ -38,12 +41,9 @@ export class FilePreviewStateService { readonly isWritable: Signal; readonly dossierDictionary: Signal; readonly blob$: Observable; - readonly dossierId = getParam(DOSSIER_ID); readonly dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly fileId = getParam(FILE_ID); - readonly #reloadBlob$ = new Subject(); - readonly #dossierFileChange: Signal; // readonly #routeKey = getReusableRouteKey(inject(ActivatedRoute).snapshot); // readonly isAttached = inject(CustomRouteReuseStrategy).attached$.pipe( diff --git a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts index 00b4e0fdc..6935802b5 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts @@ -11,7 +11,7 @@ import type { ManualRedactionActions, } from '@red/domain'; import { type AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { GenericService, IqserPermissionsService, List, Toaster } from '@iqser/common-ui'; +import { GenericService, IqserPermissionsService, Toaster } from '@iqser/common-ui'; import { tap } from 'rxjs/operators'; import { PermissionsService } from '@services/permissions.service'; import { dictionaryActionsTranslations, manualRedactionActionsTranslations } from '@translations/annotation-actions-translations'; @@ -22,6 +22,7 @@ import { type ManualRedactionEntryType } from '@models/file/manual-redaction-ent import { NGXLogger } from 'ngx-logger'; import { Roles } from '@users/roles'; import { firstValueFrom, of } from 'rxjs'; +import { List } from '@iqser/common-ui/lib/utils'; function getResponseType(error: boolean, isConflict: boolean) { const isConflictError = isConflict ? 'conflictError' : 'error'; diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts index 8af835fd4..410899cb4 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts @@ -5,11 +5,12 @@ import { PermissionsService } from '@services/permissions.service'; import { FilePreviewStateService } from './file-preview-state.service'; import { TranslateService } from '@ngx-translate/core'; import { AnnotationActionsService } from './annotation-actions.service'; -import { BASE_HREF_FN, IqserPermissionsService } from '@iqser/common-ui'; +import { IqserPermissionsService } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { IHeaderElement } from '@red/domain'; import { Roles } from '@users/roles'; import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service'; +import { BASE_HREF_FN } from '@iqser/common-ui/lib/utils'; @Injectable() export class PdfAnnotationActionsService { diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts index e7f53ac51..edfa6f2a0 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts @@ -9,7 +9,7 @@ import { } from '@models/file/manual-redaction-entry.wrapper'; import { AnnotationDrawService } from '../../pdf-viewer/services/annotation-draw.service'; import { UserPreferenceService } from '@users/user-preference.service'; -import { BASE_HREF_FN, getCurrentUser, IqserPermissionsService, isJustOne, shareDistinctLast } from '@iqser/common-ui'; +import { IqserPermissionsService } from '@iqser/common-ui'; import { toPosition } from '../utils/pdf-calculation.utils'; import { MultiSelectService } from './multi-select.service'; import { FilePreviewStateService } from './file-preview-state.service'; @@ -35,11 +35,21 @@ import { PdfAnnotationActionsService } from './pdf-annotation-actions.service'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { Roles } from '@users/roles'; import { AnnotationActionsService } from './annotation-actions.service'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { BASE_HREF_FN, isJustOne, shareDistinctLast } from '@iqser/common-ui/lib/utils'; import Annotation = Core.Annotations.Annotation; import Quad = Core.Math.Quad; @Injectable() export class PdfProxyService { + private readonly _convertPath = inject(BASE_HREF_FN); + readonly #visibilityOffIcon = this._convertPath('/assets/icons/general/visibility-off.svg'); + readonly #visibilityIcon = this._convertPath('/assets/icons/general/visibility.svg'); + readonly #falsePositiveIcon = this._convertPath('/assets/icons/general/pdftron-action-false-positive.svg'); + readonly #addRedactionIcon = this._iqserPermissionsService.has(Roles.getRss) + ? this._convertPath('/assets/icons/general/pdftron-action-add-component.svg') + : this._convertPath('/assets/icons/general/pdftron-action-add-redaction.svg'); + readonly #addHintIcon = this._convertPath('/assets/icons/general/pdftron-action-add-hint.svg'); readonly annotationSelected$ = this.#annotationSelected$; readonly manualAnnotationRequested$ = new Subject(); readonly redactTextRequested$ = new Subject(); @@ -54,14 +64,6 @@ export class PdfProxyService { const isAllowed = this._permissionsService.canPerformAnnotationActions(this._state.file(), this._state.dossier()); return isAllowed && isStandard; }); - private readonly _convertPath = inject(BASE_HREF_FN); - readonly #visibilityOffIcon = this._convertPath('/assets/icons/general/visibility-off.svg'); - readonly #visibilityIcon = this._convertPath('/assets/icons/general/visibility.svg'); - readonly #falsePositiveIcon = this._convertPath('/assets/icons/general/pdftron-action-false-positive.svg'); - readonly #addRedactionIcon = this._iqserPermissionsService.has(Roles.getRss) - ? this._convertPath('/assets/icons/general/pdftron-action-add-component.svg') - : this._convertPath('/assets/icons/general/pdftron-action-add-redaction.svg'); - readonly #addHintIcon = this._convertPath('/assets/icons/general/pdftron-action-add-hint.svg'); constructor( private readonly _translateService: TranslateService, diff --git a/apps/red-ui/src/app/modules/file-preview/services/skipped.service.ts b/apps/red-ui/src/app/modules/file-preview/services/skipped.service.ts index ed8be6319..eae50c4b3 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/skipped.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/skipped.service.ts @@ -1,11 +1,11 @@ import { effect, Injectable, Signal, signal } from '@angular/core'; -import { bool } from '@iqser/common-ui'; +import { bool } from '@iqser/common-ui/lib/utils'; import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service'; @Injectable() export class SkippedService { - readonly hideSkipped: Signal; readonly #hideSkipped = signal(false); + readonly hideSkipped: Signal; constructor(private readonly _annotationManager: REDAnnotationManager) { this.hideSkipped = this.#hideSkipped.asReadonly(); diff --git a/apps/red-ui/src/app/modules/file-preview/services/suggestions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/suggestions.service.ts index 806c69ac2..3730ae6e0 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/suggestions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/suggestions.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { bool } from '@iqser/common-ui'; +import { bool } from '@iqser/common-ui/lib/utils'; import { Core } from '@pdftron/webviewer'; import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service'; import { UserPreferenceService } from '@users/user-preference.service'; diff --git a/apps/red-ui/src/app/modules/file-preview/utils/constants.ts b/apps/red-ui/src/app/modules/file-preview/utils/constants.ts index 2d2dc7cfd..087c3f576 100644 --- a/apps/red-ui/src/app/modules/file-preview/utils/constants.ts +++ b/apps/red-ui/src/app/modules/file-preview/utils/constants.ts @@ -1,4 +1,4 @@ -import { List, ValuesOf } from '@iqser/common-ui'; +import { List, ValuesOf } from '@iqser/common-ui/lib/utils'; export const ActionsHelpModeKeys = { redaction: 'redaction', diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts index 7599b054e..0e0ca0860 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts @@ -9,7 +9,7 @@ import { IRectangle, ISectionGrid, ISectionRectangle, SuperTypes } from '@red/do import { firstValueFrom } from 'rxjs'; import { PdfViewer } from './pdf-viewer.service'; import { REDAnnotationManager } from './annotation-manager.service'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { REDDocumentViewer } from './document-viewer.service'; import { DefaultColorsService } from '@services/entity-services/default-colors.service'; import Annotation = Core.Annotations.Annotation; diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts index 2394c07bb..3a02cb459 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts @@ -1,6 +1,6 @@ import { Injectable, signal } from '@angular/core'; import { Core } from '@pdftron/webviewer'; -import type { List } from '@iqser/common-ui'; +import type { List } from '@iqser/common-ui/lib/utils'; import { AnnotationPredicate, DeleteAnnotationsOptions } from '../utils/types'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { fromEvent, Observable } from 'rxjs'; @@ -13,13 +13,12 @@ import Annotation = Core.Annotations.Annotation; @Injectable() export class REDAnnotationManager { + readonly #hidden = signal(new Set()); + #manager: AnnotationManager; annotationSelected$: Observable<[Annotation[], string]>; resizingAnnotationId?: string = undefined; - readonly #hidden = signal(new Set()); readonly hidden = this.#hidden.asReadonly(); - #manager: AnnotationManager; - get selected() { return this.#manager.getSelectedAnnotations(); } diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts index 9d2aabf60..65724b262 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts @@ -6,7 +6,7 @@ import { filter, tap } from 'rxjs/operators'; import { ActivatedRoute } from '@angular/router'; import { PdfViewer } from './pdf-viewer.service'; import { UserPreferenceService } from '@users/user-preference.service'; -import { log } from '@iqser/common-ui'; +import { log } from '@iqser/common-ui/lib/utils'; import { stopAndPrevent, stopAndPreventIfNotAllowed } from '../utils/functions'; import { RotationType, RotationTypes } from '@red/domain'; import { AnnotationToolNames } from '../utils/constants'; @@ -17,22 +17,20 @@ import Quad = Core.Math.Quad; @Injectable() export class REDDocumentViewer { - readonly loaded$: Observable; - keyUp$: Observable; - readonly selectedText: Signal; - readonly loaded: Signal; - readonly pageComplete: Signal; - #document: DocumentViewer; readonly #loaded = signal(false); readonly #pageComplete = signal(undefined); readonly #selectedText = signal(''); - readonly #logger = inject(NGXLogger); readonly #userPreferenceService = inject(UserPreferenceService); readonly #pdf = inject(PdfViewer); readonly #activatedRoute = inject(ActivatedRoute); readonly #ngZone = inject(NgZone); + readonly loaded$: Observable; + keyUp$: Observable; + readonly selectedText: Signal; + readonly loaded: Signal; + readonly pageComplete: Signal; constructor() { this.loaded = this.#loaded.asReadonly(); diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts index 31c4d6dc4..40944b5ba 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts @@ -1,6 +1,6 @@ import { DestroyRef, inject, Injectable, signal, Signal } from '@angular/core'; import WebViewer, { Core, WebViewerInstance, WebViewerOptions } from '@pdftron/webviewer'; -import { BASE_HREF_FN, ErrorService, getConfig, shareDistinctLast } from '@iqser/common-ui'; +import { ErrorService, getConfig } from '@iqser/common-ui'; import { AppConfig, File, IHeaderElement } from '@red/domain'; import { ActivatedRoute } from '@angular/router'; import { map, startWith } from 'rxjs/operators'; @@ -15,6 +15,7 @@ import { UserPreferenceService } from '@users/user-preference.service'; import { environment } from '@environments/environment'; import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { BASE_HREF_FN, shareDistinctLast } from '@iqser/common-ui/lib/utils'; import TextTool = Core.Tools.TextTool; import Annotation = Core.Annotations.Annotation; import TextHighlightAnnotation = Core.Annotations.TextHighlightAnnotation; @@ -23,21 +24,6 @@ import Quad = Core.Math.Quad; @Injectable() export class PdfViewer { - readonly currentPage$ = inject(ActivatedRoute).queryParamMap.pipe( - map(params => Number(params.get('page') ?? '1')), - shareDistinctLast(), - ); - readonly currentPage = toSignal(this.currentPage$); - - documentViewer: DocumentViewer; - - fileId: string; - dossierId: string; - - pageChanged$: Observable; - readonly isCompareMode: Signal; - readonly totalPages: Signal; - private readonly _convertPath = inject(BASE_HREF_FN); #instance: WebViewerInstance; readonly #licenseKey = inject(LicenseService).activeLicenseKey; @@ -55,6 +41,17 @@ export class PdfViewer { }; readonly #destroyRef = inject(DestroyRef); readonly #totalPages = signal(0); + readonly currentPage$ = inject(ActivatedRoute).queryParamMap.pipe( + map(params => Number(params.get('page') ?? '1')), + shareDistinctLast(), + ); + readonly currentPage = toSignal(this.currentPage$); + documentViewer: DocumentViewer; + fileId: string; + dossierId: string; + pageChanged$: Observable; + readonly isCompareMode: Signal; + readonly totalPages: Signal; constructor( private readonly _logger: NGXLogger, diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/readable-redactions.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/readable-redactions.service.ts index c9417bee2..d0bbfbbb7 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/readable-redactions.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/readable-redactions.service.ts @@ -1,5 +1,4 @@ import { inject, Injectable } from '@angular/core'; -import { BASE_HREF_FN } from '@iqser/common-ui'; import { TranslateService } from '@ngx-translate/core'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { HeaderElements } from '../../file-preview/utils/constants'; @@ -8,15 +7,16 @@ import { REDAnnotationManager } from './annotation-manager.service'; import { AnnotationDrawService } from './annotation-draw.service'; import { BehaviorSubject, Observable } from 'rxjs'; import { Core } from '@pdftron/webviewer'; +import { BASE_HREF_FN } from '@iqser/common-ui/lib/utils'; import Annotation = Core.Annotations.Annotation; @Injectable() export class ReadableRedactionsService { - readonly active$: Observable; private readonly _convertPath = inject(BASE_HREF_FN); readonly #enableIcon = this._convertPath('/assets/icons/general/redaction-preview.svg'); readonly #disableIcon = this._convertPath('/assets/icons/general/redaction-final.svg'); readonly #active$ = new BehaviorSubject(true); + readonly active$: Observable; constructor( private readonly _pdf: PdfViewer, diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/tooltips.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/tooltips.service.ts index 945d64bbb..d4918dd23 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/tooltips.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/tooltips.service.ts @@ -3,9 +3,9 @@ import { UserPreferenceService } from '@users/user-preference.service'; import { HeaderElements } from '../../file-preview/utils/constants'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { TranslateService } from '@ngx-translate/core'; -import { BASE_HREF_FN } from '@iqser/common-ui'; import { PdfViewer } from './pdf-viewer.service'; import { REDDocumentViewer } from './document-viewer.service'; +import { BASE_HREF_FN } from '@iqser/common-ui/lib/utils'; @Injectable() export class TooltipsService { diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts index 2375b1c05..30a65c431 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts @@ -2,7 +2,7 @@ import { inject, Injectable, NgZone } from '@angular/core'; import { IHeaderElement, RotationTypes } from '@red/domain'; import { HeaderElements, HeaderElementType } from '../../file-preview/utils/constants'; import { TranslateService } from '@ngx-translate/core'; -import { BASE_HREF_FN, IqserPermissionsService } from '@iqser/common-ui'; +import { IqserPermissionsService } from '@iqser/common-ui'; import { TooltipsService } from './tooltips.service'; import { PageRotationService } from './page-rotation.service'; import { PdfViewer } from './pdf-viewer.service'; @@ -14,6 +14,7 @@ import { ViewerEvent, VisibilityChangedEvent } from '../utils/types'; import { ReadableRedactionsService } from './readable-redactions.service'; import { filter, map, tap } from 'rxjs/operators'; import { Roles } from '@users/roles'; +import { BASE_HREF_FN } from '@iqser/common-ui/lib/utils'; const divider: IHeaderElement = { type: 'divider', @@ -21,8 +22,6 @@ const divider: IHeaderElement = { @Injectable() export class ViewerHeaderService { - readonly events$: Observable; - toggleLoadAnnotations$: Observable; readonly #convertPath = inject(BASE_HREF_FN); readonly #iqserPermissionService = inject(IqserPermissionsService); #buttons: Map; @@ -40,6 +39,8 @@ export class ViewerHeaderService { ]); #docBeforeCompare: Blob; readonly #events$ = new Subject(); + readonly events$: Observable; + toggleLoadAnnotations$: Observable; constructor( private readonly _filesMapService: FilesMapService, diff --git a/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts b/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts index 18de282ff..06321a60a 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts @@ -1,6 +1,7 @@ -import { CustomError, List } from '@iqser/common-ui'; +import { CustomError } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { HeaderElements, TextPopups } from '../../file-preview/utils/constants'; +import { List } from '@iqser/common-ui/lib/utils'; export const ROTATION_BUTTONS = [HeaderElements.ROTATE_LEFT_BUTTON, HeaderElements.ROTATE_RIGHT_BUTTON]; export const ROTATION_ACTION_BUTTONS = [HeaderElements.APPLY_ROTATION, HeaderElements.DISCARD_ROTATION]; diff --git a/apps/red-ui/src/app/modules/pdf-viewer/utils/functions.ts b/apps/red-ui/src/app/modules/pdf-viewer/utils/functions.ts index 74239b114..356021ce2 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/utils/functions.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/utils/functions.ts @@ -1,4 +1,4 @@ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { ALLOWED_KEYBOARD_SHORTCUTS } from './constants'; diff --git a/apps/red-ui/src/app/modules/search/search-item-template/search-item-template.component.ts b/apps/red-ui/src/app/modules/search/search-item-template/search-item-template.component.ts index 5ba409269..fff7c1e2f 100644 --- a/apps/red-ui/src/app/modules/search/search-item-template/search-item-template.component.ts +++ b/apps/red-ui/src/app/modules/search/search-item-template/search-item-template.component.ts @@ -1,7 +1,7 @@ import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; import { workflowFileStatusTranslations } from '@translations/file-status-translations'; import { ISearchListItem } from '@red/domain'; -import { escapeHtml } from '@iqser/common-ui'; +import { escapeHtml } from '@iqser/common-ui/lib/utils'; import { getDossierRouterLink } from '@utils/router-links'; @Component({ 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 6bd587d2f..017076a13 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 @@ -1,15 +1,5 @@ import { ChangeDetectionStrategy, Component, OnDestroy } from '@angular/core'; -import { - IFilterGroup, - keyChecker, - ListingComponent, - listingProvidersFactory, - LoadingService, - NestedFilter, - SearchPositions, - SortingOrders, - TableColumnConfig, -} from '@iqser/common-ui'; +import { ListingComponent, listingProvidersFactory, LoadingService, SearchPositions, TableColumnConfig } from '@iqser/common-ui'; import { combineLatest, Observable, of } from 'rxjs'; import { debounceTime, map, startWith, switchMap, tap } from 'rxjs/operators'; import { ActivatedRoute, Router } from '@angular/router'; @@ -33,6 +23,8 @@ 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'; +import { IFilterGroup, keyChecker, NestedFilter } from '@iqser/common-ui/lib/filtering'; +import { SortingOrders } from '@iqser/common-ui/lib/sorting'; @Component({ templateUrl: './search-screen.component.html', diff --git a/apps/red-ui/src/app/modules/search/search.module.ts b/apps/red-ui/src/app/modules/search/search.module.ts index 1a6943185..f6232c367 100644 --- a/apps/red-ui/src/app/modules/search/search.module.ts +++ b/apps/red-ui/src/app/modules/search/search.module.ts @@ -2,10 +2,11 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { SearchScreenComponent } from './search-screen/search-screen.component'; import { RouterModule } from '@angular/router'; -import { IqserListingModule, IqserUsersModule, StatusBarComponent, StopPropagationDirective, TenantPipe } from '@iqser/common-ui'; +import { IqserListingModule, StatusBarComponent, StopPropagationDirective, TenantPipe } from '@iqser/common-ui'; import { SharedModule } from '@shared/shared.module'; import { TranslateModule } from '@ngx-translate/core'; import { SearchItemTemplateComponent } from './search-item-template/search-item-template.component'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; const routes = [{ path: '', component: SearchScreenComponent }]; diff --git a/apps/red-ui/src/app/modules/shared-dossiers/components/dossiers-listing-actions/dossiers-listing-actions.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/components/dossiers-listing-actions/dossiers-listing-actions.component.ts index ca07bbd07..49e2b55a6 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/components/dossiers-listing-actions/dossiers-listing-actions.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/components/dossiers-listing-actions/dossiers-listing-actions.component.ts @@ -1,6 +1,6 @@ import { Component, Input, OnChanges } from '@angular/core'; import { PermissionsService } from '@services/permissions.service'; -import { CircleButtonTypes, getCurrentUser, IqserPermissionsService, ScrollableParentViews } from '@iqser/common-ui'; +import { CircleButtonTypes, IqserPermissionsService, ScrollableParentViews } from '@iqser/common-ui'; import type { Dossier, File, User } from '@red/domain'; import { DossiersDialogService } from '../../services/dossiers-dialog.service'; import { LongPressEvent } from '@shared/directives/long-press.directive'; @@ -8,6 +8,7 @@ import { UserPreferenceService } from '@users/user-preference.service'; import { FilesMapService } from '@services/files/files-map.service'; import { ReanalysisService } from '@services/reanalysis.service'; import { Roles } from '@users/roles'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; @Component({ selector: 'redaction-dossiers-listing-actions [dossier]', 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 7efcbda12..44690834d 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 @@ -5,10 +5,8 @@ import { DossiersDialogService } from '../../services/dossiers-dialog.service'; import { CircleButtonType, CircleButtonTypes, - getCurrentUser, IConfirmationDialogData, IqserPermissionsService, - IqserTooltipPositions, LoadingService, TenantsService, Toaster, @@ -33,6 +31,8 @@ import { Roles } from '@users/roles'; import { FileAttributesService } from '@services/entity-services/file-attributes.service'; import { toObservable } from '@angular/core/rxjs-interop'; import { setLocalStorageDataByFileId } from '@utils/local-storage'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { IqserTooltipPositions } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-file-actions', @@ -40,20 +40,19 @@ import { setLocalStorageDataByFileId } from '@utils/local-storage'; styleUrls: ['./file-actions.component.scss'], }) export class FileActionsComponent implements OnChanges { + @ViewChild(ExpandableFileActionsComponent) + private readonly _expandableActionsComponent: ExpandableFileActionsComponent; @Input({ required: true }) file: File; @Input({ required: true }) dossier: Dossier; @Input({ required: true }) type: 'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow'; @Input() maxWidth: number; @Input() minWidth: number; @Input() fileActionsHelpModeKey: 'document_features_in_dossier' | 'editor_document_features' = 'document_features_in_dossier'; - readonly circleButtonTypes = CircleButtonTypes; readonly currentUser = getCurrentUser(); - toggleTooltip?: string; assignTooltip?: string; buttonType?: CircleButtonType; - showSetToNew = false; showUndoApproval = false; showAssignToSelf = false; @@ -80,9 +79,6 @@ export class FileActionsComponent implements OnChanges { tooltipPosition = IqserTooltipPositions.above; buttons: Action[]; - @ViewChild(ExpandableFileActionsComponent) - private readonly _expandableActionsComponent: ExpandableFileActionsComponent; - constructor( private readonly _injector: Injector, private readonly _filesService: FilesService, diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts index 1d2b8f2d8..2ac3bf1ea 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { UserService } from '@users/user.service'; -import { getCurrentUser, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui'; +import { IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui'; import { FormBuilder, Validators } from '@angular/forms'; import { File, User, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -9,6 +9,7 @@ import { FilesService } from '@services/files/files.service'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { PermissionsService } from '@services/permissions.service'; import { moveElementInArray } from '@utils/functions'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; class DialogData { targetStatus: WorkflowFileStatus; diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts index 104924c9a..c8c1d00a3 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts @@ -8,7 +8,7 @@ import { PermissionsService } from '@services/permissions.service'; import { firstValueFrom, Observable } from 'rxjs'; import { DossiersService } from '@services/dossiers/dossiers.service'; import { WatermarksMapService } from '@services/entity-services/watermarks-map.service'; -import { ContextComponent, shareLast } from '@iqser/common-ui'; +import { ContextComponent, shareLast } from '@iqser/common-ui/lib/utils'; import { Roles } from '@users/roles'; interface EditDossierDownloadPackageContext { @@ -24,6 +24,7 @@ export class EditDossierDownloadPackageComponent extends ContextComponent implements OnInit, EditDossierSectionInterface { + #existsWatermarks$: Observable; form: FormGroup; downloadTypes: { key: DownloadFileType; label: string }[] = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map( (type: DownloadFileType) => ({ @@ -32,10 +33,8 @@ export class EditDossierDownloadPackageComponent }), ); availableReportTypes: IReportTemplate[] = []; - readonly roles = Roles; @Input() dossier: Dossier; - #existsWatermarks$: Observable; constructor( private readonly _dossiersService: DossiersService, diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts index ece30b9ba..d787fca08 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts @@ -4,14 +4,7 @@ import { Dossier, User } from '@red/domain'; import { EditDossierGeneralInfoComponent } from './general-info/edit-dossier-general-info.component'; import { EditDossierDownloadPackageComponent } from './download-package/edit-dossier-download-package.component'; import { EditDossierSectionInterface } from './edit-dossier-section.interface'; -import { - BaseDialogComponent, - ConfirmOptions, - getCurrentUser, - IconButtonTypes, - IqserPermissionsService, - SaveOptions, -} from '@iqser/common-ui'; +import { BaseDialogComponent, ConfirmOptions, IconButtonTypes, IqserPermissionsService, SaveOptions } from '@iqser/common-ui'; import { EditDossierDictionaryComponent } from './dictionary/edit-dossier-dictionary.component'; import { EditDossierAttributesComponent } from './attributes/edit-dossier-attributes.component'; @@ -23,6 +16,7 @@ import { PermissionsService } from '@services/permissions.service'; import { DossiersService } from '@services/dossiers/dossiers.service'; import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider'; import { Roles } from '@users/roles'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; type Section = 'dossierInfo' | 'downloadPackage' | 'dossierDictionary' | 'members' | 'dossierAttributes'; @@ -40,6 +34,8 @@ interface NavItem { providers: [dossiersServiceProvider], }) export class EditDossierDialogComponent extends BaseDialogComponent implements AfterViewInit { + readonly #currentUser = getCurrentUser(); + private _dossier: Dossier; readonly roles = Roles; navItems: NavItem[] = []; readonly iconButtonTypes = IconButtonTypes; @@ -50,8 +46,6 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A @ViewChild(EditDossierDictionaryComponent) dictionaryComponent: EditDossierDictionaryComponent; @ViewChild(EditDossierTeamComponent) membersComponent: EditDossierTeamComponent; @ViewChild(EditDossierAttributesComponent) attributesComponent: EditDossierAttributesComponent; - readonly #currentUser = getCurrentUser(); - private _dossier: Dossier; constructor( readonly iqserPermissionsService: IqserPermissionsService, diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.ts index e64a0671b..ad1fa12a5 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.ts @@ -8,8 +8,8 @@ import { PermissionsService } from '@services/permissions.service'; import { DossiersService } from '@services/dossiers/dossiers.service'; import { compareLists } from '@utils/functions'; import { FilesService } from '@services/files/files.service'; -import { Debounce } from '@iqser/common-ui'; import { map } from 'rxjs/operators'; +import { Debounce } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-edit-dossier-team', @@ -18,16 +18,16 @@ import { map } from 'rxjs/operators'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class EditDossierTeamComponent implements EditDossierSectionInterface, OnChanges { - form = this.#getForm(); - searchQuery = ''; - @Input() dossier: Dossier; - membersSelectOptions: string[] = []; readonly #userService = inject(UserService); readonly #dossiersService = inject(DossiersService); readonly #permissionsService = inject(PermissionsService); readonly #filesService = inject(FilesService); - readonly ownersSelectOptions = this.#userService.all.filter(u => u.isManager).map(m => m.id); + form = this.#getForm(); readonly #formValue$ = this.form.valueChanges; + searchQuery = ''; + @Input() dossier: Dossier; + membersSelectOptions: string[] = []; + readonly ownersSelectOptions = this.#userService.all.filter(u => u.isManager).map(m => m.id); readonly selectedReviewers$ = this.#formValue$.pipe(map(v => v.members.filter(m => !v.approvers.includes(m)))); readonly selectedApprovers$ = this.#formValue$.pipe(map(v => v.approvers)); diff --git a/apps/red-ui/src/app/modules/shared-dossiers/services/file-assign.service.ts b/apps/red-ui/src/app/modules/shared-dossiers/services/file-assign.service.ts index 06a9f335b..e661a3b6a 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/services/file-assign.service.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/services/file-assign.service.ts @@ -3,9 +3,10 @@ import { Dossier, File, User, WorkflowFileStatus, WorkflowFileStatuses } from '@ import { DossiersDialogService } from './dossiers-dialog.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { FilesService } from '@services/files/files.service'; -import { getCurrentUser, IConfirmationDialogData, LoadingService, Toaster } from '@iqser/common-ui'; +import { IConfirmationDialogData, LoadingService, Toaster } from '@iqser/common-ui'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { firstValueFrom } from 'rxjs'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; const atLeastOneAssignee = (files: File[]) => files.reduce((acc, fs) => acc || !!fs.assignee, false); diff --git a/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts b/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts index 6e1627e3b..247bbf31b 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts @@ -22,7 +22,6 @@ import { IqserAllowDirective, IqserDenyDirective, IqserHelpModeModule, - IqserUsersModule, RoundCheckboxComponent, SideNavComponent, SmallChipComponent, @@ -31,6 +30,7 @@ import { } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { DossiersListingActionsComponent } from './components/dossiers-listing-actions/dossiers-listing-actions.component'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; const components = [ FileActionsComponent, diff --git a/apps/red-ui/src/app/modules/shared/components/assign-user-dropdown/assign-user-dropdown.component.ts b/apps/red-ui/src/app/modules/shared/components/assign-user-dropdown/assign-user-dropdown.component.ts index eabc22a63..c1bc526cc 100644 --- a/apps/red-ui/src/app/modules/shared/components/assign-user-dropdown/assign-user-dropdown.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/assign-user-dropdown/assign-user-dropdown.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; import { UserService } from '@users/user.service'; import { User } from '@red/domain'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-assign-user-dropdown', @@ -10,11 +10,11 @@ import { List } from '@iqser/common-ui'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class AssignUserDropdownComponent { + private _currentUser: User | string; oldUser: User | string; @Input() options: List; @Output() readonly save = new EventEmitter(); @Output() readonly cancel = new EventEmitter(); - private _currentUser: User | string; constructor(private readonly _userService: UserService) {} diff --git a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts index 9ea29d8c1..8f35df1a1 100644 --- a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild } from '@angular/core'; -import { Debounce, IconButtonTypes, List, LoadingService } from '@iqser/common-ui'; +import { IconButtonTypes, LoadingService } from '@iqser/common-ui'; import { Dictionary, DICTIONARY_TYPE_KEY_MAP, DictionaryType, Dossier, DossierTemplate } from '@red/domain'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { DictionaryService } from '@services/entity-services/dictionary.service'; @@ -8,6 +8,7 @@ import { DossierTemplatesService } from '@services/dossier-templates/dossier-tem import { EditorComponent } from '@shared/components/editor/editor.component'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { saveAs } from 'file-saver'; +import { Debounce, List } from '@iqser/common-ui/lib/utils'; import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration; import FindMatch = monaco.editor.FindMatch; @@ -24,6 +25,8 @@ const HELP_MODE_KEYS = { styleUrls: ['./dictionary-manager.component.scss'], }) export class DictionaryManagerComponent implements OnChanges { + private _searchDecorations: string[] = []; + readonly #currentTab = window.location.href.split('/').pop(); @Input() type: DictionaryType = 'dictionary'; @Input() entityType?: string; @Input() withFloatingActions = true; @@ -34,9 +37,7 @@ export class DictionaryManagerComponent implements OnChanges { @Input() isLeavingPage = false; @Output() readonly saveDictionary = new EventEmitter(); @ViewChild(EditorComponent) readonly editor: EditorComponent; - readonly iconButtonTypes = IconButtonTypes; - currentMatch = 0; findMatches: FindMatch[] = []; diffEditorText = ''; @@ -46,12 +47,10 @@ export class DictionaryManagerComponent implements OnChanges { selectDictionary = { label: _('dictionary-overview.compare.select-dictionary'), } as Dictionary; + #compareDictionary = this.selectDictionary; selectDossierTemplate = { name: _('dictionary-overview.compare.select-dossier-template') } as DossierTemplate; compare: false; dictionaries: List = this.#dictionaries; - private _searchDecorations: string[] = []; - readonly #currentTab = window.location.href.split('/').pop(); - #compareDictionary = this.selectDictionary; constructor( private readonly _dictionaryService: DictionaryService, diff --git a/apps/red-ui/src/app/modules/shared/components/donut-chart/donut-chart.component.ts b/apps/red-ui/src/app/modules/shared/components/donut-chart/donut-chart.component.ts index 5b2c6d94a..40bbf9e92 100644 --- a/apps/red-ui/src/app/modules/shared/components/donut-chart/donut-chart.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/donut-chart/donut-chart.component.ts @@ -1,10 +1,12 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Optional, Output } from '@angular/core'; import { DonutChartConfig } from '@red/domain'; -import { FilterService, get, INestedFilter, IqserHelpModeModule, shareLast, StatusBarComponent } from '@iqser/common-ui'; +import { IqserHelpModeModule, StatusBarComponent } from '@iqser/common-ui'; import { Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; import { AsyncPipe, NgForOf, NgIf } from '@angular/common'; import { MatSelectModule } from '@angular/material/select'; +import { FilterService, INestedFilter } from '@iqser/common-ui/lib/filtering'; +import { get, shareLast } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-donut-chart', @@ -33,6 +35,10 @@ export class DonutChartComponent implements OnChanges, OnInit { size = 0; filters$: Observable; + constructor(@Optional() readonly filterService: FilterService) { + // TODO: move this component to a separate module, split into smaller components, improve filters + } + get circumference(): number { return 2 * Math.PI * this.radius; } @@ -45,10 +51,6 @@ export class DonutChartComponent implements OnChanges, OnInit { return this.totalType === 'sum' ? this.dataTotal : this.config.length; } - constructor(@Optional() readonly filterService: FilterService) { - // TODO: move this component to a separate module, split into smaller components, improve filters - } - ngOnInit() { const filterModels$ = this.filterService?.getFilterModels$(this.filterKey).pipe( map(filters => filters ?? []), diff --git a/apps/red-ui/src/app/modules/shared/components/dossier-name-column/dossier-name-column.component.ts b/apps/red-ui/src/app/modules/shared/components/dossier-name-column/dossier-name-column.component.ts index 0d0028068..c46dc98ef 100644 --- a/apps/red-ui/src/app/modules/shared/components/dossier-name-column/dossier-name-column.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/dossier-name-column/dossier-name-column.component.ts @@ -1,9 +1,9 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { DossierStats, IDossier } from '@red/domain'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; -import { List, ScrollableParentView, ScrollableParentViews } from '@iqser/common-ui'; import dayjs from 'dayjs'; import { dateWithoutTime } from '@utils/functions'; +import { List } from '@iqser/common-ui/lib/utils'; const DUE_DATE_WARN_DAYS = 14; diff --git a/apps/red-ui/src/app/modules/shared/components/dossier-watermark-selector/watermark-selector.component.ts b/apps/red-ui/src/app/modules/shared/components/dossier-watermark-selector/watermark-selector.component.ts index bf29d44b6..14b47c44d 100644 --- a/apps/red-ui/src/app/modules/shared/components/dossier-watermark-selector/watermark-selector.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/dossier-watermark-selector/watermark-selector.component.ts @@ -1,11 +1,12 @@ import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; -import { FormFieldComponent, shareLast } from '@iqser/common-ui'; +import { FormFieldComponent } from '@iqser/common-ui'; import { filter, map, tap } from 'rxjs/operators'; import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms'; import { Watermark } from '@red/domain'; import { WatermarksMapService } from '@services/entity-services/watermarks-map.service'; import { MatCheckboxChange } from '@angular/material/checkbox'; +import { shareLast } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-watermark-selector [dossierTemplateId] [label]', @@ -26,13 +27,13 @@ import { MatCheckboxChange } from '@angular/material/checkbox'; ], }) export class WatermarkSelectorComponent extends FormFieldComponent implements OnChanges { + #watermarks: Watermark[] = []; + readonly #dossierTemplateId$ = new BehaviorSubject(null); @Input() dossierTemplateId: string; @Input() label: string; @Input() isReadonly: boolean; readonly watermarks$: Observable; watermarksMap = new Map(); - #watermarks: Watermark[] = []; - readonly #dossierTemplateId$ = new BehaviorSubject(null); constructor(private readonly _watermarksMapService: WatermarksMapService) { super(); diff --git a/apps/red-ui/src/app/modules/shared/components/dossiers-type-switch/dossiers-type-switch.component.ts b/apps/red-ui/src/app/modules/shared/components/dossiers-type-switch/dossiers-type-switch.component.ts index b3fd3e003..3febb956a 100644 --- a/apps/red-ui/src/app/modules/shared/components/dossiers-type-switch/dossiers-type-switch.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/dossiers-type-switch/dossiers-type-switch.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { ARCHIVE_ROUTE, DOSSIER_TEMPLATE_ID, DOSSIERS_ROUTE } from '@red/domain'; import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service'; -import { getParam } from '@iqser/common-ui'; +import { getParam } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-dossiers-type-switch', diff --git a/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts b/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts index 43a7dc865..97ccc3f9c 100644 --- a/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts @@ -1,9 +1,10 @@ import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; -import { List, LoadingService, OnChange } from '@iqser/common-ui'; +import { LoadingService } from '@iqser/common-ui'; import { EditorThemeService } from '@services/editor-theme.service'; import { Subject } from 'rxjs'; import { debounceTime, filter, tap } from 'rxjs/operators'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { List, OnChange } from '@iqser/common-ui/lib/utils'; import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions; import ICodeEditor = monaco.editor.ICodeEditor; import IDiffEditor = monaco.editor.IDiffEditor; @@ -29,11 +30,14 @@ const notZero = (lineChange: ILineChange) => lineChange.originalEndLineNumber != styleUrls: ['./editor.component.scss'], }) export class EditorComponent implements OnInit, OnChanges { + #initialEntriesSet = new Set(); + private _diffEditor: IDiffEditor; + private _decorations: string[] = []; + protected readonly _editorTextChanged$ = new Subject(); @Input() showDiffEditor = false; @Input() diffEditorText: string; @Input() @OnChange('revert') initialEntries: List; @Input() canEdit = false; - /** * Used as [modified] input on diff editor * Shouldn't be updated when editing in diff editor. @@ -42,10 +46,6 @@ export class EditorComponent implements OnInit, OnChanges { editorOptions: IStandaloneEditorConstructionOptions = {}; codeEditor: ICodeEditor; value: string; - protected readonly _editorTextChanged$ = new Subject(); - #initialEntriesSet = new Set(); - private _diffEditor: IDiffEditor; - private _decorations: string[] = []; constructor(private readonly _loadingService: LoadingService, private readonly _editorThemeService: EditorThemeService) { const textChanged$ = this._editorTextChanged$.pipe( diff --git a/apps/red-ui/src/app/modules/shared/components/expandable-file-actions/expandable-file-actions.component.ts b/apps/red-ui/src/app/modules/shared/components/expandable-file-actions/expandable-file-actions.component.ts index 8fcf207a8..0e802282b 100644 --- a/apps/red-ui/src/app/modules/shared/components/expandable-file-actions/expandable-file-actions.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/expandable-file-actions/expandable-file-actions.component.ts @@ -1,11 +1,12 @@ import { Component, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core'; import { Action, ActionTypes, Dossier, File } from '@red/domain'; -import { CircleButtonType, IqserDialog, IqserTooltipPosition, TenantsService, Toaster, trackByFactory } from '@iqser/common-ui'; +import { CircleButtonType, IqserDialog, TenantsService, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { FileDownloadService } from '@upload-download/services/file-download.service'; import { PermissionsService } from '@services/permissions.service'; import { MatMenuTrigger } from '@angular/material/menu'; import { DownloadDialogComponent } from '@shared/dialogs/download-dialog/download-dialog.component'; +import { IqserTooltipPosition, trackByFactory } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-expandable-file-actions', diff --git a/apps/red-ui/src/app/modules/shared/components/file-name-column/file-name-column.component.ts b/apps/red-ui/src/app/modules/shared/components/file-name-column/file-name-column.component.ts index 797059be8..71981ce8b 100644 --- a/apps/red-ui/src/app/modules/shared/components/file-name-column/file-name-column.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/file-name-column/file-name-column.component.ts @@ -1,9 +1,9 @@ import { ChangeDetectionStrategy, Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { PrimaryFileAttributeService } from '@services/primary-file-attribute.service'; import { FileAttributes } from '@red/domain'; -import { ContextComponent } from '@iqser/common-ui'; import { FileAttributesService } from '@services/entity-services/file-attributes.service'; import { combineLatest, map, ReplaySubject } from 'rxjs'; +import { ContextComponent } from '@iqser/common-ui/lib/utils'; interface PartialFile { readonly isError: boolean; @@ -27,9 +27,9 @@ interface FileNameColumnContext { changeDetection: ChangeDetectionStrategy.OnPush, }) export class FileNameColumnComponent extends ContextComponent implements OnInit, OnChanges { + readonly #reloadAttribute = new ReplaySubject(1); @Input() file: PartialFile; @Input() dossierTemplateId: string; - readonly #reloadAttribute = new ReplaySubject(1); constructor( private readonly _fileAttributeService: FileAttributesService, diff --git a/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.ts b/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.ts index b2fdc9a8b..9272c9f73 100644 --- a/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.ts @@ -1,9 +1,11 @@ import { Component, ElementRef, EventEmitter, inject, Input, OnChanges, Output, ViewChild } from '@angular/core'; -import { CircleButtonTypes, getCurrentUser, List } from '@iqser/common-ui'; +import { CircleButtonTypes } from '@iqser/common-ui'; import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service'; import { Roles } from '@users/roles'; import { User } from '@red/domain'; import { UserService } from '@users/user.service'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { List } from '@iqser/common-ui/lib/utils'; @Component({ selector: 'redaction-team-members', diff --git a/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts b/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts index f75245113..1df39b876 100644 --- a/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts @@ -1,8 +1,8 @@ import { Component, Input, OnChanges } from '@angular/core'; -import { INestedFilter } from '@iqser/common-ui'; import { SuperTypes } from '@red/domain'; import { DefaultColorsService } from '@services/entity-services/default-colors.service'; import { TranslateService } from '@ngx-translate/core'; +import { INestedFilter } from '@iqser/common-ui/lib/filtering'; @Component({ selector: 'redaction-type-filter [dossierTemplateId]', @@ -10,12 +10,6 @@ import { TranslateService } from '@ngx-translate/core'; styleUrls: ['./type-filter.component.scss'], }) export class TypeFilterComponent implements OnChanges { - @Input() filter: INestedFilter; - @Input() dossierTemplateId: string; - @Input() dossierId: string; - - label: string; - private _suggestionsKeys: string[] = [ SuperTypes.SuggestionRemove, SuperTypes.SuggestionForceRedaction, @@ -26,6 +20,10 @@ export class TypeFilterComponent implements OnChanges { 'suggestion', ]; private _needsAnalysisKeys: string[] = ['remove-only-here', 'analysis']; + @Input() filter: INestedFilter; + @Input() dossierTemplateId: string; + @Input() dossierId: string; + label: string; constructor(private readonly _defaultColorsService: DefaultColorsService, private readonly _translateService: TranslateService) {} diff --git a/apps/red-ui/src/app/modules/shared/dialogs/download-dialog/download-dialog.component.ts b/apps/red-ui/src/app/modules/shared/dialogs/download-dialog/download-dialog.component.ts index 6459b005d..806d188a4 100644 --- a/apps/red-ui/src/app/modules/shared/dialogs/download-dialog/download-dialog.component.ts +++ b/apps/red-ui/src/app/modules/shared/dialogs/download-dialog/download-dialog.component.ts @@ -4,8 +4,9 @@ import { downloadTypesForDownloadTranslations } from '@translations/download-typ import { ReportTemplateService } from '@services/report-template.service'; import { AbstractControl, FormBuilder } from '@angular/forms'; import { DefaultColorsService } from '@services/entity-services/default-colors.service'; -import { IconButtonTypes, IqserDialogComponent, List } from '@iqser/common-ui'; +import { IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui'; import { Roles } from '@users/roles'; +import { List } from '@iqser/common-ui/lib/utils'; export interface DownloadDialogData { readonly dossier: Dossier; diff --git a/apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts b/apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts index 315d9de5d..c633e678a 100644 --- a/apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts +++ b/apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts @@ -1,7 +1,7 @@ import { Inject, LOCALE_ID, Pipe, PipeTransform } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { DatePipe as BaseDatePipe } from '@angular/common'; -import { getLeftDateTime } from '@iqser/common-ui'; +import { getLeftDateTime } from '@iqser/common-ui/lib/utils'; import dayjs from 'dayjs'; @Pipe({ diff --git a/apps/red-ui/src/app/modules/shared/shared.module.ts b/apps/red-ui/src/app/modules/shared/shared.module.ts index 4009a8470..7b57efef5 100644 --- a/apps/red-ui/src/app/modules/shared/shared.module.ts +++ b/apps/red-ui/src/app/modules/shared/shared.module.ts @@ -15,7 +15,6 @@ import { IqserAllowDirective, IqserDenyDirective, IqserHelpModeModule, - IqserUsersModule, SmallChipComponent, StopPropagationDirective, } from '@iqser/common-ui'; @@ -47,6 +46,7 @@ import { WatermarkSelectorComponent } from './components/dossier-watermark-selec import { OcrProgressBarComponent } from './components/ocr-progress-bar/ocr-progress-bar.component'; import { DownloadDialogComponent } from './dialogs/download-dialog/download-dialog.component'; import { CustomDateAdapter } from '@shared/CustomDateAdapter'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; const buttons = [FileDownloadBtnComponent]; diff --git a/apps/red-ui/src/app/modules/trash/trash-screen/trash-screen.component.ts b/apps/red-ui/src/app/modules/trash/trash-screen/trash-screen.component.ts index fd09a00c3..42848bc46 100644 --- a/apps/red-ui/src/app/modules/trash/trash-screen/trash-screen.component.ts +++ b/apps/red-ui/src/app/modules/trash/trash-screen/trash-screen.component.ts @@ -1,12 +1,5 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { - CircleButtonTypes, - ListingComponent, - listingProvidersFactory, - LoadingService, - SortingOrders, - TableColumnConfig, -} from '@iqser/common-ui'; +import { CircleButtonTypes, ListingComponent, listingProvidersFactory, LoadingService, TableColumnConfig } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { firstValueFrom, Observable } from 'rxjs'; import { distinctUntilChanged, map } from 'rxjs/operators'; @@ -14,6 +7,7 @@ import { RouterHistoryService } from '@services/router-history.service'; import { TrashItem } from '@red/domain'; import { TrashService } from '@services/entity-services/trash.service'; import { TrashDialogService } from '../services/trash-dialog.service'; +import { SortingOrders } from '@iqser/common-ui/lib/sorting'; @Component({ templateUrl: './trash-screen.component.html', diff --git a/apps/red-ui/src/app/modules/trash/trash.module.ts b/apps/red-ui/src/app/modules/trash/trash.module.ts index aa1cfe00e..7bd88b50e 100644 --- a/apps/red-ui/src/app/modules/trash/trash.module.ts +++ b/apps/red-ui/src/app/modules/trash/trash.module.ts @@ -2,11 +2,12 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; import { TrashScreenComponent } from './trash-screen/trash-screen.component'; -import { CircleButtonComponent, IqserListingModule, IqserUsersModule, TenantPipe } from '@iqser/common-ui'; +import { CircleButtonComponent, IqserListingModule, TenantPipe } from '@iqser/common-ui'; import { TrashTableItemComponent } from './trash-screen/trash-table-item/trash-table-item.component'; import { SharedModule } from '@shared/shared.module'; import { TrashDialogService } from './services/trash-dialog.service'; import { TranslateModule } from '@ngx-translate/core'; +import { IqserUsersModule } from '@iqser/common-ui/lib/users'; const routes = [{ path: '', component: TrashScreenComponent }]; diff --git a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts index 460e55592..881a61d29 100644 --- a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts +++ b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts @@ -3,8 +3,9 @@ import { DownloadStatus, IDownloadStatus, IDownloadStatusResponse, IPrepareDownl import { firstValueFrom, Observable } from 'rxjs'; import { ConfigService } from '@services/config.service'; import { map, tap } from 'rxjs/operators'; -import { EntitiesService, mapEach, TenantsService } from '@iqser/common-ui'; +import { EntitiesService, TenantsService } from '@iqser/common-ui'; import { NGXLogger } from 'ngx-logger'; +import { mapEach } from '@iqser/common-ui/lib/utils'; @Injectable() export class FileDownloadService extends EntitiesService { 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 2a85dda07..a324624e8 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 @@ -6,12 +6,13 @@ import { ConfigService } from '@services/config.service'; import { TranslateService } from '@ngx-translate/core'; import { IFileUploadResult, OverwriteFileOption, OverwriteFileOptions } from '@red/domain'; import { isAcceptedFileType, isCsv, isZip } from '@utils/file-drop-utils'; -import { ErrorMessageService, GenericService, HeadersConfiguration, Toaster } from '@iqser/common-ui'; +import { ErrorMessageService, GenericService, Toaster } from '@iqser/common-ui'; import { FilesMapService } from '@services/files/files-map.service'; import { switchMap, tap, throttleTime } from 'rxjs/operators'; import { FilesService } from '@services/files/files.service'; import { UploadDownloadDialogService } from './upload-download-dialog.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { HeadersConfiguration } from '@iqser/common-ui/lib/utils'; export interface ActiveUpload { subscription: Subscription; @@ -21,15 +22,14 @@ export interface ActiveUpload { @Injectable() export class FileUploadService extends GenericService implements OnDestroy { static readonly MAX_PARALLEL_UPLOADS = 5; + #pendingUploads: FileUploadModel[] = []; + #activeUploads: ActiveUpload[] = []; + readonly #fetchFiles$ = new Subject(); + readonly #subscriptions = new Subscription(); + protected readonly _defaultModelPath = 'upload'; files: FileUploadModel[] = []; groupedFiles: { [key: string]: FileUploadModel[] } = {}; activeUploads = 0; - protected readonly _defaultModelPath = 'upload'; - #pendingUploads: FileUploadModel[] = []; - #activeUploads: ActiveUpload[] = []; - - readonly #fetchFiles$ = new Subject(); - readonly #subscriptions = new Subscription(); constructor( private readonly _filesService: FilesService, diff --git a/apps/red-ui/src/app/services/breadcrumbs.service.ts b/apps/red-ui/src/app/services/breadcrumbs.service.ts index 5233556ef..a2a2242f4 100644 --- a/apps/red-ui/src/app/services/breadcrumbs.service.ts +++ b/apps/red-ui/src/app/services/breadcrumbs.service.ts @@ -1,5 +1,5 @@ import { Injectable, Injector } from '@angular/core'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { ActivatedRouteSnapshot, IsActiveMatchOptions, NavigationEnd, Router } from '@angular/router'; import { BehaviorSubject, Observable, of } from 'rxjs'; import { filter, pluck } from 'rxjs/operators'; @@ -32,8 +32,8 @@ export type Breadcrumbs = List; providedIn: 'root', }) export class BreadcrumbsService { - readonly breadcrumbs$: Observable; readonly #store$ = new BehaviorSubject([]); + readonly breadcrumbs$: Observable; constructor( private readonly _injector: Injector, diff --git a/apps/red-ui/src/app/services/dossier-templates/dashboard-stats.service.ts b/apps/red-ui/src/app/services/dossier-templates/dashboard-stats.service.ts index 3fab25c8c..80a7de45c 100644 --- a/apps/red-ui/src/app/services/dossier-templates/dashboard-stats.service.ts +++ b/apps/red-ui/src/app/services/dossier-templates/dashboard-stats.service.ts @@ -1,9 +1,10 @@ -import { EntitiesService, mapEach } from '@iqser/common-ui'; +import { EntitiesService } from '@iqser/common-ui'; import { DashboardStats, IDashboardStats } from '@red/domain'; import { inject, Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map, switchMap, tap } from 'rxjs/operators'; import { DossierStatesService } from '../entity-services/dossier-states.service'; +import { mapEach } from '@iqser/common-ui/lib/utils'; const templatesSorter = (a: DashboardStats, b: DashboardStats) => { if (!a.isEmpty && b.isEmpty) { @@ -18,11 +19,10 @@ const templatesSorter = (a: DashboardStats, b: DashboardStats) => { providedIn: 'root', }) export class DashboardStatsService extends EntitiesService { + readonly #dossierStatesService = inject(DossierStatesService); protected readonly _defaultModelPath = 'dossier-template/stats'; protected readonly _entityClass = DashboardStats; - readonly #dossierStatesService = inject(DossierStatesService); - loadAll(): Observable { return this.getAll(this._defaultModelPath).pipe( mapEach(entity => new DashboardStats(entity)), diff --git a/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts b/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts index 9d3fc3d8c..001ea18b3 100644 --- a/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts +++ b/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts @@ -1,4 +1,4 @@ -import { EntitiesService, List, mapEach, Toaster } from '@iqser/common-ui'; +import { EntitiesService, Toaster } from '@iqser/common-ui'; import { DossierTemplate, IDossierTemplate } from '@red/domain'; import { Injectable } from '@angular/core'; import { firstValueFrom, forkJoin, Observable, of } from 'rxjs'; @@ -10,6 +10,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { DictionaryService } from '../entity-services/dictionary.service'; import { DefaultColorsService } from '@services/entity-services/default-colors.service'; import { WatermarkService } from '@services/entity-services/watermark.service'; +import { List, mapEach } from '@iqser/common-ui/lib/utils'; const DOSSIER_TEMPLATE_CONFLICT_MSG = _('dossier-templates-listing.error.conflict'); const GENERIC_MSG = _('dossier-templates-listing.error.generic'); diff --git a/apps/red-ui/src/app/services/dossiers/dossier-changes.service.ts b/apps/red-ui/src/app/services/dossiers/dossier-changes.service.ts index d8f0ad4a6..59ff85819 100644 --- a/apps/red-ui/src/app/services/dossiers/dossier-changes.service.ts +++ b/apps/red-ui/src/app/services/dossiers/dossier-changes.service.ts @@ -1,4 +1,4 @@ -import { GenericService, LAST_CHECKED_OFFSET, List, QueryParam, ROOT_CHANGES_KEY } from '@iqser/common-ui'; +import { GenericService, LAST_CHECKED_OFFSET, QueryParam, ROOT_CHANGES_KEY } from '@iqser/common-ui'; import { Dossier, DossierStats, IDossierChanges } from '@red/domain'; import { forkJoin, Observable, of, Subscription, throwError, timer } from 'rxjs'; import { catchError, filter, map, switchMap, take, tap } from 'rxjs/operators'; @@ -9,16 +9,16 @@ import { ArchivedDossiersService } from './archived-dossiers.service'; import { inject, Injectable, OnDestroy } from '@angular/core'; import { DashboardStatsService } from '../dossier-templates/dashboard-stats.service'; import { CHANGED_CHECK_INTERVAL } from '@utils/constants'; +import { List } from '@iqser/common-ui/lib/utils'; @Injectable({ providedIn: 'root' }) export class DossiersChangesService extends GenericService implements OnDestroy { - protected readonly _defaultModelPath = 'dossier'; readonly #subscription = new Subscription(); - readonly #activeDossiersService = inject(ActiveDossiersService); readonly #archivedDossiersService = inject(ArchivedDossiersService); readonly #dashboardStatsService = inject(DashboardStatsService); readonly #logger = inject(NGXLogger); + protected readonly _defaultModelPath = 'dossier'; loadOnlyChanged(): Observable { const removeIfNotFound = (id: string) => diff --git a/apps/red-ui/src/app/services/dossiers/dossiers.service.ts b/apps/red-ui/src/app/services/dossiers/dossiers.service.ts index deeda58bf..23393b67c 100644 --- a/apps/red-ui/src/app/services/dossiers/dossiers.service.ts +++ b/apps/red-ui/src/app/services/dossiers/dossiers.service.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/member-ordering */ -import { EntitiesService, mapEach, Toaster } from '@iqser/common-ui'; +import { EntitiesService, Toaster } from '@iqser/common-ui'; import { Dossier, DossierStats, IDossier, IDossierChanges, IDossierRequest } from '@red/domain'; import { Observable, of, Subject } from 'rxjs'; import { catchError, map, switchMap, tap } from 'rxjs/operators'; @@ -8,18 +8,19 @@ import { DossierStatsService } from './dossier-stats.service'; import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { DashboardStatsService } from '../dossier-templates/dashboard-stats.service'; +import { mapEach } from '@iqser/common-ui/lib/utils'; const CONFLICT_MSG = _('add-dossier-dialog.errors.dossier-already-exists'); const GENERIC_MSG = _('add-dossier-dialog.errors.generic'); export abstract class DossiersService extends EntitiesService { - readonly dossierFileChanges$ = new Subject(); - abstract readonly routerPath: string; protected readonly _dossierStatsService = inject(DossierStatsService); protected readonly _dashboardStatsService = inject(DashboardStatsService); protected readonly _toaster = inject(Toaster); protected readonly _entityClass = Dossier; protected abstract readonly _defaultModelPath: string; + readonly dossierFileChanges$ = new Subject(); + abstract readonly routerPath: string; createOrUpdate(dossier: IDossierRequest): Observable { const showToast = (error: HttpErrorResponse) => { diff --git a/apps/red-ui/src/app/services/entity-permissions/entity-permissions.service.ts b/apps/red-ui/src/app/services/entity-permissions/entity-permissions.service.ts index 09bd2dccf..f753cd5c0 100644 --- a/apps/red-ui/src/app/services/entity-permissions/entity-permissions.service.ts +++ b/apps/red-ui/src/app/services/entity-permissions/entity-permissions.service.ts @@ -1,19 +1,19 @@ import { inject, Injectable } from '@angular/core'; -import { GenericService, mapEach } from '@iqser/common-ui'; +import { GenericService } from '@iqser/common-ui'; import { IPermissionsMapping, PermissionsMapping } from '@red/domain'; import { firstValueFrom, Observable } from 'rxjs'; import { switchMap, tap } from 'rxjs/operators'; import { PermissionsConfigurationMapService } from './permissions-configuration-map.service'; import { PermissionsMapService } from './permissions-map.service'; +import { mapEach } from '@iqser/common-ui/lib/utils'; @Injectable({ providedIn: 'root', }) export class EntityPermissionsService extends GenericService { - protected readonly _defaultModelPath = 'permissions'; - readonly #permissionsConfigurationMapService = inject(PermissionsConfigurationMapService); readonly #permissionsMapService = inject(PermissionsMapService); + protected readonly _defaultModelPath = 'permissions'; loadConfigFor(targetObject: string): Observable { return this._http.get(`/${this._serviceName}/${this._defaultModelPath}/${targetObject}/mapping`).pipe( diff --git a/apps/red-ui/src/app/services/entity-services/default-colors.service.ts b/apps/red-ui/src/app/services/entity-services/default-colors.service.ts index 127c15a5f..dbc5a6f7f 100644 --- a/apps/red-ui/src/app/services/entity-services/default-colors.service.ts +++ b/apps/red-ui/src/app/services/entity-services/default-colors.service.ts @@ -1,8 +1,9 @@ import { Injectable } from '@angular/core'; -import { EntitiesService, mapEach } from '@iqser/common-ui'; +import { EntitiesService } from '@iqser/common-ui'; import { DefaultColors, DefaultColorType, IDefaultColors } from '@red/domain'; import { forkJoin, Observable } from 'rxjs'; import { map, switchMap, tap } from 'rxjs/operators'; +import { mapEach } from '@iqser/common-ui/lib/utils'; @Injectable({ providedIn: 'root', diff --git a/apps/red-ui/src/app/services/entity-services/dictionary.service.ts b/apps/red-ui/src/app/services/entity-services/dictionary.service.ts index 46277ea1c..56cfdb919 100644 --- a/apps/red-ui/src/app/services/entity-services/dictionary.service.ts +++ b/apps/red-ui/src/app/services/entity-services/dictionary.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { firstValueFrom, forkJoin, Observable, throwError } from 'rxjs'; -import { EntitiesService, List, QueryParam, Toaster } from '@iqser/common-ui'; +import { EntitiesService, QueryParam, Toaster } from '@iqser/common-ui'; import { Dictionary, DictionaryEntryType, DictionaryEntryTypes, IDictionary, IUpdateDictionary, SuperTypes } from '@red/domain'; import { catchError, map, switchMap, tap } from 'rxjs/operators'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -9,6 +9,7 @@ import { DictionariesMapService } from './dictionaries-map.service'; import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { FALLBACK_COLOR } from '@utils/constants'; import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service'; +import { List } from '@iqser/common-ui/lib/utils'; const MIN_WORD_LENGTH = 2; diff --git a/apps/red-ui/src/app/services/entity-services/dossier-attributes.service.ts b/apps/red-ui/src/app/services/entity-services/dossier-attributes.service.ts index 2b7ad34e6..96e5eb509 100644 --- a/apps/red-ui/src/app/services/entity-services/dossier-attributes.service.ts +++ b/apps/red-ui/src/app/services/entity-services/dossier-attributes.service.ts @@ -1,8 +1,9 @@ import { Injectable } from '@angular/core'; import { Dossier, DossierAttributeConfig, DossierAttributeWithValue, IDossierAttribute, IDossierAttributeConfig } from '@red/domain'; import { firstValueFrom, Observable } from 'rxjs'; -import { EntitiesService, List, mapEach } from '@iqser/common-ui'; +import { EntitiesService } from '@iqser/common-ui'; import { map, tap } from 'rxjs/operators'; +import { List, mapEach } from '@iqser/common-ui/lib/utils'; @Injectable({ providedIn: 'root', 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 e50468aa4..a10efcb51 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 @@ -1,5 +1,5 @@ import { inject, Injectable } from '@angular/core'; -import { EntitiesService, mapEach, Toaster } from '@iqser/common-ui'; +import { EntitiesService, Toaster } from '@iqser/common-ui'; import { DossierState, IDossierState } from '@red/domain'; import { EMPTY, firstValueFrom, forkJoin, Observable, switchMap } from 'rxjs'; import { DossierTemplatesService } from '../dossier-templates/dossier-templates.service'; @@ -7,6 +7,7 @@ import { catchError, defaultIfEmpty, tap } from 'rxjs/operators'; import { DossierStatesMapService } from '../entity-services/dossier-states-map.service'; import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; 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'); @@ -15,12 +16,11 @@ const GENERIC_MSG = _('dossier-states-listing.error.generic'); 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) => { diff --git a/apps/red-ui/src/app/services/entity-services/file-attributes.service.ts b/apps/red-ui/src/app/services/entity-services/file-attributes.service.ts index f42f701c0..5b478953d 100644 --- a/apps/red-ui/src/app/services/entity-services/file-attributes.service.ts +++ b/apps/red-ui/src/app/services/entity-services/file-attributes.service.ts @@ -1,8 +1,9 @@ -import { EntitiesService, List } from '@iqser/common-ui'; +import { EntitiesService } from '@iqser/common-ui'; import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable, of } from 'rxjs'; import { catchError, tap } from 'rxjs/operators'; import { FileAttributeConfig, FileAttributes, IFileAttributeConfig, IFileAttributesConfig } from '@red/domain'; +import { List } from '@iqser/common-ui/lib/utils'; export type FileAttributesConfigMap = Readonly>; @@ -10,10 +11,10 @@ export type FileAttributesConfigMap = Readonly { - readonly fileAttributesConfig$ = new BehaviorSubject({}); - readonly isEditingFileAttribute$ = new BehaviorSubject(false); protected readonly _defaultModelPath = 'fileAttributes'; protected readonly _entityClass = FileAttributeConfig; + readonly fileAttributesConfig$ = new BehaviorSubject({}); + readonly isEditingFileAttribute$ = new BehaviorSubject(false); /** * Get the file attributes that can be used at importing csv. diff --git a/apps/red-ui/src/app/services/entity-services/trash.service.ts b/apps/red-ui/src/app/services/entity-services/trash.service.ts index ea2da9f94..921c40d9f 100644 --- a/apps/red-ui/src/app/services/entity-services/trash.service.ts +++ b/apps/red-ui/src/app/services/entity-services/trash.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { EntitiesService, List, mapEach, QueryParam, Toaster } from '@iqser/common-ui'; +import { EntitiesService, QueryParam, Toaster } from '@iqser/common-ui'; import { Dossier, File, IDossier, IFile, TrashDossier, TrashFile, TrashItem } from '@red/domain'; import { catchError, switchMap, take, tap } from 'rxjs/operators'; import { forkJoin, map, Observable, of } from 'rxjs'; @@ -12,6 +12,7 @@ import { DossierStatsService } from '../dossiers/dossier-stats.service'; import { FilesService } from '../files/files.service'; import { SystemPreferencesService } from '@services/system-preferences.service'; import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.service'; +import { List, mapEach } from '@iqser/common-ui/lib/utils'; @Injectable({ providedIn: 'root', diff --git a/apps/red-ui/src/app/services/entity-services/watermark.service.ts b/apps/red-ui/src/app/services/entity-services/watermark.service.ts index decb17bce..a88897203 100644 --- a/apps/red-ui/src/app/services/entity-services/watermark.service.ts +++ b/apps/red-ui/src/app/services/entity-services/watermark.service.ts @@ -1,9 +1,10 @@ import { inject, Injectable } from '@angular/core'; -import { GenericService, mapEach, QueryParam } from '@iqser/common-ui'; +import { GenericService, QueryParam } from '@iqser/common-ui'; import { IWatermark, Watermark } from '@red/domain'; import { firstValueFrom, forkJoin, Observable } from 'rxjs'; import { map, tap } from 'rxjs/operators'; import { WatermarksMapService } from '@services/entity-services/watermarks-map.service'; +import { mapEach } from '@iqser/common-ui/lib/utils'; interface IsUsedResponse { value: boolean; @@ -13,8 +14,8 @@ interface IsUsedResponse { providedIn: 'root', }) export class WatermarkService extends GenericService { - protected readonly _defaultModelPath = 'watermark'; readonly #watermarksMapService = inject(WatermarksMapService); + protected readonly _defaultModelPath = 'watermark'; async deleteWatermark(dossierTemplateId: string, watermarkId: number) { await firstValueFrom(super.delete(null, `${this._defaultModelPath}/${watermarkId}`)); diff --git a/apps/red-ui/src/app/services/files/file-management.service.ts b/apps/red-ui/src/app/services/files/file-management.service.ts index c742b4dea..c8462183c 100644 --- a/apps/red-ui/src/app/services/files/file-management.service.ts +++ b/apps/red-ui/src/app/services/files/file-management.service.ts @@ -1,17 +1,18 @@ -import { GenericService, HeadersConfiguration, List, QueryParam } from '@iqser/common-ui'; +import { GenericService, QueryParam } from '@iqser/common-ui'; import { inject, Injectable } from '@angular/core'; import { HttpEvent, HttpHeaders, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { switchMap } from 'rxjs/operators'; import { FilesService } from './files.service'; import { File, IPageRotationRequest } from '@red/domain'; +import { HeadersConfiguration, List } from '@iqser/common-ui/lib/utils'; @Injectable({ providedIn: 'root', }) export class FileManagementService extends GenericService { - protected readonly _defaultModelPath = ''; readonly #filesService = inject(FilesService); + protected readonly _defaultModelPath = ''; delete(files: List, dossierId: string) { const fileIds = files.map(f => f.id); diff --git a/apps/red-ui/src/app/services/files/files-map.service.ts b/apps/red-ui/src/app/services/files/files-map.service.ts index 4d7ff84e0..97b72b6e9 100644 --- a/apps/red-ui/src/app/services/files/files-map.service.ts +++ b/apps/red-ui/src/app/services/files/files-map.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; import { File, IFile } from '@red/domain'; -import { EntitiesMapService, NonFunctionKeys } from '@iqser/common-ui'; +import { EntitiesMapService } from '@iqser/common-ui'; +import { NonFunctionKeys } from '@iqser/common-ui/lib/utils'; @Injectable({ providedIn: 'root' }) export class FilesMapService extends EntitiesMapService { diff --git a/apps/red-ui/src/app/services/files/files.service.ts b/apps/red-ui/src/app/services/files/files.service.ts index b177c6c6c..34ffe30f2 100644 --- a/apps/red-ui/src/app/services/files/files.service.ts +++ b/apps/red-ui/src/app/services/files/files.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { EntitiesService, isArray, List, mapEach, QueryParam } from '@iqser/common-ui'; +import { EntitiesService, isArray, QueryParam } from '@iqser/common-ui'; import { File, IFile } from '@red/domain'; import { firstValueFrom } from 'rxjs'; import { UserService } from '@users/user.service'; @@ -7,6 +7,7 @@ import { FilesMapService } from './files-map.service'; import { map, switchMap, tap } from 'rxjs/operators'; import { DossierStatsService } from '../dossiers/dossier-stats.service'; import { NGXLogger } from 'ngx-logger'; +import { List, mapEach } from '@iqser/common-ui/lib/utils'; const asList = (value: T | List): List => (isArray(value) ? value : [value]); diff --git a/apps/red-ui/src/app/services/files/redaction-import.service.ts b/apps/red-ui/src/app/services/files/redaction-import.service.ts index fc5451b62..22d3ea1cb 100644 --- a/apps/red-ui/src/app/services/files/redaction-import.service.ts +++ b/apps/red-ui/src/app/services/files/redaction-import.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@angular/core'; -import { GenericService, HeadersConfiguration } from '@iqser/common-ui'; +import { GenericService } from '@iqser/common-ui'; +import { HeadersConfiguration } from '@iqser/common-ui/lib/utils'; @Injectable({ providedIn: 'root' }) export class RedactionImportService extends GenericService { diff --git a/apps/red-ui/src/app/services/files/viewed-pages.service.ts b/apps/red-ui/src/app/services/files/viewed-pages.service.ts index 7db4f0875..a13f61dc0 100644 --- a/apps/red-ui/src/app/services/files/viewed-pages.service.ts +++ b/apps/red-ui/src/app/services/files/viewed-pages.service.ts @@ -1,8 +1,9 @@ import { Injectable } from '@angular/core'; -import { GenericService, mapEach } from '@iqser/common-ui'; +import { GenericService } from '@iqser/common-ui'; import { catchError, map } from 'rxjs/operators'; import { IViewedPage, IViewedPagesRequest, ViewedPage } from '@red/domain'; import { firstValueFrom, of } from 'rxjs'; +import { mapEach } from '@iqser/common-ui/lib/utils'; @Injectable({ providedIn: 'root', diff --git a/apps/red-ui/src/app/services/notifications.service.ts b/apps/red-ui/src/app/services/notifications.service.ts index a6c54e82b..ddcf42191 100644 --- a/apps/red-ui/src/app/services/notifications.service.ts +++ b/apps/red-ui/src/app/services/notifications.service.ts @@ -1,5 +1,5 @@ import { Inject, Injectable, OnDestroy } from '@angular/core'; -import { BASE_HREF, EntitiesService, getConfig, List, mapEach, QueryParam, TenantsService } from '@iqser/common-ui'; +import { EntitiesService, getConfig, QueryParam, TenantsService } from '@iqser/common-ui'; import { TranslateService } from '@ngx-translate/core'; import { EMPTY, firstValueFrom, iif, merge, Observable, of, Subscription, timer } from 'rxjs'; import { AppConfig, Dossier, INotification, Notification, NotificationTypes } from '@red/domain'; @@ -10,6 +10,7 @@ import { UserService } from '@users/user.service'; import { CHANGED_CHECK_INTERVAL } from '@utils/constants'; import { DossiersCacheService } from './dossiers/dossiers-cache.service'; import dayjs from 'dayjs'; +import { BASE_HREF, List, mapEach } from '@iqser/common-ui/lib/utils'; const INCLUDE_SEEN = false; @@ -21,11 +22,10 @@ const NOTIFICATIONS_THRESHOLD = 1000; providedIn: 'root', }) export class NotificationsService extends EntitiesService implements OnDestroy { - protected readonly _defaultModelPath = 'notification'; - protected readonly _entityClass = Notification; - readonly #config = getConfig(); readonly #subscription = new Subscription(); + protected readonly _defaultModelPath = 'notification'; + protected readonly _entityClass = Notification; constructor( @Inject(BASE_HREF) private readonly _baseHref: string, diff --git a/apps/red-ui/src/app/services/reanalysis.service.ts b/apps/red-ui/src/app/services/reanalysis.service.ts index 74977606e..181ca4481 100644 --- a/apps/red-ui/src/app/services/reanalysis.service.ts +++ b/apps/red-ui/src/app/services/reanalysis.service.ts @@ -1,11 +1,12 @@ import { Injectable } from '@angular/core'; -import { GenericService, List, QueryParam, Toaster } from '@iqser/common-ui'; +import { GenericService, QueryParam, Toaster } from '@iqser/common-ui'; import { Dossier, File, IPageExclusionRequest } from '@red/domain'; import { catchError, tap } from 'rxjs/operators'; import { FilesService } from './files/files.service'; import { FilesMapService } from './files/files-map.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { firstValueFrom, of } from 'rxjs'; +import { List } from '@iqser/common-ui/lib/utils'; export interface ReanalyzeQueryParams { force?: boolean; diff --git a/apps/red-ui/src/app/services/report-template.service.ts b/apps/red-ui/src/app/services/report-template.service.ts index 792dad7ef..c2c835c2f 100644 --- a/apps/red-ui/src/app/services/report-template.service.ts +++ b/apps/red-ui/src/app/services/report-template.service.ts @@ -1,9 +1,10 @@ import { Injectable } from '@angular/core'; -import { GenericService, HeadersConfiguration } from '@iqser/common-ui'; +import { GenericService } from '@iqser/common-ui'; import { IPlaceholdersResponse, IReportTemplate } from '@red/domain'; import { firstValueFrom, Observable, of } from 'rxjs'; import { HttpResponse } from '@angular/common/http'; import { catchError, map } from 'rxjs/operators'; +import { HeadersConfiguration } from '@iqser/common-ui/lib/utils'; @Injectable({ providedIn: 'root', diff --git a/apps/red-ui/src/app/translations/annotation-changes-translations.ts b/apps/red-ui/src/app/translations/annotation-changes-translations.ts index 999f8616b..cdc0a534f 100644 --- a/apps/red-ui/src/app/translations/annotation-changes-translations.ts +++ b/apps/red-ui/src/app/translations/annotation-changes-translations.ts @@ -1,6 +1,6 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { KeysOf } from '@iqser/common-ui'; +import { KeysOf } from '@iqser/common-ui/lib/utils'; export const annotationChangesTranslations: { [key in KeysOf]?: string } = { hasBeenResized: _('annotation-changes.resized'), diff --git a/apps/red-ui/src/app/translations/system-preferences-translations.ts b/apps/red-ui/src/app/translations/system-preferences-translations.ts index d2aaf0f93..c1a050298 100644 --- a/apps/red-ui/src/app/translations/system-preferences-translations.ts +++ b/apps/red-ui/src/app/translations/system-preferences-translations.ts @@ -1,6 +1,6 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { SystemPreferences } from '@red/domain'; -import { KeysOf } from '@iqser/common-ui'; +import { KeysOf } from '@iqser/common-ui/lib/utils'; export const systemPreferencesTranslations: Record<'label' | 'placeholder', Record, string>> = { label: { diff --git a/apps/red-ui/src/app/users/red-role.guard.ts b/apps/red-ui/src/app/users/red-role.guard.ts index f8c9d442f..8cb5a9746 100644 --- a/apps/red-ui/src/app/users/red-role.guard.ts +++ b/apps/red-ui/src/app/users/red-role.guard.ts @@ -1,17 +1,23 @@ import { inject, Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; -import { IqserPermissionsService, IqserRoleGuard } from '@iqser/common-ui'; +import { IqserPermissionsService } from '@iqser/common-ui'; +import { IqserRoleGuard } from '@iqser/common-ui/lib/users'; +import { UserService } from '@users/user.service'; +import { NGXLogger } from 'ngx-logger'; @Injectable({ providedIn: 'root', }) export class RedRoleGuard extends IqserRoleGuard { protected readonly _permissionsService = inject(IqserPermissionsService); + protected readonly _userService = inject(UserService); + protected readonly _logger = inject(NGXLogger); async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise { const currentUser = this._userService.currentUser; if (!currentUser?.hasAnyRole) { + this._logger.warn('[GUARD] User has no roles, redirect to auth-error'); await this._router.navigate([`/${this._tenantsService.activeTenantId}/auth-error`]); this._loadingService.stop(); return false; @@ -19,6 +25,7 @@ export class RedRoleGuard extends IqserRoleGuard { // we have at least 1 RED Role -> if it's not user he must be an admin if (currentUser.isUserAdmin && !currentUser.isAdmin && state.url.includes('admin') && !state.url.includes('users')) { + this._logger.warn('[GUARD] Redirect to users page'); await this._router.navigate([`/${this._tenantsService.activeTenantId}/main/admin/users`]); return false; } @@ -40,6 +47,7 @@ export class RedRoleGuard extends IqserRoleGuard { if (!currentUser.isUser) { await this._router.navigate([`/${this._tenantsService.activeTenantId}/main/admin`]); } else { + this._logger.warn('[GUARD] Redirect to tenant route'); await this._router.navigate([`/${this._tenantsService.activeTenantId}`]); } return false; diff --git a/apps/red-ui/src/app/users/user.service.ts b/apps/red-ui/src/app/users/user.service.ts index f1a012108..aaf2a7074 100644 --- a/apps/red-ui/src/app/users/user.service.ts +++ b/apps/red-ui/src/app/users/user.service.ts @@ -1,8 +1,10 @@ import { inject, Injectable } from '@angular/core'; import { User } from '@red/domain'; -import { IIqserUser, IqserUserService, List, QueryParam } from '@iqser/common-ui'; +import { QueryParam } from '@iqser/common-ui'; import { Roles } from '@users/roles'; import { of } from 'rxjs'; +import { IIqserUser, IqserUserService } from '@iqser/common-ui/lib/users'; +import { List } from '@iqser/common-ui/lib/utils'; @Injectable({ providedIn: 'root', diff --git a/apps/red-ui/src/app/utils/csv-utils.ts b/apps/red-ui/src/app/utils/csv-utils.ts index 672960308..4f9edd3ac 100644 --- a/apps/red-ui/src/app/utils/csv-utils.ts +++ b/apps/red-ui/src/app/utils/csv-utils.ts @@ -1,5 +1,5 @@ -import { humanize } from '@iqser/common-ui'; import { saveAs } from 'file-saver'; +import { humanize } from '@iqser/common-ui/lib/utils'; function toCSVContent(lines: any[], keys: string[]) { return lines diff --git a/apps/red-ui/src/app/utils/filter-utils.ts b/apps/red-ui/src/app/utils/filter-utils.ts index c680682cf..939bde6a2 100644 --- a/apps/red-ui/src/app/utils/filter-utils.ts +++ b/apps/red-ui/src/app/utils/filter-utils.ts @@ -1,5 +1,5 @@ import { Dossier, File, User, UserType } from '@red/domain'; -import { handleCheckedValue, INestedFilter } from '@iqser/common-ui'; +import { handleCheckedValue, INestedFilter } from '@iqser/common-ui/lib/filtering'; export function handleFilterDelta(oldFilters: INestedFilter[], newFilters: INestedFilter[], allFilters: INestedFilter[]) { const newFiltersDelta = {}; diff --git a/apps/red-ui/src/app/utils/functions.ts b/apps/red-ui/src/app/utils/functions.ts index ed720c96f..b63b3aa2a 100644 --- a/apps/red-ui/src/app/utils/functions.ts +++ b/apps/red-ui/src/app/utils/functions.ts @@ -1,4 +1,4 @@ -import type { List } from '@iqser/common-ui'; +import type { List } from '@iqser/common-ui/lib/utils'; import { ITrackable } from '@iqser/common-ui'; import type { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { Dayjs } from 'dayjs'; diff --git a/apps/red-ui/src/app/utils/main.resolver.ts b/apps/red-ui/src/app/utils/main.resolver.ts index 2ebc0f383..ad732fca3 100644 --- a/apps/red-ui/src/app/utils/main.resolver.ts +++ b/apps/red-ui/src/app/utils/main.resolver.ts @@ -5,7 +5,7 @@ import { UserService } from '@users/user.service'; import { SystemPreferencesService } from '@services/system-preferences.service'; import { UserPreferenceService } from '@users/user-preference.service'; import { LicenseService } from '@services/license.service'; -import { BASE_HREF, IqserPermissionsService, LoadingService, TenantsService } from '@iqser/common-ui'; +import { IqserPermissionsService, LoadingService, TenantsService } from '@iqser/common-ui'; import { FeaturesService } from '@services/features.service'; import { GeneralSettingsService } from '@services/general-settings.service'; import { tap } from 'rxjs/operators'; @@ -13,6 +13,7 @@ import { firstValueFrom } from 'rxjs'; import { Roles } from '@users/roles'; import { DossiersChangesService } from '@services/dossiers/dossier-changes.service'; import { ResolveFn } from '@angular/router'; +import { BASE_HREF } from '@iqser/common-ui/lib/utils'; function redirectToLastDossierTemplate(baseHref: string, tenant: string, lastDossierTemplate: string) { const lastUrlSegment = window.location.pathname.split('/').filter(Boolean).pop(); @@ -43,7 +44,6 @@ export const mainResolver: ResolveFn = async () => { const updatedDisplayName$ = generalConfig$.pipe(tap(config => configService.updateDisplayName(config.displayName))); await Promise.all([ - userService.initialize(), systemPreferencesService.loadPreferences(), userPreferenceService.reload(), firstValueFrom(updatedDisplayName$), diff --git a/libs/common-ui b/libs/common-ui index cc8d04065..8ac4bbfd9 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit cc8d040654ab4d3bc1e8e95368a69d495bb3b9b7 +Subproject commit 8ac4bbfd9fa98c9172bf2040c763cb934d7f00a7 diff --git a/libs/red-domain/src/lib/audit/audit.response.ts b/libs/red-domain/src/lib/audit/audit.response.ts index 31ebc9543..91c835167 100644 --- a/libs/red-domain/src/lib/audit/audit.response.ts +++ b/libs/red-domain/src/lib/audit/audit.response.ts @@ -1,5 +1,5 @@ import { IAudit } from './audit'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface IAuditResponse { data: List; diff --git a/libs/red-domain/src/lib/dictionaries/dictionary.model.ts b/libs/red-domain/src/lib/dictionaries/dictionary.model.ts index 8c5e2e5c1..329d8472f 100644 --- a/libs/red-domain/src/lib/dictionaries/dictionary.model.ts +++ b/libs/red-domain/src/lib/dictionaries/dictionary.model.ts @@ -1,6 +1,7 @@ -import { Entity, List } from '@iqser/common-ui'; +import { Entity } from '@iqser/common-ui'; import { IDictionary } from './dictionary'; import { DICTIONARY_TYPE_KEY_MAP, DictionaryType } from '../redaction-log'; +import { List } from '@iqser/common-ui/lib/utils'; export class Dictionary extends Entity implements IDictionary { readonly addToDictionaryAction: boolean; diff --git a/libs/red-domain/src/lib/dictionaries/dictionary.ts b/libs/red-domain/src/lib/dictionaries/dictionary.ts index bb525afe2..2a6261360 100644 --- a/libs/red-domain/src/lib/dictionaries/dictionary.ts +++ b/libs/red-domain/src/lib/dictionaries/dictionary.ts @@ -1,7 +1,7 @@ /** * Object containing a list of dictionary entries and colors of an entry type. */ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface IDictionary { /** diff --git a/libs/red-domain/src/lib/dossier-templates/dashboard-stats.model.ts b/libs/red-domain/src/lib/dossier-templates/dashboard-stats.model.ts index a70f48b9f..8e1ff4ace 100644 --- a/libs/red-domain/src/lib/dossier-templates/dashboard-stats.model.ts +++ b/libs/red-domain/src/lib/dossier-templates/dashboard-stats.model.ts @@ -1,7 +1,8 @@ -import { IListable, List } from '@iqser/common-ui'; +import { IListable } from '@iqser/common-ui'; import { CountByStatus, CountPerProcessingStatus, CountPerWorkflowStatus, IDashboardStats } from './dashboard-stats'; import { DonutChartConfig, StatusSorter } from '../shared'; import { DossierTemplateStatus, DossierTemplateStatuses } from './constants'; +import { List } from '@iqser/common-ui/lib/utils'; export class DashboardStats implements IListable, IDashboardStats { readonly dossierCountByStatus: List; diff --git a/libs/red-domain/src/lib/dossier-templates/dashboard-stats.ts b/libs/red-domain/src/lib/dossier-templates/dashboard-stats.ts index cf90e0545..1118bf9ca 100644 --- a/libs/red-domain/src/lib/dossier-templates/dashboard-stats.ts +++ b/libs/red-domain/src/lib/dossier-templates/dashboard-stats.ts @@ -1,5 +1,5 @@ import { ProcessingFileStatus, WorkflowFileStatus } from '../files'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { DossierTemplateStatus } from './constants'; interface Counter { diff --git a/libs/red-domain/src/lib/dossier-templates/dossier-template.model.ts b/libs/red-domain/src/lib/dossier-templates/dossier-template.model.ts index 811a06cc9..6285071a3 100644 --- a/libs/red-domain/src/lib/dossier-templates/dossier-template.model.ts +++ b/libs/red-domain/src/lib/dossier-templates/dossier-template.model.ts @@ -1,7 +1,8 @@ -import { IListable, List } from '@iqser/common-ui'; +import { IListable } from '@iqser/common-ui'; import { IDossierTemplate } from './dossier-template'; import { DownloadFileType } from '../shared'; import { DossierTemplateStatus, DossierTemplateStatuses } from './constants'; +import { List } from '@iqser/common-ui/lib/utils'; export class DossierTemplate implements IDossierTemplate, IListable { readonly createdBy: string; diff --git a/libs/red-domain/src/lib/dossier-templates/dossier-template.ts b/libs/red-domain/src/lib/dossier-templates/dossier-template.ts index b92254a06..17719be09 100644 --- a/libs/red-domain/src/lib/dossier-templates/dossier-template.ts +++ b/libs/red-domain/src/lib/dossier-templates/dossier-template.ts @@ -1,4 +1,4 @@ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { DownloadFileType } from '../shared'; import { DossierTemplateStatus } from './constants'; diff --git a/libs/red-domain/src/lib/dossiers/dossier.model.ts b/libs/red-domain/src/lib/dossiers/dossier.model.ts index c11c62a58..cc670c2fd 100644 --- a/libs/red-domain/src/lib/dossiers/dossier.model.ts +++ b/libs/red-domain/src/lib/dossiers/dossier.model.ts @@ -1,7 +1,8 @@ -import { IListable, List } from '@iqser/common-ui'; +import { IListable } from '@iqser/common-ui'; import { IDossier } from './dossier'; import { DownloadFileType } from '../shared'; import { ARCHIVE_ROUTE, DOSSIERS_ROUTE } from './constants'; +import { List } from '@iqser/common-ui/lib/utils'; export class Dossier implements IDossier, IListable { readonly dossierId: string; diff --git a/libs/red-domain/src/lib/dossiers/dossier.request.ts b/libs/red-domain/src/lib/dossiers/dossier.request.ts index d31e01c90..ce7d14935 100644 --- a/libs/red-domain/src/lib/dossiers/dossier.request.ts +++ b/libs/red-domain/src/lib/dossiers/dossier.request.ts @@ -1,4 +1,4 @@ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { DownloadFileType } from '../shared'; /** diff --git a/libs/red-domain/src/lib/dossiers/dossier.ts b/libs/red-domain/src/lib/dossiers/dossier.ts index b99bebb6b..0c8a48f10 100644 --- a/libs/red-domain/src/lib/dossiers/dossier.ts +++ b/libs/red-domain/src/lib/dossiers/dossier.ts @@ -1,5 +1,5 @@ import { DownloadFileType } from '../shared'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface IDossier { readonly approverIds: List; diff --git a/libs/red-domain/src/lib/downloads/download-status.model.ts b/libs/red-domain/src/lib/downloads/download-status.model.ts index 4b61210a8..7d42dae95 100644 --- a/libs/red-domain/src/lib/downloads/download-status.model.ts +++ b/libs/red-domain/src/lib/downloads/download-status.model.ts @@ -1,6 +1,7 @@ -import { IListable, List } from '@iqser/common-ui'; +import { IListable } from '@iqser/common-ui'; import { DownloadStatusType, IDownloadStatus } from './download-status'; import { DownloadFileType } from '../shared'; +import { List } from '@iqser/common-ui/lib/utils'; export class DownloadStatus implements IDownloadStatus, IListable { readonly storageId: string; diff --git a/libs/red-domain/src/lib/downloads/download-status.ts b/libs/red-domain/src/lib/downloads/download-status.ts index fc5b8f28a..23cf854a5 100644 --- a/libs/red-domain/src/lib/downloads/download-status.ts +++ b/libs/red-domain/src/lib/downloads/download-status.ts @@ -1,4 +1,4 @@ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { DownloadFileType } from '../shared'; export interface IDownloadStatus { diff --git a/libs/red-domain/src/lib/downloads/prepare-download.request.ts b/libs/red-domain/src/lib/downloads/prepare-download.request.ts index 22f7295ef..daddcaa95 100644 --- a/libs/red-domain/src/lib/downloads/prepare-download.request.ts +++ b/libs/red-domain/src/lib/downloads/prepare-download.request.ts @@ -1,7 +1,7 @@ /** * Object containing information on which file and report types should be included in the download. */ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { DownloadFileType } from '../shared'; export interface IPrepareDownloadRequest { diff --git a/libs/red-domain/src/lib/downloads/remove-download.request.ts b/libs/red-domain/src/lib/downloads/remove-download.request.ts index bef3953de..4a76e78fb 100644 --- a/libs/red-domain/src/lib/downloads/remove-download.request.ts +++ b/libs/red-domain/src/lib/downloads/remove-download.request.ts @@ -1,4 +1,4 @@ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface IRemoveDownloadRequest { storageIds: List; diff --git a/libs/red-domain/src/lib/files/file-upload-result.ts b/libs/red-domain/src/lib/files/file-upload-result.ts index ff9182102..856201a94 100644 --- a/libs/red-domain/src/lib/files/file-upload-result.ts +++ b/libs/red-domain/src/lib/files/file-upload-result.ts @@ -1,7 +1,7 @@ /** * Object containing information about a successfully uploaded file. */ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface IFileUploadResult { /** diff --git a/libs/red-domain/src/lib/files/super-types.ts b/libs/red-domain/src/lib/files/super-types.ts index 29ec299cc..f8794e157 100644 --- a/libs/red-domain/src/lib/files/super-types.ts +++ b/libs/red-domain/src/lib/files/super-types.ts @@ -1,4 +1,4 @@ -import { ValuesOf } from '@iqser/common-ui'; +import { ValuesOf } from '@iqser/common-ui/lib/utils'; export const SuperTypes = { TextHighlight: 'text-highlight', diff --git a/libs/red-domain/src/lib/files/types.ts b/libs/red-domain/src/lib/files/types.ts index 39341993f..7c5c081a2 100644 --- a/libs/red-domain/src/lib/files/types.ts +++ b/libs/red-domain/src/lib/files/types.ts @@ -1,4 +1,4 @@ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export const FILE_ID = 'fileId'; diff --git a/libs/red-domain/src/lib/geometry/section-grid.ts b/libs/red-domain/src/lib/geometry/section-grid.ts index 93d06e15f..a79532a23 100644 --- a/libs/red-domain/src/lib/geometry/section-grid.ts +++ b/libs/red-domain/src/lib/geometry/section-grid.ts @@ -1,5 +1,5 @@ import { ISectionRectangle } from './section-rectangle'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface ISectionGrid { rectanglesPerPage: Record>; diff --git a/libs/red-domain/src/lib/geometry/section-rectangle.ts b/libs/red-domain/src/lib/geometry/section-rectangle.ts index 4e0307779..f9d666b3f 100644 --- a/libs/red-domain/src/lib/geometry/section-rectangle.ts +++ b/libs/red-domain/src/lib/geometry/section-rectangle.ts @@ -1,5 +1,5 @@ import { ICellRectangle } from './cell-rectangle'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface ISectionRectangle extends ICellRectangle { numberOfParts?: number; diff --git a/libs/red-domain/src/lib/pages/page-exclusion.request.ts b/libs/red-domain/src/lib/pages/page-exclusion.request.ts index b77c01987..55f84ba16 100644 --- a/libs/red-domain/src/lib/pages/page-exclusion.request.ts +++ b/libs/red-domain/src/lib/pages/page-exclusion.request.ts @@ -1,5 +1,5 @@ import { IPageRange } from './page-range'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface IPageExclusionRequest { pageRanges: List; diff --git a/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts b/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts index da708bad8..f7121dc86 100644 --- a/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts +++ b/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts @@ -1,5 +1,5 @@ import { IRectangle } from '../geometry'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { DictionaryEntryType } from './dictionary-entry-types'; export interface IAddRedactionRequest { diff --git a/libs/red-domain/src/lib/redaction-log/change.ts b/libs/red-domain/src/lib/redaction-log/change.ts index 0c7344274..8e6eb26e5 100644 --- a/libs/red-domain/src/lib/redaction-log/change.ts +++ b/libs/red-domain/src/lib/redaction-log/change.ts @@ -1,4 +1,4 @@ -import { ValuesOf } from '@iqser/common-ui'; +import { ValuesOf } from '@iqser/common-ui/lib/utils'; export interface IChange { dateTime: string; diff --git a/libs/red-domain/src/lib/redaction-log/types.ts b/libs/red-domain/src/lib/redaction-log/types.ts index 7e8965ff2..41116c670 100644 --- a/libs/red-domain/src/lib/redaction-log/types.ts +++ b/libs/red-domain/src/lib/redaction-log/types.ts @@ -1,4 +1,4 @@ -import { ValuesOf } from '@iqser/common-ui'; +import { ValuesOf } from '@iqser/common-ui/lib/utils'; export const LogEntryEngines = { DICTIONARY: 'DICTIONARY', diff --git a/libs/red-domain/src/lib/search/matched-document.ts b/libs/red-domain/src/lib/search/matched-document.ts index 6eba56b59..4d5522bc9 100644 --- a/libs/red-domain/src/lib/search/matched-document.ts +++ b/libs/red-domain/src/lib/search/matched-document.ts @@ -1,5 +1,5 @@ import { IMatchedSection } from './matched-section'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface IMatchedDocument { containsAllMatchedSections?: boolean; diff --git a/libs/red-domain/src/lib/search/matched-section.ts b/libs/red-domain/src/lib/search/matched-section.ts index 2ec1893f8..db704f813 100644 --- a/libs/red-domain/src/lib/search/matched-section.ts +++ b/libs/red-domain/src/lib/search/matched-section.ts @@ -1,4 +1,4 @@ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface IMatchedSection { headline?: string; diff --git a/libs/red-domain/src/lib/search/search-input.ts b/libs/red-domain/src/lib/search/search-input.ts index 020d8bac9..af06fcf80 100644 --- a/libs/red-domain/src/lib/search/search-input.ts +++ b/libs/red-domain/src/lib/search/search-input.ts @@ -1,4 +1,4 @@ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { WorkflowFileStatus } from '../files'; export interface ISearchInput { diff --git a/libs/red-domain/src/lib/search/search-list-item.ts b/libs/red-domain/src/lib/search/search-list-item.ts index f8a815ddc..1cd7000d1 100644 --- a/libs/red-domain/src/lib/search/search-list-item.ts +++ b/libs/red-domain/src/lib/search/search-list-item.ts @@ -1,4 +1,5 @@ -import { IListable, List } from '@iqser/common-ui'; +import { IListable } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface ISearchListItem extends IListable { readonly dossierId: string; diff --git a/libs/red-domain/src/lib/search/search.request.ts b/libs/red-domain/src/lib/search/search.request.ts index a7d19af88..88462b42e 100644 --- a/libs/red-domain/src/lib/search/search.request.ts +++ b/libs/red-domain/src/lib/search/search.request.ts @@ -1,4 +1,4 @@ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { WorkflowFileStatus } from '../files'; export interface ISearchRequest { diff --git a/libs/red-domain/src/lib/search/search.response.ts b/libs/red-domain/src/lib/search/search.response.ts index 861d89ef9..adb4c418a 100644 --- a/libs/red-domain/src/lib/search/search.response.ts +++ b/libs/red-domain/src/lib/search/search.response.ts @@ -1,5 +1,5 @@ import { IMatchedDocument } from './matched-document'; -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; export interface ISearchResponse { matchedDocuments?: List; diff --git a/libs/red-domain/src/lib/shared/app-config.ts b/libs/red-domain/src/lib/shared/app-config.ts index 5b1728a55..343b6b097 100644 --- a/libs/red-domain/src/lib/shared/app-config.ts +++ b/libs/red-domain/src/lib/shared/app-config.ts @@ -1,4 +1,4 @@ -import { IqserAppConfig } from '@iqser/common-ui'; +import { IqserAppConfig } from '@iqser/common-ui/lib/utils'; export interface AppConfig extends IqserAppConfig { readonly ADMIN_CONTACT_NAME: string; diff --git a/libs/red-domain/src/lib/shared/pdf.types.ts b/libs/red-domain/src/lib/shared/pdf.types.ts index 2ce74eeb5..b4b41a5f8 100644 --- a/libs/red-domain/src/lib/shared/pdf.types.ts +++ b/libs/red-domain/src/lib/shared/pdf.types.ts @@ -1,4 +1,4 @@ -import { ValuesOf } from '@iqser/common-ui'; +import { ValuesOf } from '@iqser/common-ui/lib/utils'; export interface IBasicHeaderElement { readonly img?: string; diff --git a/libs/red-domain/src/lib/trash/trash-dossier.model.ts b/libs/red-domain/src/lib/trash/trash-dossier.model.ts index 2cf8d073c..e4baa3d31 100644 --- a/libs/red-domain/src/lib/trash/trash-dossier.model.ts +++ b/libs/red-domain/src/lib/trash/trash-dossier.model.ts @@ -1,4 +1,4 @@ -import { List } from '@iqser/common-ui'; +import { List } from '@iqser/common-ui/lib/utils'; import { IDossier } from '../dossiers'; import { TrashItem } from './trash.item'; diff --git a/libs/red-domain/src/lib/trash/trash.item.ts b/libs/red-domain/src/lib/trash/trash.item.ts index 68b4d025d..27256bb7c 100644 --- a/libs/red-domain/src/lib/trash/trash.item.ts +++ b/libs/red-domain/src/lib/trash/trash.item.ts @@ -1,5 +1,5 @@ -import { getLeftDateTime } from '@iqser/common-ui'; import * as dayjs from 'dayjs'; +import { getLeftDateTime } from '@iqser/common-ui/lib/utils'; export abstract class TrashItem { abstract readonly type: 'dossier' | 'file'; diff --git a/libs/red-domain/src/lib/users/user.model.ts b/libs/red-domain/src/lib/users/user.model.ts index e11761922..895743b4f 100644 --- a/libs/red-domain/src/lib/users/user.model.ts +++ b/libs/red-domain/src/lib/users/user.model.ts @@ -1,5 +1,6 @@ -import { IIqserUser, IqserUser, List } from '@iqser/common-ui'; import { KeycloakProfile } from 'keycloak-js'; +import { IIqserUser, IqserUser } from '@iqser/common-ui/lib/users'; +import { List } from '@iqser/common-ui/lib/utils'; export class User extends IqserUser { readonly isManager = this.has('RED_MANAGER'); diff --git a/tsconfig.json b/tsconfig.json index 4bd96eee4..8f7ec4bd3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,6 +23,7 @@ "@guards/*": ["apps/red-ui/src/app/guards/*"], "@i18n/*": ["apps/red-ui/src/app/i18n/*"], "@iqser/common-ui": ["libs/common-ui/src/index.ts"], + "@iqser/common-ui/*": ["libs/common-ui/src/*"], "@models/*": ["apps/red-ui/src/app/models/*"], "@red/domain": ["libs/red-domain/src/index.ts"], "@services/*": ["apps/red-ui/src/app/services/*"], From 2355fe03757bd14437779350969de260218b2937 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Thu, 6 Jul 2023 14:21:46 +0300 Subject: [PATCH 04/23] RED-6713 try fix filter service imports --- apps/red-ui/src/app/app-routing.module.ts | 13 +++------ apps/red-ui/src/app/app.module.ts | 9 ++---- .../base-screen/base-screen.component.ts | 3 +- .../tenants-menu/tenants-menu.component.ts | 3 +- .../user-menu/user-menu.component.ts | 3 +- .../src/app/guards/dossier-files-guard.ts | 2 +- .../guards/dossier-template-exists.guard.ts | 2 +- apps/red-ui/src/app/guards/dossiers.guard.ts | 2 +- .../app/guards/entity-exists-guard.service.ts | 2 +- .../src/app/guards/if-logged-in.guard.ts | 2 +- .../src/app/guards/if-not-logged-in.guard.ts | 29 +++++++++++++++++++ .../src/app/guards/watermark-exists.guard.ts | 2 +- .../src/app/modules/account/account.module.ts | 3 +- .../user-profile-screen.component.ts | 14 ++------- .../src/app/modules/admin/admin.module.ts | 2 +- .../base-entity-screen.component.ts | 3 +- .../watermark-screen.component.ts | 3 +- .../screens/watermark/watermark.module.ts | 2 +- .../admin-side-nav.component.ts | 4 ++- .../dossier-template-actions.component.ts | 3 +- .../dossier-template-breadcrumbs.component.ts | 2 +- ...ossier-overview-screen-header.component.ts | 11 ++----- .../dossier-overview.module.ts | 4 +-- .../dossier-documents-status.component.ts | 2 +- .../dossiers-listing.module.ts | 10 ++----- .../file-preview-screen.component.ts | 2 +- .../file-preview/file-preview.module.ts | 4 +-- .../src/app/modules/search/search.module.ts | 4 ++- .../file-actions/file-actions.component.ts | 2 +- .../edit-dossier-general-info.component.ts | 11 ++----- .../shared-dossiers/shared-dossiers.module.ts | 4 +-- .../file-download-btn.component.ts | 3 +- .../donut-chart/donut-chart.component.ts | 3 +- .../expandable-file-actions.component.ts | 3 +- .../add-dossier-dialog.component.ts | 3 +- .../src/app/modules/shared/shared.module.ts | 2 +- .../src/app/modules/trash/trash.module.ts | 3 +- .../services/file-download.service.ts | 3 +- .../dossiers/archived-dossiers.service.ts | 7 ++--- .../src/app/services/notifications.service.ts | 3 +- .../app/services/router-history.service.ts | 2 +- apps/red-ui/src/app/utils/main.resolver.ts | 3 +- libs/common-ui | 2 +- 43 files changed, 104 insertions(+), 95 deletions(-) create mode 100644 apps/red-ui/src/app/guards/if-not-logged-in.guard.ts diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts index 16f944ec6..01ba8ff2e 100644 --- a/apps/red-ui/src/app/app-routing.module.ts +++ b/apps/red-ui/src/app/app-routing.module.ts @@ -1,12 +1,5 @@ import { AuthErrorComponent } from '@components/auth-error/auth-error.component'; -import { - CompositeRouteGuard, - DEFAULT_REDIRECT_KEY, - ifNotLoggedIn, - IqserPermissionsGuard, - IqserRoutes, - TenantSelectComponent, -} from '@iqser/common-ui'; +import { CompositeRouteGuard, DEFAULT_REDIRECT_KEY, IqserPermissionsGuard, IqserRoutes } from '@iqser/common-ui'; import { RedRoleGuard } from '@users/red-role.guard'; import { BaseScreenComponent } from '@components/base-screen/base-screen.component'; import { RouteReuseStrategy, RouterModule } from '@angular/router'; @@ -27,6 +20,8 @@ import { mainResolver } from '@utils/main.resolver'; import { hasAnyRoleGuard, IqserAuthGuard } from '@iqser/common-ui/lib/users'; import { CustomRouteReuseStrategy } from '@iqser/common-ui/lib/utils'; import { ifLoggedIn } from '@guards/if-logged-in.guard'; +import { ifNotLoggedIn } from '@guards/if-not-logged-in.guard'; +import { TenantSelectComponent } from '@iqser/common-ui/lib/tenants'; const dossierTemplateIdRoutes: IqserRoutes = [ { @@ -210,7 +205,7 @@ const routes: IqserRoutes = [ { path: '', pathMatch: 'full', - canActivate: [ifNotLoggedIn], + canActivate: [ifNotLoggedIn()], component: TenantSelectComponent, }, { diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index 0feb32e33..fc52f4819 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -9,7 +9,6 @@ import { CachingModule, ChevronButtonComponent, CircleButtonComponent, - CommonUiModule, EmptyStateComponent, HelpModeKey, HiddenActionDirective, @@ -22,16 +21,11 @@ import { IqserLoadingModule, IqserTranslateModule, LanguageService, - LogoComponent, MAX_RETRIES_ON_SERVER_ERROR, RoundCheckboxComponent, SERVER_ERROR_SKIP_PATHS, ServerErrorInterceptor, - SkeletonComponent, StopPropagationDirective, - TenantPipe, - TenantsModule, - ToastComponent, } from '@iqser/common-ui'; import { ToastrModule } from 'ngx-toastr'; import { ServiceWorkerModule } from '@angular/service-worker'; @@ -71,6 +65,9 @@ import { UserMenuComponent } from '@components/user-menu/user-menu.component'; import { TenantsMenuComponent } from '@components/tenants-menu/tenants-menu.component'; import { MatDividerModule } from '@angular/material/divider'; import { IqserUsersModule } from '@iqser/common-ui/lib/users'; +import { CommonUiModule } from '@iqser/common-ui/lib/common-ui.module'; +import { LogoComponent, SkeletonComponent, ToastComponent } from '@iqser/common-ui/lib/shared'; +import { TenantPipe, TenantsModule } from '@iqser/common-ui/lib/tenants'; export const appModuleFactory = (config: AppConfig) => { @NgModule({ 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 086985221..4f8e37679 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 @@ -6,7 +6,7 @@ import { Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; import { SpotlightSearchAction } from '@components/spotlight-search/spotlight-search-action'; import { filter, map, startWith } from 'rxjs/operators'; -import { IqserPermissionsService, TenantsService } from '@iqser/common-ui'; +import { 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'; @@ -14,6 +14,7 @@ import { Roles } from '@users/roles'; import { REDDocumentViewer } from '../../modules/pdf-viewer/services/document-viewer.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { List, shareDistinctLast } from '@iqser/common-ui/lib/utils'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; const isNavigationStart = event => event instanceof NavigationStart; const isSearchScreen: (url: string) => boolean = url => url.includes('/search'); diff --git a/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.ts b/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.ts index 7e2a755d0..01054e7ea 100644 --- a/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.ts +++ b/apps/red-ui/src/app/components/tenants-menu/tenants-menu.component.ts @@ -1,9 +1,10 @@ import { Component, inject } from '@angular/core'; -import { getConfig, getKeycloakOptions, IStoredTenantId, KeycloakStatusService, TenantsService } from '@iqser/common-ui'; +import { getConfig } from '@iqser/common-ui'; import { User } from '@red/domain'; import { KeycloakService } from 'keycloak-angular'; import { getCurrentUser } from '@iqser/common-ui/lib/users'; import { BASE_HREF } from '@iqser/common-ui/lib/utils'; +import { getKeycloakOptions, IStoredTenantId, KeycloakStatusService, TenantsService } from '@iqser/common-ui/lib/tenants'; @Component({ selector: 'app-tenants-menu', diff --git a/apps/red-ui/src/app/components/user-menu/user-menu.component.ts b/apps/red-ui/src/app/components/user-menu/user-menu.component.ts index f42a374f7..3ff2442e5 100644 --- a/apps/red-ui/src/app/components/user-menu/user-menu.component.ts +++ b/apps/red-ui/src/app/components/user-menu/user-menu.component.ts @@ -1,11 +1,12 @@ import { Component, inject } from '@angular/core'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { Roles } from '@users/roles'; -import { IqserPermissionsService, TenantsService } from '@iqser/common-ui'; +import { IqserPermissionsService } from '@iqser/common-ui'; import { User } from '@red/domain'; import { UserService } from '@users/user.service'; import { getCurrentUser } from '@iqser/common-ui/lib/users'; import { List } from '@iqser/common-ui/lib/utils'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; interface MenuItem { readonly id: string; diff --git a/apps/red-ui/src/app/guards/dossier-files-guard.ts b/apps/red-ui/src/app/guards/dossier-files-guard.ts index 11c6914f4..45ece236d 100644 --- a/apps/red-ui/src/app/guards/dossier-files-guard.ts +++ b/apps/red-ui/src/app/guards/dossier-files-guard.ts @@ -7,7 +7,7 @@ import { DOSSIER_ID, DOSSIER_TEMPLATE_ID } from '@red/domain'; import { DossiersService } from '@services/dossiers/dossiers.service'; import { DictionaryService } from '@services/entity-services/dictionary.service'; import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service'; -import { TenantsService } from '@iqser/common-ui'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Injectable({ providedIn: 'root' }) export class DossierFilesGuard implements CanActivate { 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 8e49a7fc0..840b5c94e 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 @@ -2,7 +2,7 @@ import { inject } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivateFn, Router } from '@angular/router'; import { DOSSIER_TEMPLATE_ID } from '@red/domain'; import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service'; -import { TenantsService } from '@iqser/common-ui'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; import { NGXLogger } from 'ngx-logger'; import { firstValueFrom } from 'rxjs'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; diff --git a/apps/red-ui/src/app/guards/dossiers.guard.ts b/apps/red-ui/src/app/guards/dossiers.guard.ts index 880b45b02..35632190f 100644 --- a/apps/red-ui/src/app/guards/dossiers.guard.ts +++ b/apps/red-ui/src/app/guards/dossiers.guard.ts @@ -7,7 +7,7 @@ import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.se import { DossiersService } from '@services/dossiers/dossiers.service'; import { ARCHIVE_ROUTE, DOSSIER_TEMPLATE_ID } from '@red/domain'; import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service'; -import { TenantsService } from '@iqser/common-ui'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Injectable({ providedIn: 'root' }) export class DossiersGuard implements CanActivate { diff --git a/apps/red-ui/src/app/guards/entity-exists-guard.service.ts b/apps/red-ui/src/app/guards/entity-exists-guard.service.ts index 285e1b806..6ade34350 100644 --- a/apps/red-ui/src/app/guards/entity-exists-guard.service.ts +++ b/apps/red-ui/src/app/guards/entity-exists-guard.service.ts @@ -3,7 +3,7 @@ import { ActivatedRouteSnapshot, CanActivateFn, Router } from '@angular/router'; import { DOSSIER_TEMPLATE_ID, ENTITY_TYPE } from '@red/domain'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; -import { TenantsService } from '@iqser/common-ui'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; export function entityExistsGuard(): CanActivateFn { return async function (route: ActivatedRouteSnapshot): Promise { diff --git a/apps/red-ui/src/app/guards/if-logged-in.guard.ts b/apps/red-ui/src/app/guards/if-logged-in.guard.ts index b7b6707a1..184426d94 100644 --- a/apps/red-ui/src/app/guards/if-logged-in.guard.ts +++ b/apps/red-ui/src/app/guards/if-logged-in.guard.ts @@ -1,7 +1,7 @@ import { ActivatedRouteSnapshot, CanActivateFn, Router } from '@angular/router'; import { inject } from '@angular/core'; import { NGXLogger } from 'ngx-logger'; -import { keycloakInitializer, KeycloakStatusService, TenantsService } from '@iqser/common-ui'; +import { keycloakInitializer, KeycloakStatusService, TenantsService } from '@iqser/common-ui/lib/tenants'; import { KeycloakService } from 'keycloak-angular'; import { UserService } from '@users/user.service'; diff --git a/apps/red-ui/src/app/guards/if-not-logged-in.guard.ts b/apps/red-ui/src/app/guards/if-not-logged-in.guard.ts new file mode 100644 index 000000000..80b5beb85 --- /dev/null +++ b/apps/red-ui/src/app/guards/if-not-logged-in.guard.ts @@ -0,0 +1,29 @@ +import { ActivatedRouteSnapshot, CanActivateFn, Router } from '@angular/router'; +import { inject } from '@angular/core'; +import { NGXLogger } from 'ngx-logger'; +import { KeycloakService } from 'keycloak-angular'; + +export function ifNotLoggedIn(): CanActivateFn { + return async (route: ActivatedRouteSnapshot) => { + const logger = inject(NGXLogger); + const router = inject(Router); + const keycloakService = inject(KeycloakService); + + const isLoggedIn = await keycloakService.isLoggedIn(); + + if (!isLoggedIn) { + logger.info('[ROUTES] Not logged in, continuing to selected route'); + return true; + } + + const tenant = route.paramMap.get('tenant') || keycloakService.getKeycloakInstance().realm; + if (!tenant) { + logger.error('[ROUTES] Tenant not found in route or keycloak realm'); + return false; + } + + logger.warn('[ROUTES] Is logged in for ' + tenant + ', redirecting to /' + tenant); + await router.navigate([tenant]); + return false; + }; +} diff --git a/apps/red-ui/src/app/guards/watermark-exists.guard.ts b/apps/red-ui/src/app/guards/watermark-exists.guard.ts index 02a3b19d9..c0312d7ee 100644 --- a/apps/red-ui/src/app/guards/watermark-exists.guard.ts +++ b/apps/red-ui/src/app/guards/watermark-exists.guard.ts @@ -2,7 +2,7 @@ import { inject } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivateFn, Router } from '@angular/router'; import { WatermarksMapService } from '@services/entity-services/watermarks-map.service'; import { DOSSIER_TEMPLATE_ID, WATERMARK_ID } from '@red/domain'; -import { TenantsService } from '@iqser/common-ui'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; export function watermarkExistsGuard(): CanActivateFn { return async function (route: ActivatedRouteSnapshot) { diff --git a/apps/red-ui/src/app/modules/account/account.module.ts b/apps/red-ui/src/app/modules/account/account.module.ts index a8b2382fa..7f35e0d7a 100644 --- a/apps/red-ui/src/app/modules/account/account.module.ts +++ b/apps/red-ui/src/app/modules/account/account.module.ts @@ -6,8 +6,9 @@ import { AccountSideNavComponent } from './account-side-nav/account-side-nav.com import { BaseAccountScreenComponent } from './base-account-screen/base-account-screen-component'; import { NotificationPreferencesService } from './services/notification-preferences.service'; import { TranslateModule } from '@ngx-translate/core'; -import { IconButtonComponent, IqserHelpModeModule, SideNavComponent } from '@iqser/common-ui'; +import { IconButtonComponent, IqserHelpModeModule } from '@iqser/common-ui'; import { PreferencesComponent } from './screens/preferences/preferences.component'; +import { SideNavComponent } from '@iqser/common-ui/lib/shared'; @NgModule({ declarations: [AccountSideNavComponent, BaseAccountScreenComponent, PreferencesComponent], diff --git a/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.ts b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.ts index 442b268ce..97ac2f444 100644 --- a/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.ts +++ b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.ts @@ -2,15 +2,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, OnInit } import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { DomSanitizer } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; -import { - BaseFormComponent, - getConfig, - IqserPermissionsService, - LanguageService, - LoadingService, - TenantsService, - Toaster, -} from '@iqser/common-ui'; +import { BaseFormComponent, getConfig, IqserPermissionsService, LanguageService, LoadingService, Toaster } from '@iqser/common-ui'; import { AppConfig, IProfile } from '@red/domain'; import { languagesTranslations } from '@translations/languages-translations'; import { UserService } from '@users/user.service'; @@ -19,6 +11,7 @@ import { UserPreferenceService } from '@users/user-preference.service'; import { Roles } from '@users/roles'; import { UserProfileDialogService } from '../services/user-profile-dialog.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Component({ templateUrl: './user-profile-screen.component.html', @@ -26,12 +19,11 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class UserProfileScreenComponent extends BaseFormComponent implements OnInit { + #profileModel: IProfile; readonly translations = languagesTranslations; readonly devMode = this._userPreferenceService.areDevFeaturesEnabled; readonly changePasswordUrl: string; - #profileModel: IProfile; - constructor( domSanitizer: DomSanitizer, private readonly _userService: UserService, 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 e38c6febe..67eff6d7f 100644 --- a/apps/red-ui/src/app/modules/admin/admin.module.ts +++ b/apps/red-ui/src/app/modules/admin/admin.module.ts @@ -50,12 +50,12 @@ import { IqserListingModule, IqserUploadFileModule, RoundCheckboxComponent, - TenantPipe, } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { AuditInfoDialogComponent } from './dialogs/audit-info-dialog/audit-info-dialog.component'; import { DossierTemplateActionsComponent } from './shared/components/dossier-template-actions/dossier-template-actions.component'; import { IqserUsersModule } from '@iqser/common-ui/lib/users'; +import { TenantPipe } from '@iqser/common-ui/lib/tenants'; const dialogs = [ AddEditCloneDossierTemplateDialogComponent, diff --git a/apps/red-ui/src/app/modules/admin/base-entity-screen/base-entity-screen.component.ts b/apps/red-ui/src/app/modules/admin/base-entity-screen/base-entity-screen.component.ts index 4e5b7e28e..635cd8392 100644 --- a/apps/red-ui/src/app/modules/admin/base-entity-screen/base-entity-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/base-entity-screen/base-entity-screen.component.ts @@ -4,12 +4,13 @@ import { Router } from '@angular/router'; import { firstValueFrom, Observable } from 'rxjs'; import { AdminDialogService } from '../services/admin-dialog.service'; import { DictionaryService } from '@services/entity-services/dictionary.service'; -import { LoadingService, TenantsService } from '@iqser/common-ui'; +import { LoadingService } from '@iqser/common-ui'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { map } from 'rxjs/operators'; import { PermissionsService } from '@services/permissions.service'; import { getParam } from '@iqser/common-ui/lib/utils'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Component({ templateUrl: './base-entity-screen.component.html', diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts index e8e87ef69..f8fabc61f 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts @@ -2,7 +2,7 @@ import { ChangeDetectorRef, Component, ElementRef, inject, OnInit, ViewChild } f import WebViewer, { WebViewerInstance } from '@pdftron/webviewer'; import { HttpClient } from '@angular/common/http'; import { FormBuilder, FormGroup } from '@angular/forms'; -import { getConfig, IconButtonTypes, IqserPermissionsService, LoadingService, TenantsService, Toaster } from '@iqser/common-ui'; +import { getConfig, IconButtonTypes, IqserPermissionsService, LoadingService, Toaster } from '@iqser/common-ui'; import { AppConfig, DOSSIER_TEMPLATE_ID, @@ -31,6 +31,7 @@ import { tap } from 'rxjs/operators'; import { watermarkTranslations } from '@translations/watermark-translations'; import { getCurrentUser } from '@iqser/common-ui/lib/users'; import { AsControl, BASE_HREF_FN, Debounce, getParam, trackByFactory } from '@iqser/common-ui/lib/utils'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; export const DEFAULT_WATERMARK: Partial = { text: 'Watermark', diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark.module.ts b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark.module.ts index d169929dd..8fbfbb910 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark.module.ts +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark.module.ts @@ -12,7 +12,6 @@ import { IqserHelpModeModule, IqserListingModule, IqserRoutes, - TenantPipe, } from '@iqser/common-ui'; import { RedRoleGuard } from '@users/red-role.guard'; import { WATERMARK_ID } from '@red/domain'; @@ -26,6 +25,7 @@ import { ColorPickerModule } from 'ngx-color-picker'; import { MatTooltipModule } from '@angular/material/tooltip'; import { MatSlideToggleModule } from '@angular/material/slide-toggle'; import { IqserAuthGuard, IqserUsersModule } from '@iqser/common-ui/lib/users'; +import { TenantPipe } from '@iqser/common-ui/lib/tenants'; const routes: IqserRoutes = [ { 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 e755d7e1a..b78a3cf3d 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 @@ -5,10 +5,12 @@ import { adminSideNavTranslations } from '@translations/admin-side-nav-translati import { ActivatedRoute, RouterLink, RouterLinkActive } from '@angular/router'; import { AdminSideNavType, AdminSideNavTypes, DOSSIER_TEMPLATE_ID, ENTITY_TYPE, User, WATERMARK_ID } from '@red/domain'; import { Roles } from '@users/roles'; -import { IqserHelpModeModule, IqserPermissionsService, SideNavComponent, TenantPipe } from '@iqser/common-ui'; +import { IqserHelpModeModule, IqserPermissionsService } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { NgForOf, NgIf } from '@angular/common'; import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { SideNavComponent } from '@iqser/common-ui/lib/shared'; +import { TenantPipe } from '@iqser/common-ui/lib/tenants'; interface NavItem { readonly label: string; diff --git a/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.ts b/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.ts index 4b72cf055..dec85ea38 100644 --- a/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.ts +++ b/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.ts @@ -1,13 +1,14 @@ import { Component, Input, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { AdminDialogService } from '../../../services/admin-dialog.service'; -import { CircleButtonComponent, CircleButtonTypes, IqserHelpModeModule, LoadingService, TenantsService } from '@iqser/common-ui'; +import { CircleButtonComponent, CircleButtonTypes, IqserHelpModeModule, LoadingService } from '@iqser/common-ui'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { firstValueFrom } from 'rxjs'; import { DOSSIER_TEMPLATE_ID, type User } from '@red/domain'; import { NgIf } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Component({ selector: 'redaction-dossier-template-actions', diff --git a/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-breadcrumbs/dossier-template-breadcrumbs.component.ts b/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-breadcrumbs/dossier-template-breadcrumbs.component.ts index 62e110ec2..a2eabf69d 100644 --- a/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-breadcrumbs/dossier-template-breadcrumbs.component.ts +++ b/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-breadcrumbs/dossier-template-breadcrumbs.component.ts @@ -8,7 +8,7 @@ import { DictionariesMapService } from '@services/entity-services/dictionaries-m import { AsyncPipe, NgIf } from '@angular/common'; import { MatIconModule } from '@angular/material/icon'; import { TranslateModule } from '@ngx-translate/core'; -import { TenantPipe } from '@iqser/common-ui'; +import { TenantPipe } from '@iqser/common-ui/lib/tenants'; @Component({ selector: 'redaction-dossier-template-breadcrumbs', diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts index 41e30706e..326f802fd 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts @@ -1,13 +1,5 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { - ActionConfig, - CircleButtonTypes, - EntitiesService, - ListingService, - LoadingService, - TenantsService, - Toaster, -} from '@iqser/common-ui'; +import { ActionConfig, CircleButtonTypes, EntitiesService, ListingService, LoadingService, Toaster } from '@iqser/common-ui'; import { Dossier, File, IFile } from '@red/domain'; import { PermissionsService } from '@services/permissions.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -21,6 +13,7 @@ import { Router } from '@angular/router'; import { Roles } from '@users/roles'; import { SortingService } from '@iqser/common-ui/lib/sorting'; import { List, some } from '@iqser/common-ui/lib/utils'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Component({ selector: 'redaction-dossier-overview-screen-header [dossier] [upload]', diff --git a/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts b/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts index dc17c9be2..01c5b3038 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts @@ -10,9 +10,7 @@ import { IqserListingModule, IqserLoadingModule, IqserRoutes, - StatusBarComponent, StopPropagationDirective, - TenantPipe, } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { DossierOverviewScreenComponent } from './screen/dossier-overview-screen.component'; @@ -28,6 +26,8 @@ import { ViewModeSelectionComponent } from './components/view-mode-selection/vie import { FileAttributeComponent } from './components/file-attribute/file-attribute.component'; import { SharedModule } from '@shared/shared.module'; import { IqserUsersModule } from '@iqser/common-ui/lib/users'; +import { StatusBarComponent } from '@iqser/common-ui/lib/shared'; +import { TenantPipe } from '@iqser/common-ui/lib/tenants'; const routes: IqserRoutes = [ { diff --git a/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-documents-status/dossier-documents-status.component.ts b/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-documents-status/dossier-documents-status.component.ts index fc932f3ac..37850cb8a 100644 --- a/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-documents-status/dossier-documents-status.component.ts +++ b/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-documents-status/dossier-documents-status.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; import { DossierStats, StatusSorter } from '@red/domain'; -import { StatusBarConfig } from '@iqser/common-ui'; import { List } from '@iqser/common-ui/lib/utils'; +import { StatusBarConfig } from '@iqser/common-ui/lib/shared'; @Component({ selector: 'redaction-dossier-documents-status', diff --git a/apps/red-ui/src/app/modules/dossiers-listing/dossiers-listing.module.ts b/apps/red-ui/src/app/modules/dossiers-listing/dossiers-listing.module.ts index aec7245db..28b2f1109 100644 --- a/apps/red-ui/src/app/modules/dossiers-listing/dossiers-listing.module.ts +++ b/apps/red-ui/src/app/modules/dossiers-listing/dossiers-listing.module.ts @@ -1,13 +1,6 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { - CompositeRouteGuard, - HasScrollbarDirective, - IqserHelpModeModule, - IqserListingModule, - IqserRoutes, - StatusBarComponent, -} from '@iqser/common-ui'; +import { CompositeRouteGuard, HasScrollbarDirective, IqserHelpModeModule, IqserListingModule, IqserRoutes } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { DossiersListingScreenComponent } from './screen/dossiers-listing-screen.component'; import { RouterModule } from '@angular/router'; @@ -21,6 +14,7 @@ import { DossierDocumentsStatusComponent } from './components/dossier-documents- import { DossierFilesGuard } from '@guards/dossier-files-guard'; import { ACTIVE_DOSSIERS_SERVICE } from '../../tokens'; import { IqserUsersModule } from '@iqser/common-ui/lib/users'; +import { StatusBarComponent } from '@iqser/common-ui/lib/shared'; const routes: IqserRoutes = [ { diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index 0d29cf9a9..da2646e18 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -21,7 +21,6 @@ import { HelpModeService, IConfirmationDialogData, LoadingService, - TenantsService, Toaster, } from '@iqser/common-ui'; import { MatDialog } from '@angular/material/dialog'; @@ -69,6 +68,7 @@ import { RedactTextDialogComponent } from './dialogs/redact-text-dialog/redact-t import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { copyLocalStorageFiltersValues, FilterService, NestedFilter, processFilters } from '@iqser/common-ui/lib/filtering'; import { AutoUnsubscribe, Bind, bool, Debounce, List, OnAttach, OnDetach } from '@iqser/common-ui/lib/utils'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; const textActions = [TextPopups.REDACT_TEXT, TextPopups.ADD_HINT, TextPopups.ADD_FALSE_POSITIVE]; diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts index 40509cd5b..82cbd9fb1 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts @@ -18,9 +18,7 @@ import { LogPipe, PreventDefaultDirective, RoundCheckboxComponent, - StatusBarComponent, StopPropagationDirective, - TenantPipe, } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { RouterModule } from '@angular/router'; @@ -66,6 +64,8 @@ import { RedactTextDialogComponent } from './dialogs/redact-text-dialog/redact-t import { RemoveRedactionDialogComponent } from './dialogs/remove-redaction-dialog/remove-redaction-dialog.component'; import { IqserUsersModule } from '@iqser/common-ui/lib/users'; import { IqserFiltersModule } from '@iqser/common-ui/lib/filtering'; +import { StatusBarComponent } from '@iqser/common-ui/lib/shared'; +import { TenantPipe } from '@iqser/common-ui/lib/tenants'; const routes: IqserRoutes = [ { diff --git a/apps/red-ui/src/app/modules/search/search.module.ts b/apps/red-ui/src/app/modules/search/search.module.ts index f6232c367..37d5cf17e 100644 --- a/apps/red-ui/src/app/modules/search/search.module.ts +++ b/apps/red-ui/src/app/modules/search/search.module.ts @@ -2,11 +2,13 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { SearchScreenComponent } from './search-screen/search-screen.component'; import { RouterModule } from '@angular/router'; -import { IqserListingModule, StatusBarComponent, StopPropagationDirective, TenantPipe } from '@iqser/common-ui'; +import { IqserListingModule, StopPropagationDirective } from '@iqser/common-ui'; import { SharedModule } from '@shared/shared.module'; import { TranslateModule } from '@ngx-translate/core'; import { SearchItemTemplateComponent } from './search-item-template/search-item-template.component'; import { IqserUsersModule } from '@iqser/common-ui/lib/users'; +import { StatusBarComponent } from '@iqser/common-ui/lib/shared'; +import { TenantPipe } from '@iqser/common-ui/lib/tenants'; const routes = [{ path: '', component: SearchScreenComponent }]; 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 44690834d..6dea37408 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 @@ -8,7 +8,6 @@ import { IConfirmationDialogData, IqserPermissionsService, LoadingService, - TenantsService, Toaster, } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -33,6 +32,7 @@ import { toObservable } from '@angular/core/rxjs-interop'; import { setLocalStorageDataByFileId } from '@utils/local-storage'; import { getCurrentUser } from '@iqser/common-ui/lib/users'; import { IqserTooltipPositions } from '@iqser/common-ui/lib/utils'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Component({ selector: 'redaction-file-actions', diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts index 4cfec1e0b..2d0f75243 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts @@ -7,15 +7,7 @@ import { PermissionsService } from '@services/permissions.service'; import { Router } from '@angular/router'; import { MatDialogRef } from '@angular/material/dialog'; import { EditDossierDialogComponent } from '../edit-dossier-dialog.component'; -import { - ConfirmOptions, - IconButtonTypes, - IConfirmationDialogData, - LoadingService, - TenantsService, - TitleColors, - Toaster, -} from '@iqser/common-ui'; +import { ConfirmOptions, IconButtonTypes, IConfirmationDialogData, LoadingService, TitleColors, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { DossierStatsService } from '@services/dossiers/dossier-stats.service'; @@ -27,6 +19,7 @@ import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.se import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service'; import dayjs from 'dayjs'; import { dateWithoutTime } from '@utils/functions'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Component({ selector: 'redaction-edit-dossier-general-info', diff --git a/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts b/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts index 247bbf31b..b285f93e9 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts @@ -23,14 +23,12 @@ import { IqserDenyDirective, IqserHelpModeModule, RoundCheckboxComponent, - SideNavComponent, - SmallChipComponent, - StatusBarComponent, StopPropagationDirective, } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { DossiersListingActionsComponent } from './components/dossiers-listing-actions/dossiers-listing-actions.component'; import { IqserUsersModule } from '@iqser/common-ui/lib/users'; +import { SideNavComponent, SmallChipComponent, StatusBarComponent } from '@iqser/common-ui/lib/shared'; const components = [ FileActionsComponent, diff --git a/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts b/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts index d352a64cd..c55441d88 100644 --- a/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts @@ -2,9 +2,10 @@ import { Component, Input, OnChanges } from '@angular/core'; import { PermissionsService } from '@services/permissions.service'; import { Dossier, File, ProcessingFileStatuses } from '@red/domain'; import { FileDownloadService } from '@upload-download/services/file-download.service'; -import { CircleButtonType, CircleButtonTypes, IqserDialog, TenantsService, Toaster } from '@iqser/common-ui'; +import { CircleButtonType, CircleButtonTypes, IqserDialog, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { DownloadDialogComponent } from '@shared/dialogs/download-dialog/download-dialog.component'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Component({ selector: 'redaction-file-download-btn', diff --git a/apps/red-ui/src/app/modules/shared/components/donut-chart/donut-chart.component.ts b/apps/red-ui/src/app/modules/shared/components/donut-chart/donut-chart.component.ts index 40bbf9e92..3ed10e3b4 100644 --- a/apps/red-ui/src/app/modules/shared/components/donut-chart/donut-chart.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/donut-chart/donut-chart.component.ts @@ -1,12 +1,13 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Optional, Output } from '@angular/core'; import { DonutChartConfig } from '@red/domain'; -import { IqserHelpModeModule, StatusBarComponent } from '@iqser/common-ui'; +import { IqserHelpModeModule } from '@iqser/common-ui'; import { Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; import { AsyncPipe, NgForOf, NgIf } from '@angular/common'; import { MatSelectModule } from '@angular/material/select'; import { FilterService, INestedFilter } from '@iqser/common-ui/lib/filtering'; import { get, shareLast } from '@iqser/common-ui/lib/utils'; +import { StatusBarComponent } from '@iqser/common-ui/lib/shared'; @Component({ selector: 'redaction-donut-chart', diff --git a/apps/red-ui/src/app/modules/shared/components/expandable-file-actions/expandable-file-actions.component.ts b/apps/red-ui/src/app/modules/shared/components/expandable-file-actions/expandable-file-actions.component.ts index 0e802282b..ff8759052 100644 --- a/apps/red-ui/src/app/modules/shared/components/expandable-file-actions/expandable-file-actions.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/expandable-file-actions/expandable-file-actions.component.ts @@ -1,12 +1,13 @@ import { Component, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core'; import { Action, ActionTypes, Dossier, File } from '@red/domain'; -import { CircleButtonType, IqserDialog, TenantsService, Toaster } from '@iqser/common-ui'; +import { CircleButtonType, IqserDialog, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { FileDownloadService } from '@upload-download/services/file-download.service'; import { PermissionsService } from '@services/permissions.service'; import { MatMenuTrigger } from '@angular/material/menu'; import { DownloadDialogComponent } from '@shared/dialogs/download-dialog/download-dialog.component'; import { IqserTooltipPosition, trackByFactory } from '@iqser/common-ui/lib/utils'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Component({ selector: 'redaction-expandable-file-actions', diff --git a/apps/red-ui/src/app/modules/shared/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts b/apps/red-ui/src/app/modules/shared/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts index cda06c8b2..200086d3a 100644 --- a/apps/red-ui/src/app/modules/shared/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts +++ b/apps/red-ui/src/app/modules/shared/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts @@ -3,7 +3,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { DOSSIER_TEMPLATE_ID, DownloadFileType, IDossierRequest, IDossierTemplate, IReportTemplate } from '@red/domain'; import { UntypedFormGroup, Validators } from '@angular/forms'; import { downloadTypesTranslations } from '@translations/download-types-translations'; -import { BaseDialogComponent, IconButtonTypes, IqserPermissionsService, SaveOptions, TenantsService } from '@iqser/common-ui'; +import { BaseDialogComponent, IconButtonTypes, IqserPermissionsService, SaveOptions } from '@iqser/common-ui'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { ReportTemplateService } from '@services/report-template.service'; @@ -12,6 +12,7 @@ import dayjs from 'dayjs'; import { Router } from '@angular/router'; import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service'; import { Roles } from '@users/roles'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; interface DialogData { readonly dossierTemplateId?: string; diff --git a/apps/red-ui/src/app/modules/shared/shared.module.ts b/apps/red-ui/src/app/modules/shared/shared.module.ts index 7b57efef5..5da21e2b1 100644 --- a/apps/red-ui/src/app/modules/shared/shared.module.ts +++ b/apps/red-ui/src/app/modules/shared/shared.module.ts @@ -15,7 +15,6 @@ import { IqserAllowDirective, IqserDenyDirective, IqserHelpModeModule, - SmallChipComponent, StopPropagationDirective, } from '@iqser/common-ui'; import { SelectComponent } from './components/select/select.component'; @@ -47,6 +46,7 @@ import { OcrProgressBarComponent } from './components/ocr-progress-bar/ocr-progr import { DownloadDialogComponent } from './dialogs/download-dialog/download-dialog.component'; import { CustomDateAdapter } from '@shared/CustomDateAdapter'; import { IqserUsersModule } from '@iqser/common-ui/lib/users'; +import { SmallChipComponent } from '@iqser/common-ui/lib/shared'; const buttons = [FileDownloadBtnComponent]; diff --git a/apps/red-ui/src/app/modules/trash/trash.module.ts b/apps/red-ui/src/app/modules/trash/trash.module.ts index 7bd88b50e..946fb64c1 100644 --- a/apps/red-ui/src/app/modules/trash/trash.module.ts +++ b/apps/red-ui/src/app/modules/trash/trash.module.ts @@ -2,12 +2,13 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; import { TrashScreenComponent } from './trash-screen/trash-screen.component'; -import { CircleButtonComponent, IqserListingModule, TenantPipe } from '@iqser/common-ui'; +import { CircleButtonComponent, IqserListingModule } from '@iqser/common-ui'; import { TrashTableItemComponent } from './trash-screen/trash-table-item/trash-table-item.component'; import { SharedModule } from '@shared/shared.module'; import { TrashDialogService } from './services/trash-dialog.service'; import { TranslateModule } from '@ngx-translate/core'; import { IqserUsersModule } from '@iqser/common-ui/lib/users'; +import { TenantPipe } from '@iqser/common-ui/lib/tenants'; const routes = [{ path: '', component: TrashScreenComponent }]; diff --git a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts index 881a61d29..b2ea8336b 100644 --- a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts +++ b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts @@ -3,9 +3,10 @@ import { DownloadStatus, IDownloadStatus, IDownloadStatusResponse, IPrepareDownl import { firstValueFrom, Observable } from 'rxjs'; import { ConfigService } from '@services/config.service'; import { map, tap } from 'rxjs/operators'; -import { EntitiesService, TenantsService } from '@iqser/common-ui'; +import { EntitiesService } from '@iqser/common-ui'; import { NGXLogger } from 'ngx-logger'; import { mapEach } from '@iqser/common-ui/lib/utils'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Injectable() export class FileDownloadService extends EntitiesService { 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 0a927402a..abdcb784a 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 @@ -8,18 +8,17 @@ import { DossiersService } from './dossiers.service'; import { FilesMapService } from '../files/files-map.service'; import { FeaturesService } from '../features.service'; import { Router } from '@angular/router'; -import { TenantsService } from '@iqser/common-ui'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; @Injectable({ providedIn: 'root' }) export class ArchivedDossiersService extends DossiersService { - readonly routerPath = ARCHIVE_ROUTE; - protected readonly _defaultModelPath = 'archived-dossiers'; - readonly #activeDossiersService = inject(ActiveDossiersService); readonly #filesMapService = inject(FilesMapService); readonly #featuresService = inject(FeaturesService); readonly #tenantsService = inject(TenantsService); readonly #router = inject(Router); + protected readonly _defaultModelPath = 'archived-dossiers'; + readonly routerPath = ARCHIVE_ROUTE; archive(dossiers: Dossier[]): Observable { const showArchiveFailedToast = () => { diff --git a/apps/red-ui/src/app/services/notifications.service.ts b/apps/red-ui/src/app/services/notifications.service.ts index ddcf42191..c5fb6477e 100644 --- a/apps/red-ui/src/app/services/notifications.service.ts +++ b/apps/red-ui/src/app/services/notifications.service.ts @@ -1,5 +1,5 @@ import { Inject, Injectable, OnDestroy } from '@angular/core'; -import { EntitiesService, getConfig, QueryParam, TenantsService } from '@iqser/common-ui'; +import { EntitiesService, getConfig, QueryParam } from '@iqser/common-ui'; import { TranslateService } from '@ngx-translate/core'; import { EMPTY, firstValueFrom, iif, merge, Observable, of, Subscription, timer } from 'rxjs'; import { AppConfig, Dossier, INotification, Notification, NotificationTypes } from '@red/domain'; @@ -11,6 +11,7 @@ import { CHANGED_CHECK_INTERVAL } from '@utils/constants'; import { DossiersCacheService } from './dossiers/dossiers-cache.service'; import dayjs from 'dayjs'; import { BASE_HREF, List, mapEach } from '@iqser/common-ui/lib/utils'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; const INCLUDE_SEEN = false; diff --git a/apps/red-ui/src/app/services/router-history.service.ts b/apps/red-ui/src/app/services/router-history.service.ts index b51d7c552..985b5df93 100644 --- a/apps/red-ui/src/app/services/router-history.service.ts +++ b/apps/red-ui/src/app/services/router-history.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { NavigationEnd, Router } from '@angular/router'; import { filter } from 'rxjs/operators'; -import { TenantsService } from '@iqser/common-ui'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; const LAST_DOSSIERS_SCREEN = 'routerHistory_lastDossiersScreen'; diff --git a/apps/red-ui/src/app/utils/main.resolver.ts b/apps/red-ui/src/app/utils/main.resolver.ts index ad732fca3..af2388d38 100644 --- a/apps/red-ui/src/app/utils/main.resolver.ts +++ b/apps/red-ui/src/app/utils/main.resolver.ts @@ -5,7 +5,7 @@ import { UserService } from '@users/user.service'; import { SystemPreferencesService } from '@services/system-preferences.service'; import { UserPreferenceService } from '@users/user-preference.service'; import { LicenseService } from '@services/license.service'; -import { IqserPermissionsService, LoadingService, TenantsService } from '@iqser/common-ui'; +import { IqserPermissionsService, LoadingService } from '@iqser/common-ui'; import { FeaturesService } from '@services/features.service'; import { GeneralSettingsService } from '@services/general-settings.service'; import { tap } from 'rxjs/operators'; @@ -14,6 +14,7 @@ import { Roles } from '@users/roles'; import { DossiersChangesService } from '@services/dossiers/dossier-changes.service'; import { ResolveFn } from '@angular/router'; import { BASE_HREF } from '@iqser/common-ui/lib/utils'; +import { TenantsService } from '@iqser/common-ui/lib/tenants'; function redirectToLastDossierTemplate(baseHref: string, tenant: string, lastDossierTemplate: string) { const lastUrlSegment = window.location.pathname.split('/').filter(Boolean).pop(); diff --git a/libs/common-ui b/libs/common-ui index 8ac4bbfd9..a71e094e5 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 8ac4bbfd9fa98c9172bf2040c763cb934d7f00a7 +Subproject commit a71e094e55efda38556f4a6e131051996f2dbdc1 From f590b0d18cc967f6551e26c38d926c51dec23ed7 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Thu, 6 Jul 2023 16:08:36 +0300 Subject: [PATCH 05/23] DM-311 update tooltips for rss --- apps/red-ui/src/assets/i18n/scm/en.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 62c9bc50b..58e5b7566 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -851,7 +851,7 @@ } }, "dossier-overview": { - "approve": "Approve", + "approve": "Done", "approve-disabled": "File can only be approved once it has been analysed with the latest dictionaries and all suggestions have been processed.", "assign-approver": "Assign Approver", "assign-me": "Assign To Me", @@ -948,7 +948,7 @@ "title": "{length} {length, plural, one{document} other{documents}}" }, "under-approval": "For Approval", - "under-review": "Under Review", + "under-review": "Back to In Progress", "upload-files": "Drag & drop files anywhere..." }, "dossier-permissions": "Dossier Permissions", @@ -1763,7 +1763,7 @@ "ASSIGN_REVIEWER": "When I am assigned to a document as Reviewer", "DOCUMENT_APPROVED": "When the document status changes to Approved (only for dossier owners)", "DOCUMENT_UNDER_APPROVAL": "When the document status changes to Under Approval", - "DOCUMENT_UNDER_REVIEW": "When the document status changes to Under Review", + "DOCUMENT_UNDER_REVIEW": "When the document status changes to In Progress", "DOSSIER_DELETED": "When a dossier was deleted", "DOSSIER_OWNER_DELETED": "When the owner of a dossier got deleted", "DOSSIER_OWNER_REMOVED": "When I lose dossier ownership", From ac06f8b89f18329c185b96b5c8f6980a17a635b6 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Thu, 6 Jul 2023 17:04:02 +0300 Subject: [PATCH 06/23] RED-6713 view login url --- .../src/app/components/base-screen/base-screen.component.ts | 4 ++-- libs/common-ui | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 4f8e37679..f37002b13 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 @@ -16,7 +16,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { List, shareDistinctLast } from '@iqser/common-ui/lib/utils'; import { TenantsService } from '@iqser/common-ui/lib/tenants'; -const isNavigationStart = event => event instanceof NavigationStart; +const isNavigationStart = (event: unknown): event is NavigationStart => event instanceof NavigationStart; const isSearchScreen: (url: string) => boolean = url => url.includes('/search'); @Component({ @@ -26,7 +26,7 @@ const isSearchScreen: (url: string) => boolean = url => url.includes('/search'); export class BaseScreenComponent { readonly #navigationStart$ = this._router.events.pipe( filter(isNavigationStart), - map((event: NavigationStart) => event.url), + map(event => event.url), startWith(this._router.url), shareDistinctLast(), ); diff --git a/libs/common-ui b/libs/common-ui index a71e094e5..4ee4842f7 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit a71e094e55efda38556f4a6e131051996f2dbdc1 +Subproject commit 4ee4842f744cae6161e2f324648b353ae111d1e9 From a39451dd8d4ba4020aaede43f276b60ec157997b Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Thu, 6 Jul 2023 17:09:00 +0300 Subject: [PATCH 07/23] RED-6713 add logger --- libs/common-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/common-ui b/libs/common-ui index 4ee4842f7..f631395f6 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 4ee4842f744cae6161e2f324648b353ae111d1e9 +Subproject commit f631395f613e6cbeaf71826dac4dc8446be33520 From 0d109b0066b3a6b42aaf7d438f5aa9701e209802 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Thu, 6 Jul 2023 17:38:07 +0300 Subject: [PATCH 08/23] RED-6713 load licenses in if logged in guard --- apps/red-ui/src/app/guards/if-logged-in.guard.ts | 3 +++ apps/red-ui/src/app/utils/main.resolver.ts | 9 +-------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/red-ui/src/app/guards/if-logged-in.guard.ts b/apps/red-ui/src/app/guards/if-logged-in.guard.ts index 184426d94..dc2631dbd 100644 --- a/apps/red-ui/src/app/guards/if-logged-in.guard.ts +++ b/apps/red-ui/src/app/guards/if-logged-in.guard.ts @@ -4,6 +4,7 @@ import { NGXLogger } from 'ngx-logger'; import { keycloakInitializer, KeycloakStatusService, TenantsService } from '@iqser/common-ui/lib/tenants'; import { KeycloakService } from 'keycloak-angular'; import { UserService } from '@users/user.service'; +import { LicenseService } from '@services/license.service'; export function ifLoggedIn(): CanActivateFn { return async (route: ActivatedRouteSnapshot) => { @@ -13,6 +14,7 @@ export function ifLoggedIn(): CanActivateFn { const tenantsService = inject(TenantsService); const keycloakService = inject(KeycloakService); const usersService = inject(UserService); + const licenseService = inject(LicenseService); const keycloakStatusService = inject(KeycloakStatusService); const keycloakInstance = keycloakService.getKeycloakInstance(); @@ -31,6 +33,7 @@ export function ifLoggedIn(): CanActivateFn { logger.info('[KEYCLOAK] Keycloak init done!'); await tenantsService.selectTenant(tenant); await usersService.initialize(); + await licenseService.loadLicenses(); } const isLoggedIn = await keycloakService.isLoggedIn(); diff --git a/apps/red-ui/src/app/utils/main.resolver.ts b/apps/red-ui/src/app/utils/main.resolver.ts index af2388d38..2d1bd2db7 100644 --- a/apps/red-ui/src/app/utils/main.resolver.ts +++ b/apps/red-ui/src/app/utils/main.resolver.ts @@ -4,7 +4,6 @@ import { ConfigService } from '@services/config.service'; import { UserService } from '@users/user.service'; import { SystemPreferencesService } from '@services/system-preferences.service'; import { UserPreferenceService } from '@users/user-preference.service'; -import { LicenseService } from '@services/license.service'; import { IqserPermissionsService, LoadingService } from '@iqser/common-ui'; import { FeaturesService } from '@services/features.service'; import { GeneralSettingsService } from '@services/general-settings.service'; @@ -35,7 +34,6 @@ export const mainResolver: ResolveFn = async () => { const systemPreferencesService = inject(SystemPreferencesService); const userPreferenceService = inject(UserPreferenceService); const tenantsService = inject(TenantsService); - const licenseService = inject(LicenseService); const loadingService = inject(LoadingService); const configService = inject(ConfigService); const userService = inject(UserService); @@ -44,12 +42,7 @@ export const mainResolver: ResolveFn = async () => { const generalConfig$ = inject(GeneralSettingsService).getGeneralConfigurations(); const updatedDisplayName$ = generalConfig$.pipe(tap(config => configService.updateDisplayName(config.displayName))); - await Promise.all([ - systemPreferencesService.loadPreferences(), - userPreferenceService.reload(), - firstValueFrom(updatedDisplayName$), - licenseService.loadLicenses(), - ]); + await Promise.all([systemPreferencesService.loadPreferences(), userPreferenceService.reload(), firstValueFrom(updatedDisplayName$)]); const lastDossierTemplate = userPreferenceService.getLastDossierTemplate(); From f20f7d380116b692056e90cfca8e1e567bf30aaa Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Thu, 6 Jul 2023 17:43:13 +0300 Subject: [PATCH 09/23] RED-6774 - fixed redact text issues --- .../redact-text-dialog.component.html | 26 ++++++++--------- .../redact-text-dialog.component.ts | 28 ++++++++++++++++--- .../entity-services/dictionary.service.ts | 7 +++-- apps/red-ui/src/assets/i18n/redact/de.json | 3 +- apps/red-ui/src/assets/i18n/redact/en.json | 3 +- apps/red-ui/src/assets/i18n/scm/de.json | 3 +- apps/red-ui/src/assets/i18n/scm/en.json | 3 +- .../src/lib/dictionaries/dictionary.model.ts | 2 ++ .../src/lib/dictionaries/dictionary.ts | 2 ++ .../redaction-log/add-redaction.request.ts | 1 + 10 files changed, 51 insertions(+), 27 deletions(-) diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html index f0652bbb7..8dcb7d4cc 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html @@ -1,6 +1,6 @@
-
+
@@ -39,6 +39,18 @@
+ +
+ + +
@@ -60,18 +72,6 @@
- -
- - -
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts index 10bf712eb..8915480d4 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts @@ -58,7 +58,7 @@ export class RedactTextDialogComponent readonly #translations = redactTextTranslations; readonly #dossier: Dossier; - readonly #hint: boolean; + readonly hint: boolean; constructor( private readonly _justificationsService: JustificationsService, @@ -70,7 +70,7 @@ export class RedactTextDialogComponent super(); this.#dossier = _activeDossiersService.find(this.data.dossierId); this.type = this.data.manualRedactionEntryWrapper.type; - this.#hint = this.type === ManualRedactionEntryTypes.HINT; + this.hint = this.type === ManualRedactionEntryTypes.HINT; this.#applyToAllDossiers = this.data.applyToAllDossiers ?? true; this.#manualRedactionTypeExists = this._dictionaryService.hasManualType(this.#dossier.dossierTemplateId); this.options = this.#options(); @@ -98,14 +98,18 @@ export class RedactTextDialogComponent } get disabled() { - if (this.dictionaryRequest || this.#hint) { + if (this.dictionaryRequest || this.hint) { return !this.form.get('dictionary').value; } return !this.form.get('reason').value; } async ngOnInit(): Promise { - this.dictionaries = this._dictionaryService.getPossibleDictionaries(this.#dossier.dossierTemplateId, this.#hint); + this.dictionaries = this._dictionaryService.getPossibleDictionaries( + this.#dossier.dossierTemplateId, + this.hint, + !this.#applyToAllDossiers, + ); const data = await firstValueFrom(this._justificationsService.getForDossierTemplate(this.#dossier.dossierTemplateId)); this.legalOptions = data.map(lbm => ({ @@ -121,6 +125,19 @@ export class RedactTextDialogComponent extraOptionChanged(option: DetailsRadioOption): void { this.#applyToAllDossiers = option.extraOption.checked; + + this.dictionaries = this._dictionaryService.getPossibleDictionaries( + this.#dossier.dossierTemplateId, + this.hint, + !this.#applyToAllDossiers, + ); + if (this.#applyToAllDossiers && this.form.get('dictionary').value) { + const selectedDictionaryLabel = this.form.get('dictionary').value; + const selectedDictionary = this.dictionaries.find(d => d.type === selectedDictionaryLabel); + if (!selectedDictionary) { + this.form.get('dictionary').setValue(null); + } + } } save(): void { @@ -185,6 +202,9 @@ export class RedactTextDialogComponent addRedactionRequest.value = addRedactionRequest.rectangle ? this.form.get('classification').value : this.form.get('selectedText').value; + if (this.dictionaryRequest) { + addRedactionRequest.addToAllDossiers = this.#applyToAllDossiers; + } } #options() { diff --git a/apps/red-ui/src/app/services/entity-services/dictionary.service.ts b/apps/red-ui/src/app/services/entity-services/dictionary.service.ts index 56cfdb919..76b19b3bd 100644 --- a/apps/red-ui/src/app/services/entity-services/dictionary.service.ts +++ b/apps/red-ui/src/app/services/entity-services/dictionary.service.ts @@ -146,12 +146,15 @@ export class DictionaryService extends EntitiesService return !!this._dictionariesMapService.get(dossierTemplateId).find(e => e.type === SuperTypes.ManualRedaction && !e.virtual); } - getPossibleDictionaries(dossierTemplateId: string, hintTypes: boolean): Dictionary[] { + getPossibleDictionaries(dossierTemplateId: string, hintTypes: boolean, dossierDictionaryOnly = false): Dictionary[] { const possibleDictionaries: Dictionary[] = []; this._dictionariesMapService.get(dossierTemplateId).forEach((d: Dictionary) => { if (!hintTypes) { - if (!d.virtual && !d.hint && !d.systemManaged) { + if ( + (!d.virtual && !d.hint && !d.systemManaged && d.hasDictionary && d.addToDictionaryAction) || + (dossierDictionaryOnly && d.dossierDictionaryOnly) + ) { possibleDictionaries.push(d); } } else if (d.hint) { diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index 294073cf1..87314194d 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -1647,8 +1647,6 @@ "license-info-screen": { "backend-version": "Backend-Version der Anwendung", "chart": { - "cumulative": "Seiten insgesamt", - "legend": "", "pages-per-month": "Seiten pro Monat", "total-pages": "Gesamtzahl der Seiten" }, @@ -1943,6 +1941,7 @@ "type": "", "type-placeholder": "" }, + "hint-title": "", "title": "" } }, diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 0c2d1092d..4da79ce07 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -1647,8 +1647,6 @@ "license-info-screen": { "backend-version": "Backend Application Version", "chart": { - "cumulative": "Cumulative Pages", - "legend": "Legend", "pages-per-month": "Pages per Month", "total-pages": "Total Pages" }, @@ -1943,6 +1941,7 @@ "type": "Type", "type-placeholder": "Select type ..." }, + "hint-title": "Add Hint", "title": "Redact text" } }, diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index 33d99d99a..38db993c9 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -1647,8 +1647,6 @@ "license-info-screen": { "backend-version": "Backend-Version der Anwendung", "chart": { - "cumulative": "Seiten insgesamt", - "legend": "", "pages-per-month": "Seiten pro Monat", "total-pages": "Gesamtzahl der Seiten" }, @@ -1943,6 +1941,7 @@ "type": "", "type-placeholder": "" }, + "hint-title": "", "title": "" } }, diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 58e5b7566..d89f46b0b 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -1647,8 +1647,6 @@ "license-info-screen": { "backend-version": "Backend Application Version", "chart": { - "cumulative": "Cumulative Pages", - "legend": "Legend", "pages-per-month": "Pages per Month", "total-pages": "Total Pages" }, @@ -1943,6 +1941,7 @@ "type": "Type", "type-placeholder": "Select type ..." }, + "hint-title": "Add Hint", "title": "Redact text" } }, diff --git a/libs/red-domain/src/lib/dictionaries/dictionary.model.ts b/libs/red-domain/src/lib/dictionaries/dictionary.model.ts index 329d8472f..9c20bec42 100644 --- a/libs/red-domain/src/lib/dictionaries/dictionary.model.ts +++ b/libs/red-domain/src/lib/dictionaries/dictionary.model.ts @@ -18,6 +18,7 @@ export class Dictionary extends Entity implements IDictionary { readonly type: string; readonly hasDictionary?: boolean; readonly systemManaged?: boolean; + readonly dossierDictionaryOnly?: boolean; entries: List; falsePositiveEntries: List; @@ -42,6 +43,7 @@ export class Dictionary extends Entity implements IDictionary { this.type = entity.type; this.hasDictionary = entity.hasDictionary; this.systemManaged = entity.systemManaged; + this.dossierDictionaryOnly = entity.dossierDictionaryOnly; } get id(): string { diff --git a/libs/red-domain/src/lib/dictionaries/dictionary.ts b/libs/red-domain/src/lib/dictionaries/dictionary.ts index 2a6261360..d5bcfb254 100644 --- a/libs/red-domain/src/lib/dictionaries/dictionary.ts +++ b/libs/red-domain/src/lib/dictionaries/dictionary.ts @@ -58,4 +58,6 @@ export interface IDictionary { readonly hasDictionary?: boolean; readonly systemManaged?: boolean; + + readonly dossierDictionaryOnly?: boolean; } diff --git a/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts b/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts index f7121dc86..95e06eece 100644 --- a/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts +++ b/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts @@ -14,4 +14,5 @@ export interface IAddRedactionRequest { value?: string; section?: string; rectangle?: boolean; + addToAllDossiers?: boolean; } From 0c0d72aef1c33dfde2239dcb7775518e6fc6dd7d Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 7 Jul 2023 12:08:19 +0300 Subject: [PATCH 10/23] RED-7054 fix not found http errors --- .../edit-dossier-general-info.component.ts | 22 ++++++---- .../services/entity-services/trash.service.ts | 10 +++-- .../src/app/services/license.service.ts | 41 +++++++++++-------- libs/common-ui | 2 +- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts index 2d0f75243..c0b5cf9b0 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts @@ -144,15 +144,11 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti this._dialogService.openDialog('confirm', data, async () => { this._loadingService.start(); - await firstValueFrom(this._trashService.deleteDossier(this.dossier)); - this._editDossierDialogRef.close(); - await this._router.navigate([`/${this._tenantsService.activeTenantId}${this.dossier.dossiersListRouterLink}`]); + const successful = await this._trashService.deleteDossier(this.dossier); + if (successful) { + await this.#closeDialogAndRedirectToDossier(); + } this._loadingService.stop(); - this._toaster.success(_('edit-dossier-dialog.delete-successful'), { - params: { - dossierName: this.dossier.dossierName, - }, - }); }); } @@ -193,6 +189,16 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti return this._dossierStatesMapService.get(this.dossier.dossierTemplateId, stateId).color; } + async #closeDialogAndRedirectToDossier() { + this._editDossierDialogRef.close(); + await this._router.navigate([`/${this._tenantsService.activeTenantId}${this.dossier.dossiersListRouterLink}`]); + this._toaster.success(_('edit-dossier-dialog.delete-successful'), { + params: { + dossierName: this.dossier.dossierName, + }, + }); + } + #getForm(): UntypedFormGroup { const formFieldWithArchivedCheck = value => ({ value, disabled: !this.dossier.isActive }); return this._formBuilder.group({ diff --git a/apps/red-ui/src/app/services/entity-services/trash.service.ts b/apps/red-ui/src/app/services/entity-services/trash.service.ts index 921c40d9f..2b8365f93 100644 --- a/apps/red-ui/src/app/services/entity-services/trash.service.ts +++ b/apps/red-ui/src/app/services/entity-services/trash.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { EntitiesService, QueryParam, Toaster } from '@iqser/common-ui'; import { Dossier, File, IDossier, IFile, TrashDossier, TrashFile, TrashItem } from '@red/domain'; import { catchError, switchMap, take, tap } from 'rxjs/operators'; -import { forkJoin, map, Observable, of } from 'rxjs'; +import { firstValueFrom, forkJoin, map, Observable, of } from 'rxjs'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { PermissionsService } from '../permissions.service'; import { ActiveDossiersService } from '../dossiers/active-dossiers.service'; @@ -31,18 +31,20 @@ export class TrashService extends EntitiesService { super(); } - deleteDossier(dossier: Dossier): Observable { + deleteDossier(dossier: Dossier) { const showToast = () => { this._toaster.error(_('dossier-listing.delete.delete-failed'), { params: { dossierName: dossier.dossierName } }); - return of({}); + return of(undefined); }; const reloadDossiers$ = dossier.isActive ? this._activeDossiersService.loadAll() : this._archivedDossiersService.loadAll(); - return this.delete(dossier.id, 'dossier').pipe( + const request$ = this.delete(dossier.id, 'dossier').pipe( switchMap(() => reloadDossiers$), catchError(showToast), ); + + return firstValueFrom(request$); } restore(items: TrashItem[]): Observable { diff --git a/apps/red-ui/src/app/services/license.service.ts b/apps/red-ui/src/app/services/license.service.ts index 7c1dd0d14..8ababb1a5 100644 --- a/apps/red-ui/src/app/services/license.service.ts +++ b/apps/red-ui/src/app/services/license.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; import { GenericService } from '@iqser/common-ui'; import { ILicense, ILicenseReport, ILicenseReportRequest, ILicenses } from '@red/domain'; import { BehaviorSubject, firstValueFrom, Observable, of } from 'rxjs'; @@ -39,6 +39,10 @@ const defaultOnError: ILicenses = { providedIn: 'root', }) export class LicenseService extends GenericService { + readonly #licenseData$ = new BehaviorSubject(undefined); + readonly #selectedLicense$ = new BehaviorSubject(undefined); + readonly #logger = inject(NGXLogger); + protected readonly _defaultModelPath = 'report'; readonly licenseData$: Observable; readonly selectedLicense$: Observable; activeLicenseId: string; @@ -48,9 +52,19 @@ export class LicenseService extends GenericService { unlicensedPages = 0; analyzedPagesInCurrentLicensingPeriod = 0; uploadedBytesCapacity = 0; - protected readonly _defaultModelPath = 'report'; - readonly #licenseData$ = new BehaviorSubject(undefined); - readonly #selectedLicense$ = new BehaviorSubject(undefined); + + constructor() { + super(); + this.selectedLicense$ = this.#selectedLicense$.pipe(filter(license => !!license)); + this.licenseData$ = this.#licenseData$.pipe( + filter(licenses => !!licenses), + tap(data => (this.activeLicenseId = data.activeLicense)), + tap(() => { + const uploadedBytesCapacity = this.activeLicense.features.find(f => f.name === 'uploadedBytesCapacity')?.value; + this.uploadedBytesCapacity = uploadedBytesCapacity ? parseInt(uploadedBytesCapacity, 10) : 0; + }), + ); + } get selectedLicense() { return this.#selectedLicense$.value; @@ -66,20 +80,13 @@ export class LicenseService extends GenericService { } get activeLicenseKey(): string { - return this.activeLicense.features.find(f => f.name === 'pdftron').value; - } + const activeLicense = this.activeLicense; + if (!activeLicense) { + this.#logger.error('[LICENSE] No active license found!'); + return ''; + } - constructor(private readonly _logger: NGXLogger) { - super(); - this.selectedLicense$ = this.#selectedLicense$.pipe(filter(license => !!license)); - this.licenseData$ = this.#licenseData$.pipe( - filter(licenses => !!licenses), - tap(data => (this.activeLicenseId = data.activeLicense)), - tap(() => { - const uploadedBytesCapacity = this.activeLicense.features.find(f => f.name === 'uploadedBytesCapacity')?.value; - this.uploadedBytesCapacity = uploadedBytesCapacity ? parseInt(uploadedBytesCapacity, 10) : 0; - }), - ); + return activeLicense.features.find(f => f.name === 'pdftron').value; } async loadLicenseData(license: ILicense = this.selectedLicense) { diff --git a/libs/common-ui b/libs/common-ui index f631395f6..30846478e 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit f631395f613e6cbeaf71826dac4dc8446be33520 +Subproject commit 30846478ed6a112813953b9217a69ef047ffa217 From e473db9c16c92dfe8bd62ddfc3b9d815b8fce907 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 7 Jul 2023 13:25:03 +0300 Subject: [PATCH 11/23] RED-3800 update config & common-ui --- apps/red-ui/src/assets/config/config.json | 4 ++-- libs/common-ui | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index 311b38e1a..3e5de8134 100644 --- a/apps/red-ui/src/assets/config/config.json +++ b/apps/red-ui/src/assets/config/config.json @@ -1,7 +1,7 @@ { "ADMIN_CONTACT_NAME": null, "ADMIN_CONTACT_URL": null, - "API_URL": "https://dev-02.iqser.cloud", + "API_URL": "https://dev-04.iqser.cloud", "APP_NAME": "RedactManager", "AUTO_READ_TIME": 3, "BACKEND_APP_VERSION": "4.4.40", @@ -11,7 +11,7 @@ "MAX_RETRIES_ON_SERVER_ERROR": 3, "OAUTH_CLIENT_ID": "redaction", "OAUTH_IDP_HINT": null, - "OAUTH_URL": "https://dev-02.iqser.cloud/auth", + "OAUTH_URL": "https://dev-04.iqser.cloud/auth", "RECENT_PERIOD_IN_HOURS": 24, "SELECTION_MODE": "structural", "MANUAL_BASE_URL": "https://docs.redactmanager.com/preview", diff --git a/libs/common-ui b/libs/common-ui index 30846478e..da18c68a8 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 30846478ed6a112813953b9217a69ef047ffa217 +Subproject commit da18c68a861a8d343dd3f63298e825543714f743 From 72130128dca630e19310e9c4da1ce09c931fae9c Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 7 Jul 2023 15:13:42 +0300 Subject: [PATCH 12/23] RED-6713 fix page refresh loop --- apps/red-ui/src/app/app-routing.module.ts | 28 ++++---- apps/red-ui/src/app/guards/dossiers.guard.ts | 72 +++++++++++-------- .../src/app/guards/if-logged-in.guard.ts | 2 +- .../watermark-screen.component.html | 14 ++-- .../file-preview-screen.component.ts | 6 +- .../pdf-viewer/pdf-viewer.component.html | 2 - .../pdf-viewer/pdf-viewer.component.scss | 12 ---- .../modules/pdf-viewer/pdf-viewer.module.ts | 2 - .../services/document-viewer.service.ts | 18 ++++- .../services/webviewer-loaded.guard.ts | 47 ++++++------ apps/red-ui/src/index.html | 1 + apps/red-ui/src/styles.scss | 8 +++ 12 files changed, 114 insertions(+), 98 deletions(-) diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts index 01ba8ff2e..ccf478b4b 100644 --- a/apps/red-ui/src/app/app-routing.module.ts +++ b/apps/red-ui/src/app/app-routing.module.ts @@ -5,8 +5,8 @@ import { BaseScreenComponent } from '@components/base-screen/base-screen.compone import { RouteReuseStrategy, RouterModule } from '@angular/router'; import { NgModule } from '@angular/core'; import { DownloadsListScreenComponent } from '@components/downloads-list-screen/downloads-list-screen.component'; -import { DossiersGuard } from '@guards/dossiers.guard'; -import { ACTIVE_DOSSIERS_SERVICE, ARCHIVED_DOSSIERS_SERVICE } from './tokens'; +import { loadActiveDossiersGuard, loadAllDossiersGuard, loadArchivedDossiersGuard } from '@guards/dossiers.guard'; +import { ACTIVE_DOSSIERS_SERVICE } from './tokens'; import { FeaturesGuard } from '@guards/features-guard.service'; import { DossierTemplatesGuard } from '@guards/dossier-templates.guard'; import { templateExistsWhenEnteringDossierList } from '@guards/dossier-template-exists.guard'; @@ -14,7 +14,7 @@ import { DashboardGuard } from '@guards/dashboard-guard.service'; import { TrashGuard } from '@guards/trash.guard'; import { ARCHIVE_ROUTE, BreadcrumbTypes, DOSSIER_ID, DOSSIER_TEMPLATE_ID, DOSSIERS_ARCHIVE, DOSSIERS_ROUTE, FILE_ID } from '@red/domain'; import { DossierFilesGuard } from '@guards/dossier-files-guard'; -import { WebViewerLoadedGuard } from './modules/pdf-viewer/services/webviewer-loaded.guard'; +import { webViewerLoadedGuard } from './modules/pdf-viewer/services/webviewer-loaded.guard'; import { Roles } from '@users/roles'; import { mainResolver } from '@utils/main.resolver'; import { hasAnyRoleGuard, IqserAuthGuard } from '@iqser/common-ui/lib/users'; @@ -26,10 +26,8 @@ import { TenantSelectComponent } from '@iqser/common-ui/lib/tenants'; const dossierTemplateIdRoutes: IqserRoutes = [ { path: `${DOSSIERS_ROUTE}`, - canActivate: [CompositeRouteGuard, IqserPermissionsGuard], + canActivate: [loadActiveDossiersGuard(), IqserPermissionsGuard], data: { - routeGuards: [DossiersGuard], - dossiersService: ACTIVE_DOSSIERS_SERVICE, permissions: { allow: [Roles.files.readStatus], redirectTo: '/auth-error', @@ -53,9 +51,9 @@ const dossierTemplateIdRoutes: IqserRoutes = [ }, { path: `:${DOSSIER_ID}/file/:${FILE_ID}`, - canActivate: [CompositeRouteGuard, IqserPermissionsGuard], + canActivate: [CompositeRouteGuard, IqserPermissionsGuard, webViewerLoadedGuard()], data: { - routeGuards: [DossierFilesGuard, WebViewerLoadedGuard], + routeGuards: [DossierFilesGuard], breadcrumbs: [BreadcrumbTypes.dossierTemplate, BreadcrumbTypes.dossier, BreadcrumbTypes.file], dossiersService: ACTIVE_DOSSIERS_SERVICE, permissions: { @@ -78,10 +76,9 @@ const dossierTemplateIdRoutes: IqserRoutes = [ { path: `${ARCHIVE_ROUTE}`, loadChildren: () => import('./modules/archive/archive.module').then(m => m.ArchiveModule), - canActivate: [CompositeRouteGuard, WebViewerLoadedGuard], + canActivate: [CompositeRouteGuard, webViewerLoadedGuard(), loadArchivedDossiersGuard()], data: { - routeGuards: [FeaturesGuard, DossiersGuard], - dossiersService: ARCHIVED_DOSSIERS_SERVICE, + routeGuards: [FeaturesGuard], features: [DOSSIERS_ARCHIVE], }, }, @@ -150,9 +147,9 @@ const mainRoutes: IqserRoutes = [ { path: 'search', loadChildren: () => import('./modules/search/search.module').then(m => m.SearchModule), - canActivate: [CompositeRouteGuard, IqserPermissionsGuard], + canActivate: [CompositeRouteGuard, IqserPermissionsGuard, loadAllDossiersGuard()], data: { - routeGuards: [IqserAuthGuard, RedRoleGuard, DossiersGuard], + routeGuards: [IqserAuthGuard, RedRoleGuard], permissions: { allow: [Roles.search], redirectTo: '/auth-error', @@ -162,10 +159,9 @@ const mainRoutes: IqserRoutes = [ { path: 'trash', loadChildren: () => import('./modules/trash/trash.module').then(m => m.TrashModule), - canActivate: [CompositeRouteGuard, IqserPermissionsGuard], + canActivate: [CompositeRouteGuard, IqserPermissionsGuard, loadActiveDossiersGuard()], data: { - routeGuards: [IqserAuthGuard, RedRoleGuard, DossiersGuard, TrashGuard], - dossiersService: ACTIVE_DOSSIERS_SERVICE, + routeGuards: [IqserAuthGuard, RedRoleGuard, TrashGuard], permissions: { allow: [Roles.dossiers.read, Roles.files.readStatus], redirectTo: '/auth-error', diff --git a/apps/red-ui/src/app/guards/dossiers.guard.ts b/apps/red-ui/src/app/guards/dossiers.guard.ts index 35632190f..01be634ee 100644 --- a/apps/red-ui/src/app/guards/dossiers.guard.ts +++ b/apps/red-ui/src/app/guards/dossiers.guard.ts @@ -1,45 +1,57 @@ -import { Injectable, Injector, ProviderToken } from '@angular/core'; -import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router'; -import { firstValueFrom, forkJoin } from 'rxjs'; -import { take } from 'rxjs/operators'; +import { inject } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivateFn, Router } from '@angular/router'; +import { firstValueFrom } from 'rxjs'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.service'; -import { DossiersService } from '@services/dossiers/dossiers.service'; -import { ARCHIVE_ROUTE, DOSSIER_TEMPLATE_ID } from '@red/domain'; +import { DOSSIER_TEMPLATE_ID } from '@red/domain'; import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service'; import { TenantsService } from '@iqser/common-ui/lib/tenants'; +import { NGXLogger } from 'ngx-logger'; +import { ACTIVE_DOSSIERS_SERVICE, ARCHIVED_DOSSIERS_SERVICE } from '../tokens'; -@Injectable({ providedIn: 'root' }) -export class DossiersGuard implements CanActivate { - constructor( - private readonly _injector: Injector, - private readonly _router: Router, - private readonly _tenantsService: TenantsService, - private readonly _dashboardStatsService: DashboardStatsService, - private readonly _activeDossiersService: ActiveDossiersService, - private readonly _archivedDossiersService: ArchivedDossiersService, - ) {} +export function loadAllDossiersGuard(): CanActivateFn { + return async () => { + const logger = inject(NGXLogger); + logger.info('[GUARDS] loadAllDossiersGuard start'); - async canActivate(route: ActivatedRouteSnapshot): Promise { - const token: ProviderToken = route.data.dossiersService; - if (!token) { - const services = [this._archivedDossiersService, this._activeDossiersService]; - const loading$ = forkJoin(services.map(service => service.loadAll().pipe(take(1)))); - await firstValueFrom(loading$); - return true; - } + const services = [inject(ArchivedDossiersService), inject(ActiveDossiersService)]; + const requests = services.map(service => firstValueFrom(service.loadAll())); + await Promise.all(requests); - const dossiersService: DossiersService = this._injector.get(token); - const isArchive = dossiersService.routerPath === ARCHIVE_ROUTE; + logger.info('[GUARDS] loadAllDossiersGuard end'); + return true; + }; +} + +export function loadActiveDossiersGuard(): CanActivateFn { + return async () => { + const logger = inject(NGXLogger); + logger.info('[GUARDS] loadDossiersGuard start'); + + await firstValueFrom(inject(ACTIVE_DOSSIERS_SERVICE).loadAll()); + + logger.info('[GUARDS] loadDossiersGuard end'); + return true; + }; +} + +export function loadArchivedDossiersGuard(): CanActivateFn { + return async (route: ActivatedRouteSnapshot) => { + const logger = inject(NGXLogger); + logger.info('[GUARDS] loadArchivedDossiersGuard start'); + + const dossiersService = inject(ARCHIVED_DOSSIERS_SERVICE); const dossierTemplateId = route.paramMap.get(DOSSIER_TEMPLATE_ID); - const dossierTemplateStats = this._dashboardStatsService.find(dossierTemplateId); + const dossierTemplateStats = inject(DashboardStatsService).find(dossierTemplateId); - if (isArchive && dossierTemplateStats?.numberOfArchivedDossiers === 0) { - await this._router.navigate([this._tenantsService.activeTenantId, 'main', dossierTemplateId, 'dossiers']); + if (dossierTemplateStats?.numberOfArchivedDossiers === 0) { + logger.info('[GUARDS] loadArchivedDossiersGuard no archived dossiers, redirect to active dossiers page'); + await inject(Router).navigate([inject(TenantsService).activeTenantId, 'main', dossierTemplateId, 'dossiers']); return false; } await firstValueFrom(dossiersService.loadAll()); + logger.info('[GUARDS] loadArchivedDossiersGuard end'); return true; - } + }; } diff --git a/apps/red-ui/src/app/guards/if-logged-in.guard.ts b/apps/red-ui/src/app/guards/if-logged-in.guard.ts index dc2631dbd..91a51e440 100644 --- a/apps/red-ui/src/app/guards/if-logged-in.guard.ts +++ b/apps/red-ui/src/app/guards/if-logged-in.guard.ts @@ -9,7 +9,7 @@ import { LicenseService } from '@services/license.service'; export function ifLoggedIn(): CanActivateFn { return async (route: ActivatedRouteSnapshot) => { const logger = inject(NGXLogger); - logger.info('[ROUTES] Check if can activate main'); + logger.info('[ROUTES] Check if can activate route', route); const tenantsService = inject(TenantsService); const keycloakService = inject(KeycloakService); diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.html index c0a2d0a50..defe51978 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.html @@ -1,5 +1,5 @@
-
+
@@ -54,30 +54,30 @@
-
+
-
+
diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index da2646e18..fb61214bb 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -11,7 +11,7 @@ import { TemplateRef, ViewChild, } from '@angular/core'; -import { ActivatedRoute, ActivatedRouteSnapshot, NavigationExtras, Router } from '@angular/router'; +import { ActivatedRouteSnapshot, NavigationExtras, Router } from '@angular/router'; import { CircleButtonTypes, ConfirmOption, @@ -20,6 +20,7 @@ import { ErrorService, HelpModeService, IConfirmationDialogData, + IqserDialog, LoadingService, Toaster, } from '@iqser/common-ui'; @@ -63,7 +64,6 @@ import { ConfigService } from '@services/config.service'; import { ReadableRedactionsService } from '../pdf-viewer/services/readable-redactions.service'; import { Roles } from '@users/roles'; import { SuggestionsService } from './services/suggestions.service'; -import { IqserDialog } from '../../../../../../libs/common-ui/src/lib/dialog/iqser-dialog.service'; import { RedactTextDialogComponent } from './dialogs/redact-text-dialog/redact-text-dialog.component'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { copyLocalStorageFiltersValues, FilterService, NestedFilter, processFilters } from '@iqser/common-ui/lib/filtering'; @@ -108,7 +108,6 @@ export class FilePreviewScreenComponent private readonly _annotationManager: REDAnnotationManager, private readonly _errorService: ErrorService, private readonly _filterService: FilterService, - private readonly _activatedRoute: ActivatedRoute, private readonly _loadingService: LoadingService, private readonly _filesMapService: FilesMapService, private readonly _dossiersService: DossiersService, @@ -161,6 +160,7 @@ export class FilePreviewScreenComponent effect(() => { const selectedText = this._documentViewer.selectedText(); + console.log('selectedText', selectedText); const canPerformActions = this.pdfProxyService.canPerformActions(); const isCurrentPageExcluded = this.state.file().isPageExcluded(this.pdf.currentPage()); diff --git a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.html b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.html index 0df39e49d..3fd4bcd55 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.html +++ b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.html @@ -1,5 +1,3 @@ -
- diff --git a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.scss b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.scss index 37792961d..e69de29bb 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.scss +++ b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.scss @@ -1,12 +0,0 @@ -:host { - --workload-width: 350px; - --header-height: calc(var(--iqser-top-bar-height) + 50px); -} - -div { - width: calc(100% - var(--workload-width)); - height: calc(100% - var(--header-height)); - bottom: 0; - left: 0; - position: absolute; -} diff --git a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts index d49e497f6..7af623aba 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts @@ -11,7 +11,6 @@ import { PaginatorComponent } from './components/paginator/paginator.component'; import { MatIconModule } from '@angular/material/icon'; import { AnnotationDrawService } from './services/annotation-draw.service'; import { REDDocumentViewer } from './services/document-viewer.service'; -import { WebViewerLoadedGuard } from './services/webviewer-loaded.guard'; import { ReadableRedactionsService } from './services/readable-redactions.service'; @NgModule({ @@ -27,7 +26,6 @@ import { ReadableRedactionsService } from './services/readable-redactions.servic ReadableRedactionsService, ViewerHeaderService, AnnotationDrawService, - WebViewerLoadedGuard, ], }) export class PdfViewerModule {} diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts index 65724b262..7561fc1ce 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts @@ -1,4 +1,4 @@ -import { inject, Injectable, NgZone, Signal, signal } from '@angular/core'; +import { effect, inject, Injectable, Signal, signal } from '@angular/core'; import { Core } from '@pdftron/webviewer'; import { NGXLogger } from 'ngx-logger'; import { fromEvent, Observable } from 'rxjs'; @@ -25,7 +25,6 @@ export class REDDocumentViewer { readonly #userPreferenceService = inject(UserPreferenceService); readonly #pdf = inject(PdfViewer); readonly #activatedRoute = inject(ActivatedRoute); - readonly #ngZone = inject(NgZone); readonly loaded$: Observable; keyUp$: Observable; readonly selectedText: Signal; @@ -37,6 +36,21 @@ export class REDDocumentViewer { this.loaded$ = toObservable(this.#loaded); this.pageComplete = this.#pageComplete.asReadonly(); this.selectedText = this.#selectedText.asReadonly(); + + effect(() => { + const viewerElement = document.getElementById('viewer'); + if (!viewerElement) { + return; + } + + if (this.loaded()) { + this.#logger.info('[PDF] Show viewer'); + viewerElement.style.visibility = 'visible'; + } else { + this.#logger.info('[PDF] Hide viewer'); + viewerElement.style.visibility = 'hidden'; + } + }); } get PDFDoc() { diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/webviewer-loaded.guard.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/webviewer-loaded.guard.ts index 62feb6842..6278b91af 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/webviewer-loaded.guard.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/webviewer-loaded.guard.ts @@ -1,41 +1,42 @@ -import { Injectable } from '@angular/core'; -import { CanActivate, Router } from '@angular/router'; +import { inject } from '@angular/core'; +import { CanActivateFn, ResolveFn, Router } from '@angular/router'; import { REDDocumentViewer } from './document-viewer.service'; import { PdfViewer } from './pdf-viewer.service'; import { REDAnnotationManager } from './annotation-manager.service'; import { ViewerHeaderService } from './viewer-header.service'; import { LoadingService } from '@iqser/common-ui'; import { WebViewerInstance } from '@pdftron/webviewer'; +import { NGXLogger } from 'ngx-logger'; +import { DOCUMENT } from '@angular/common'; -@Injectable() -export class WebViewerLoadedGuard implements CanActivate { - constructor( - private readonly _documentViewer: REDDocumentViewer, - private readonly _pdf: PdfViewer, - private readonly _router: Router, - private readonly _annotationManager: REDAnnotationManager, - private readonly _viewerHeaderService: ViewerHeaderService, - private readonly _loadingService: LoadingService, - ) {} +export function webViewerLoadedGuard(): CanActivateFn | ResolveFn { + return async (_, state) => { + const pdf = inject(PdfViewer); + const logger = inject(NGXLogger); - async canActivate(_, state) { - if (this._pdf.instance) { + if (pdf.instance) { + logger.info('[PDF] WebViewerGuard already loaded.'); return true; } - this._loadingService.start(); + inject(LoadingService).start(); + const router = inject(Router); + const annotationManager = inject(REDAnnotationManager); + const documentViewer = inject(REDDocumentViewer); + const viewerHeaderService = inject(ViewerHeaderService); let instance: WebViewerInstance | undefined; try { - instance = await this._pdf.init(document.getElementById('viewer')); - } catch { - return this._router.navigateByUrl(state.url); + instance = await pdf.init(inject(DOCUMENT).getElementById('viewer')); + } catch (e) { + logger.warn('[PDF] WebViewerGuard error: ', e, 'redirecting to', state.url); + return router.navigateByUrl(state.url); } - this._annotationManager.init(instance.Core.annotationManager); - this._documentViewer.init(instance.Core.documentViewer); - this._viewerHeaderService.init(); + annotationManager.init(instance.Core.annotationManager); + documentViewer.init(instance.Core.documentViewer); + viewerHeaderService.init(); - return !!this._pdf.instance; - } + return !!pdf.instance; + }; } diff --git a/apps/red-ui/src/index.html b/apps/red-ui/src/index.html index e54d15cff..52dbffae2 100644 --- a/apps/red-ui/src/index.html +++ b/apps/red-ui/src/index.html @@ -10,6 +10,7 @@ +
diff --git a/apps/red-ui/src/styles.scss b/apps/red-ui/src/styles.scss index c05edc9ac..716f736f0 100644 --- a/apps/red-ui/src/styles.scss +++ b/apps/red-ui/src/styles.scss @@ -143,3 +143,11 @@ $dark-accent-10: darken(vars.$accent, 10%); $iqser-app-name-font-size: 13px, $iqser-app-name-color: vars.$white ); + +#viewer { + width: calc(100% - 350px); + height: calc(100% - calc(var(--iqser-top-bar-height) + 50px)); + bottom: 0; + left: 0; + position: absolute; +} From b1ed0818958c47c117bb2b82f3ae7d13cf9f9a5c Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Fri, 7 Jul 2023 15:28:44 +0300 Subject: [PATCH 13/23] RED-6774 - fixed add hint issues --- .../redact-text-dialog.component.html | 26 +++++++++---------- .../redact-text-dialog.component.ts | 4 +-- .../entity-services/dictionary.service.ts | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html index 8dcb7d4cc..fec0d8467 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html @@ -39,22 +39,10 @@
- -
- - -
-
+
@@ -72,6 +60,18 @@
+ +
+ + +
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts index 8915480d4..70c794561 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts @@ -202,9 +202,7 @@ export class RedactTextDialogComponent addRedactionRequest.value = addRedactionRequest.rectangle ? this.form.get('classification').value : this.form.get('selectedText').value; - if (this.dictionaryRequest) { - addRedactionRequest.addToAllDossiers = this.#applyToAllDossiers; - } + addRedactionRequest.addToAllDossiers = this.dictionaryRequest && this.#applyToAllDossiers; } #options() { diff --git a/apps/red-ui/src/app/services/entity-services/dictionary.service.ts b/apps/red-ui/src/app/services/entity-services/dictionary.service.ts index 76b19b3bd..e8a9dee5c 100644 --- a/apps/red-ui/src/app/services/entity-services/dictionary.service.ts +++ b/apps/red-ui/src/app/services/entity-services/dictionary.service.ts @@ -157,7 +157,7 @@ export class DictionaryService extends EntitiesService ) { possibleDictionaries.push(d); } - } else if (d.hint) { + } else if ((d.hint && d.hasDictionary && d.addToDictionaryAction) || (dossierDictionaryOnly && d.dossierDictionaryOnly)) { possibleDictionaries.push(d); } }); From 1ab46577f3dccd76cfe52ff9b5cb3563bf5f1a6d Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 7 Jul 2023 16:00:34 +0300 Subject: [PATCH 14/23] RED-6922 fix selected text delay --- .../file-preview-screen.component.ts | 27 ++++++++++--------- .../services/pdf-proxy.service.ts | 6 ++--- .../services/document-viewer.service.ts | 12 +++++---- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index fb61214bb..f5dce87ef 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -158,19 +158,6 @@ export class FilePreviewScreenComponent } }); - effect(() => { - const selectedText = this._documentViewer.selectedText(); - console.log('selectedText', selectedText); - const canPerformActions = this.pdfProxyService.canPerformActions(); - const isCurrentPageExcluded = this.state.file().isPageExcluded(this.pdf.currentPage()); - - if ((selectedText.length > 2 || this._isJapaneseString(selectedText)) && canPerformActions && !isCurrentPageExcluded) { - this.pdf.enable(textActions); - } else { - this.pdf.disable(textActions); - } - }); - effect(() => { if (this._viewModeService.viewMode()) { this.updateViewMode().then(); @@ -734,6 +721,20 @@ export class FilePreviewScreenComponent ), ) .subscribe(); + + const selectedTextEffect = this._documentViewer.selectedText$.pipe( + tap(selectedText => { + const canPerformActions = this.pdfProxyService.canPerformActions(); + const isCurrentPageExcluded = this.state.file().isPageExcluded(this.pdf.currentPage()); + + if ((selectedText.length > 2 || this._isJapaneseString(selectedText)) && canPerformActions && !isCurrentPageExcluded) { + this.pdf.enable(textActions); + } else { + this.pdf.disable(textActions); + } + }), + ); + this.addActiveScreenSubscription = selectedTextEffect.subscribe(); } #handleDeletedDossier(): void { diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts index edfa6f2a0..6f0792a4b 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts @@ -186,14 +186,14 @@ export class PdfProxyService { #addManualRedactionOfType(type: ManualRedactionEntryType) { const selectedQuads: Record = this._pdf.documentViewer.getSelectedTextQuads(); - const text = this._documentViewer.selectedText(); + const text = this._documentViewer.selectedText; const manualRedactionEntry = this.#getManualRedaction(selectedQuads, text, true); this.manualAnnotationRequested$.next({ manualRedactionEntry, type }); } #redactText(type: ManualRedactionEntryType) { const selectedQuads: Record = this._pdf.documentViewer.getSelectedTextQuads(); - const text = this._documentViewer.selectedText(); + const text = this._documentViewer.selectedText; const manualRedactionEntry = this.#getManualRedaction(selectedQuads, text, true); this.redactTextRequested$.next({ manualRedactionEntry, type }); } @@ -241,7 +241,7 @@ export class PdfProxyService { this._pdf.enable(TEXT_POPUPS_TO_TOGGLE); this._viewerHeaderService.enable(HEADER_ITEMS_TO_TOGGLE); - if (this._documentViewer.selectedText().length > 2) { + if (this._documentViewer.selectedText.length > 2) { this._pdf.enable([TextPopups.REDACT_TEXT, TextPopups.ADD_HINT, TextPopups.ADD_FALSE_POSITIVE]); } } diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts index 7561fc1ce..1bdeea966 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts @@ -1,7 +1,7 @@ import { effect, inject, Injectable, Signal, signal } from '@angular/core'; import { Core } from '@pdftron/webviewer'; import { NGXLogger } from 'ngx-logger'; -import { fromEvent, Observable } from 'rxjs'; +import { BehaviorSubject, fromEvent, Observable } from 'rxjs'; import { filter, tap } from 'rxjs/operators'; import { ActivatedRoute } from '@angular/router'; import { PdfViewer } from './pdf-viewer.service'; @@ -20,14 +20,13 @@ export class REDDocumentViewer { #document: DocumentViewer; readonly #loaded = signal(false); readonly #pageComplete = signal(undefined); - readonly #selectedText = signal(''); readonly #logger = inject(NGXLogger); readonly #userPreferenceService = inject(UserPreferenceService); readonly #pdf = inject(PdfViewer); readonly #activatedRoute = inject(ActivatedRoute); readonly loaded$: Observable; keyUp$: Observable; - readonly selectedText: Signal; + readonly selectedText$ = new BehaviorSubject(''); readonly loaded: Signal; readonly pageComplete: Signal; @@ -35,7 +34,6 @@ export class REDDocumentViewer { this.loaded = this.#loaded.asReadonly(); this.loaded$ = toObservable(this.#loaded); this.pageComplete = this.#pageComplete.asReadonly(); - this.selectedText = this.#selectedText.asReadonly(); effect(() => { const viewerElement = document.getElementById('viewer'); @@ -53,6 +51,10 @@ export class REDDocumentViewer { }); } + get selectedText() { + return this.selectedText$.value; + } + get PDFDoc() { return this.document?.getPDFDoc(); } @@ -156,7 +158,7 @@ export class REDDocumentViewer { #listenForDocEvents() { this.#document.addEventListener('textSelected', (quads: Quad, selectedText: string, pageNumber: number) => { - this.#selectedText.set(selectedText); + this.selectedText$.next(selectedText); this.#disableTextPopupIfCompareMode(pageNumber); }); From 5d952332c7bc88df6238b8680f68dbd4bd859ea6 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 7 Jul 2023 16:56:05 +0300 Subject: [PATCH 15/23] RED-6713 fix pdf viewer visibility --- apps/red-ui/src/styles.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/red-ui/src/styles.scss b/apps/red-ui/src/styles.scss index 716f736f0..7ead7b9ab 100644 --- a/apps/red-ui/src/styles.scss +++ b/apps/red-ui/src/styles.scss @@ -145,6 +145,7 @@ $dark-accent-10: darken(vars.$accent, 10%); ); #viewer { + visibility: hidden; width: calc(100% - 350px); height: calc(100% - calc(var(--iqser-top-bar-height) + 50px)); bottom: 0; From 8bc9267058aca79c2db2874c76e88e50fb174357 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 7 Jul 2023 17:03:47 +0300 Subject: [PATCH 16/23] RED-6713 fix switch accounts button --- .../src/app/components/user-menu/user-menu.component.html | 2 +- libs/common-ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/red-ui/src/app/components/user-menu/user-menu.component.html b/apps/red-ui/src/app/components/user-menu/user-menu.component.html index e58926fa9..5cc6b5e25 100644 --- a/apps/red-ui/src/app/components/user-menu/user-menu.component.html +++ b/apps/red-ui/src/app/components/user-menu/user-menu.component.html @@ -5,7 +5,7 @@ - + {{ 'top-bar.navigation-items.my-account.children.select-tenant' | translate }} diff --git a/libs/common-ui b/libs/common-ui index da18c68a8..f33ada72f 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit da18c68a861a8d343dd3f63298e825543714f743 +Subproject commit f33ada72f4fe41dc8eb2f51142b657c2b7e856b8 From d72d865ad834004fcbc2927b5131b4aed4fce80e Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 7 Jul 2023 18:20:07 +0300 Subject: [PATCH 17/23] RED-3800 add disable stop propagation --- .../notifications.component.html | 8 ++++---- .../file-attribute.component.html | 20 +++++++++---------- .../workflow-item.component.html | 9 +++++---- .../dossier-overview.module.ts | 2 ++ .../annotation-wrapper.component.html | 2 +- .../comments/comments.component.html | 2 +- .../file-workload.component.html | 4 ++-- .../search-item-template.component.html | 4 ++-- .../edit-dossier-team.component.html | 2 +- .../expandable-file-actions.component.html | 2 +- .../components/select/select.component.html | 4 ++-- libs/common-ui | 2 +- 12 files changed, 32 insertions(+), 29 deletions(-) diff --git a/apps/red-ui/src/app/components/notifications/notifications.component.html b/apps/red-ui/src/app/components/notifications/notifications.component.html index 8b65174a4..5f2b7e66b 100644 --- a/apps/red-ui/src/app/components/notifications/notifications.component.html +++ b/apps/red-ui/src/app/components/notifications/notifications.component.html @@ -1,8 +1,8 @@ @@ -25,7 +25,7 @@ *ngIf="(hasUnreadNotifications$ | async) && first" class="view-all" id="notifications-mark-all-as-read-btn" - stopPropagation + iqserStopPropagation > {{ 'notifications.mark-all-as-read' | translate }}
@@ -37,8 +37,8 @@ [class.unread]="!notification.readDate" [id]="'notifications-mark-as-read-' + notification.id + '-btn'" class="notification" + iqserStopPropagation mat-menu-item - stopPropagation > @@ -51,9 +51,9 @@ (click)="markRead([notification], !notification.readDate)" [id]="'notifications-mark-' + notification.id" class="dot" + iqserStopPropagation matTooltip="{{ 'notifications.mark-as' | translate : { type: notification.readDate ? 'unread' : 'read' } }}" matTooltipPosition="before" - stopPropagation >
diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/file-attribute/file-attribute.component.html b/apps/red-ui/src/app/modules/dossier-overview/components/file-attribute/file-attribute.component.html index de7e1d214..5242f5f5a 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/file-attribute/file-attribute.component.html +++ b/apps/red-ui/src/app/modules/dossier-overview/components/file-attribute/file-attribute.component.html @@ -1,6 +1,6 @@ -
-
+
+
{{ fileAttribute.label }}: {{ fileAttributeValue || '-' }}
-
+
@@ -35,15 +35,15 @@
-
+
- +
diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.html b/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.html index 40cd96b34..2c0632a24 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.html +++ b/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.html @@ -1,10 +1,10 @@ -
+
@@ -20,7 +20,7 @@
- +
@@ -31,10 +31,11 @@
diff --git a/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts b/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts index 01c5b3038..972364348 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/dossier-overview.module.ts @@ -3,6 +3,7 @@ import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; import { CircleButtonComponent, + DisableStopPropagationDirective, DynamicInputComponent, HasScrollbarDirective, IqserAllowDirective, @@ -70,6 +71,7 @@ const routes: IqserRoutes = [ DynamicInputComponent, IqserAllowDirective, TenantPipe, + DisableStopPropagationDirective, ], }) export class DossierOverviewModule {} diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.html index dfd222f5e..7482014ca 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.html @@ -13,8 +13,8 @@ (click)="comments.toggleExpandComments()" [matTooltip]="'comments.comments' | translate : { count: annotation.item.comments?.length }" class="comments-counter" + iqserStopPropagation matTooltipPosition="above" - stopPropagation > {{ annotation.item.comments.length }} diff --git a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html index 8ddd05bf0..3b7c4a0a2 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html @@ -33,7 +33,7 @@
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 771002e53..78c824d35 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 @@ -29,9 +29,9 @@ *ngIf="documentInfoService.hidden()" [actionsTemplate]="annotationFilterActionTemplate" [attr.help-mode-key]="'workload_in_editor'" + [fileId]="state.file()?.id" [primaryFiltersSlug]="'primaryFilters'" [secondaryFiltersSlug]="'secondaryFilters'" - [fileId]="state.file()?.id" >
@@ -217,6 +217,6 @@ *ngIf="filter.id === 'skipped'" [icon]="skippedService.hideSkipped() ? 'red:visibility-off' : 'red:visibility'" [type]="circleButtonTypes.dark" - preventDefault + iqserPreventDefault > diff --git a/apps/red-ui/src/app/modules/search/search-item-template/search-item-template.component.html b/apps/red-ui/src/app/modules/search/search-item-template/search-item-template.component.html index e6a250561..ead328b06 100644 --- a/apps/red-ui/src/app/modules/search/search-item-template/search-item-template.component.html +++ b/apps/red-ui/src/app/modules/search/search-item-template/search-item-template.component.html @@ -22,7 +22,7 @@ {{ 'search-screen.missing' | translate }}: {{ term }}. {{ 'search-screen.must-contain' | translate }}: -  {{ term }} @@ -50,7 +50,7 @@ diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.html b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.html index a39644661..b444ecbf5 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.html +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component.html @@ -67,7 +67,7 @@ (click)="!disabled && toggleApprover(userId)" *ngIf="!disabled || isApprover(userId)" class="make-approver" - stopPropagation + iqserStopPropagation >
diff --git a/apps/red-ui/src/app/modules/shared/components/select/select.component.html b/apps/red-ui/src/app/modules/shared/components/select/select.component.html index ebdd68eaf..8eac16b2a 100644 --- a/apps/red-ui/src/app/modules/shared/components/select/select.component.html +++ b/apps/red-ui/src/app/modules/shared/components/select/select.component.html @@ -5,14 +5,14 @@ (click)="selectAll()" [class.disabled]="disabled" class="all-caps-label primary pointer" - stopPropagation + iqserStopPropagation translate="actions.all" >
diff --git a/libs/common-ui b/libs/common-ui index f33ada72f..137a62338 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit f33ada72f4fe41dc8eb2f51142b657c2b7e856b8 +Subproject commit 137a62338ce5c890fe337ab8da8bbe9279463730 From a93527e963d601190a5d32eaf148742000b7b7a5 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 7 Jul 2023 19:23:25 +0300 Subject: [PATCH 18/23] RED-6892 deselect text when redaction added --- apps/red-ui/src/app/app.module.ts | 4 +- .../file-preview-screen.component.ts | 57 +++++++++---------- .../services/file-preview-state.service.ts | 35 +++++------- .../services/pdf-proxy.service.ts | 4 +- .../services/annotation-manager.service.ts | 34 ++++++----- .../dossiers/dossier-changes.service.ts | 2 +- .../app/services/dossiers/dossiers.service.ts | 1 - apps/red-ui/src/styles.scss | 6 +- 8 files changed, 73 insertions(+), 70 deletions(-) diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index fc52f4819..944d621cd 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -141,10 +141,10 @@ export const appModuleFactory = (config: AppConfig) => { enabled: true, }, FILE: { - enabled: false, + enabled: true, }, CHANGES: { - enabled: false, + enabled: true, }, STATS: { enabled: false, diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index f5dce87ef..f4cb8f203 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -308,7 +308,7 @@ export class FilePreviewScreenComponent this._loadingService.start(); this.userPreferenceService.saveLastOpenedFileForDossier(this.dossierId, this.fileId).then(); - this._subscribeToFileUpdates(); + this.#subscribeToFileUpdates(); if (file?.analysisRequired && !file.excludedFromAutomaticAnalysis) { await this._reanalysisService.reanalyzeFilesForDossier([file], this.dossierId, { force: true }); @@ -354,34 +354,33 @@ export class FilePreviewScreenComponent async openRedactTextDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) { const file = this.state.file(); const dossierTemplate = this._dossierTemplatesService.find(this.state.dossierTemplateId); - const result = await this._iqserDialog - .openDefault(RedactTextDialogComponent, { - data: { - manualRedactionEntryWrapper, - dossierId: this.dossierId, - file, - applyToAllDossiers: dossierTemplate.applyDictionaryUpdatesToAllDossiersByDefault, - }, - }) - .result(); + const ref = this._iqserDialog.openDefault(RedactTextDialogComponent, { + data: { + manualRedactionEntryWrapper, + dossierId: this.dossierId, + file, + applyToAllDossiers: dossierTemplate.applyDictionaryUpdatesToAllDossiersByDefault, + }, + }); - if (result) { - const add$ = this._manualRedactionService.addAnnotation( - [result.redaction], - this.dossierId, - this.fileId, - result.dictionary?.label, - ); - - if (result.applyToAllDossiers !== null) { - const { ...body } = dossierTemplate; - body.applyDictionaryUpdatesToAllDossiersByDefault = result.applyToAllDossiers; - await this._dossierTemplatesService.createOrUpdate(body); - } - - const addAndReload$ = add$.pipe(switchMap(() => this._filesService.reload(this.dossierId, file))); - return firstValueFrom(addAndReload$.pipe(catchError(() => of(undefined)))); + const result = await ref.result(); + if (!result) { + return; } + + const add$ = this._manualRedactionService.addAnnotation([result.redaction], this.dossierId, this.fileId, result.dictionary?.label); + + if (result.applyToAllDossiers !== null) { + const { ...body } = dossierTemplate; + body.applyDictionaryUpdatesToAllDossiersByDefault = result.applyToAllDossiers; + await this._dossierTemplatesService.createOrUpdate(body); + } + + const addAndReload$ = add$.pipe( + tap(() => this._documentViewer.clearSelection()), + switchMap(() => this._filesService.reload(this.dossierId, file)), + ); + return firstValueFrom(addAndReload$.pipe(catchError(() => of(undefined)))); } toggleFullScreen() { @@ -610,7 +609,7 @@ export class FilePreviewScreenComponent }, 100); } - private _subscribeToFileUpdates(): void { + #subscribeToFileUpdates(): void { this.addActiveScreenSubscription = this.loadAnnotations().subscribe(); this.addActiveScreenSubscription = this._dossiersService @@ -642,7 +641,7 @@ export class FilePreviewScreenComponent }); this.addActiveScreenSubscription = this.pdfProxyService.redactTextRequested$.subscribe($event => { - this.openRedactTextDialog($event); + this.openRedactTextDialog($event).then(); }); this.addActiveScreenSubscription = this.pdfProxyService.pageChanged$.subscribe(page => diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts index 7acc03014..1d4c7daf0 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts @@ -13,9 +13,10 @@ import { HttpEvent, HttpEventType, HttpProgressEvent, HttpResponse } from '@angu import { TranslateService } from '@ngx-translate/core'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service'; -import { toSignal } from '@angular/core/rxjs-interop'; +import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop'; import { ViewModeService } from './view-mode.service'; import { getParam } from '@iqser/common-ui/lib/utils'; +import { NGXLogger } from 'ngx-logger'; const ONE_MEGABYTE = 1024 * 1024; @@ -33,7 +34,6 @@ function isDownload(event: HttpEvent): event is HttpProgressEvent { @Injectable() export class FilePreviewStateService { readonly #reloadBlob$ = new Subject(); - readonly #dossierFileChange: Signal; readonly file$: Observable; readonly file: Signal; readonly dossier: Signal; @@ -45,12 +45,6 @@ export class FilePreviewStateService { readonly dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly fileId = getParam(FILE_ID); - // readonly #routeKey = getReusableRouteKey(inject(ActivatedRoute).snapshot); - // readonly isAttached = inject(CustomRouteReuseStrategy).attached$.pipe( - // map(route => getReusableRouteKey(route) === this.#routeKey), - // startWith(true), - // ); - constructor( private readonly _permissionsService: PermissionsService, private readonly _filesService: FilesService, @@ -60,28 +54,27 @@ export class FilePreviewStateService { private readonly _translateService: TranslateService, private readonly _loadingService: LoadingService, private readonly _viewModeService: ViewModeService, + private readonly _logger: NGXLogger, ) { this.dossier = toSignal(dossiersServiceResolver().getEntityChanged$(this.dossierId)); this.file$ = inject(FilesMapService).watch$(this.dossierId, this.fileId); this.file = toSignal(this.file$); - // this.file$ = combineLatest([this.isAttached, file$]).pipe( - // filter(([isAttached]) => isAttached), - // map(([, file]) => file), - // log('file$'), - // shareDistinctLast(), - // ); - this.isWritable = computed(() => this._permissionsService.canPerformAnnotationActions(this.file(), this.dossier())); + this.isWritable = computed(() => { + const isWritable = this._permissionsService.canPerformAnnotationActions(this.file(), this.dossier()); + this._logger.info('[FILE] Is writeable:', isWritable); + return isWritable; + }); this.isReadonly = computed(() => !this.isWritable()); this.blob$ = this.#blob$; this.dossierDictionary = toSignal(inject(DossierDictionariesMapService).watch$(this.dossierId, 'dossier_redaction')); - this.#dossierFileChange = toSignal(this.#dossierFilesChange$); - effect(() => { - if (this.#dossierFileChange()) { - this._filesService.loadAll(this.dossierId); - } - }); + this.#dossierFilesChange$ + .pipe( + switchMap(() => this._filesService.loadAll(this.dossierId)), + takeUntilDestroyed(), + ) + .subscribe(); effect( () => { if (this._viewModeService.isEarmarks() && !this.file().hasHighlights) { diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts index 6f0792a4b..b2058dd3e 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts @@ -101,8 +101,8 @@ export class PdfProxyService { get #annotationSelected$() { return this._annotationManager.annotationSelected$.pipe( - map(value => this._ngZone.run(() => this.#processSelectedAnnotations(...value))), - tap(annotations => this._ngZone.run(() => this.handleAnnotationSelected(annotations))), + map(value => this.#processSelectedAnnotations(...value)), + tap(annotations => this.handleAnnotationSelected(annotations)), ); } diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts index 3a02cb459..ad79534b7 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts @@ -1,13 +1,13 @@ -import { Injectable, signal } from '@angular/core'; +import { inject, Injectable, signal } from '@angular/core'; import { Core } from '@pdftron/webviewer'; import type { List } from '@iqser/common-ui/lib/utils'; import { AnnotationPredicate, DeleteAnnotationsOptions } from '../utils/types'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { fromEvent, Observable } from 'rxjs'; -import { tap } from 'rxjs/operators'; +import { Subject } from 'rxjs'; import { asList, getId, isStringOrWrapper } from '../utils/functions'; import { getLast } from '@utils/functions'; import { AnnotationToolNames } from '../utils/constants'; +import { NGXLogger } from 'ngx-logger'; import AnnotationManager = Core.AnnotationManager; import Annotation = Core.Annotations.Annotation; @@ -15,7 +15,9 @@ import Annotation = Core.Annotations.Annotation; export class REDAnnotationManager { readonly #hidden = signal(new Set()); #manager: AnnotationManager; - annotationSelected$: Observable<[Annotation[], string]>; + readonly #logger = inject(NGXLogger); + readonly #annotationSelected$ = new Subject<[Annotation[], string]>(); + readonly annotationSelected$ = this.#annotationSelected$.asObservable(); resizingAnnotationId?: string = undefined; readonly hidden = this.#hidden.asReadonly(); @@ -27,11 +29,6 @@ export class REDAnnotationManager { return this.#get(); } - get #annotationSelected$() { - const onSelect$ = fromEvent<[Annotation[], string]>(this.#manager, 'annotationSelected'); - return onSelect$.pipe(tap(value => console.log('Annotation selected: ', value))); - } - addToHidden(value: string) { this.#hidden.mutate(set => set.add(value)); } @@ -42,7 +39,7 @@ export class REDAnnotationManager { init(annotationManager: AnnotationManager) { this.#manager = annotationManager; - this.annotationSelected$ = this.#annotationSelected$; + this.#listenForAnnotationSelected(); this.#autoSelectRectangleAfterCreation(); } @@ -60,8 +57,11 @@ export class REDAnnotationManager { } get(annotation: AnnotationWrapper | string): Annotation; + get(annotations: List | List): Annotation[]; + get(predicate?: (value: Annotation) => boolean): Annotation[]; + get(argument?: AnnotationPredicate | List | List | AnnotationWrapper | string): Annotation | Annotation[] { if (isStringOrWrapper(argument)) { return this.#getById(argument); @@ -71,8 +71,8 @@ export class REDAnnotationManager { return isList ? this.#getByIds(argument) : this.#get(argument); } - deselect(annotation: string | AnnotationWrapper); - deselect(annotations?: List | List); + deselect(annotation: string | AnnotationWrapper): void; + deselect(annotations?: List | List): void; deselect(argument?: string | AnnotationWrapper | List | List) { if (!argument) { return this.#manager.deselectAllAnnotations(); @@ -121,12 +121,20 @@ export class REDAnnotationManager { this.show(hidden); } + #listenForAnnotationSelected() { + this.#manager.addEventListener('annotationSelected', (annotations: Annotation[], action: string) => { + this.#logger.info('[PDF] Annotation selected: ', annotations, action); + this.#annotationSelected$.next([annotations, action]); + }); + } + #getById(annotation: AnnotationWrapper | string) { return this.#manager.getAnnotationById(getId(annotation)); } #autoSelectRectangleAfterCreation() { - this.#manager.addEventListener('annotationChanged', (annotations: Annotation[]) => { + this.#manager.addEventListener('annotationChanged', (annotations: Annotation[], action: string, options) => { + this.#logger.info('[PDF] Annotations changed: ', annotations, action, options); // when a rectangle is drawn, // it returns one annotation with tool name 'AnnotationCreateRectangle; // this will auto select rectangle after drawing diff --git a/apps/red-ui/src/app/services/dossiers/dossier-changes.service.ts b/apps/red-ui/src/app/services/dossiers/dossier-changes.service.ts index 59ff85819..f7db33bd6 100644 --- a/apps/red-ui/src/app/services/dossiers/dossier-changes.service.ts +++ b/apps/red-ui/src/app/services/dossiers/dossier-changes.service.ts @@ -35,7 +35,7 @@ export class DossiersChangesService extends GenericService implements O changes.map(change => this.#load(change.dossierId).pipe(removeIfNotFound(change.dossierId))); return this.hasChangesDetails$().pipe( - tap(changes => this.#logger.info('[CHANGES] ', changes)), + tap(changes => this.#logger.info('[CHANGES] Dossier changes', changes)), switchMap(dossierChanges => forkJoin([...load(dossierChanges), this.#dashboardStatsService.loadAll().pipe(take(1))]).pipe(map(() => dossierChanges)), ), diff --git a/apps/red-ui/src/app/services/dossiers/dossiers.service.ts b/apps/red-ui/src/app/services/dossiers/dossiers.service.ts index 23393b67c..d4873fef6 100644 --- a/apps/red-ui/src/app/services/dossiers/dossiers.service.ts +++ b/apps/red-ui/src/app/services/dossiers/dossiers.service.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/member-ordering */ import { EntitiesService, Toaster } from '@iqser/common-ui'; import { Dossier, DossierStats, IDossier, IDossierChanges, IDossierRequest } from '@red/domain'; import { Observable, of, Subject } from 'rxjs'; diff --git a/apps/red-ui/src/styles.scss b/apps/red-ui/src/styles.scss index 7ead7b9ab..862abfa29 100644 --- a/apps/red-ui/src/styles.scss +++ b/apps/red-ui/src/styles.scss @@ -144,9 +144,13 @@ $dark-accent-10: darken(vars.$accent, 10%); $iqser-app-name-color: vars.$white ); +body { + --workload-width: 350px; +} + #viewer { visibility: hidden; - width: calc(100% - 350px); + width: calc(100% - var(--workload-width)); height: calc(100% - calc(var(--iqser-top-bar-height) + 50px)); bottom: 0; left: 0; From b22e47cec381e424d9ff776b45d39825ebb6c608 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 7 Jul 2023 19:56:12 +0300 Subject: [PATCH 19/23] RED-6680 fix annotation deselecting while selected --- .../services/pdf-proxy.service.ts | 145 +++++++++--------- .../services/annotation-manager.service.ts | 2 + 2 files changed, 78 insertions(+), 69 deletions(-) diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts index b2058dd3e..a6a71e2a1 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts @@ -37,6 +37,7 @@ import { Roles } from '@users/roles'; import { AnnotationActionsService } from './annotation-actions.service'; import { getCurrentUser } from '@iqser/common-ui/lib/users'; import { BASE_HREF_FN, isJustOne, shareDistinctLast } from '@iqser/common-ui/lib/utils'; +import { NGXLogger } from 'ngx-logger'; import Annotation = Core.Annotations.Annotation; import Quad = Core.Math.Quad; @@ -55,7 +56,7 @@ export class PdfProxyService { readonly redactTextRequested$ = new Subject(); readonly currentUser = getCurrentUser(); readonly pageChanged$ = this._pdf.pageChanged$.pipe( - tap(() => this.#handleCustomActions()), + tap(() => this.#handleExcludedPageActions()), tap(() => this._pdf.resetAnnotationActions()), shareDistinctLast(), ); @@ -80,6 +81,7 @@ export class PdfProxyService { private readonly _documentViewer: REDDocumentViewer, private readonly _annotationManager: REDAnnotationManager, private readonly _pdf: PdfViewer, + private readonly _logger: NGXLogger, private readonly _state: FilePreviewStateService, private readonly _multiSelectService: MultiSelectService, private readonly _listingService: AnnotationsListingService, @@ -88,15 +90,29 @@ export class PdfProxyService { ) { effect( () => { - this.canPerformActions(); + const canPerformActions = this.canPerformActions(); this._pdf.isCompareMode(); - this.#handleCustomActions(); this.#configureTextPopup(); - this.#deactivateMultiSelect(); + this.#handleExcludedPageActions(); + + if (canPerformActions) { + this.#enableActions(); + } else { + this.#disableActions(); + this.#deactivateMultiSelect(); + } }, { allowSignalWrites: true }, ); + + effect(() => { + if (this._viewModeService.isRedacted()) { + this._viewerHeaderService.enable([HeaderElements.TOGGLE_READABLE_REDACTIONS]); + } else { + this._viewerHeaderService.disable([HeaderElements.TOGGLE_READABLE_REDACTIONS]); + } + }); } get #annotationSelected$() { @@ -146,42 +162,41 @@ export class PdfProxyService { } #configureTextPopup() { + if (this._state.file().isApproved) { + this._pdf.configureTextPopups([]); + } + const popups: IHeaderElement[] = []; + // Adding directly to the false-positive dict is only available in dev-mode + if (this._userPreferenceService.areDevFeaturesEnabled) { + popups.push({ + type: 'actionButton', + dataElement: TextPopups.ADD_FALSE_POSITIVE, + img: this.#falsePositiveIcon, + title: this.#getTitle(ManualRedactionEntryTypes.FALSE_POSITIVE), + onClick: () => this._ngZone.run(() => this.#addManualRedactionOfType(ManualRedactionEntryTypes.FALSE_POSITIVE)), + }); + } - if (!this._state.file().isApproved) { - // Adding directly to the false-positive dict is only available in dev-mode - if (this._userPreferenceService.areDevFeaturesEnabled) { - popups.push({ - type: 'actionButton', - dataElement: TextPopups.ADD_FALSE_POSITIVE, - img: this.#falsePositiveIcon, - title: this.#getTitle(ManualRedactionEntryTypes.FALSE_POSITIVE), - onClick: () => this._ngZone.run(() => this.#addManualRedactionOfType(ManualRedactionEntryTypes.FALSE_POSITIVE)), - }); - } - - const isApprover = this._permissionsService.isApprover(this._state.dossier()); - if (this._iqserPermissionsService.has(Roles.redactions.write) && isApprover) { - popups.push({ - type: 'actionButton', - dataElement: TextPopups.REDACT_TEXT, - img: this.#addRedactionIcon, - title: this.#getTitle(ManualRedactionEntryTypes.REDACT), - onClick: () => this._ngZone.run(() => this.#redactText(ManualRedactionEntryTypes.REDACT)), - }); - popups.push({ - type: 'actionButton', - dataElement: TextPopups.ADD_HINT, - img: this.#addHintIcon, - title: this.#getTitle(ManualRedactionEntryTypes.HINT), - onClick: () => this._ngZone.run(() => this.#redactText(ManualRedactionEntryTypes.HINT)), - }); - } + const isApprover = this._permissionsService.isApprover(this._state.dossier()); + if (this._iqserPermissionsService.has(Roles.redactions.write) && isApprover) { + popups.push({ + type: 'actionButton', + dataElement: TextPopups.REDACT_TEXT, + img: this.#addRedactionIcon, + title: this.#getTitle(ManualRedactionEntryTypes.REDACT), + onClick: () => this._ngZone.run(() => this.#redactText(ManualRedactionEntryTypes.REDACT)), + }); + popups.push({ + type: 'actionButton', + dataElement: TextPopups.ADD_HINT, + img: this.#addHintIcon, + title: this.#getTitle(ManualRedactionEntryTypes.HINT), + onClick: () => this._ngZone.run(() => this.#redactText(ManualRedactionEntryTypes.HINT)), + }); } this._pdf.configureTextPopups(popups); - - return this.#handleCustomActions(); } #addManualRedactionOfType(type: ManualRedactionEntryType) { @@ -198,46 +213,37 @@ export class PdfProxyService { this.redactTextRequested$.next({ manualRedactionEntry, type }); } - #handleCustomActions() { + #handleExcludedPageActions() { const isCurrentPageExcluded = this._state.file().isPageExcluded(this._pdf.currentPage()); - - if (this._viewModeService.isRedacted()) { - this._viewerHeaderService.enable([HeaderElements.TOGGLE_READABLE_REDACTIONS]); - } else { - this._viewerHeaderService.disable([HeaderElements.TOGGLE_READABLE_REDACTIONS]); - } - - if (isCurrentPageExcluded) { - let textPopupElementsToDisable = [...TEXT_POPUPS_TO_TOGGLE]; - let headerElementsToDisable = [...HEADER_ITEMS_TO_TOGGLE]; - - if (this.canPerformActions()) { - this._pdf.enable(ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED); - this._viewerHeaderService.enable(ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED as HeaderElementType[]); - - textPopupElementsToDisable = textPopupElementsToDisable.filter( - element => !ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED.includes(element), - ); - headerElementsToDisable = headerElementsToDisable.filter(element => !ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED.includes(element)); - } - - this._pdf.disable(textPopupElementsToDisable); - this._viewerHeaderService.disable(headerElementsToDisable); + if (!isCurrentPageExcluded) { return; } - if (!this.canPerformActions()) { - this._pdf.instance.UI.disableTools([AnnotationToolNames.AnnotationCreateRectangle]); - this._pdf.disable(TEXT_POPUPS_TO_TOGGLE); - this._viewerHeaderService.disable(HEADER_ITEMS_TO_TOGGLE); - return; + let textPopupElementsToDisable = [...TEXT_POPUPS_TO_TOGGLE]; + let headerElementsToDisable = [...HEADER_ITEMS_TO_TOGGLE]; + + if (this.canPerformActions()) { + this._pdf.enable(ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED); + this._viewerHeaderService.enable(ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED as HeaderElementType[]); + + textPopupElementsToDisable = textPopupElementsToDisable.filter( + element => !ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED.includes(element), + ); + headerElementsToDisable = headerElementsToDisable.filter(element => !ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED.includes(element)); } - try { - this._pdf.instance.UI.enableTools([AnnotationToolNames.AnnotationCreateRectangle]); - } catch (e) { - // happens - } + this._pdf.disable(textPopupElementsToDisable); + this._viewerHeaderService.disable(headerElementsToDisable); + } + + #disableActions() { + this._pdf.instance.UI.disableTools([AnnotationToolNames.AnnotationCreateRectangle]); + this._pdf.disable(TEXT_POPUPS_TO_TOGGLE); + this._viewerHeaderService.disable(HEADER_ITEMS_TO_TOGGLE); + } + + #enableActions() { + this._pdf.instance.UI.enableTools([AnnotationToolNames.AnnotationCreateRectangle]); this._pdf.enable(TEXT_POPUPS_TO_TOGGLE); this._viewerHeaderService.enable(HEADER_ITEMS_TO_TOGGLE); @@ -263,6 +269,7 @@ export class PdfProxyService { } #deactivateMultiSelect() { + this._logger.info('[PDF] Deactivating multi-select'); this._multiSelectService.deactivate(); this._annotationManager.deselect(); this.handleAnnotationSelected([]); diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts index ad79534b7..e0f0def1e 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts @@ -75,9 +75,11 @@ export class REDAnnotationManager { deselect(annotations?: List | List): void; deselect(argument?: string | AnnotationWrapper | List | List) { if (!argument) { + this.#logger.info('[ANNOTATIONS] Deselect all'); return this.#manager.deselectAllAnnotations(); } + this.#logger.info('[ANNOTATIONS] Deselecting: ', argument); const ann = isStringOrWrapper(argument) ? [this.#getById(argument)] : this.#getByIds(argument); this.#manager.deselectAnnotations(ann); } From af3ceccac28c052dd0a517cd9da2a02c452b5ad1 Mon Sep 17 00:00:00 2001 From: Nicoleta Panaghiu Date: Fri, 7 Jul 2023 21:01:29 +0300 Subject: [PATCH 20/23] RED-6382: Fix edit value in the workflow view. --- .../file-attribute.component.html | 10 +++-- .../file-attribute.component.ts | 44 ++++++++++++++----- .../file-actions/file-actions.component.html | 2 +- .../file-attributes.service.ts | 18 ++++++-- 4 files changed, 55 insertions(+), 19 deletions(-) diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/file-attribute/file-attribute.component.html b/apps/red-ui/src/app/modules/dossier-overview/components/file-attribute/file-attribute.component.html index 5242f5f5a..b4c80aaa1 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/file-attribute/file-attribute.component.html +++ b/apps/red-ui/src/app/modules/dossier-overview/components/file-attribute/file-attribute.component.html @@ -2,7 +2,11 @@
{{ fileAttribute.label }}: - + {{ fileAttributeValue || '-' }} @@ -14,7 +18,7 @@
-
+ + this.fileAttributesService.isEditingFileAttribute() && + (this.fileAttribute.id !== this.fileAttributesService.openAttributeEdit() || + this.file.fileId !== this.fileAttributesService.fileEdit()), + ); constructor( router: Router, @@ -46,6 +52,15 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr tap(() => this.close()), ); this.#subscriptions.add(sub2.subscribe()); + + effect( + () => { + if (this.#shouldClose()) { + this.close(); + } + }, + { allowSignalWrites: true }, + ); } get isDate(): boolean { @@ -56,6 +71,13 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr return this.file.fileAttributes.attributeIdToValue[this.fileAttribute.id]; } + @HostListener('document:click') + clickOutside() { + if (this.isInEditMode && this.closedDatepicker) { + this.close(); + } + } + ngOnDestroy() { this.#subscriptions.unsubscribe(); } @@ -64,6 +86,8 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr if (!this.file.isInitialProcessing && this.permissionsService.canEditFileAttributes(this.file, this.dossier)) { $event.stopPropagation(); this.#toggleEdit(); + this.fileAttributesService.setFileEdit(this.file.fileId); + this.fileAttributesService.setOpenAttributeEdit(this.fileAttribute.id); } } @@ -95,13 +119,6 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr } } - @HostListener('document:click') - clickOutside() { - if (this.isInEditMode && this.closedDatepicker) { - this.close(); - } - } - #initFileAttributes() { const configs = this.fileAttributesService.getFileAttributeConfig(this.file.dossierTemplateId).fileAttributeConfigs; configs.forEach(config => { @@ -116,13 +133,16 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr const fileAttributes = this.file.fileAttributes.attributeIdToValue; Object.keys(fileAttributes).forEach(key => { const attrValue = fileAttributes[key]; - config[key] = [dayjs(attrValue, 'YYYY-MM-DD', true).isValid() ? dayjs(attrValue).toDate() : attrValue]; + config[key] = [ + dayjs(attrValue, 'YYYY-MM-DD', true).isValid() ? dayjs(attrValue).toDate() : attrValue, + Validators.pattern(/^(\s+\S+\s*)*(?!\s).*$/), + ]; }); return this._formBuilder.group(config); } #formatAttributeValue(attrValue) { - return this.isDate ? attrValue && dayjs(attrValue).format('YYYY-MM-DD') : attrValue; + return this.isDate ? attrValue && dayjs(attrValue).format('YYYY-MM-DD') : attrValue.replaceAll(/\s\s+/g, ' '); } #toggleEdit(): void { @@ -133,7 +153,7 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr } this.isInEditMode = !this.isInEditMode; - this.fileAttributesService.isEditingFileAttribute$.next(this.isInEditMode); + this.fileAttributesService.isEditingFileAttribute.set(this.isInEditMode); if (this.isInEditMode) { this.#focusOnEditInput(); diff --git a/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.html b/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.html index b413965aa..95c4b1213 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.html +++ b/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/apps/red-ui/src/app/services/entity-services/file-attributes.service.ts b/apps/red-ui/src/app/services/entity-services/file-attributes.service.ts index 5b478953d..0f74df8a5 100644 --- a/apps/red-ui/src/app/services/entity-services/file-attributes.service.ts +++ b/apps/red-ui/src/app/services/entity-services/file-attributes.service.ts @@ -1,5 +1,5 @@ import { EntitiesService } from '@iqser/common-ui'; -import { Injectable } from '@angular/core'; +import { Injectable, signal } from '@angular/core'; import { BehaviorSubject, Observable, of } from 'rxjs'; import { catchError, tap } from 'rxjs/operators'; import { FileAttributeConfig, FileAttributes, IFileAttributeConfig, IFileAttributesConfig } from '@red/domain'; @@ -11,10 +11,22 @@ export type FileAttributesConfigMap = Readonly { + readonly fileAttributesConfig$ = new BehaviorSubject({}); + readonly isEditingFileAttribute = signal(false); + + readonly openAttributeEdit = signal(''); + readonly fileEdit = signal(''); + protected readonly _defaultModelPath = 'fileAttributes'; protected readonly _entityClass = FileAttributeConfig; - readonly fileAttributesConfig$ = new BehaviorSubject({}); - readonly isEditingFileAttribute$ = new BehaviorSubject(false); + + setOpenAttributeEdit(attributeId: string) { + this.openAttributeEdit.set(attributeId); + } + + setFileEdit(fileId: string) { + this.fileEdit.set(fileId); + } /** * Get the file attributes that can be used at importing csv. From 97fa06ef7e3b5b551f6d8b908b82f013981a38b9 Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Sat, 8 Jul 2023 21:26:24 +0300 Subject: [PATCH 21/23] RED-6774 - fixed remove redaction issues --- .../remove-redaction-dialog.component.ts | 15 +++++++--- .../services/annotation-actions.service.ts | 29 ++++++++++--------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts index 1ffd08512..743ff5bcd 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts @@ -9,6 +9,7 @@ import { IqserDialogComponent } from '../../../../../../../../libs/common-ui/src import { PermissionsService } from '@services/permissions.service'; import { tap } from 'rxjs/operators'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { RedactTextOption } from '../redact-text-dialog/redact-text-options'; const PIN_ICON = 'red:push-pin'; const FOLDER_ICON = 'red:folder'; @@ -25,6 +26,7 @@ export interface RemoveRedactionData { dossier: Dossier; falsePositiveContext: string; permissions: RemoveRedactionPermissions; + applyToAllDossiers: boolean; } export interface RemoveRedactionResult { @@ -50,6 +52,7 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent< readonly #redaction: AnnotationWrapper; readonly #permissions: RemoveRedactionPermissions; readonly #translations = removeRedactionTranslations; + #applyToAllDossiers: boolean; constructor(private readonly _formBuilder: FormBuilder, private readonly _permissionsService: PermissionsService) { super(); @@ -57,13 +60,17 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent< this.#permissions = this.data.permissions; this.options = this.#options(); this.form = this.#getForm(); + this.#applyToAllDossiers = this.data.applyToAllDossiers ?? true; this.form .get('option') .valueChanges.pipe( tap(() => { - this.options[1].extraOption.checked = true; - this.options[2].extraOption.checked = true; + for (const option of this.options) { + if (option.extraOption) { + option.extraOption.checked = this.#applyToAllDossiers; + } + } }), takeUntilDestroyed(), ) @@ -101,7 +108,7 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent< value: RemoveRedactionOptions.IN_DOSSIER, extraOption: { label: this.#translations.IN_DOSSIER.extraOptionLabel, - checked: true, + checked: this.data.applyToAllDossiers ?? true, }, }); } @@ -114,7 +121,7 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent< value: RemoveRedactionOptions.FALSE_POSITIVE, extraOption: { label: this.#translations.FALSE_POSITIVE.extraOptionLabel, - checked: true, + checked: this.data.applyToAllDossiers ?? true, }, }); } diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts index c49211e79..6d8db68f3 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts @@ -125,6 +125,7 @@ export class AnnotationActionsService { canRemoveOrSuggestToRemoveFromDictionary: permissions.canRemoveOrSuggestToRemoveFromDictionary, canMarkAsFalsePositive: permissions.canMarkAsFalsePositive, }; + const dossierTemplate = this._dossierTemplatesService.find(this._state.dossierTemplateId); const result: RemoveRedactionResult = await this._iqserDialog .openDefault(RemoveRedactionDialogComponent, { @@ -133,24 +134,23 @@ export class AnnotationActionsService { dossier: this._state.dossier(), falsePositiveContext: this._getFalsePositiveText(redaction), permissions: removePermissions, + applyToAllDossiers: dossierTemplate.applyDictionaryUpdatesToAllDossiersByDefault, }, }) .result(); if (result) { if (result.option.value === RemoveRedactionOptions.FALSE_POSITIVE) { - this.#setAsFalsePositive(redaction, result.comment); + this.#setAsFalsePositive(redaction, result); } else { - const removeFromDictionary = result.option.value === RemoveRedactionOptions.IN_DOSSIER; - this.#removeRedaction(redaction, result.comment, removeFromDictionary); + this.#removeRedaction(redaction, result); } - } - if (result.option.extraOption) { - const dossierTemplate = this._dossierTemplatesService.find(this._state.dossierTemplateId); - const { ...body } = dossierTemplate; - body.applyDictionaryUpdatesToAllDossiersByDefault = result.applyToAllDossiers; - await this._dossierTemplatesService.createOrUpdate(body); + if (result.option.extraOption) { + const { ...body } = dossierTemplate; + body.applyDictionaryUpdatesToAllDossiersByDefault = result.option.extraOption.checked; + await this._dossierTemplatesService.createOrUpdate(body); + } } } @@ -380,29 +380,32 @@ export class AnnotationActionsService { return words; } - #setAsFalsePositive(redaction: AnnotationWrapper, comment: string) { + #setAsFalsePositive(redaction: AnnotationWrapper, dialogResult: RemoveRedactionResult) { const request = { sourceId: redaction.id, value: this._getFalsePositiveText(redaction), type: redaction.type, positions: redaction.positions, addToDictionary: true, + addToAllDossiers: !!dialogResult.option.extraOption?.checked, reason: 'False Positive', dictionaryEntryType: redaction.isRecommendation ? DictionaryEntryTypes.FALSE_RECOMMENDATION : DictionaryEntryTypes.FALSE_POSITIVE, - comment: comment ? { text: comment } : null, + comment: dialogResult.comment ? { text: dialogResult.comment } : null, }; const { dossierId, fileId } = this._state; this.#processObsAndEmit(this._manualRedactionService.addAnnotation([request], dossierId, fileId)).then(); } - #removeRedaction(redaction: AnnotationWrapper, comment: string, removeFromDictionary: boolean) { + #removeRedaction(redaction: AnnotationWrapper, dialogResult: RemoveRedactionResult) { + const removeFromDictionary = dialogResult.option.value === RemoveRedactionOptions.IN_DOSSIER; const body = { annotationId: redaction.id, - comment: comment, + comment: dialogResult.comment, removeFromDictionary, + removeFromAllDossiers: !!dialogResult.option.extraOption?.checked, }; const { dossierId, fileId } = this._state; this.#processObsAndEmit( From 79daeb9178d05bef15635facea3f7815d0f95d21 Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Sun, 9 Jul 2023 22:59:07 +0300 Subject: [PATCH 22/23] RED-6774 - updated redact/remove endpoints and permissions for users that are not approvers --- .../redact-text-dialog.component.ts | 4 ++- .../remove-redaction-dialog.component.ts | 3 ++ .../file-preview-screen.component.ts | 6 ++-- .../services/annotation-actions.service.ts | 10 ++++-- .../services/manual-redaction.service.ts | 31 ++----------------- .../services/pdf-proxy.service.ts | 3 +- libs/common-ui | 2 +- 7 files changed, 22 insertions(+), 37 deletions(-) diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts index 70c794561..080bd28bd 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts @@ -28,6 +28,7 @@ interface RedactTextData { dossierId: string; file: File; applyToAllDossiers: boolean; + isApprover: boolean; } interface DialogResult { @@ -202,7 +203,7 @@ export class RedactTextDialogComponent addRedactionRequest.value = addRedactionRequest.rectangle ? this.form.get('classification').value : this.form.get('selectedText').value; - addRedactionRequest.addToAllDossiers = this.dictionaryRequest && this.#applyToAllDossiers; + addRedactionRequest.addToAllDossiers = this.data.isApprover && this.dictionaryRequest && this.#applyToAllDossiers; } #options() { @@ -224,6 +225,7 @@ export class RedactTextDialogComponent extraOption: { label: this.#translations[this.type].inDossier.extraOptionLabel, checked: this.data.applyToAllDossiers ?? true, + hidden: !this.data.isApprover, }, }); } diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts index 743ff5bcd..e783a0b4e 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts @@ -27,6 +27,7 @@ export interface RemoveRedactionData { falsePositiveContext: string; permissions: RemoveRedactionPermissions; applyToAllDossiers: boolean; + isApprover: boolean; } export interface RemoveRedactionResult { @@ -109,6 +110,7 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent< extraOption: { label: this.#translations.IN_DOSSIER.extraOptionLabel, checked: this.data.applyToAllDossiers ?? true, + hidden: !this.data.isApprover, }, }); } @@ -122,6 +124,7 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent< extraOption: { label: this.#translations.FALSE_POSITIVE.extraOptionLabel, checked: this.data.applyToAllDossiers ?? true, + hidden: !this.data.isApprover, }, }); } diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index f4cb8f203..7f122e60a 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -354,12 +354,14 @@ export class FilePreviewScreenComponent async openRedactTextDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) { const file = this.state.file(); const dossierTemplate = this._dossierTemplatesService.find(this.state.dossierTemplateId); + const isApprover = this.permissionsService.isApprover(this.state.dossier()); const ref = this._iqserDialog.openDefault(RedactTextDialogComponent, { data: { manualRedactionEntryWrapper, dossierId: this.dossierId, file, - applyToAllDossiers: dossierTemplate.applyDictionaryUpdatesToAllDossiersByDefault, + applyToAllDossiers: isApprover ? dossierTemplate.applyDictionaryUpdatesToAllDossiersByDefault : false, + isApprover, }, }); @@ -370,7 +372,7 @@ export class FilePreviewScreenComponent const add$ = this._manualRedactionService.addAnnotation([result.redaction], this.dossierId, this.fileId, result.dictionary?.label); - if (result.applyToAllDossiers !== null) { + if (isApprover && result.applyToAllDossiers !== null) { const { ...body } = dossierTemplate; body.applyDictionaryUpdatesToAllDossiersByDefault = result.applyToAllDossiers; await this._dossierTemplatesService.createOrUpdate(body); diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts index 6d8db68f3..19397e5d2 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts @@ -38,6 +38,7 @@ import { RemoveRedactionOptions } from '../dialogs/remove-redaction-dialog/remov import { IqserDialog } from '../../../../../../../libs/common-ui/src/lib/dialog/iqser-dialog.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { isJustOne, List } from '@iqser/common-ui/lib/utils'; +import { PermissionsService } from '@services/permissions.service'; @Injectable() export class AnnotationActionsService { @@ -54,6 +55,7 @@ export class AnnotationActionsService { private readonly _fileDataService: FileDataService, private readonly _skippedService: SkippedService, private readonly _dossierTemplatesService: DossierTemplatesService, + private readonly _permissionsService: PermissionsService, ) {} acceptSuggestion(annotations: AnnotationWrapper[]) { @@ -126,6 +128,7 @@ export class AnnotationActionsService { canMarkAsFalsePositive: permissions.canMarkAsFalsePositive, }; const dossierTemplate = this._dossierTemplatesService.find(this._state.dossierTemplateId); + const isApprover = this._permissionsService.isApprover(this._state.dossier()); const result: RemoveRedactionResult = await this._iqserDialog .openDefault(RemoveRedactionDialogComponent, { @@ -134,7 +137,8 @@ export class AnnotationActionsService { dossier: this._state.dossier(), falsePositiveContext: this._getFalsePositiveText(redaction), permissions: removePermissions, - applyToAllDossiers: dossierTemplate.applyDictionaryUpdatesToAllDossiersByDefault, + applyToAllDossiers: isApprover ? dossierTemplate.applyDictionaryUpdatesToAllDossiersByDefault : false, + isApprover, }, }) .result(); @@ -146,7 +150,7 @@ export class AnnotationActionsService { this.#removeRedaction(redaction, result); } - if (result.option.extraOption) { + if (isApprover && result.option.extraOption) { const { ...body } = dossierTemplate; body.applyDictionaryUpdatesToAllDossiersByDefault = result.option.extraOption.checked; await this._dossierTemplatesService.createOrUpdate(body); @@ -409,7 +413,7 @@ export class AnnotationActionsService { }; const { dossierId, fileId } = this._state; this.#processObsAndEmit( - this._manualRedactionService.removeOrSuggestRemove([body], dossierId, fileId, removeFromDictionary, redaction.isHint), + this._manualRedactionService.removeRedaction([body], dossierId, fileId, removeFromDictionary, redaction.isHint), ).then(); } } diff --git a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts index 6935802b5..1f4d040ce 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts @@ -97,15 +97,10 @@ export class ManualRedactionService extends GenericService { addAnnotation(requests: List, dossierId: string, fileId: string, dictionaryLabel?: string) { const toast = requests[0].addToDictionary ? this.#showAddToDictionaryToast(requests, dictionaryLabel) : this.#showToast('add'); const canAddRedaction = this._iqaerPermissionsService.has(Roles.redactions.write); - if (canAddRedaction && this._permissionsService.isApprover(this.#dossier(dossierId))) { + if (canAddRedaction) { return this.add(requests, dossierId, fileId).pipe(toast); } - const canRequestRedaction = this._iqaerPermissionsService.has(Roles.redactions.request); - if (canRequestRedaction) { - return this.requestAdd(requests, dossierId, fileId).pipe(toast); - } - return of(undefined); } @@ -141,20 +136,8 @@ export class ManualRedactionService extends GenericService { return this.requestResize(requests, dossierId, fileId); } - removeOrSuggestRemove( - body: List, - dossierId: string, - fileId: string, - removeFromDictionary = false, - isHint = false, - ) { - if (this._permissionsService.isApprover(this.#dossier(dossierId))) { - return this.remove(body, dossierId, fileId).pipe(this.#showToast(!isHint ? 'remove' : 'remove-hint', removeFromDictionary)); - } - - return this.requestRemoveRedaction(body, dossierId, fileId).pipe( - this.#showToast(!isHint ? 'request-remove' : 'request-remove-hint', removeFromDictionary), - ); + removeRedaction(body: List, dossierId: string, fileId: string, removeFromDictionary = false, isHint = false) { + return this.remove(body, dossierId, fileId).pipe(this.#showToast(!isHint ? 'remove' : 'remove-hint', removeFromDictionary)); } getTitle(type: ManualRedactionEntryType) { @@ -194,10 +177,6 @@ export class ManualRedactionService extends GenericService { ); } - requestRemoveRedaction(body: List, dossierId: string, fileId: string) { - return this._post(body, `${this.#bulkRequest}/remove/${dossierId}/${fileId}`).pipe(this.#log('Request remove', body)); - } - approve(annotationIds: List, dossierId: string, fileId: string) { return this._post(annotationIds, `${this._defaultModelPath}/bulk/approve/${dossierId}/${fileId}`).pipe( this.#log('Approve', annotationIds), @@ -220,10 +199,6 @@ export class ManualRedactionService extends GenericService { return this._post(body, `${this.#bulkRedaction}/remove/${dossierId}/${fileId}`).pipe(this.#log('Remove', body)); } - requestAdd(body: List, dossierId: string, fileId: string) { - return this._post(body, `${this.#bulkRequest}/add/${dossierId}/${fileId}`).pipe(this.#log('Request add', body)); - } - forceRedaction(body: List, dossierId: string, fileId: string) { return this._post(body, `${this.#bulkRedaction}/force/${dossierId}/${fileId}`).pipe(this.#log('Force redaction', body)); } diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts index a6a71e2a1..b21363ca4 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts @@ -178,8 +178,7 @@ export class PdfProxyService { }); } - const isApprover = this._permissionsService.isApprover(this._state.dossier()); - if (this._iqserPermissionsService.has(Roles.redactions.write) && isApprover) { + if (this._iqserPermissionsService.has(Roles.redactions.write)) { popups.push({ type: 'actionButton', dataElement: TextPopups.REDACT_TEXT, diff --git a/libs/common-ui b/libs/common-ui index 137a62338..a4e425d37 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 137a62338ce5c890fe337ab8da8bbe9279463730 +Subproject commit a4e425d3739d6145325a8fe347d9fcae1e12a662 From 01cf4713153b2f401099c850763fb7a493650349 Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Sun, 9 Jul 2023 23:11:11 +0300 Subject: [PATCH 23/23] RED-7020 - Remove Edit Dossier Dictionary dialog --- .../dictionary-details-dialog.component.html | 25 ------------ .../dictionary-details-dialog.component.ts | 39 ------------------- .../edit-dossier-dictionary.component.html | 9 ----- .../edit-dossier-dictionary.component.ts | 7 ---- .../services/dossiers-dialog.service.ts | 7 +--- .../shared-dossiers/shared-dossiers.module.ts | 3 +- apps/red-ui/src/assets/i18n/redact/de.json | 14 +------ apps/red-ui/src/assets/i18n/redact/en.json | 14 +------ apps/red-ui/src/assets/i18n/scm/de.json | 14 +------ apps/red-ui/src/assets/i18n/scm/en.json | 14 +------ 10 files changed, 10 insertions(+), 136 deletions(-) delete mode 100644 apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/dictionary-details-dialog/dictionary-details-dialog.component.html delete mode 100644 apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/dictionary-details-dialog/dictionary-details-dialog.component.ts diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/dictionary-details-dialog/dictionary-details-dialog.component.html b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/dictionary-details-dialog/dictionary-details-dialog.component.html deleted file mode 100644 index 8a83d08e7..000000000 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/dictionary-details-dialog/dictionary-details-dialog.component.html +++ /dev/null @@ -1,25 +0,0 @@ -
-
{{ 'dictionary-details.title' | translate : { readOnly: data.readOnly } }}
- -
- -
- -
- - -
-
- - -
diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/dictionary-details-dialog/dictionary-details-dialog.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/dictionary-details-dialog/dictionary-details-dialog.component.ts deleted file mode 100644 index 2a793184e..000000000 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/dictionary-details-dialog/dictionary-details-dialog.component.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Component, Inject, ViewChild } from '@angular/core'; -import { BaseDialogComponent } from '@iqser/common-ui'; -import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { Dictionary } from '@red/domain'; -import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-edit-entity.component'; - -@Component({ - templateUrl: './dictionary-details-dialog.component.html', - providers: [dossiersServiceProvider], -}) -export class DictionaryDetailsDialogComponent extends BaseDialogComponent { - @ViewChild(AddEditEntityComponent, { static: true }) private readonly _addEditEntityComponent: AddEditEntityComponent; - - constructor( - @Inject(MAT_DIALOG_DATA) - readonly data: { dictionary: Dictionary; dossierId: string; readOnly: boolean }, - protected readonly _dialogRef: MatDialogRef, - ) { - super(_dialogRef, true); - } - - get valid(): boolean { - return this._addEditEntityComponent.valid; - } - - get changed(): boolean { - return this._addEditEntityComponent.changed; - } - - get disabled(): boolean { - return this._addEditEntityComponent.disabled; - } - - async save(): Promise { - await this._addEditEntityComponent.save(); - this._dialogRef.close(true); - } -} diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html index 8c23e65e9..e60075d6a 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html @@ -10,15 +10,6 @@
- -
- -
{ - await this.#updateDossierDictionary(); - }); - } - async #updateDossierDictionary() { const { dossierId, dossierTemplateId } = this.dossier; this.dossierDictionary = await this._dictionaryService.loadDossierDictionary(dossierTemplateId, dossierId); diff --git a/apps/red-ui/src/app/modules/shared-dossiers/services/dossiers-dialog.service.ts b/apps/red-ui/src/app/modules/shared-dossiers/services/dossiers-dialog.service.ts index 708bb9cfb..4ec625777 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/services/dossiers-dialog.service.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/services/dossiers-dialog.service.ts @@ -4,9 +4,8 @@ import { EditDossierDialogComponent } from '../dialogs/edit-dossier-dialog/edit- import { AssignReviewerApproverDialogComponent } from '../dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component'; import { ConfirmationDialogComponent, DialogConfig, DialogService, largeDialogConfig } from '@iqser/common-ui'; import { ImportRedactionsDialogComponent } from '../../file-preview/dialogs/import-redactions-dialog/import-redactions-dialog'; -import { DictionaryDetailsDialogComponent } from '../dialogs/edit-dossier-dialog/dictionary/dictionary-details-dialog/dictionary-details-dialog.component'; -type DialogType = 'confirm' | 'editDossier' | 'assignFile' | 'importRedactions' | 'editDictionaryDetails'; +type DialogType = 'confirm' | 'editDossier' | 'assignFile' | 'importRedactions'; @Injectable({ providedIn: 'root', @@ -29,10 +28,6 @@ export class DossiersDialogService extends DialogService { component: ImportRedactionsDialogComponent, dialogConfig: { disableClose: false }, }, - editDictionaryDetails: { - component: DictionaryDetailsDialogComponent, - dialogConfig: { disableClose: false }, - }, }; constructor(protected readonly _dialog: MatDialog) { diff --git a/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts b/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts index b285f93e9..885cfbd15 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/shared-dossiers.module.ts @@ -11,7 +11,6 @@ import { EditDossierAttributesComponent } from './dialogs/edit-dossier-dialog/at import { EditDossierTeamComponent } from './dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component'; import { DateColumnComponent } from './components/date-column/date-column.component'; import { FileAssignService } from './services/file-assign.service'; -import { DictionaryDetailsDialogComponent } from './dialogs/edit-dossier-dialog/dictionary/dictionary-details-dialog/dictionary-details-dialog.component'; import { CircleButtonComponent, DynamicInputComponent, @@ -41,7 +40,7 @@ const components = [ DateColumnComponent, DossiersListingActionsComponent, ]; -const dialogs = [EditDossierDialogComponent, AssignReviewerApproverDialogComponent, DictionaryDetailsDialogComponent]; +const dialogs = [EditDossierDialogComponent, AssignReviewerApproverDialogComponent]; @NgModule({ declarations: [...components, ...dialogs], diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index 87314194d..aa85fbac9 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -664,13 +664,6 @@ }, "dev-mode": "DEV", "dictionary": "Wörterbuch", - "dictionary-details": { - "actions": { - "cancel": "", - "save": "" - }, - "title": "" - }, "dictionary-overview": { "compare": { "compare": "Vergleichen", @@ -1130,9 +1123,7 @@ "change-successful": "Dossier wurde aktualisiert.", "delete-successful": "Dossier wurde gelöscht.", "dictionary": { - "edit": "", - "entries": "{length} {length, plural, one{entry} other{entries}}", - "info": "" + "entries": "{length} {length, plural, one{entry} other{entries}}" }, "general-info": { "form": { @@ -2141,8 +2132,7 @@ "sign-in-previous-domain": "", "youre-logged-out": "" }, - "input-placeholder": "", - "tenant-does-not-exist": "" + "input-placeholder": "" }, "time": { "days": "{days} {days, plural, one{Tag} other{Tage}}", diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 4da79ce07..0c5c768e4 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -664,13 +664,6 @@ }, "dev-mode": "DEV", "dictionary": "Dictionary", - "dictionary-details": { - "actions": { - "cancel": "Cancel", - "save": "Save" - }, - "title": "{readOnly, select, false{Edit } other{}}Dossier Dictionary" - }, "dictionary-overview": { "compare": { "compare": "Compare", @@ -1130,9 +1123,7 @@ "change-successful": "Dossier {dossierName} was updated.", "delete-successful": "Dossier {dossierName} was deleted.", "dictionary": { - "edit": "Edit", - "entries": "{length} {length, plural, one{entry} other{entries}}", - "info": "Info" + "entries": "{length} {length, plural, one{entry} other{entries}}" }, "general-info": { "form": { @@ -2141,8 +2132,7 @@ "sign-in-previous-domain": "Sign in to a previously used domain", "youre-logged-out": "You have successfully been logged out." }, - "input-placeholder": "your domain's name", - "tenant-does-not-exist": "Selected tenant does not exist." + "input-placeholder": "your domain's name" }, "time": { "days": "{days} {days, plural, one{day} other{days}}", diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index 38db993c9..94cbae7e1 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -664,13 +664,6 @@ }, "dev-mode": "DEV", "dictionary": "Wörterbuch", - "dictionary-details": { - "actions": { - "cancel": "", - "save": "" - }, - "title": "" - }, "dictionary-overview": { "compare": { "compare": "Vergleichen", @@ -1130,9 +1123,7 @@ "change-successful": "Dossier wurde aktualisiert.", "delete-successful": "Dossier wurde gelöscht.", "dictionary": { - "edit": "", - "entries": "{length} {length, plural, one{entry} other{entries}}", - "info": "" + "entries": "{length} {length, plural, one{entry} other{entries}}" }, "general-info": { "form": { @@ -2141,8 +2132,7 @@ "sign-in-previous-domain": "", "youre-logged-out": "" }, - "input-placeholder": "", - "tenant-does-not-exist": "" + "input-placeholder": "" }, "time": { "days": "{days} {days, plural, one{Tag} other{Tage}}", diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index d89f46b0b..aa7231b6b 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -664,13 +664,6 @@ }, "dev-mode": "DEV", "dictionary": "Dictionary", - "dictionary-details": { - "actions": { - "cancel": "Cancel", - "save": "Save" - }, - "title": "{readOnly, select, false{Edit } other{}}Dossier Dictionary" - }, "dictionary-overview": { "compare": { "compare": "Compare", @@ -1130,9 +1123,7 @@ "change-successful": "Dossier {dossierName} was updated.", "delete-successful": "Dossier {dossierName} was deleted.", "dictionary": { - "edit": "Edit", - "entries": "{length} {length, plural, one{entry} other{entries}}", - "info": "Info" + "entries": "{length} {length, plural, one{entry} other{entries}}" }, "general-info": { "form": { @@ -2141,8 +2132,7 @@ "sign-in-previous-domain": "Sign in to a previously used domain", "youre-logged-out": "You have successfully been logged out." }, - "input-placeholder": "your domain's name", - "tenant-does-not-exist": "Selected tenant does not exist." + "input-placeholder": "your domain's name" }, "time": { "days": "{days} {days, plural, one{day} other{days}}",