Merge branch 'dan' into 'master'
RED-7393 update logo color See merge request redactmanager/red-ui!37
This commit is contained in:
commit
c0084258b0
@ -131,7 +131,7 @@ export const appModuleFactory = (config: AppConfig) => {
|
|||||||
features: {
|
features: {
|
||||||
ANNOTATIONS: {
|
ANNOTATIONS: {
|
||||||
color: 'aqua',
|
color: 'aqua',
|
||||||
enabled: false,
|
enabled: true,
|
||||||
level: NgxLoggerLevel.DEBUG,
|
level: NgxLoggerLevel.DEBUG,
|
||||||
},
|
},
|
||||||
FILTERS: {
|
FILTERS: {
|
||||||
@ -147,7 +147,7 @@ export const appModuleFactory = (config: AppConfig) => {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
FILE: {
|
FILE: {
|
||||||
enabled: true,
|
enabled: false,
|
||||||
},
|
},
|
||||||
CHANGES: {
|
CHANGES: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
|
||||||
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||||
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
import { Dictionary } from '@red/domain';
|
import { Dictionary } from '@red/domain';
|
||||||
|
|
||||||
export const canUndo = (annotation: AnnotationWrapper, isApprover: boolean) =>
|
export const canUndo = (annotation: AnnotationWrapper, isApprover: boolean) =>
|
||||||
@ -39,7 +39,9 @@ export const canRecategorizeAnnotation = (annotation: AnnotationWrapper, canReca
|
|||||||
|
|
||||||
export const canResizeAnnotation = (annotation: AnnotationWrapper, canAddRedaction: boolean) =>
|
export const canResizeAnnotation = (annotation: AnnotationWrapper, canAddRedaction: boolean) =>
|
||||||
canAddRedaction &&
|
canAddRedaction &&
|
||||||
|
!annotation.isSkipped &&
|
||||||
|
!annotation.pending &&
|
||||||
(((annotation.isRedacted || annotation.isImage) && !annotation.isSuggestion) ||
|
(((annotation.isRedacted || annotation.isImage) && !annotation.isSuggestion) ||
|
||||||
annotation.isSuggestionResize ||
|
annotation.isSuggestionResize ||
|
||||||
annotation.isRecommendation) &&
|
annotation.isDictBasedHint ||
|
||||||
!annotation.pending;
|
annotation.isRecommendation);
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
import { AnnotationWrapper } from './annotation.wrapper';
|
|
||||||
import { Dictionary } from '@red/domain';
|
|
||||||
import { isArray } from 'lodash-es';
|
|
||||||
import { IqserPermissionsService } from '@iqser/common-ui';
|
import { IqserPermissionsService } from '@iqser/common-ui';
|
||||||
|
import { Dictionary } from '@red/domain';
|
||||||
import { Roles } from '@users/roles';
|
import { Roles } from '@users/roles';
|
||||||
|
import { isArray } from 'lodash-es';
|
||||||
import {
|
import {
|
||||||
canAcceptRecommendation,
|
canAcceptRecommendation,
|
||||||
canChangeLegalBasis,
|
canChangeLegalBasis,
|
||||||
@ -16,6 +15,7 @@ import {
|
|||||||
canResizeAnnotation,
|
canResizeAnnotation,
|
||||||
canUndo,
|
canUndo,
|
||||||
} from './annotation-permissions.utils';
|
} from './annotation-permissions.utils';
|
||||||
|
import { AnnotationWrapper } from './annotation.wrapper';
|
||||||
|
|
||||||
export class AnnotationPermissions {
|
export class AnnotationPermissions {
|
||||||
canUndo = true;
|
canUndo = true;
|
||||||
@ -64,6 +64,22 @@ export class AnnotationPermissions {
|
|||||||
return summedPermissions;
|
return summedPermissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static reduce(permissions: AnnotationPermissions[]): AnnotationPermissions {
|
||||||
|
const result = new AnnotationPermissions();
|
||||||
|
result.canResizeAnnotation = permissions.length === 1 && permissions[0].canResizeAnnotation;
|
||||||
|
result.canChangeLegalBasis = permissions.reduce((acc, next) => acc && next.canChangeLegalBasis, true);
|
||||||
|
result.canRecategorizeAnnotation = permissions.reduce((acc, next) => acc && next.canRecategorizeAnnotation, true);
|
||||||
|
result.canRemoveFromDictionary = permissions.reduce((acc, next) => acc && next.canRemoveFromDictionary, true);
|
||||||
|
result.canAcceptRecommendation = permissions.reduce((acc, next) => acc && next.canAcceptRecommendation, true);
|
||||||
|
result.canMarkAsFalsePositive = permissions.reduce((acc, next) => acc && next.canMarkAsFalsePositive, true);
|
||||||
|
result.canForceRedaction = permissions.reduce((acc, next) => acc && next.canForceRedaction, true);
|
||||||
|
result.canForceHint = permissions.reduce((acc, next) => acc && next.canForceHint, true);
|
||||||
|
result.canRemoveOnlyHere = permissions.reduce((acc, next) => acc && next.canRemoveOnlyHere, true);
|
||||||
|
result.canRemoveRedaction = permissions.reduce((acc, next) => acc && next.canRemoveRedaction, true);
|
||||||
|
result.canUndo = permissions.reduce((acc, next) => acc && next.canUndo, true);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private _merge(permissions: AnnotationPermissions) {
|
private _merge(permissions: AnnotationPermissions) {
|
||||||
for (const key of Object.keys(this)) {
|
for (const key of Object.keys(this)) {
|
||||||
if (typeof this[key] === 'boolean') {
|
if (typeof this[key] === 'boolean') {
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import {
|
|||||||
IRectangle,
|
IRectangle,
|
||||||
IRedactionLogEntry,
|
IRedactionLogEntry,
|
||||||
LogEntryEngine,
|
LogEntryEngine,
|
||||||
|
LogEntryEngines,
|
||||||
LogEntryStatuses,
|
LogEntryStatuses,
|
||||||
LowLevelFilterTypes,
|
LowLevelFilterTypes,
|
||||||
ManualRedactionTypes,
|
ManualRedactionTypes,
|
||||||
@ -180,6 +181,10 @@ export class AnnotationWrapper implements IListable {
|
|||||||
return 'square';
|
return 'square';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isDictBasedHint() {
|
||||||
|
return this.isHint && this.engines.includes(LogEntryEngines.DICTIONARY);
|
||||||
|
}
|
||||||
|
|
||||||
get isIgnoredHint() {
|
get isIgnoredHint() {
|
||||||
return this.superType === SuperTypes.IgnoredHint;
|
return this.superType === SuperTypes.IgnoredHint;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, inject, OnInit } from '@angular/core';
|
||||||
|
import { FormBuilder } from '@angular/forms';
|
||||||
import { DetailsRadioOption, IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui';
|
import { DetailsRadioOption, IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui';
|
||||||
import { Dictionary, Dossier, SuperTypes } from '@red/domain';
|
import { Dictionary, SuperTypes } from '@red/domain';
|
||||||
import { FormBuilder, UntypedFormGroup } from '@angular/forms';
|
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||||
|
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||||
|
import { JustificationsService } from '@services/entity-services/justifications.service';
|
||||||
import { Roles } from '@users/roles';
|
import { Roles } from '@users/roles';
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
import { JustificationsService } from '@services/entity-services/justifications.service';
|
import { IMAGE_CATEGORIES } from '../../utils/constants';
|
||||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
|
||||||
import { LegalBasisOption } from '../manual-redaction-dialog/manual-annotation-dialog.component';
|
|
||||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
|
||||||
import { getEditRedactionOptions, RedactOrHintOption } from '../../utils/dialog-options';
|
import { getEditRedactionOptions, RedactOrHintOption } from '../../utils/dialog-options';
|
||||||
import { EditRedactionData, EditRedactResult } from '../../utils/dialog-types';
|
import { EditRedactionData, EditRedactResult } from '../../utils/dialog-types';
|
||||||
import { IMAGE_CATEGORIES } from '../../utils/constants';
|
import { LegalBasisOption } from '../manual-redaction-dialog/manual-annotation-dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './edit-redaction-dialog.component.html',
|
templateUrl: './edit-redaction-dialog.component.html',
|
||||||
@ -19,6 +19,8 @@ export class EditRedactionDialogComponent
|
|||||||
extends IqserDialogComponent<EditRedactionDialogComponent, EditRedactionData, EditRedactResult>
|
extends IqserDialogComponent<EditRedactionDialogComponent, EditRedactionData, EditRedactResult>
|
||||||
implements OnInit
|
implements OnInit
|
||||||
{
|
{
|
||||||
|
readonly #dossier = inject(ActiveDossiersService).find(this.data.dossierId);
|
||||||
|
readonly #applyToAllDossiers = this.data.applyToAllDossiers;
|
||||||
readonly roles = Roles;
|
readonly roles = Roles;
|
||||||
readonly iconButtonTypes = IconButtonTypes;
|
readonly iconButtonTypes = IconButtonTypes;
|
||||||
readonly redactedText: string;
|
readonly redactedText: string;
|
||||||
@ -28,24 +30,17 @@ export class EditRedactionDialogComponent
|
|||||||
readonly showLegalReason: boolean;
|
readonly showLegalReason: boolean;
|
||||||
readonly isHint: boolean;
|
readonly isHint: boolean;
|
||||||
readonly showExtras: boolean;
|
readonly showExtras: boolean;
|
||||||
|
|
||||||
options: DetailsRadioOption<RedactOrHintOption>[] | undefined;
|
options: DetailsRadioOption<RedactOrHintOption>[] | undefined;
|
||||||
legalOptions: LegalBasisOption[] = [];
|
legalOptions: LegalBasisOption[] = [];
|
||||||
dictionaries: Dictionary[] = [];
|
dictionaries: Dictionary[] = [];
|
||||||
form: UntypedFormGroup;
|
readonly form;
|
||||||
readonly #dossier: Dossier;
|
|
||||||
|
|
||||||
#applyToAllDossiers: boolean;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _justificationsService: JustificationsService,
|
private readonly _justificationsService: JustificationsService,
|
||||||
private readonly _activeDossiersService: ActiveDossiersService,
|
|
||||||
private readonly _dictionaryService: DictionaryService,
|
private readonly _dictionaryService: DictionaryService,
|
||||||
private readonly _formBuilder: FormBuilder,
|
private readonly _formBuilder: FormBuilder,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.#dossier = this._activeDossiersService.find(this.data.dossierId);
|
|
||||||
this.#applyToAllDossiers = this.data.applyToAllDossiers;
|
|
||||||
const annotations = this.data.annotations;
|
const annotations = this.data.annotations;
|
||||||
const firstEntry = annotations[0];
|
const firstEntry = annotations[0];
|
||||||
this.isImage = [...IMAGE_CATEGORIES, 'ocr'].includes(firstEntry.type);
|
this.isImage = [...IMAGE_CATEGORIES, 'ocr'].includes(firstEntry.type);
|
||||||
@ -126,7 +121,7 @@ export class EditRedactionDialogComponent
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#getForm(): UntypedFormGroup {
|
#getForm() {
|
||||||
return this._formBuilder.group({
|
return this._formBuilder.group({
|
||||||
reason: [null],
|
reason: [null],
|
||||||
comment: [null],
|
comment: [null],
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
<section class="dialog">
|
|
||||||
<form (submit)="save()" [formGroup]="form">
|
|
||||||
<div class="dialog-header heading-l" [translate]="'recategorize-image-dialog.header'"></div>
|
|
||||||
|
|
||||||
<div class="dialog-content">
|
|
||||||
<div class="iqser-input-group required w-400">
|
|
||||||
<label [translate]="'recategorize-image-dialog.content.type'"></label>
|
|
||||||
<mat-form-field>
|
|
||||||
<mat-select
|
|
||||||
[placeholder]="'recategorize-image-dialog.content.type-placeholder' | translate"
|
|
||||||
class="full-width"
|
|
||||||
formControlName="type"
|
|
||||||
>
|
|
||||||
<mat-option *ngFor="let option of typeOptions" [value]="option">
|
|
||||||
{{ translations[option] | translate }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="iqser-input-group w-300">
|
|
||||||
<label [translate]="'recategorize-image-dialog.content.comment'"></label>
|
|
||||||
<textarea formControlName="comment" iqserHasScrollbar name="comment" rows="4" type="text"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="dialog-actions">
|
|
||||||
<iqser-icon-button
|
|
||||||
[disabled]="disabled"
|
|
||||||
[label]="'recategorize-image-dialog.actions.save' | translate"
|
|
||||||
[submit]="true"
|
|
||||||
[type]="iconButtonTypes.primary"
|
|
||||||
></iqser-icon-button>
|
|
||||||
|
|
||||||
<div class="all-caps-label cancel" mat-dialog-close [translate]="'recategorize-image-dialog.actions.cancel'"></div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<iqser-circle-button (action)="close()" class="dialog-close" icon="iqser:close"></iqser-circle-button>
|
|
||||||
</section>
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
import { Component, Inject, OnInit } from '@angular/core';
|
|
||||||
import { Validators } from '@angular/forms';
|
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
|
||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
|
||||||
import { imageCategoriesTranslations } from '@translations/image-categories-translations';
|
|
||||||
import { Dossier, ImageCategory } from '@red/domain';
|
|
||||||
import { BaseDialogComponent } from '@iqser/common-ui';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
templateUrl: './recategorize-image-dialog.component.html',
|
|
||||||
})
|
|
||||||
export class RecategorizeImageDialogComponent extends BaseDialogComponent implements OnInit {
|
|
||||||
readonly typeOptions: ImageCategory[] = ['signature', 'logo', 'formula', 'image'];
|
|
||||||
readonly translations = imageCategoriesTranslations;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
protected readonly _dialogRef: MatDialogRef<RecategorizeImageDialogComponent>,
|
|
||||||
@Inject(MAT_DIALOG_DATA) readonly data: { annotations: AnnotationWrapper[]; dossier: Dossier },
|
|
||||||
) {
|
|
||||||
super(_dialogRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
get changed(): boolean {
|
|
||||||
return this.form.get('type').value !== this.data.annotations[0].type;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.form = this._formBuilder.group({
|
|
||||||
type: [this.data.annotations[0].type, Validators.required],
|
|
||||||
comment: [null],
|
|
||||||
});
|
|
||||||
this.initialFormValue = this.form.getRawValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
save() {
|
|
||||||
this._dialogRef.close({
|
|
||||||
type: this.form.get('type').value,
|
|
||||||
comment: this.form.get('comment').value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,19 +1,19 @@
|
|||||||
<section class="dialog">
|
<section class="dialog">
|
||||||
<form (submit)="save()" [formGroup]="form">
|
<form (submit)="save()" [formGroup]="form">
|
||||||
<div
|
<div
|
||||||
[innerHTML]="'resize-redaction.dialog.header' | translate : { type: redaction.hint ? 'hint' : 'redaction' }"
|
[innerHTML]="'resize-redaction.dialog.header' | translate: { type: redaction.hint ? 'hint' : 'redaction' }"
|
||||||
class="dialog-header heading-l"
|
class="dialog-header heading-l"
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
<div class="dialog-content redaction">
|
<div class="dialog-content redaction">
|
||||||
<div class="iqser-input-group w-450">
|
<div *ngIf="!redaction.isImage" class="iqser-input-group w-450">
|
||||||
<label [translate]="'resize-redaction.dialog.content.original-text'" class="selected-text"></label>
|
<label [translate]="'resize-redaction.dialog.content.original-text'" class="selected-text"></label>
|
||||||
{{ redaction.value }}
|
<span class="pl-20">{{ redaction.value }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="iqser-input-group w-450">
|
<div *ngIf="!redaction.isImage" class="iqser-input-group w-450">
|
||||||
<label [translate]="'resize-redaction.dialog.content.resized-text'" class="selected-text"></label>
|
<label [translate]="'resize-redaction.dialog.content.resized-text'" class="selected-text"></label>
|
||||||
{{ data.text }}
|
<span class="pl-20">{{ data.text }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<iqser-details-radio [options]="options" formControlName="option"></iqser-details-radio>
|
<iqser-details-radio [options]="options" formControlName="option"></iqser-details-radio>
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { OverlayModule } from '@angular/cdk/overlay';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||||
import {
|
import {
|
||||||
CapitalizePipe,
|
CapitalizePipe,
|
||||||
CircleButtonComponent,
|
CircleButtonComponent,
|
||||||
@ -20,58 +23,54 @@ import {
|
|||||||
RoundCheckboxComponent,
|
RoundCheckboxComponent,
|
||||||
StopPropagationDirective,
|
StopPropagationDirective,
|
||||||
} from '@iqser/common-ui';
|
} from '@iqser/common-ui';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
|
||||||
import { RouterModule } from '@angular/router';
|
|
||||||
import { FilePreviewScreenComponent } from './file-preview-screen.component';
|
|
||||||
import { FileWorkloadComponent } from './components/file-workload/file-workload.component';
|
|
||||||
import { AnnotationDetailsComponent } from './components/annotation-details/annotation-details.component';
|
|
||||||
import { AnnotationsListComponent } from './components/annotations-list/annotations-list.component';
|
|
||||||
import { PageIndicatorComponent } from './components/page-indicator/page-indicator.component';
|
|
||||||
import { PageExclusionComponent } from './components/page-exclusion/page-exclusion.component';
|
|
||||||
import { AnnotationActionsComponent } from './components/annotation-actions/annotation-actions.component';
|
|
||||||
import { CommentsComponent } from './components/comments/comments.component';
|
|
||||||
import { DocumentInfoComponent } from './components/document-info/document-info.component';
|
|
||||||
import { OverlayModule } from '@angular/cdk/overlay';
|
|
||||||
import { ViewSwitchComponent } from './components/view-switch/view-switch.component';
|
|
||||||
import { UserManagementComponent } from './components/user-management/user-management.component';
|
|
||||||
import { AnnotationReferencesListComponent } from './components/annotation-references-list/annotation-references-list.component';
|
|
||||||
import { AcceptRecommendationDialogComponent } from './dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component';
|
|
||||||
import { AnnotationCardComponent } from './components/annotation-card/annotation-card.component';
|
|
||||||
import { AnnotationReferencesPageIndicatorComponent } from './components/annotation-references-page-indicator/annotation-references-page-indicator.component';
|
|
||||||
import { HighlightsSeparatorComponent } from './components/highlights-separator/highlights-separator.component';
|
|
||||||
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
|
||||||
import { ManualAnnotationDialogComponent } from './dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
|
|
||||||
import { ForceAnnotationDialogComponent } from './dialogs/force-redaction-dialog/force-annotation-dialog.component';
|
|
||||||
import { ResizeRedactionDialogComponent } from './dialogs/resize-redaction-dialog/resize-redaction-dialog.component';
|
|
||||||
import { ChangeLegalBasisDialogComponent } from './dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component';
|
|
||||||
import { RecategorizeImageDialogComponent } from './dialogs/recategorize-image-dialog/recategorize-image-dialog.component';
|
|
||||||
import { HighlightActionDialogComponent } from './dialogs/highlight-action-dialog/highlight-action-dialog.component';
|
|
||||||
import { FilePreviewDialogService } from './services/file-preview-dialog.service';
|
|
||||||
import { DocumentInfoDialogComponent } from './dialogs/document-info-dialog/document-info-dialog.component';
|
|
||||||
import { ManualRedactionService } from './services/manual-redaction.service';
|
|
||||||
import { AnnotationWrapperComponent } from './components/annotation-wrapper/annotation-wrapper.component';
|
|
||||||
import { AnnotationReferenceComponent } from './components/annotation-reference/annotation-reference.component';
|
|
||||||
import { ImportRedactionsDialogComponent } from './dialogs/import-redactions-dialog/import-redactions-dialog';
|
|
||||||
import { DocumentUnloadedGuard } from './services/document-unloaded.guard';
|
|
||||||
import { FilePreviewRightContainerComponent } from './components/right-container/file-preview-right-container.component';
|
|
||||||
import { ReadonlyBannerComponent } from './components/readonly-banner/readonly-banner.component';
|
|
||||||
import { PagesComponent } from './components/pages/pages.component';
|
|
||||||
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';
|
import { IqserFiltersModule } from '@iqser/common-ui/lib/filtering';
|
||||||
import { StatusBarComponent } from '@iqser/common-ui/lib/shared';
|
import { StatusBarComponent } from '@iqser/common-ui/lib/shared';
|
||||||
import { TenantPipe } from '@iqser/common-ui/lib/tenants';
|
import { TenantPipe } from '@iqser/common-ui/lib/tenants';
|
||||||
|
import { IqserUsersModule } from '@iqser/common-ui/lib/users';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { SharedModule } from '@shared/shared.module';
|
||||||
|
import { SharedDossiersModule } from '../shared-dossiers/shared-dossiers.module';
|
||||||
|
import { AnnotationActionsComponent } from './components/annotation-actions/annotation-actions.component';
|
||||||
|
import { AnnotationCardComponent } from './components/annotation-card/annotation-card.component';
|
||||||
|
import { AnnotationDetailsComponent } from './components/annotation-details/annotation-details.component';
|
||||||
|
import { AnnotationReferenceComponent } from './components/annotation-reference/annotation-reference.component';
|
||||||
|
import { AnnotationReferencesListComponent } from './components/annotation-references-list/annotation-references-list.component';
|
||||||
|
import { AnnotationReferencesPageIndicatorComponent } from './components/annotation-references-page-indicator/annotation-references-page-indicator.component';
|
||||||
|
import { AnnotationWrapperComponent } from './components/annotation-wrapper/annotation-wrapper.component';
|
||||||
|
import { AnnotationsListComponent } from './components/annotations-list/annotations-list.component';
|
||||||
|
import { CommentsComponent } from './components/comments/comments.component';
|
||||||
|
import { DocumentInfoComponent } from './components/document-info/document-info.component';
|
||||||
|
import { FileWorkloadComponent } from './components/file-workload/file-workload.component';
|
||||||
|
import { HighlightsSeparatorComponent } from './components/highlights-separator/highlights-separator.component';
|
||||||
|
import { PageExclusionComponent } from './components/page-exclusion/page-exclusion.component';
|
||||||
|
import { PageIndicatorComponent } from './components/page-indicator/page-indicator.component';
|
||||||
|
import { PagesComponent } from './components/pages/pages.component';
|
||||||
|
import { ReadonlyBannerComponent } from './components/readonly-banner/readonly-banner.component';
|
||||||
|
import { FilePreviewRightContainerComponent } from './components/right-container/file-preview-right-container.component';
|
||||||
|
import { UserManagementComponent } from './components/user-management/user-management.component';
|
||||||
|
import { ViewSwitchComponent } from './components/view-switch/view-switch.component';
|
||||||
|
import { AcceptRecommendationDialogComponent } from './dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component';
|
||||||
import { AddHintDialogComponent } from './dialogs/add-hint-dialog/add-hint-dialog.component';
|
import { AddHintDialogComponent } from './dialogs/add-hint-dialog/add-hint-dialog.component';
|
||||||
|
import { ChangeLegalBasisDialogComponent } from './dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component';
|
||||||
import { AddAnnotationDialogComponent } from './dialogs/docu-mine/add-annotation-dialog/add-annotation-dialog.component';
|
import { AddAnnotationDialogComponent } from './dialogs/docu-mine/add-annotation-dialog/add-annotation-dialog.component';
|
||||||
|
import { EditAnnotationDialogComponent } from './dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component';
|
||||||
import { RemoveAnnotationDialogComponent } from './dialogs/docu-mine/remove-annotation-dialog/remove-annotation-dialog.component';
|
import { RemoveAnnotationDialogComponent } from './dialogs/docu-mine/remove-annotation-dialog/remove-annotation-dialog.component';
|
||||||
import { ResizeAnnotationDialogComponent } from './dialogs/docu-mine/resize-annotation-dialog/resize-annotation-dialog.component';
|
import { ResizeAnnotationDialogComponent } from './dialogs/docu-mine/resize-annotation-dialog/resize-annotation-dialog.component';
|
||||||
import { EditAnnotationDialogComponent } from './dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component';
|
import { DocumentInfoDialogComponent } from './dialogs/document-info-dialog/document-info-dialog.component';
|
||||||
import { EditRedactionDialogComponent } from './dialogs/edit-redaction-dialog/edit-redaction-dialog.component';
|
import { EditRedactionDialogComponent } from './dialogs/edit-redaction-dialog/edit-redaction-dialog.component';
|
||||||
import { TablesService } from './services/tables.service';
|
import { ForceAnnotationDialogComponent } from './dialogs/force-redaction-dialog/force-annotation-dialog.component';
|
||||||
|
import { HighlightActionDialogComponent } from './dialogs/highlight-action-dialog/highlight-action-dialog.component';
|
||||||
|
import { ImportRedactionsDialogComponent } from './dialogs/import-redactions-dialog/import-redactions-dialog';
|
||||||
|
import { ManualAnnotationDialogComponent } from './dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
|
||||||
import { RedactRecommendationDialogComponent } from './dialogs/redact-recommendation-dialog/redact-recommendation-dialog.component';
|
import { RedactRecommendationDialogComponent } from './dialogs/redact-recommendation-dialog/redact-recommendation-dialog.component';
|
||||||
|
import { RedactTextDialogComponent } from './dialogs/redact-text-dialog/redact-text-dialog.component';
|
||||||
|
import { RemoveRedactionDialogComponent } from './dialogs/remove-redaction-dialog/remove-redaction-dialog.component';
|
||||||
|
import { ResizeRedactionDialogComponent } from './dialogs/resize-redaction-dialog/resize-redaction-dialog.component';
|
||||||
|
import { FilePreviewScreenComponent } from './file-preview-screen.component';
|
||||||
|
import { DocumentUnloadedGuard } from './services/document-unloaded.guard';
|
||||||
|
import { FilePreviewDialogService } from './services/file-preview-dialog.service';
|
||||||
|
import { ManualRedactionService } from './services/manual-redaction.service';
|
||||||
|
import { TablesService } from './services/tables.service';
|
||||||
|
|
||||||
const routes: IqserRoutes = [
|
const routes: IqserRoutes = [
|
||||||
{
|
{
|
||||||
@ -87,7 +86,6 @@ const dialogs = [
|
|||||||
ForceAnnotationDialogComponent,
|
ForceAnnotationDialogComponent,
|
||||||
ResizeRedactionDialogComponent,
|
ResizeRedactionDialogComponent,
|
||||||
ChangeLegalBasisDialogComponent,
|
ChangeLegalBasisDialogComponent,
|
||||||
RecategorizeImageDialogComponent,
|
|
||||||
HighlightActionDialogComponent,
|
HighlightActionDialogComponent,
|
||||||
AcceptRecommendationDialogComponent,
|
AcceptRecommendationDialogComponent,
|
||||||
DocumentInfoDialogComponent,
|
DocumentInfoDialogComponent,
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
|
|||||||
import { IqserDialog } from '@common-ui/dialog/iqser-dialog.service';
|
import { IqserDialog } from '@common-ui/dialog/iqser-dialog.service';
|
||||||
import { getConfig } from '@iqser/common-ui';
|
import { getConfig } from '@iqser/common-ui';
|
||||||
import { List, log } from '@iqser/common-ui/lib/utils';
|
import { List, log } from '@iqser/common-ui/lib/utils';
|
||||||
|
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
import { Core } from '@pdftron/webviewer';
|
import { Core } from '@pdftron/webviewer';
|
||||||
import {
|
import {
|
||||||
@ -44,7 +45,7 @@ import { SkippedService } from './skipped.service';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AnnotationActionsService {
|
export class AnnotationActionsService {
|
||||||
readonly #isDocumine;
|
readonly #isDocumine = getConfig().IS_DOCUMINE;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _manualRedactionService: ManualRedactionService,
|
private readonly _manualRedactionService: ManualRedactionService,
|
||||||
@ -59,9 +60,7 @@ export class AnnotationActionsService {
|
|||||||
private readonly _skippedService: SkippedService,
|
private readonly _skippedService: SkippedService,
|
||||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||||
private readonly _permissionsService: PermissionsService,
|
private readonly _permissionsService: PermissionsService,
|
||||||
) {
|
) {}
|
||||||
this.#isDocumine = getConfig().IS_DOCUMINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
removeHighlights(highlights: AnnotationWrapper[]): void {
|
removeHighlights(highlights: AnnotationWrapper[]): void {
|
||||||
const data = this.#getHighlightOperationData(EarmarkOperation.REMOVE, highlights);
|
const data = this.#getHighlightOperationData(EarmarkOperation.REMOVE, highlights);
|
||||||
@ -73,18 +72,6 @@ export class AnnotationActionsService {
|
|||||||
this._dialogService.openDialog('highlightAction', data);
|
this._dialogService.openDialog('highlightAction', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
rejectSuggestion(annotations: AnnotationWrapper[]) {
|
|
||||||
const { dossierId, fileId } = this._state;
|
|
||||||
this.#processObsAndEmit(
|
|
||||||
this._manualRedactionService.declineOrRemove(
|
|
||||||
annotations.map(a => a.id),
|
|
||||||
dossierId,
|
|
||||||
fileId,
|
|
||||||
annotations[0].isModifyDictionary,
|
|
||||||
),
|
|
||||||
).then();
|
|
||||||
}
|
|
||||||
|
|
||||||
forceAnnotation(annotations: AnnotationWrapper[], hint: boolean = false) {
|
forceAnnotation(annotations: AnnotationWrapper[], hint: boolean = false) {
|
||||||
const { dossierId, fileId } = this._state;
|
const { dossierId, fileId } = this._state;
|
||||||
const data = { dossier: this._state.dossier(), annotations, hint };
|
const data = { dossier: this._state.dossier(), annotations, hint };
|
||||||
@ -147,7 +134,7 @@ export class AnnotationActionsService {
|
|||||||
await this.#processObsAndEmit(zip(requests).pipe(log()));
|
await this.#processObsAndEmit(zip(requests).pipe(log()));
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeRedaction(redaction: AnnotationWrapper, permissions) {
|
async removeRedaction(redaction: AnnotationWrapper, permissions: AnnotationPermissions) {
|
||||||
const removePermissions: RemoveRedactionPermissions = {
|
const removePermissions: RemoveRedactionPermissions = {
|
||||||
canRemoveOnlyHere: permissions.canRemoveOnlyHere,
|
canRemoveOnlyHere: permissions.canRemoveOnlyHere,
|
||||||
canRemoveFromDictionary: permissions.canRemoveFromDictionary,
|
canRemoveFromDictionary: permissions.canRemoveFromDictionary,
|
||||||
@ -181,19 +168,6 @@ export class AnnotationActionsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recategorizeImages(annotations: AnnotationWrapper[]) {
|
|
||||||
const data = { annotations, dossier: this._state.dossier() };
|
|
||||||
const { dossierId, fileId } = this._state;
|
|
||||||
this._dialogService.openDialog('recategorizeImage', data, ({ comment, type }: { type: string; comment: string }) => {
|
|
||||||
const body: List<IRecategorizationRequest> = annotations.map(({ id }) => ({
|
|
||||||
annotationId: id,
|
|
||||||
type,
|
|
||||||
comment,
|
|
||||||
}));
|
|
||||||
this.#processObsAndEmit(this._manualRedactionService.recategorizeRedactions(body, dossierId, fileId)).then();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
undoDirectAction(annotations: AnnotationWrapper[]) {
|
undoDirectAction(annotations: AnnotationWrapper[]) {
|
||||||
const { dossierId, fileId } = this._state;
|
const { dossierId, fileId } = this._state;
|
||||||
const modifyDictionary = annotations[0].isModifyDictionary;
|
const modifyDictionary = annotations[0].isModifyDictionary;
|
||||||
@ -231,7 +205,6 @@ export class AnnotationActionsService {
|
|||||||
if (annotationWrapper.rectangle || annotationWrapper.imported || annotationWrapper.isImage) {
|
if (annotationWrapper.rectangle || annotationWrapper.imported || annotationWrapper.isImage) {
|
||||||
this._annotationManager.delete(annotationWrapper);
|
this._annotationManager.delete(annotationWrapper);
|
||||||
const rectangleAnnotation = this.#generateRectangle(annotationWrapper);
|
const rectangleAnnotation = this.#generateRectangle(annotationWrapper);
|
||||||
console.log(rectangleAnnotation);
|
|
||||||
return this._annotationManager.add(rectangleAnnotation);
|
return this._annotationManager.add(rectangleAnnotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,11 +266,9 @@ export class AnnotationActionsService {
|
|||||||
|
|
||||||
async cancelResize(annotationWrapper: AnnotationWrapper) {
|
async cancelResize(annotationWrapper: AnnotationWrapper) {
|
||||||
this._annotationManager.resizingAnnotationId = undefined;
|
this._annotationManager.resizingAnnotationId = undefined;
|
||||||
this._annotationManager.resizingHasStarted = false;
|
|
||||||
this._annotationManager.delete(annotationWrapper);
|
this._annotationManager.delete(annotationWrapper);
|
||||||
await this._annotationDrawService.draw([annotationWrapper], this._skippedService.hideSkipped(), this._state.dossierTemplateId);
|
await this._annotationDrawService.draw([annotationWrapper], this._skippedService.hideSkipped(), this._state.dossierTemplateId);
|
||||||
this._annotationManager.deselect();
|
this._annotationManager.deselect();
|
||||||
await this._fileDataService.annotationsChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#generateRectangle(annotationWrapper: AnnotationWrapper) {
|
#generateRectangle(annotationWrapper: AnnotationWrapper) {
|
||||||
@ -333,9 +304,7 @@ export class AnnotationActionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async #processObsAndEmit(obs: Observable<unknown>) {
|
async #processObsAndEmit(obs: Observable<unknown>) {
|
||||||
await firstValueFrom(obs)
|
await firstValueFrom(obs).finally(() => this._fileDataService.annotationsChanged());
|
||||||
.then(() => this._fileDataService.annotationsChanged())
|
|
||||||
.catch(() => this._fileDataService.annotationsChanged());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#getFalsePositiveText(annotation: AnnotationWrapper) {
|
#getFalsePositiveText(annotation: AnnotationWrapper) {
|
||||||
@ -389,7 +358,7 @@ export class AnnotationActionsService {
|
|||||||
rect.topLeft.x + rect.width - 2,
|
rect.topLeft.x + rect.width - 2,
|
||||||
rect.topLeft.y + rect.height - percentHeightOffset,
|
rect.topLeft.y + rect.height - percentHeightOffset,
|
||||||
);
|
);
|
||||||
const quadWords = await this._extractTextFromRect(page, pdfNetRect);
|
const quadWords = await this.#extractTextFromRect(page, pdfNetRect);
|
||||||
words.push(...quadWords);
|
words.push(...quadWords);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,7 +380,7 @@ export class AnnotationActionsService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _extractTextFromRect(page: Core.PDFNet.Page, rect: Core.PDFNet.Rect) {
|
async #extractTextFromRect(page: Core.PDFNet.Page, rect: Core.PDFNet.Rect) {
|
||||||
const txt = await this._pdf.PDFNet.TextExtractor.create();
|
const txt = await this._pdf.PDFNet.TextExtractor.create();
|
||||||
await txt.begin(page, rect); // Read the page.
|
await txt.begin(page, rect); // Read the page.
|
||||||
|
|
||||||
|
|||||||
@ -1,23 +1,14 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { ForceAnnotationDialogComponent } from '../dialogs/force-redaction-dialog/force-annotation-dialog.component';
|
|
||||||
import { DocumentInfoDialogComponent } from '../dialogs/document-info-dialog/document-info-dialog.component';
|
|
||||||
import { ManualAnnotationDialogComponent } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
|
|
||||||
import { ChangeLegalBasisDialogComponent } from '../dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component';
|
|
||||||
import { RecategorizeImageDialogComponent } from '../dialogs/recategorize-image-dialog/recategorize-image-dialog.component';
|
|
||||||
import { ConfirmationDialogComponent, DialogConfig, DialogService } from '@iqser/common-ui';
|
import { ConfirmationDialogComponent, DialogConfig, DialogService } from '@iqser/common-ui';
|
||||||
|
import { ChangeLegalBasisDialogComponent } from '../dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component';
|
||||||
|
import { DocumentInfoDialogComponent } from '../dialogs/document-info-dialog/document-info-dialog.component';
|
||||||
|
import { ForceAnnotationDialogComponent } from '../dialogs/force-redaction-dialog/force-annotation-dialog.component';
|
||||||
import { HighlightActionDialogComponent } from '../dialogs/highlight-action-dialog/highlight-action-dialog.component';
|
import { HighlightActionDialogComponent } from '../dialogs/highlight-action-dialog/highlight-action-dialog.component';
|
||||||
|
import { ManualAnnotationDialogComponent } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
|
||||||
import { StructuredComponentManagementDialogComponent } from '../dialogs/structured-component-management-dialog/structured-component-management-dialog.component';
|
import { StructuredComponentManagementDialogComponent } from '../dialogs/structured-component-management-dialog/structured-component-management-dialog.component';
|
||||||
|
|
||||||
type DialogType =
|
type DialogType = 'confirm' | 'documentInfo' | 'rss' | 'changeLegalBasis' | 'forceAnnotation' | 'manualAnnotation' | 'highlightAction';
|
||||||
| 'confirm'
|
|
||||||
| 'documentInfo'
|
|
||||||
| 'rss'
|
|
||||||
| 'recategorizeImage'
|
|
||||||
| 'changeLegalBasis'
|
|
||||||
| 'forceAnnotation'
|
|
||||||
| 'manualAnnotation'
|
|
||||||
| 'highlightAction';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FilePreviewDialogService extends DialogService<DialogType> {
|
export class FilePreviewDialogService extends DialogService<DialogType> {
|
||||||
@ -30,9 +21,6 @@ export class FilePreviewDialogService extends DialogService<DialogType> {
|
|||||||
component: DocumentInfoDialogComponent,
|
component: DocumentInfoDialogComponent,
|
||||||
dialogConfig: { autoFocus: true },
|
dialogConfig: { autoFocus: true },
|
||||||
},
|
},
|
||||||
recategorizeImage: {
|
|
||||||
component: RecategorizeImageDialogComponent,
|
|
||||||
},
|
|
||||||
changeLegalBasis: {
|
changeLegalBasis: {
|
||||||
component: ChangeLegalBasisDialogComponent,
|
component: ChangeLegalBasisDialogComponent,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
import { inject, Injectable, NgZone } from '@angular/core';
|
import { inject, Injectable, NgZone } from '@angular/core';
|
||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
|
||||||
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
|
||||||
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 { IqserPermissionsService } from '@iqser/common-ui';
|
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { IHeaderElement } from '@red/domain';
|
import { IqserPermissionsService } from '@iqser/common-ui';
|
||||||
import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service';
|
|
||||||
import { BASE_HREF_FN } from '@iqser/common-ui/lib/utils';
|
import { BASE_HREF_FN } from '@iqser/common-ui/lib/utils';
|
||||||
|
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||||
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { IHeaderElement } from '@red/domain';
|
||||||
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
|
import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service';
|
||||||
|
import { AnnotationActionsService } from './annotation-actions.service';
|
||||||
|
import { FilePreviewStateService } from './file-preview-state.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PdfAnnotationActionsService {
|
export class PdfAnnotationActionsService {
|
||||||
@ -27,21 +27,18 @@ export class PdfAnnotationActionsService {
|
|||||||
const permissions = this.#getAnnotationsPermissions(annotations);
|
const permissions = this.#getAnnotationsPermissions(annotations);
|
||||||
|
|
||||||
// you can only resize one annotation at a time
|
// you can only resize one annotation at a time
|
||||||
if (permissions.canResize) {
|
if (permissions.canResizeAnnotation) {
|
||||||
const firstAnnotation = annotations[0];
|
const firstAnnotation = annotations[0];
|
||||||
// if we already entered resize-mode previously
|
// if we already entered resize-mode previously
|
||||||
if (firstAnnotation.id === this.#annotationManager.resizingAnnotationId) {
|
if (firstAnnotation.id === this.#annotationManager.resizingAnnotationId) {
|
||||||
if (this.#annotationManager.resizingHasStarted) {
|
const acceptResizeButton = this.#getButton('check', _('annotation-actions.resize-accept.label'), () =>
|
||||||
const acceptResizeButton = this.#getButton('check', _('annotation-actions.resize-accept.label'), () =>
|
this.#annotationActionsService.acceptResize(firstAnnotation),
|
||||||
this.#annotationActionsService.acceptResize(firstAnnotation),
|
);
|
||||||
);
|
const cancelResizeButton = this.#getButton('close', _('annotation-actions.resize-cancel.label'), () =>
|
||||||
const cancelResizeButton = this.#getButton('close', _('annotation-actions.resize-cancel.label'), () =>
|
this.#annotationActionsService.cancelResize(firstAnnotation),
|
||||||
this.#annotationActionsService.cancelResize(firstAnnotation),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
return [acceptResizeButton, cancelResizeButton];
|
return [acceptResizeButton, cancelResizeButton];
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const resizeButton = this.#getButton('resize', _('annotation-actions.resize.label'), () =>
|
const resizeButton = this.#getButton('resize', _('annotation-actions.resize.label'), () =>
|
||||||
@ -103,22 +100,11 @@ export class PdfAnnotationActionsService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#getAnnotationsPermissions(annotations: AnnotationWrapper[]) {
|
#getAnnotationsPermissions(annotations: AnnotationWrapper[]): AnnotationPermissions {
|
||||||
const dossier = this.#state.dossier();
|
const dossier = this.#state.dossier();
|
||||||
const isApprover = this.#permissionsService.isApprover(dossier);
|
const isApprover = this.#permissionsService.isApprover(dossier);
|
||||||
const dictionaries = this.#state.dictionaries;
|
const dictionaries = this.#state.dictionaries;
|
||||||
const permissions = annotations.map(a => AnnotationPermissions.forUser(isApprover, a, dictionaries, this.#iqserPermissionsService));
|
const permissions = annotations.map(a => AnnotationPermissions.forUser(isApprover, a, dictionaries, this.#iqserPermissionsService));
|
||||||
return {
|
return AnnotationPermissions.reduce(permissions);
|
||||||
canResize: permissions.length === 1 && permissions[0].canResizeAnnotation,
|
|
||||||
canChangeLegalBasis: permissions.reduce((acc, next) => acc && next.canChangeLegalBasis, true),
|
|
||||||
canRecategorizeAnnotation: permissions.reduce((acc, next) => acc && next.canRecategorizeAnnotation, true),
|
|
||||||
canRemoveFromDictionary: permissions.reduce((acc, next) => acc && next.canRemoveFromDictionary, true),
|
|
||||||
canAcceptRecommendation: permissions.reduce((acc, next) => acc && next.canAcceptRecommendation, true),
|
|
||||||
canMarkAsFalsePositive: permissions.reduce((acc, next) => acc && next.canMarkAsFalsePositive, true),
|
|
||||||
canForceRedaction: permissions.reduce((acc, next) => acc && next.canForceRedaction, true),
|
|
||||||
canForceHint: permissions.reduce((acc, next) => acc && next.canForceHint, true),
|
|
||||||
canRemoveOnlyHere: permissions.reduce((acc, next) => acc && next.canRemoveOnlyHere, true),
|
|
||||||
canRemoveRedaction: permissions.reduce((acc, next) => acc && next.canRemoveRedaction, true),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -286,7 +286,7 @@ export class PdfProxyService {
|
|||||||
this.handleAnnotationSelected([]);
|
this.handleAnnotationSelected([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#processSelectedAnnotations(annotations: Annotation[], action) {
|
#processSelectedAnnotations(annotations: Annotation[], action: string) {
|
||||||
let nextAnnotations: Annotation[];
|
let nextAnnotations: Annotation[];
|
||||||
|
|
||||||
if (action === 'deselected') {
|
if (action === 'deselected') {
|
||||||
@ -313,7 +313,10 @@ export class PdfProxyService {
|
|||||||
nextAnnotations = this._annotationManager.selected;
|
nextAnnotations = this._annotationManager.selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#configureAnnotationSpecificActions(nextAnnotations);
|
const annotationWasResized = this._annotationManager.resizingAnnotationId && action === 'modify';
|
||||||
|
if (!this._annotationManager.resizingAnnotationId || annotationWasResized) {
|
||||||
|
this.#configureAnnotationSpecificActions(nextAnnotations);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(annotations.length === 1 && annotations[0].ReadOnly)) {
|
if (!(annotations.length === 1 && annotations[0].ReadOnly)) {
|
||||||
this._pdf.enable(TextPopups.ADD_RECTANGLE);
|
this._pdf.enable(TextPopups.ADD_RECTANGLE);
|
||||||
@ -344,7 +347,6 @@ export class PdfProxyService {
|
|||||||
// which is automatically converted to redaction when resized,
|
// which is automatically converted to redaction when resized,
|
||||||
// so the original annotation(wrapper) is removed
|
// so the original annotation(wrapper) is removed
|
||||||
this._annotationManager.resizingAnnotationId = undefined;
|
this._annotationManager.resizingAnnotationId = undefined;
|
||||||
this._annotationManager.resizingHasStarted = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,20 +361,20 @@ export class PdfProxyService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#configureAnnotationSpecificActions(viewerAnnotations: Annotation[]) {
|
#configureAnnotationSpecificActions(viewerAnnotations: Annotation[]) {
|
||||||
|
this._pdf.resetAnnotationActions();
|
||||||
|
|
||||||
if (!this.canPerformActions()) {
|
if (!this.canPerformActions()) {
|
||||||
return this._pdf.resetAnnotationActions();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const annotationWrappers = viewerAnnotations.map(va => this._fileDataService.find(va.Id)).filter(va => !!va);
|
const annotationWrappers = viewerAnnotations.map(va => this._fileDataService.find(va.Id)).filter(va => !!va);
|
||||||
this._pdf.resetAnnotationActions();
|
|
||||||
|
|
||||||
if (annotationWrappers.length === 0) {
|
if (annotationWrappers.length === 0) {
|
||||||
return this.#configureRectangleAnnotationPopup(viewerAnnotations[0]);
|
return this.#configureRectangleAnnotationPopup(viewerAnnotations[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add hide action as last item
|
// Add hide action as last item
|
||||||
const allAnnotationsHaveImageAction = annotationWrappers.reduce((acc, next) => acc && next.isImage, true);
|
const allAreImage = annotationWrappers.reduce((acc, next) => acc && next.isImage, true);
|
||||||
if (allAnnotationsHaveImageAction) {
|
if (allAreImage && !this._annotationManager.resizingAnnotationId) {
|
||||||
const allAreVisible = viewerAnnotations.reduce((acc, next) => next.isVisible() && acc, true);
|
const allAreVisible = viewerAnnotations.reduce((acc, next) => next.isVisible() && acc, true);
|
||||||
|
|
||||||
const visibilityButton = {
|
const visibilityButton = {
|
||||||
|
|||||||
@ -4,8 +4,6 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
|||||||
import { Core } from '@pdftron/webviewer';
|
import { Core } from '@pdftron/webviewer';
|
||||||
import { IRectangle, ISectionRectangle, SuperTypes } from '@red/domain';
|
import { IRectangle, ISectionRectangle, SuperTypes } from '@red/domain';
|
||||||
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
||||||
import { RedactionLogService } from '@services/files/redaction-log.service';
|
|
||||||
import { UserPreferenceService } from '@users/user-preference.service';
|
|
||||||
import { hexToRgb } from '@utils/functions';
|
import { hexToRgb } from '@utils/functions';
|
||||||
import { BoundingBox, Table } from '../../file-preview/services/tables.service';
|
import { BoundingBox, Table } from '../../file-preview/services/tables.service';
|
||||||
import { REDAnnotationManager } from './annotation-manager.service';
|
import { REDAnnotationManager } from './annotation-manager.service';
|
||||||
@ -31,8 +29,6 @@ export function getSectionRectangle(box: BoundingBox): ISectionRectangle {
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class AnnotationDrawService {
|
export class AnnotationDrawService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _redactionLogService: RedactionLogService,
|
|
||||||
private readonly _userPreferenceService: UserPreferenceService,
|
|
||||||
private readonly _annotationManager: REDAnnotationManager,
|
private readonly _annotationManager: REDAnnotationManager,
|
||||||
private readonly _pdf: PdfViewer,
|
private readonly _pdf: PdfViewer,
|
||||||
private readonly _documentViewer: REDDocumentViewer,
|
private readonly _documentViewer: REDDocumentViewer,
|
||||||
@ -41,7 +37,7 @@ export class AnnotationDrawService {
|
|||||||
|
|
||||||
async draw(annotations: List<AnnotationWrapper>, hideSkipped: boolean, dossierTemplateId: string) {
|
async draw(annotations: List<AnnotationWrapper>, hideSkipped: boolean, dossierTemplateId: string) {
|
||||||
try {
|
try {
|
||||||
return this._pdf.runWithCleanup(() => this._draw(annotations, hideSkipped, dossierTemplateId));
|
return this._pdf.runWithCleanup(() => this.#draw(annotations, hideSkipped, dossierTemplateId));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
@ -70,7 +66,7 @@ export class AnnotationDrawService {
|
|||||||
async drawTables(tables: Table[], page: number, dossierTemplateId: string) {
|
async drawTables(tables: Table[], page: number, dossierTemplateId: string) {
|
||||||
const sections: Core.Annotations.RectangleAnnotation[] = [];
|
const sections: Core.Annotations.RectangleAnnotation[] = [];
|
||||||
tables.forEach(table => {
|
tables.forEach(table => {
|
||||||
const section = this._computeSection(page, getSectionRectangle(table.boundingBox), dossierTemplateId);
|
const section = this.#computeSection(page, getSectionRectangle(table.boundingBox), dossierTemplateId);
|
||||||
if (table.experimental) {
|
if (table.experimental) {
|
||||||
section.StrokeColor = this.convertColor('#800080');
|
section.StrokeColor = this.convertColor('#800080');
|
||||||
} else {
|
} else {
|
||||||
@ -80,7 +76,7 @@ export class AnnotationDrawService {
|
|||||||
table.cellsPerRow
|
table.cellsPerRow
|
||||||
.flatMap(row => row)
|
.flatMap(row => row)
|
||||||
.forEach(row => {
|
.forEach(row => {
|
||||||
const cellSection = this._computeSection(page, getSectionRectangle(row.boundingBox), dossierTemplateId);
|
const cellSection = this.#computeSection(page, getSectionRectangle(row.boundingBox), dossierTemplateId);
|
||||||
if (table.experimental) {
|
if (table.experimental) {
|
||||||
cellSection.StrokeColor = this.convertColor('#800080');
|
cellSection.StrokeColor = this.convertColor('#800080');
|
||||||
} else {
|
} else {
|
||||||
@ -93,10 +89,10 @@ export class AnnotationDrawService {
|
|||||||
await this._annotationManager.add(sections);
|
await this._annotationManager.add(sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _draw(annotationWrappers: List<AnnotationWrapper>, hideSkipped: boolean, dossierTemplateId: string) {
|
async #draw(annotationWrappers: List<AnnotationWrapper>, hideSkipped: boolean, dossierTemplateId: string) {
|
||||||
const totalPages = this._pdf.totalPages();
|
const totalPages = this._pdf.totalPages();
|
||||||
const annotations = annotationWrappers
|
const annotations = annotationWrappers
|
||||||
?.map(annotation => this._computeAnnotation(annotation, hideSkipped, totalPages, dossierTemplateId))
|
?.map(annotation => this.#computeAnnotation(annotation, hideSkipped, totalPages, dossierTemplateId))
|
||||||
.filterTruthy();
|
.filterTruthy();
|
||||||
if (!this._documentViewer.loaded()) {
|
if (!this._documentViewer.loaded()) {
|
||||||
return;
|
return;
|
||||||
@ -104,7 +100,7 @@ export class AnnotationDrawService {
|
|||||||
await this._annotationManager.add(annotations);
|
await this._annotationManager.add(annotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeSection(pageNumber: number, sectionRectangle: ISectionRectangle, dossierTemplateId: string) {
|
#computeSection(pageNumber: number, sectionRectangle: ISectionRectangle, dossierTemplateId: string) {
|
||||||
const rectangleAnnot = this._pdf.rectangle();
|
const rectangleAnnot = this._pdf.rectangle();
|
||||||
const pageHeight = this._documentViewer.getHeight(pageNumber);
|
const pageHeight = this._documentViewer.getHeight(pageNumber);
|
||||||
const rectangle: IRectangle = {
|
const rectangle: IRectangle = {
|
||||||
@ -125,7 +121,7 @@ export class AnnotationDrawService {
|
|||||||
return rectangleAnnot;
|
return rectangleAnnot;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeAnnotation(annotationWrapper: AnnotationWrapper, hideSkipped: boolean, totalPages: number, dossierTemplateId: string) {
|
#computeAnnotation(annotationWrapper: AnnotationWrapper, hideSkipped: boolean, totalPages: number, dossierTemplateId: string) {
|
||||||
const pageNumber = this._pdf.isCompareMode() ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber;
|
const pageNumber = this._pdf.isCompareMode() ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber;
|
||||||
if (pageNumber > totalPages) {
|
if (pageNumber > totalPages) {
|
||||||
// skip imported annotations from files that have more pages than the current one
|
// skip imported annotations from files that have more pages than the current one
|
||||||
@ -150,7 +146,7 @@ export class AnnotationDrawService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const annotation = this._pdf.textHighlight();
|
const annotation = this._pdf.textHighlight();
|
||||||
annotation.Quads = this._rectanglesToQuads(annotationWrapper.positions, pageNumber);
|
annotation.Quads = this.#rectanglesToQuads(annotationWrapper.positions, pageNumber);
|
||||||
annotation.Opacity = annotationWrapper.isChangeLogRemoved ? DEFAULT_REMOVED_ANNOTATION_OPACITY : DEFAULT_TEXT_ANNOTATION_OPACITY;
|
annotation.Opacity = annotationWrapper.isChangeLogRemoved ? DEFAULT_REMOVED_ANNOTATION_OPACITY : DEFAULT_TEXT_ANNOTATION_OPACITY;
|
||||||
annotation.setContents(annotationWrapper.content);
|
annotation.setContents(annotationWrapper.content);
|
||||||
annotation.PageNumber = pageNumber;
|
annotation.PageNumber = pageNumber;
|
||||||
@ -190,12 +186,12 @@ export class AnnotationDrawService {
|
|||||||
return annotation;
|
return annotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _rectanglesToQuads(positions: IRectangle[], pageNumber: number): Quad[] {
|
#rectanglesToQuads(positions: IRectangle[], pageNumber: number): Quad[] {
|
||||||
const pageHeight = this._documentViewer.getHeight(pageNumber);
|
const pageHeight = this._documentViewer.getHeight(pageNumber);
|
||||||
return positions.map(p => this._rectangleToQuad(p, pageHeight));
|
return positions.map(p => this.#rectangleToQuad(p, pageHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _rectangleToQuad(rectangle: IRectangle, pageHeight: number): Quad {
|
#rectangleToQuad(rectangle: IRectangle, pageHeight: number): Quad {
|
||||||
const x1 = rectangle.topLeft.x;
|
const x1 = rectangle.topLeft.x;
|
||||||
const y1 = pageHeight - (rectangle.topLeft.y + rectangle.height);
|
const y1 = pageHeight - (rectangle.topLeft.y + rectangle.height);
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import { inject, 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 type { List } from '@iqser/common-ui/lib/utils';
|
||||||
import { AnnotationPredicate, DeleteAnnotationsOptions } from '../utils/types';
|
|
||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
import { Subject } from 'rxjs';
|
import { Core } from '@pdftron/webviewer';
|
||||||
import { asList, getId, isStringOrWrapper } from '../utils/functions';
|
|
||||||
import { getLast } from '@utils/functions';
|
import { getLast } from '@utils/functions';
|
||||||
import { AnnotationToolNames } from '../utils/constants';
|
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { AnnotationToolNames } from '../utils/constants';
|
||||||
|
import { asList, getId, isStringOrWrapper } from '../utils/functions';
|
||||||
|
import { AnnotationPredicate, DeleteAnnotationsOptions } from '../utils/types';
|
||||||
import AnnotationManager = Core.AnnotationManager;
|
import AnnotationManager = Core.AnnotationManager;
|
||||||
import Annotation = Core.Annotations.Annotation;
|
import Annotation = Core.Annotations.Annotation;
|
||||||
|
|
||||||
@ -19,7 +19,6 @@ export class REDAnnotationManager {
|
|||||||
readonly #annotationSelected$ = new Subject<[Annotation[], string]>();
|
readonly #annotationSelected$ = new Subject<[Annotation[], string]>();
|
||||||
readonly annotationSelected$ = this.#annotationSelected$.asObservable();
|
readonly annotationSelected$ = this.#annotationSelected$.asObservable();
|
||||||
resizingAnnotationId?: string = undefined;
|
resizingAnnotationId?: string = undefined;
|
||||||
resizingHasStarted = false;
|
|
||||||
readonly hidden = this.#hidden.asReadonly();
|
readonly hidden = this.#hidden.asReadonly();
|
||||||
|
|
||||||
get selected() {
|
get selected() {
|
||||||
@ -141,14 +140,12 @@ export class REDAnnotationManager {
|
|||||||
// when a rectangle is drawn,
|
// when a rectangle is drawn,
|
||||||
// it returns one annotation with tool name 'AnnotationCreateRectangle;
|
// it returns one annotation with tool name 'AnnotationCreateRectangle;
|
||||||
// this will auto select rectangle after drawing
|
// this will auto select rectangle after drawing
|
||||||
if (annotations.length === 1 && annotations[0].ToolName === AnnotationToolNames.AnnotationCreateRectangle) {
|
const annotation = annotations.length === 1 ? annotations[0] : undefined;
|
||||||
this.#manager.selectAnnotations(annotations);
|
if (annotation && annotation.ToolName === AnnotationToolNames.AnnotationCreateRectangle) {
|
||||||
annotations[0].disableRotationControl();
|
this.#manager.selectAnnotation(annotation);
|
||||||
}
|
annotation.disableRotationControl();
|
||||||
if (action === 'modify' && options.source === 'resize' && !this.resizingHasStarted) {
|
|
||||||
this.resizingHasStarted = true;
|
|
||||||
this.#annotationSelected$.next([annotations, action]);
|
|
||||||
}
|
}
|
||||||
|
this.#annotationSelected$.next([annotations, action]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
import { effect, inject, Injectable, Signal, signal } from '@angular/core';
|
import { effect, inject, Injectable, Signal, signal } from '@angular/core';
|
||||||
|
import { toObservable } from '@angular/core/rxjs-interop';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { log } from '@iqser/common-ui/lib/utils';
|
||||||
import { Core } from '@pdftron/webviewer';
|
import { Core } from '@pdftron/webviewer';
|
||||||
|
import { RotationType, RotationTypes } from '@red/domain';
|
||||||
|
import { UserPreferenceService } from '@users/user-preference.service';
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
import { BehaviorSubject, fromEvent, Observable } from 'rxjs';
|
import { BehaviorSubject, fromEvent, Observable } from 'rxjs';
|
||||||
import { filter, tap } from 'rxjs/operators';
|
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/lib/utils';
|
|
||||||
import { stopAndPrevent, stopAndPreventIfNotAllowed } from '../utils/functions';
|
|
||||||
import { RotationType, RotationTypes } from '@red/domain';
|
|
||||||
import { AnnotationToolNames } from '../utils/constants';
|
import { AnnotationToolNames } from '../utils/constants';
|
||||||
import { toObservable } from '@angular/core/rxjs-interop';
|
import { stopAndPrevent, stopAndPreventIfNotAllowed } from '../utils/functions';
|
||||||
import DocumentViewer = Core.DocumentViewer;
|
import { PdfViewer } from './pdf-viewer.service';
|
||||||
import Color = Core.Annotations.Color;
|
import Color = Core.Annotations.Color;
|
||||||
|
import DocumentViewer = Core.DocumentViewer;
|
||||||
import Quad = Core.Math.Quad;
|
import Quad = Core.Math.Quad;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|||||||
@ -1,26 +1,26 @@
|
|||||||
import { DestroyRef, inject, Injectable, signal, Signal } from '@angular/core';
|
import { DestroyRef, inject, Injectable, signal, Signal } from '@angular/core';
|
||||||
import WebViewer, { Core, WebViewerInstance, WebViewerOptions } from '@pdftron/webviewer';
|
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
|
||||||
import { ErrorService, getConfig } from '@iqser/common-ui';
|
|
||||||
import { AppConfig, File, IHeaderElement } from '@red/domain';
|
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { map, startWith } from 'rxjs/operators';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { combineLatest, fromEvent, Observable } from 'rxjs';
|
import { environment } from '@environments/environment';
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { ErrorService, getConfig } from '@iqser/common-ui';
|
||||||
import { DISABLED_HOTKEYS, DOCUMENT_LOADING_ERROR, SEARCH_OPTIONS, USELESS_ELEMENTS } from '../utils/constants';
|
import { BASE_HREF_FN, shareDistinctLast } from '@iqser/common-ui/lib/utils';
|
||||||
import { Rgb } from '../utils/types';
|
|
||||||
import { asList } from '../utils/functions';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import WebViewer, { Core, WebViewerInstance, WebViewerOptions } from '@pdftron/webviewer';
|
||||||
|
import { AppConfig, File, IHeaderElement } from '@red/domain';
|
||||||
import { LicenseService } from '@services/license.service';
|
import { LicenseService } from '@services/license.service';
|
||||||
import { UserPreferenceService } from '@users/user-preference.service';
|
import { UserPreferenceService } from '@users/user-preference.service';
|
||||||
import { environment } from '@environments/environment';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
|
import { combineLatest, fromEvent, Observable } from 'rxjs';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { map, startWith } from 'rxjs/operators';
|
||||||
import { BASE_HREF_FN, shareDistinctLast } from '@iqser/common-ui/lib/utils';
|
import { DISABLED_HOTKEYS, DOCUMENT_LOADING_ERROR, SEARCH_OPTIONS, USELESS_ELEMENTS } from '../utils/constants';
|
||||||
import TextTool = Core.Tools.TextTool;
|
import { asList } from '../utils/functions';
|
||||||
|
import { Rgb } from '../utils/types';
|
||||||
import Annotation = Core.Annotations.Annotation;
|
import Annotation = Core.Annotations.Annotation;
|
||||||
import TextHighlightAnnotation = Core.Annotations.TextHighlightAnnotation;
|
import TextHighlightAnnotation = Core.Annotations.TextHighlightAnnotation;
|
||||||
import DocumentViewer = Core.DocumentViewer;
|
import DocumentViewer = Core.DocumentViewer;
|
||||||
import Quad = Core.Math.Quad;
|
import Quad = Core.Math.Quad;
|
||||||
|
import TextTool = Core.Tools.TextTool;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PdfViewer {
|
export class PdfViewer {
|
||||||
@ -40,6 +40,7 @@ export class PdfViewer {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
readonly #destroyRef = inject(DestroyRef);
|
readonly #destroyRef = inject(DestroyRef);
|
||||||
|
readonly #logger = inject(NGXLogger);
|
||||||
readonly #totalPages = signal<number>(0);
|
readonly #totalPages = signal<number>(0);
|
||||||
readonly currentPage$ = inject(ActivatedRoute).queryParamMap.pipe(
|
readonly currentPage$ = inject(ActivatedRoute).queryParamMap.pipe(
|
||||||
map(params => Number(params.get('page') ?? '1')),
|
map(params => Number(params.get('page') ?? '1')),
|
||||||
@ -118,6 +119,7 @@ export class PdfViewer {
|
|||||||
|
|
||||||
resetAnnotationActions() {
|
resetAnnotationActions() {
|
||||||
if (this.#instance.UI.annotationPopup.getItems().length) {
|
if (this.#instance.UI.annotationPopup.getItems().length) {
|
||||||
|
this.#logger.info('[PDF] Reset annotation actions');
|
||||||
this.#instance.UI.annotationPopup.update([]);
|
this.#instance.UI.annotationPopup.update([]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<svg fill="currentColor" id="ReadactManager_symbol_positive"
|
<svg fill="#dd4d50" id="ReadactManager_symbol_positive"
|
||||||
version="1.1" viewBox="0 0 119.476 121.277" x="0px" xml:space="preserve"
|
version="1.1" viewBox="0 0 119.476 121.277" x="0px" xml:space="preserve"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
y="0px">
|
y="0px">
|
||||||
@ -8,5 +8,5 @@
|
|||||||
s-1.904-4.254-4.254-4.254H28.843H15.793H4.254C1.904,73.401,0,71.496,0,69.146c0-2.349,1.904-4.254,4.254-4.254h24.59h41.062
|
s-1.904-4.254-4.254-4.254H28.843H15.793H4.254C1.904,73.401,0,71.496,0,69.146c0-2.349,1.904-4.254,4.254-4.254h24.59h41.062
|
||||||
c2.349,0,4.255-1.904,4.255-4.254s-1.906-4.254-4.255-4.254H28.843H4.254C1.904,56.385,0,54.48,0,52.13
|
c2.349,0,4.255-1.904,4.255-4.254s-1.906-4.254-4.255-4.254H28.843H4.254C1.904,56.385,0,54.48,0,52.13
|
||||||
c0-2.349,1.904-4.254,4.254-4.254h11.539h13.051H52.6c2.349,0,4.254-1.905,4.254-4.254c0-2.35-1.904-4.254-4.254-4.254H28.843
|
c0-2.349,1.904-4.254,4.254-4.254h11.539h13.051H52.6c2.349,0,4.254-1.905,4.254-4.254c0-2.35-1.904-4.254-4.254-4.254H28.843
|
||||||
h-7.283c-2.349,0-4.254-1.905-4.254-4.254c0-2.349,1.904-4.254,4.254-4.254h7.283V14.712C59.063,14.712,74.16,0,74.16,0z" />
|
h-7.283c-2.349,0-4.254-1.905-4.254-4.254c0-2.349,1.904-4.254,4.254-4.254h7.283V14.712C59.063,14.712,74.16,0,74.16,0z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 948 B After Width: | Height: | Size: 942 B |
@ -1 +1 @@
|
|||||||
Subproject commit c9abddb3017082bb169ef6da2c1a63b0b3cdf837
|
Subproject commit 21d387912ca7788f4dc9675edca1c0cdc40e8bac
|
||||||
Loading…
x
Reference in New Issue
Block a user