Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f182be3db0 | ||
|
|
81a32f6d58 | ||
|
|
82552b1748 | ||
|
|
af7a45d739 | ||
|
|
21013a6fe5 | ||
|
|
c81ad67844 | ||
|
|
13797f1fb3 | ||
|
|
ef5cd39b16 | ||
|
|
e133e944e3 | ||
|
|
2ffb5bbb63 | ||
|
|
0f16644944 | ||
|
|
0b41159ee4 | ||
|
|
2a78aea898 | ||
|
|
4c5face779 | ||
|
|
b3a8a8d30c | ||
|
|
7836750171 | ||
|
|
ef9d3d2e8f | ||
|
|
bfe409305c |
@ -57,6 +57,7 @@ export class FileAttributesConfigurationsDialogComponent extends BaseDialogCompo
|
||||
if (supportCsvMapping) {
|
||||
return {
|
||||
...this.#configuration,
|
||||
keyColumn: this.form.get('keyColumn').value,
|
||||
filenameMappingColumnHeaderName: this.form.get('keyColumn').value,
|
||||
delimiter: this.form.get('delimiter').value,
|
||||
encoding: this.form.get('encodingType').value,
|
||||
@ -66,13 +67,14 @@ export class FileAttributesConfigurationsDialogComponent extends BaseDialogCompo
|
||||
return {
|
||||
...this.#configuration,
|
||||
filenameMappingColumnHeaderName: '',
|
||||
keyColumn: this.form.get('keyColumn').value,
|
||||
};
|
||||
}
|
||||
|
||||
#getForm() {
|
||||
return this._formBuilder.group({
|
||||
supportCsvMapping: [!!this.#configuration.filenameMappingColumnHeaderName],
|
||||
keyColumn: [this.#configuration.filenameMappingColumnHeaderName || '', [Validators.required]],
|
||||
keyColumn: [this.#configuration.filenameMappingColumnHeaderName || this.#configuration.keyColumn || '', [Validators.required]],
|
||||
delimiter: [this.#configuration.delimiter || '', [Validators.required]],
|
||||
encodingType: [this.#configuration.encoding || FileAttributeEncodingTypes['UTF-8'], [Validators.required]],
|
||||
});
|
||||
|
||||
@ -85,6 +85,7 @@ export default class FileAttributesListingScreenComponent extends ListingCompone
|
||||
},
|
||||
];
|
||||
readonly roles = Roles;
|
||||
keyColumnValue: string = '';
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
@ -171,13 +172,13 @@ export default class FileAttributesListingScreenComponent extends ListingCompone
|
||||
FileAttributesConfigurationsDialogComponent,
|
||||
{
|
||||
...defaultDialogConfig,
|
||||
data: this.#existingConfiguration,
|
||||
data: { ...this.#existingConfiguration, keyColumn: this.keyColumnValue },
|
||||
},
|
||||
);
|
||||
|
||||
const configuration = await firstValueFrom(ref.afterClosed());
|
||||
|
||||
if (configuration) {
|
||||
this.keyColumnValue = configuration.keyColumn;
|
||||
await this.#setConfigAndLoadData(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,6 +22,8 @@ import { ConfigureCertificateDialogComponent } from '../dialogs/configure-digita
|
||||
import { EditColorDialogComponent } from '../dialogs/edit-color-dialog/edit-color-dialog.component';
|
||||
import { SmtpAuthDialogComponent } from '../dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
|
||||
import { UploadDictionaryDialogComponent } from '../dialogs/upload-dictionary-dialog/upload-dictionary-dialog.component';
|
||||
import { UserStatsService } from './user-stats.service';
|
||||
import { result } from 'lodash-es';
|
||||
|
||||
type DialogType =
|
||||
| 'confirm'
|
||||
@ -73,19 +75,26 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _userStatsService: UserStatsService,
|
||||
private readonly _reportTemplateService: ReportTemplateService,
|
||||
) {
|
||||
super(_dialog);
|
||||
}
|
||||
|
||||
deleteUsers(userIds: string[], cb?: () => Promise<void> | void): void {
|
||||
async deleteUsers(userIds: string[], cb?: () => Promise<void> | void): Promise<void> {
|
||||
const userStats = await firstValueFrom(this._userStatsService.getOne(userIds[0]));
|
||||
|
||||
const data: IConfirmationDialogData = {
|
||||
title: _('confirm-delete-users.title'),
|
||||
question: _('confirm-delete-users.warning'),
|
||||
confirmationText: _('confirm-delete-users.delete'),
|
||||
denyText: _('confirm-delete-users.cancel'),
|
||||
titleColor: TitleColors.WARN,
|
||||
translateParams: { usersCount: 1, dossiersCount: this._getUsersDossiersCount(userIds) },
|
||||
translateParams: {
|
||||
usersCount: 1,
|
||||
dossiersCount: userStats.numberOfDossierOwnerships,
|
||||
documentsCount: userStats.numberOfAssignedFiles,
|
||||
},
|
||||
checkboxes: [
|
||||
{ value: false, label: _('confirm-delete-users.impacted-dossiers') },
|
||||
{ value: false, label: _('confirm-delete-users.impacted-documents') },
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
import { StatsService } from '@iqser/common-ui';
|
||||
import { IUserStats, USER_ID, UserStats } from '@red/domain';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class UserStatsService extends StatsService<UserStats, IUserStats> {
|
||||
protected readonly _primaryKey = USER_ID;
|
||||
protected readonly _entityClass = UserStats;
|
||||
protected readonly _defaultModelPath = 'user-stats';
|
||||
}
|
||||
@ -27,7 +27,9 @@
|
||||
<redaction-file-attribute [dossier]="dossier" [fileAttribute]="config" [file]="file"></redaction-file-attribute>
|
||||
</div>
|
||||
|
||||
<redaction-file-workload [file]="file"></redaction-file-workload>
|
||||
@if (!isDocumine) {
|
||||
<redaction-file-workload [file]="file"></redaction-file-workload>
|
||||
}
|
||||
|
||||
<div class="file-actions overflow-visible">
|
||||
<redaction-processing-indicator [file]="file" class="mr-8"></redaction-processing-indicator>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { ChangeDetectorRef, Component, computed, ElementRef, Input, OnInit, Optional, ViewChild } from '@angular/core';
|
||||
import { DisableStopPropagationDirective, HelpModeService } from '@iqser/common-ui';
|
||||
import { ChangeDetectorRef, Component, ElementRef, Input, OnInit, Optional, ViewChild } from '@angular/core';
|
||||
import { DisableStopPropagationDirective, getConfig, HelpModeService } from '@iqser/common-ui';
|
||||
import { Debounce, trackByFactory } from '@iqser/common-ui/lib/utils';
|
||||
import { Dossier, File, IFileAttributeConfig } from '@red/domain';
|
||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||
@ -36,6 +36,7 @@ import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
|
||||
export class WorkflowItemComponent implements OnInit {
|
||||
@ViewChild('actionsWrapper', { static: true }) private _actionsWrapper: ElementRef;
|
||||
width: number;
|
||||
readonly isDocumine = getConfig().IS_DOCUMINE;
|
||||
readonly trackBy = trackByFactory();
|
||||
@Input({ required: true }) file: File;
|
||||
@Input({ required: true }) dossier: Dossier;
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
class="draggable"
|
||||
svgIcon="red:draggable-dots"
|
||||
></mat-icon>
|
||||
<div [attr.help-mode-key]="'edit_component'" class="iqser-input-group w-full">
|
||||
<div [attr.help-mode-key]="'editor_edit_component'" class="iqser-input-group w-full">
|
||||
<textarea [id]="'value-input-' + $index" [(ngModel)]="value.value" rows="1" type="text"></textarea>
|
||||
</div>
|
||||
<iqser-circle-button
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<iqser-popup-filter [primaryFiltersSlug]="'componentLogFilters'" [attr.help-mode-key]="'filter_components'"></iqser-popup-filter>
|
||||
</div>
|
||||
|
||||
<div *ngIf="componentLogService.all$ | async as components" class="components-container" id="components-view">
|
||||
<div class="components-container" id="components-view">
|
||||
<div class="component-row">
|
||||
<div class="header">
|
||||
<div class="component">{{ 'component-management.table-header.component' | translate }}</div>
|
||||
@ -12,7 +12,7 @@
|
||||
<div class="row-separator"></div>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let entry of components" class="component-row">
|
||||
<div *ngFor="let entry of filteredComponents()" class="component-row">
|
||||
<redaction-editable-structured-component-value
|
||||
#editableComponent
|
||||
[entry]="entry"
|
||||
|
||||
@ -1,21 +1,22 @@
|
||||
import { Component, effect, Input, OnInit, signal, ViewChildren } from '@angular/core';
|
||||
import { Component, computed, effect, Input, OnInit, ViewChildren } from '@angular/core';
|
||||
import { List } from '@common-ui/utils';
|
||||
import { IconButtonTypes, LoadingService } from '@iqser/common-ui';
|
||||
import { ComponentLogEntry, Dictionary, File, IComponentLogEntry, WorkflowFileStatuses } from '@red/domain';
|
||||
import { combineLatest, firstValueFrom, Observable } from 'rxjs';
|
||||
import { firstValueFrom, map } from 'rxjs';
|
||||
import { EditableStructuredComponentValueComponent } from '../editable-structured-component-value/editable-structured-component-value.component';
|
||||
import { FilterService, PopupFilterComponent } from '@common-ui/filtering';
|
||||
import { ComponentLogFilterService } from '../../services/component-log-filter.service';
|
||||
import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
|
||||
import { NgForOf } from '@angular/common';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { FilePreviewStateService } from '../../services/file-preview-state.service';
|
||||
import { ComponentLogService } from '@services/entity-services/component-log.service';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-structured-component-management',
|
||||
templateUrl: './structured-component-management.component.html',
|
||||
styleUrls: ['./structured-component-management.component.scss'],
|
||||
imports: [PopupFilterComponent, NgIf, AsyncPipe, TranslateModule, NgForOf, EditableStructuredComponentValueComponent],
|
||||
imports: [PopupFilterComponent, TranslateModule, NgForOf, EditableStructuredComponentValueComponent],
|
||||
})
|
||||
export class StructuredComponentManagementComponent implements OnInit {
|
||||
protected readonly iconButtonTypes = IconButtonTypes;
|
||||
@ -23,6 +24,12 @@ export class StructuredComponentManagementComponent implements OnInit {
|
||||
@Input() dictionaries: Dictionary[];
|
||||
@ViewChildren('editableComponent') editableComponents: List<EditableStructuredComponentValueComponent>;
|
||||
|
||||
readonly filteredComponents = computed(() => this.#filteredComponents);
|
||||
readonly #displayedComponents = toSignal(this.componentLogService.all$);
|
||||
readonly #filterModel = toSignal(
|
||||
this._filterService.getFilterModels$('componentLogFilters').pipe(map(filters => (filters ? [...filters] : []))),
|
||||
);
|
||||
|
||||
constructor(
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _componentLogFilterService: ComponentLogFilterService,
|
||||
@ -40,6 +47,13 @@ export class StructuredComponentManagementComponent implements OnInit {
|
||||
return this.file.workflowStatus !== WorkflowFileStatuses.APPROVED;
|
||||
}
|
||||
|
||||
get #filteredComponents() {
|
||||
if (this.#filterModel() && this.#displayedComponents()) {
|
||||
return this._componentLogFilterService.filterComponents(this.#displayedComponents(), this.#filterModel());
|
||||
}
|
||||
return this.#displayedComponents();
|
||||
}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.#loadData();
|
||||
}
|
||||
|
||||
@ -58,9 +58,9 @@ redaction-pdf-viewer.hidden {
|
||||
}
|
||||
|
||||
.resize {
|
||||
background: #444857;
|
||||
background: var(--iqser-grey-4);
|
||||
height: 100%;
|
||||
width: 14px;
|
||||
width: 10px;
|
||||
cursor: col-resize;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
@ -74,7 +74,7 @@ redaction-pdf-viewer.hidden {
|
||||
transform: translate(-50%, -50%);
|
||||
width: 3px;
|
||||
height: 15px;
|
||||
border-inline: 1px solid #fff;
|
||||
border-inline: 1px solid var(--iqser-grey-1);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1015px) {
|
||||
|
||||
@ -122,6 +122,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
readonly fileId = this.state.fileId;
|
||||
readonly dossierId = this.state.dossierId;
|
||||
readonly resizeHandle = viewChild<ElementRef>('resize');
|
||||
#overlayElement: HTMLDivElement | null = null;
|
||||
|
||||
constructor(
|
||||
readonly pdf: PdfViewer,
|
||||
@ -177,16 +178,13 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._fileDataService.loadAnnotations(file).then();
|
||||
}
|
||||
|
||||
effect(
|
||||
() => {
|
||||
if (this._documentViewer.loaded()) {
|
||||
this._pageRotationService.clearRotations();
|
||||
this._viewerHeaderService.disable(ROTATION_ACTION_BUTTONS);
|
||||
this.viewerReady().then();
|
||||
}
|
||||
},
|
||||
{ allowSignalWrites: true },
|
||||
);
|
||||
effect(() => {
|
||||
if (this._documentViewer.loaded()) {
|
||||
this._pageRotationService.clearRotations();
|
||||
this._viewerHeaderService.disable(ROTATION_ACTION_BUTTONS);
|
||||
this.viewerReady().then();
|
||||
}
|
||||
});
|
||||
|
||||
effect(() => {
|
||||
this.state.updateExcludedPagesStyle();
|
||||
@ -252,10 +250,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
onDragStart(event: CdkDragStart) {
|
||||
event.event.preventDefault();
|
||||
if (!this.isDocumine) return;
|
||||
const contentInnerElement = document.body.getElementsByClassName('content-inner').item(0) as HTMLElement;
|
||||
if (contentInnerElement) {
|
||||
contentInnerElement.classList.add('dragging');
|
||||
}
|
||||
this.#createDragOverlay();
|
||||
}
|
||||
|
||||
onDragMove(event: CdkDragMove) {
|
||||
@ -269,10 +264,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
onDragEnd(event: CdkDragEnd) {
|
||||
event.event.preventDefault();
|
||||
if (!this.isDocumine) return;
|
||||
const contentInnerElement = document.body.getElementsByClassName('content-inner').item(0) as HTMLElement;
|
||||
if (contentInnerElement) {
|
||||
contentInnerElement.classList.remove('dragging');
|
||||
}
|
||||
this.#removeDragOverlay();
|
||||
}
|
||||
|
||||
deleteEarmarksOnViewChange$() {
|
||||
@ -311,7 +303,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
handleEscInsideViewer($event: KeyboardEvent) {
|
||||
$event.preventDefault();
|
||||
if (!!this._annotationManager.selected[0]) {
|
||||
if (this._annotationManager.selected[0]) {
|
||||
const doesHaveWrapper = this._fileDataService.find(this._annotationManager.selected[0]?.Id);
|
||||
if (!doesHaveWrapper) {
|
||||
this._annotationManager.delete(this._annotationManager.selected[0]?.Id);
|
||||
@ -332,24 +324,17 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
@Bind()
|
||||
handleViewerClick(event: MouseEvent) {
|
||||
this._ngZone.run(() => {
|
||||
if (event.isTrusted) {
|
||||
const clickedElement = event.target as HTMLElement;
|
||||
const actionIconClicked = ANNOTATION_ACTION_ICONS.some(action =>
|
||||
(clickedElement as HTMLImageElement).src?.includes(action),
|
||||
);
|
||||
const actionClicked = ANNOTATION_ACTIONS.some(action => clickedElement.getAttribute('aria-label')?.includes(action));
|
||||
if (this._multiSelectService.active() && !actionIconClicked && !actionClicked) {
|
||||
if (
|
||||
clickedElement.querySelector('#selectionrect') ||
|
||||
clickedElement.id === `pageWidgetContainer${this.pdf.currentPage()}`
|
||||
) {
|
||||
if (!this._annotationManager.selected.length) {
|
||||
this._multiSelectService.deactivate();
|
||||
}
|
||||
} else {
|
||||
this._multiSelectService.deactivate();
|
||||
}
|
||||
if (!event.isTrusted) return;
|
||||
const clickedElement = event.target as HTMLElement;
|
||||
const actionIconClicked = ANNOTATION_ACTION_ICONS.some(action => (clickedElement as HTMLImageElement).src?.includes(action));
|
||||
const actionClicked = ANNOTATION_ACTIONS.some(action => clickedElement.getAttribute('aria-label')?.includes(action));
|
||||
if (!this._multiSelectService.active() || actionIconClicked || actionClicked) return;
|
||||
if (clickedElement.querySelector('#selectionrect') || clickedElement.id === `pageWidgetContainer${this.pdf.currentPage()}`) {
|
||||
if (!this._annotationManager.selected.length) {
|
||||
this._multiSelectService.deactivate();
|
||||
}
|
||||
} else {
|
||||
this._multiSelectService.deactivate();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -471,7 +456,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
#getPixelsInPercentage(pixels: number) {
|
||||
return (pixels / window.screen.width) * 100;
|
||||
return (pixels / document.body.getBoundingClientRect().width) * 100;
|
||||
}
|
||||
|
||||
async #updateViewMode(): Promise<void> {
|
||||
@ -902,32 +887,30 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
const components = this._componentLogService.all;
|
||||
const filteredComponentIds = untracked(this.state.componentReferenceIds);
|
||||
|
||||
if (filteredComponentIds && annotationFilters) {
|
||||
const filteredComponentIdsSet = new Set(filteredComponentIds);
|
||||
if (!filteredComponentIds || !annotationFilters) return annotationFilters;
|
||||
|
||||
const references = new Set<string>();
|
||||
for (const component of components) {
|
||||
for (const componentValue of component.componentValues) {
|
||||
for (const reference of componentValue.entityReferences) {
|
||||
if (filteredComponentIdsSet.has(reference.id)) {
|
||||
references.add(reference.type);
|
||||
}
|
||||
const filteredComponentIdsSet = new Set(filteredComponentIds);
|
||||
|
||||
const references = new Set<string>();
|
||||
for (const component of components) {
|
||||
for (const componentValue of component.componentValues) {
|
||||
for (const reference of componentValue.entityReferences) {
|
||||
if (filteredComponentIdsSet.has(reference.id)) {
|
||||
references.add(reference.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return annotationFilters
|
||||
.map(filter => {
|
||||
const filteredChildren = filter.children.filter(c => references.has(c.label.replace(/ /g, '_').toLowerCase()));
|
||||
if (filteredChildren.length) {
|
||||
return { ...filter, children: filteredChildren };
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(f => f !== null);
|
||||
}
|
||||
|
||||
return annotationFilters;
|
||||
return annotationFilters
|
||||
.map(filter => {
|
||||
const filteredChildren = filter.children.filter(c => references.has(c.label.replace(/ /g, '_').toLowerCase()));
|
||||
if (filteredChildren.length) {
|
||||
return { ...filter, children: filteredChildren };
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(f => f !== null);
|
||||
}
|
||||
|
||||
#updateViewerPosition() {
|
||||
@ -942,4 +925,27 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
document.getElementById('viewer')?.classList?.add('redaction-viewer');
|
||||
}
|
||||
|
||||
#createDragOverlay() {
|
||||
if (this.#overlayElement || document.body.contains(this.#overlayElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#overlayElement = document.createElement('div');
|
||||
this.#overlayElement.style.position = 'fixed';
|
||||
this.#overlayElement.style.top = '0';
|
||||
this.#overlayElement.style.left = '0';
|
||||
this.#overlayElement.style.width = '100%';
|
||||
this.#overlayElement.style.height = '100%';
|
||||
this.#overlayElement.style.zIndex = '9999';
|
||||
this.#overlayElement.style.background = 'transparent';
|
||||
this.#overlayElement.style.pointerEvents = 'all';
|
||||
document.body.appendChild(this.#overlayElement);
|
||||
}
|
||||
|
||||
#removeDragOverlay() {
|
||||
if (!this.#overlayElement || !document.body.contains(this.#overlayElement)) return;
|
||||
document.body.removeChild(this.#overlayElement);
|
||||
this.#overlayElement = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +137,11 @@ export class AnnotationActionsService {
|
||||
|
||||
let recategorizeBody: List<IRecategorizationRequest> | IBulkRecategorizationRequest;
|
||||
|
||||
if (result.option === RedactOrHintOptions.ONLY_HERE || result.option === RectangleRedactOptions.ONLY_THIS_PAGE) {
|
||||
if (
|
||||
result.option === RedactOrHintOptions.ONLY_HERE ||
|
||||
result.option === RectangleRedactOptions.ONLY_THIS_PAGE ||
|
||||
this.#isDocumine
|
||||
) {
|
||||
recategorizeBody = annotations.map(annotation => {
|
||||
const body: IRecategorizationRequest = {
|
||||
annotationId: annotation.id,
|
||||
@ -167,6 +171,7 @@ export class AnnotationActionsService {
|
||||
};
|
||||
}
|
||||
|
||||
result.pageNumbers = result.pageNumbers || [];
|
||||
await this.#processObsAndEmit(
|
||||
this._manualRedactionService.recategorizeRedactions(
|
||||
recategorizeBody,
|
||||
@ -606,6 +611,7 @@ export class AnnotationActionsService {
|
||||
redactions: AnnotationWrapper[],
|
||||
dialogResult: RemoveRedactionResult,
|
||||
): List<IRemoveRedactionRequest | IBulkLocalRemoveRequest> {
|
||||
dialogResult.pageNumbers = dialogResult.pageNumbers || [];
|
||||
if (dialogResult.bulkLocal || !!dialogResult.pageNumbers.length) {
|
||||
return dialogResult.positions.map((position, index) => ({
|
||||
value: redactions[index].value,
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { ComponentLogEntry } from '@red/domain';
|
||||
import { INestedFilter, NestedFilter } from '@common-ui/filtering';
|
||||
import { IFilterGroup, INestedFilter, keyChecker, NestedFilter } from '@common-ui/filtering';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { sortArray } from '@utils/sorters/custom-sort';
|
||||
|
||||
@Injectable()
|
||||
export class ComponentLogFilterService {
|
||||
readonly #translateService = inject(TranslateService);
|
||||
|
||||
filterGroups(entities: ComponentLogEntry[]) {
|
||||
const allDistinctComponentLogs = new Set<string>();
|
||||
|
||||
entities?.forEach(entry => allDistinctComponentLogs.add(entry.name));
|
||||
|
||||
const componentLogFilters = [...allDistinctComponentLogs].map(
|
||||
const componentLogFilters = sortArray([...allDistinctComponentLogs]).map(
|
||||
id =>
|
||||
new NestedFilter({
|
||||
id: id,
|
||||
@ -21,7 +25,9 @@ export class ComponentLogFilterService {
|
||||
{
|
||||
slug: 'componentLogFilters',
|
||||
filters: componentLogFilters,
|
||||
},
|
||||
checker: keyChecker('name'),
|
||||
filterceptionPlaceholder: this.#translateService.instant('component-management.filter.search-placeholder'),
|
||||
} as IFilterGroup,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -296,7 +296,7 @@ export class FileActionsComponent {
|
||||
icon: 'iqser:refresh',
|
||||
show: this.#showReanalyseFilePreview(),
|
||||
disabled: this.file().isProcessing || this.#areRulesLocked(),
|
||||
helpModeKey: 'stop_analysis',
|
||||
helpModeKey: this.#isDocumine ? 'analyze_file' : 'stop_analysis',
|
||||
},
|
||||
{
|
||||
id: 'btn-toggle_automatic_analysis',
|
||||
@ -334,7 +334,7 @@ export class FileActionsComponent {
|
||||
icon: 'iqser:refresh',
|
||||
show: this.#showReanalyseDossierOverview(),
|
||||
disabled: this.#areRulesLocked(),
|
||||
helpModeKey: 'stop_analysis',
|
||||
helpModeKey: this.#isDocumine ? 'analyze_file' : 'stop_analysis',
|
||||
},
|
||||
{
|
||||
id: 'btn-toggle_analysis',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { StatsService } from '@iqser/common-ui';
|
||||
import { DashboardStats, DOSSIER_ID, DossierStats, IDossierStats } from '@red/domain';
|
||||
import { DOSSIER_ID, DossierStats, IDossierStats } from '@red/domain';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { UserService } from '@users/user.service';
|
||||
import { NGXLogger } from 'ngx-logger';
|
||||
|
||||
@ -577,6 +577,11 @@
|
||||
"documentKey": "dossier_stop_analysis",
|
||||
"scrollableParentView": "VIRTUAL_SCROLL"
|
||||
},
|
||||
{
|
||||
"elementKey": "dossier_analyze_file",
|
||||
"documentKey": "analyze_file",
|
||||
"scrollableParentView": "VIRTUAL_SCROLL"
|
||||
},
|
||||
{
|
||||
"elementKey": "dossier_automatic_text_recognition",
|
||||
"documentKey": "dossier_automatic_text_recognition",
|
||||
@ -626,7 +631,6 @@
|
||||
"elementKey": "workload_page_list",
|
||||
"documentKey": "workload_page_list"
|
||||
},
|
||||
|
||||
{
|
||||
"elementKey": "editor_delete_file",
|
||||
"documentKey": "editor_delete_file"
|
||||
@ -792,10 +796,6 @@
|
||||
"elementKey": "components_table",
|
||||
"documentKey": "components_table"
|
||||
},
|
||||
{
|
||||
"elementKey": "components_table",
|
||||
"documentKey": "components_table"
|
||||
},
|
||||
{
|
||||
"elementKey": "remove_annotation_DIALOG",
|
||||
"documentKey": "remove_annotation"
|
||||
|
||||
@ -560,6 +560,9 @@
|
||||
"undo": "Zurücksetzen"
|
||||
},
|
||||
"components": "Komponenten",
|
||||
"filter": {
|
||||
"search-placeholder": "Suche nach Komponente..."
|
||||
},
|
||||
"table-header": {
|
||||
"component": "Komponente",
|
||||
"value": "Wert"
|
||||
|
||||
@ -560,6 +560,9 @@
|
||||
"undo": "Undo"
|
||||
},
|
||||
"components": "Components",
|
||||
"filter": {
|
||||
"search-placeholder": "Search by component..."
|
||||
},
|
||||
"table-header": {
|
||||
"component": "Component",
|
||||
"value": "Value"
|
||||
@ -639,7 +642,7 @@
|
||||
"confirm-delete-users": {
|
||||
"cancel": "Keep {usersCount, plural, one{user} other{users}}",
|
||||
"delete": "Delete {usersCount, plural, one{user} other{users}}",
|
||||
"impacted-documents": "All documents pending review from the {usersCount, plural, one{user} other{users}} will be impacted",
|
||||
"impacted-documents": "{documentsCount} {documentsCount, plural, one{document} other{documents}} will be impacted",
|
||||
"impacted-dossiers": "{dossiersCount} {dossiersCount, plural, one{dossier} other{dossiers}} will be impacted",
|
||||
"title": "Delete {usersCount, plural, one{user} other{users}} from workspace",
|
||||
"toast-error": "Please confirm that you understand the consequences of this action.",
|
||||
|
||||
@ -560,6 +560,9 @@
|
||||
"undo": "Zurücksetzen"
|
||||
},
|
||||
"components": "Komponenten",
|
||||
"filter": {
|
||||
"search-placeholder": "Suche nach Komponente..."
|
||||
},
|
||||
"table-header": {
|
||||
"component": "Komponente",
|
||||
"value": "Wert"
|
||||
|
||||
@ -560,6 +560,9 @@
|
||||
"undo": "Undo"
|
||||
},
|
||||
"components": "Components",
|
||||
"filter": {
|
||||
"search-placeholder": "Search by component..."
|
||||
},
|
||||
"table-header": {
|
||||
"component": "Component",
|
||||
"value": "Value"
|
||||
@ -639,7 +642,7 @@
|
||||
"confirm-delete-users": {
|
||||
"cancel": "Keep {usersCount, plural, one{user} other{users}}",
|
||||
"delete": "Delete {usersCount, plural, one{user} other{users}}",
|
||||
"impacted-documents": "All documents pending review from the {usersCount, plural, one{user} other{users}} will be impacted",
|
||||
"impacted-documents": "{documentsCount} {documentsCount, plural, one{document} other{documents}} will be impacted",
|
||||
"impacted-dossiers": "{dossiersCount} {dossiersCount, plural, one{dossier} other{dossiers}} will be impacted",
|
||||
"title": "Delete {usersCount, plural, one{user} other{users}} from workspace",
|
||||
"toast-error": "Please confirm that you understand the consequences of this action.",
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit aa5fc5457618304ae413956cc8239cd79b660862
|
||||
Subproject commit 7f13fa62d3d2b346c609bc4978cff75f37f1ee6b
|
||||
1
libs/red-domain/src/lib/users/constants.ts
Normal file
1
libs/red-domain/src/lib/users/constants.ts
Normal file
@ -0,0 +1 @@
|
||||
export const USER_ID = 'userId';
|
||||
@ -1,3 +1,6 @@
|
||||
export * from './user.model';
|
||||
export * from './profile';
|
||||
export * from './types';
|
||||
export * from './user-stats';
|
||||
export * from './user-stats.model';
|
||||
export * from './constants';
|
||||
|
||||
13
libs/red-domain/src/lib/users/user-stats.model.ts
Normal file
13
libs/red-domain/src/lib/users/user-stats.model.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { IUserStats } from './user-stats';
|
||||
|
||||
export class UserStats implements IUserStats {
|
||||
readonly numberOfDossierMemberships: number;
|
||||
readonly numberOfDossierOwnerships: number;
|
||||
readonly numberOfAssignedFiles: number;
|
||||
|
||||
constructor(userStats: IUserStats) {
|
||||
this.numberOfAssignedFiles = userStats.numberOfAssignedFiles;
|
||||
this.numberOfDossierOwnerships = userStats.numberOfAssignedFiles;
|
||||
this.numberOfAssignedFiles = userStats.numberOfAssignedFiles;
|
||||
}
|
||||
}
|
||||
5
libs/red-domain/src/lib/users/user-stats.ts
Normal file
5
libs/red-domain/src/lib/users/user-stats.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export interface IUserStats {
|
||||
numberOfDossierMemberships: number;
|
||||
numberOfDossierOwnerships: number;
|
||||
numberOfAssignedFiles: number;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user