Merge branch 'master' into VM/RED-3687
This commit is contained in:
commit
d5701669ca
@ -1,37 +0,0 @@
|
||||
<div class="container" *ngIf="watermarks$ | async as watermarks">
|
||||
<div class="iqser-input-group watermark">
|
||||
<mat-checkbox color="primary" [checked]="!!watermarkId" (change)="toggleWatermarkSelection($event.checked, documentTypes.REDACTED)">
|
||||
{{ 'dossier-watermark-selector.watermark' | translate }}
|
||||
</mat-checkbox>
|
||||
<mat-select *ngIf="!!watermarkId" [(value)]="watermarkId" (selectionChange)="emitNewValues()">
|
||||
<mat-select-trigger>
|
||||
<mat-icon svgIcon="red:warning" *ngIf="!selectedWatermark(watermarkId, watermarks).enabled"></mat-icon>
|
||||
<span> {{ selectedWatermark(watermarkId, watermarks).name }} </span>
|
||||
</mat-select-trigger>
|
||||
<mat-option *ngFor="let watermark of watermarks" [value]="watermark.id" [disabled]="!watermark.enabled">
|
||||
<mat-icon svgIcon="red:warning" *ngIf="!watermark.enabled"></mat-icon>
|
||||
{{ watermark.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
|
||||
<div class="iqser-input-group watermark">
|
||||
<mat-checkbox
|
||||
color="primary"
|
||||
[checked]="!!previewWatermarkId"
|
||||
(change)="toggleWatermarkSelection($event.checked, documentTypes.PREVIEW)"
|
||||
>
|
||||
{{ 'dossier-watermark-selector.preview' | translate }}
|
||||
</mat-checkbox>
|
||||
<mat-select *ngIf="!!previewWatermarkId" [(value)]="previewWatermarkId" (selectionChange)="emitNewValues()">
|
||||
<mat-select-trigger>
|
||||
<mat-icon svgIcon="red:warning" *ngIf="!selectedWatermark(previewWatermarkId, watermarks).enabled"></mat-icon>
|
||||
<span> {{ selectedWatermark(previewWatermarkId, watermarks).name }} </span>
|
||||
</mat-select-trigger>
|
||||
<mat-option *ngFor="let watermark of watermarks" [value]="watermark.id">
|
||||
<mat-icon svgIcon="red:warning" *ngIf="!watermark.enabled"></mat-icon>
|
||||
{{ watermark.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,82 +0,0 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { IWatermark } from '@red/domain';
|
||||
import { WatermarkService } from '@services/entity-services/watermark.service';
|
||||
import { mapEach, Required } from '@iqser/common-ui';
|
||||
import { OptionWatermark } from '@components/dossier-watermark-selector/option-watermark.model';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
|
||||
const DocumentTypes = {
|
||||
REDACTED: 'REDACTED',
|
||||
PREVIEW: 'PREVIEW',
|
||||
} as const;
|
||||
type DocumentType = keyof typeof DocumentTypes;
|
||||
|
||||
export interface UpdateWatermarkIdsEvent {
|
||||
watermarkId: string | null;
|
||||
previewWatermarkId: string | null;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-watermark-selector',
|
||||
templateUrl: './dossier-watermark-selector.component.html',
|
||||
styleUrls: ['./dossier-watermark-selector.component.scss'],
|
||||
})
|
||||
export class DossierWatermarkSelectorComponent implements OnInit {
|
||||
@Input() @Required() dossierTemplateId!: string;
|
||||
@Input() watermarkId: string | null;
|
||||
@Input() previewWatermarkId: string | null;
|
||||
@Output() readonly idsUpdate = new EventEmitter<UpdateWatermarkIdsEvent>();
|
||||
watermarks$: Observable<OptionWatermark[]>;
|
||||
readonly documentTypes = DocumentTypes;
|
||||
#oldWatermarkId: string | null;
|
||||
#oldPreviewWatermarkId: string | null;
|
||||
|
||||
constructor(private readonly _watermarkService: WatermarkService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.watermarks$ = this._watermarkService.getWatermarks(this.dossierTemplateId).pipe(
|
||||
map((watermarks: IWatermark[]) => watermarks.sort(this.sortByStatusFn)),
|
||||
mapEach((watermark: IWatermark) => new OptionWatermark(watermark)),
|
||||
tap((watermarks: OptionWatermark[]) => (this.#oldWatermarkId = watermarks[0].id)),
|
||||
tap((watermarks: OptionWatermark[]) => (this.#oldPreviewWatermarkId = watermarks[0].id)),
|
||||
);
|
||||
}
|
||||
|
||||
sortByStatusFn = (a, b) => {
|
||||
if (a.enabled === b.enabled) {
|
||||
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
||||
}
|
||||
return a.enabled ? -1 : 1;
|
||||
};
|
||||
|
||||
toggleWatermarkSelection(checked: boolean, documentType: DocumentType): void {
|
||||
if (checked) {
|
||||
if (documentType === DocumentTypes.REDACTED) {
|
||||
this.watermarkId = this.#oldWatermarkId;
|
||||
} else {
|
||||
this.previewWatermarkId = this.#oldPreviewWatermarkId;
|
||||
}
|
||||
} else {
|
||||
if (documentType === DocumentTypes.REDACTED) {
|
||||
this.#oldWatermarkId = this.watermarkId;
|
||||
this.watermarkId = null;
|
||||
} else {
|
||||
this.#oldPreviewWatermarkId = this.previewWatermarkId;
|
||||
this.previewWatermarkId = null;
|
||||
}
|
||||
}
|
||||
this.emitNewValues();
|
||||
}
|
||||
|
||||
emitNewValues(): void {
|
||||
this.idsUpdate.emit({
|
||||
watermarkId: this.watermarkId,
|
||||
previewWatermarkId: this.previewWatermarkId,
|
||||
});
|
||||
}
|
||||
|
||||
selectedWatermark(id: string, watermarks: OptionWatermark[]): OptionWatermark {
|
||||
return watermarks.find(watermark => watermark.id === id);
|
||||
}
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
import { IWatermark } from '@red/domain';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
|
||||
export class OptionWatermark {
|
||||
id!: string;
|
||||
name!: string;
|
||||
enabled!: boolean;
|
||||
|
||||
constructor(watermark: IWatermark) {
|
||||
this.id = watermark.id;
|
||||
this.name = watermark.enabled ? watermark.name : `${_('disabled')} - ${watermark.name}`;
|
||||
this.enabled = watermark.enabled;
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ import { FilesService } from '@services/files/files.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DOSSIER_ID, DOSSIER_TEMPLATE_ID } from '@red/domain';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class DossierFilesGuard implements CanActivate {
|
||||
@ -12,6 +13,7 @@ export class DossierFilesGuard implements CanActivate {
|
||||
private readonly _injector: Injector,
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _filesService: FilesService,
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
private readonly _router: Router,
|
||||
) {}
|
||||
|
||||
@ -21,6 +23,8 @@ export class DossierFilesGuard implements CanActivate {
|
||||
const token: ProviderToken<DossiersService> = route.data.dossiersService;
|
||||
const dossiersService: DossiersService = this._injector.get<DossiersService>(token);
|
||||
|
||||
await firstValueFrom(this._dictionaryService.loadDossierDictionary(dossierTemplateId, dossierId));
|
||||
|
||||
if (!dossiersService.has(dossierId)) {
|
||||
await this._router.navigate(['/main', dossierTemplateId]);
|
||||
return false;
|
||||
|
||||
21
apps/red-ui/src/app/guards/watermark-exists.guard.ts
Normal file
21
apps/red-ui/src/app/guards/watermark-exists.guard.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
|
||||
import { WatermarksMapService } from '@services/entity-services/watermarks-map.service';
|
||||
import { DOSSIER_TEMPLATE_ID, WATERMARK_ID } from '@red/domain';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class WatermarkExistsGuard implements CanActivate {
|
||||
constructor(private readonly _watermarksMapService: WatermarksMapService, private readonly _router: Router) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
|
||||
const dossierTemplateId = route.parent.paramMap.get(DOSSIER_TEMPLATE_ID);
|
||||
const watermarkId = route.paramMap.get(WATERMARK_ID);
|
||||
|
||||
if (this._watermarksMapService.get(dossierTemplateId, watermarkId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
await this._router.navigate(['main', 'admin', 'dossier-templates', dossierTemplateId, 'watermarks']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -15,14 +15,12 @@ import { GeneralConfigScreenComponent } from './screens/general-config/general-c
|
||||
import { BaseAdminScreenComponent } from './base-admin-screen/base-admin-screen.component';
|
||||
import { BaseDossierTemplateScreenComponent } from './base-dossier-templates-screen/base-dossier-template-screen.component';
|
||||
import { DossierTemplatesGuard } from '@guards/dossier-templates.guard';
|
||||
import { DOSSIER_TEMPLATE_ID, ENTITY_TYPE, WATERMARK_ID } from '@red/domain';
|
||||
import { DOSSIER_TEMPLATE_ID, ENTITY_TYPE } from '@red/domain';
|
||||
import { DossierTemplateExistsGuard } from '@guards/dossier-template-exists.guard';
|
||||
import { EntityExistsGuard } from '@guards/entity-exists-guard.service';
|
||||
import { DossierStatesListingScreenComponent } from './screens/dossier-states-listing/dossier-states-listing-screen.component';
|
||||
import { BaseEntityScreenComponent } from './base-entity-screen/base-entity-screen.component';
|
||||
import { PermissionsGuard } from '../../guards/permissions-guard';
|
||||
import { WatermarksListingScreenComponent } from './screens/watermarks-listing/watermarks-listing-screen.component';
|
||||
import { BaseWatermarkScreenComponent } from './base-watermark-screen/base-watermark-screen.component';
|
||||
import { PermissionsGuard } from '@guards/permissions-guard';
|
||||
|
||||
const dossierTemplateIdRoutes: Routes = [
|
||||
{
|
||||
@ -72,25 +70,8 @@ const dossierTemplateIdRoutes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'watermarks',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: WatermarksListingScreenComponent,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: `:${WATERMARK_ID}`,
|
||||
component: BaseWatermarkScreenComponent,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
loadChildren: () => import('./screens/watermark/watermark.module').then(m => m.WatermarkModule),
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard],
|
||||
},
|
||||
},
|
||||
],
|
||||
component: BaseDossierTemplateScreenComponent,
|
||||
loadChildren: () => import('./screens/watermark/watermark.module').then(m => m.WatermarkModule),
|
||||
},
|
||||
{
|
||||
path: 'reports',
|
||||
|
||||
@ -45,8 +45,6 @@ import { SystemPreferencesFormComponent } from './screens/general-config/system-
|
||||
import { ConfigureCertificateDialogComponent } from './dialogs/configure-digital-signature-dialog/configure-certificate-dialog.component';
|
||||
import { PkcsSignatureConfigurationComponent } from './dialogs/configure-digital-signature-dialog/form/pkcs-signature-configuration/pkcs-signature-configuration.component';
|
||||
import { KmsSignatureConfigurationComponent } from './dialogs/configure-digital-signature-dialog/form/kms-signature-configuration/kms-signature-configuration.component';
|
||||
import { WatermarksListingScreenComponent } from './screens/watermarks-listing/watermarks-listing-screen.component';
|
||||
import { BaseWatermarkScreenComponent } from './base-watermark-screen/base-watermark-screen.component';
|
||||
|
||||
const dialogs = [
|
||||
AddEditCloneDossierTemplateDialogComponent,
|
||||
@ -74,7 +72,6 @@ const screens = [
|
||||
GeneralConfigScreenComponent,
|
||||
DossierAttributesListingScreenComponent,
|
||||
DossierStatesListingScreenComponent,
|
||||
WatermarksListingScreenComponent,
|
||||
];
|
||||
|
||||
const components = [
|
||||
@ -87,7 +84,6 @@ const components = [
|
||||
BaseAdminScreenComponent,
|
||||
BaseDossierTemplateScreenComponent,
|
||||
BaseEntityScreenComponent,
|
||||
BaseWatermarkScreenComponent,
|
||||
GeneralConfigFormComponent,
|
||||
SmtpFormComponent,
|
||||
SystemPreferencesFormComponent,
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
<section>
|
||||
<div class="page-header">
|
||||
<redaction-dossier-template-breadcrumbs class="flex-1"></redaction-dossier-template-breadcrumbs>
|
||||
|
||||
<div class="flex-1 actions">
|
||||
<iqser-circle-button
|
||||
*ngIf="editMode"
|
||||
(action)="openDeleteWatermarkDialog($event)"
|
||||
[tooltip]="'watermarks-listing.action.delete' | translate"
|
||||
icon="iqser:trash"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
[routerLink]="['../../watermarks']"
|
||||
[tooltip]="'common.close' | translate"
|
||||
icon="iqser:close"
|
||||
tooltipPosition="below"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-inner">
|
||||
<div class="overlay-shadow"></div>
|
||||
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</section>
|
||||
@ -1,53 +0,0 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { AdminDialogService } from '../services/admin-dialog.service';
|
||||
import { ConfirmationDialogInput, getParam, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { WatermarkService } from '../../../services/entity-services/watermark.service';
|
||||
import { DOSSIER_TEMPLATE_ID, WATERMARK_ID } from '@red/domain';
|
||||
import { Router } from '@angular/router';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
|
||||
@Component({
|
||||
templateUrl: './base-watermark-screen.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class BaseWatermarkScreenComponent {
|
||||
readonly #dossierTemplateId: string = getParam(DOSSIER_TEMPLATE_ID);
|
||||
readonly #watermarkId: string = getParam(WATERMARK_ID);
|
||||
|
||||
constructor(
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _watermarkService: WatermarkService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _router: Router,
|
||||
) {}
|
||||
|
||||
get editMode(): boolean {
|
||||
return !!Number(this.#watermarkId);
|
||||
}
|
||||
|
||||
async openDeleteWatermarkDialog($event: MouseEvent): Promise<void> {
|
||||
const isUsed = await firstValueFrom(this._watermarkService.isWatermarkUsed(this.#watermarkId));
|
||||
|
||||
if (!isUsed) {
|
||||
await this._deleteWatermark(this.#watermarkId);
|
||||
return;
|
||||
}
|
||||
|
||||
const data = new ConfirmationDialogInput({
|
||||
question: _('watermarks-listing.watermark-is-used'),
|
||||
});
|
||||
this._dialogService.openDialog('confirm', $event, data, async () => {
|
||||
await this._deleteWatermark(this.#watermarkId);
|
||||
});
|
||||
}
|
||||
|
||||
private async _deleteWatermark(watermarkId: string): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._watermarkService.deleteWatermark(watermarkId));
|
||||
this._toaster.success(_('watermarks-listing.action.delete-success'));
|
||||
await this._router.navigate([`/main/admin/dossier-templates/${this.#dossierTemplateId}/watermarks`]);
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
@ -52,7 +52,7 @@
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="delete()"
|
||||
*ngIf="user && user.id !== userService.currentUser.id"
|
||||
*ngIf="!disabledDelete(user)"
|
||||
[label]="'add-edit-user.actions.delete' | translate"
|
||||
[type]="iconButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
|
||||
@ -33,7 +33,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
readonly userService: UserService,
|
||||
private readonly _userService: UserService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@ -68,12 +68,12 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
||||
}
|
||||
|
||||
shouldBeDisabled(role: string): boolean {
|
||||
const isCurrentAdminUser = this.user && this.user.isAdmin && this.user.id === this.userService.currentUser.id;
|
||||
const isCurrentAdminUser = this.user && this.user.isAdmin && this.user.id === this._userService.currentUser.id;
|
||||
return (
|
||||
// RED_ADMIN can't remove own RED_ADMIN role
|
||||
(role === 'RED_ADMIN' && isCurrentAdminUser) ||
|
||||
// only RED_ADMINs can edit RED_ADMIN roles
|
||||
(role === 'RED_ADMIN' && !this.userService.currentUser.isAdmin) ||
|
||||
(role === 'RED_ADMIN' && !this._userService.currentUser.isAdmin) ||
|
||||
Object.keys(this._ROLE_REQUIREMENTS).reduce(
|
||||
(value, key) => value || (role === this._ROLE_REQUIREMENTS[key] && this.user?.roles.includes(key)),
|
||||
false,
|
||||
@ -86,7 +86,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
||||
const userData: IProfileUpdateRequest = { ...this.form.getRawValue(), roles: this.activeRoles };
|
||||
|
||||
if (!this.user) {
|
||||
await firstValueFrom(this.userService.create(userData))
|
||||
await firstValueFrom(this._userService.create(userData))
|
||||
.then(() => {
|
||||
this.closeDialog.emit(true);
|
||||
})
|
||||
@ -99,7 +99,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
||||
this._loadingService.stop();
|
||||
});
|
||||
} else {
|
||||
await firstValueFrom(this.userService.updateProfile(userData, this.user.id));
|
||||
await firstValueFrom(this._userService.updateProfile(userData, this.user.id));
|
||||
this.closeDialog.emit(true);
|
||||
}
|
||||
}
|
||||
@ -119,6 +119,12 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
||||
}
|
||||
}
|
||||
|
||||
disabledDelete(user: User): boolean {
|
||||
const userAdmin = user.roles.includes('RED_ADMIN');
|
||||
const currentUserAdmin = this._userService.currentUser.roles.includes('RED_ADMIN');
|
||||
return user.id === this._userService.currentUser.id || (userAdmin && !currentUserAdmin);
|
||||
}
|
||||
|
||||
private _getForm(): UntypedFormGroup {
|
||||
return this._formBuilder.group({
|
||||
firstName: [this.user?.firstName, Validators.required],
|
||||
|
||||
@ -18,5 +18,5 @@ form {
|
||||
/* target the input field inexplicably to throw Chrome's AI off.
|
||||
* feel free to use a more complicated selector */
|
||||
input[name='keySecret']:not(:placeholder-shown) {
|
||||
font-family: 'secret';
|
||||
font-family: 'secret', serif;
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ export class ComboSeriesVerticalComponent implements OnChanges {
|
||||
return item !== undefined;
|
||||
}
|
||||
|
||||
trackBy(index, bar): string {
|
||||
trackBy(_index, bar): string {
|
||||
return bar.label;
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openDeleteUsersDialog([user.id], $event)"
|
||||
[disabled]="user.id === userService.currentUser.id"
|
||||
[disabled]="deleteDisabled(user)"
|
||||
[tooltip]="'user-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
|
||||
@ -43,7 +43,7 @@ export class UserListingScreenComponent extends ListingComponent<User> implement
|
||||
readonly translations = rolesTranslations;
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = this.userService.currentUser;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly canDeleteSelected$ = this.#canDeleteSelected$;
|
||||
readonly tableHeaderLabel = _('user-listing.table-header.title');
|
||||
readonly tableColumnConfigs: TableColumnConfig<User>[] = [
|
||||
@ -58,14 +58,14 @@ export class UserListingScreenComponent extends ListingComponent<User> implement
|
||||
action: (): void => this.openAddEditUserDialog(),
|
||||
type: IconButtonTypes.primary,
|
||||
icon: 'iqser:plus',
|
||||
disabled$: this.userService.currentUser$.pipe(map(user => !user.isAdmin)),
|
||||
disabled$: this._userService.currentUser$.pipe(map(user => !user.isAdmin)),
|
||||
},
|
||||
];
|
||||
collapsedDetails = false;
|
||||
chartConfig: DonutChartConfig[] = [];
|
||||
|
||||
constructor(
|
||||
readonly userService: UserService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _translateService: TranslateService,
|
||||
@ -110,7 +110,7 @@ export class UserListingScreenComponent extends ListingComponent<User> implement
|
||||
async toggleActive(user: User) {
|
||||
this._loadingService.start();
|
||||
const requestBody = { ...user, roles: user.isActive ? [] : ['RED_USER'] };
|
||||
await firstValueFrom(this.userService.updateProfile(requestBody, user.id));
|
||||
await firstValueFrom(this._userService.updateProfile(requestBody, user.id));
|
||||
await this.#loadData();
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ export class UserListingScreenComponent extends ListingComponent<User> implement
|
||||
}
|
||||
|
||||
async #loadData() {
|
||||
await firstValueFrom(this.userService.loadAll());
|
||||
await firstValueFrom(this._userService.loadAll());
|
||||
this.#computeStats();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
@ -145,4 +145,10 @@ export class UserListingScreenComponent extends ListingComponent<User> implement
|
||||
};
|
||||
this.filterService.addFilterGroups([roleFiltersGroup]);
|
||||
}
|
||||
|
||||
deleteDisabled(user: User): boolean {
|
||||
const userAdmin = user.roles.includes('RED_ADMIN');
|
||||
const currentUserAdmin = this._userService.currentUser.roles.includes('RED_ADMIN');
|
||||
return user.id === this._userService.currentUser.id || (userAdmin && !currentUserAdmin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-container" iqserHasScrollbar>
|
||||
<div *ngIf="watermark$ | async" class="right-container" iqserHasScrollbar>
|
||||
<form (keyup)="configChanged()" [formGroup]="form">
|
||||
<div class="iqser-input-group required w-300">
|
||||
<label translate="watermark-screen.form.name-label"></label>
|
||||
@ -22,7 +22,6 @@
|
||||
<div class="iqser-input-group required w-300">
|
||||
<label translate="watermark-screen.form.text-label"></label>
|
||||
<textarea
|
||||
(mousemove)="triggerChanges()"
|
||||
[placeholder]="'watermark-screen.form.text-placeholder' | translate"
|
||||
class="w-full"
|
||||
formControlName="text"
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-direction: row !important;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@ -1,34 +1,29 @@
|
||||
import { ChangeDetectorRef, Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core';
|
||||
import { ChangeDetectorRef, Component, ElementRef, Inject, ViewChild } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import WebViewer, { WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { Debounce, getParam, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { DOSSIER_TEMPLATE_ID, IWatermark, WATERMARK_ID, WatermarkOrientation, WatermarkOrientations } from '@red/domain';
|
||||
import { DOSSIER_TEMPLATE_ID, IWatermark, Watermark, WATERMARK_ID, WatermarkOrientation, WatermarkOrientations } from '@red/domain';
|
||||
import { BASE_HREF_FN, BaseHrefFn } from '../../../../../tokens';
|
||||
import { stampPDFPage } from '@utils/page-stamper';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { WatermarkService } from '@services/entity-services/watermark.service';
|
||||
import { firstValueFrom, Observable, of } from 'rxjs';
|
||||
import { catchError, tap } from 'rxjs/operators';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { LicenseService } from '@services/license.service';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { WatermarksMapService } from '@services/entity-services/watermarks-map.service';
|
||||
|
||||
export const DEFAULT_WATERMARK: IWatermark = {
|
||||
id: null,
|
||||
dossierTemplateId: null,
|
||||
export const DEFAULT_WATERMARK: Partial<IWatermark> = {
|
||||
text: 'Watermark',
|
||||
name: '',
|
||||
enabled: true,
|
||||
hexColor: '#000000',
|
||||
opacity: 30,
|
||||
fontSize: 40,
|
||||
fontType: 'sans-serif',
|
||||
fontType: 'helvetica',
|
||||
orientation: WatermarkOrientations.HORIZONTAL,
|
||||
createdBy: null,
|
||||
dateAdded: null,
|
||||
dateModified: null,
|
||||
} as const;
|
||||
|
||||
@Component({
|
||||
@ -36,13 +31,14 @@ export const DEFAULT_WATERMARK: IWatermark = {
|
||||
templateUrl: './watermark-screen.component.html',
|
||||
styleUrls: ['./watermark-screen.component.scss'],
|
||||
})
|
||||
export class WatermarkScreenComponent implements OnInit {
|
||||
export class WatermarkScreenComponent {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly form: UntypedFormGroup = this._getForm();
|
||||
readonly watermark$: Observable<Partial<IWatermark>>;
|
||||
readonly #dossierTemplateId: string = getParam(DOSSIER_TEMPLATE_ID);
|
||||
readonly #watermarkId = getParam(WATERMARK_ID);
|
||||
private _instance: WebViewerInstance;
|
||||
private _watermark: IWatermark = {} as IWatermark;
|
||||
private _watermark: Partial<IWatermark> = {};
|
||||
@ViewChild('viewer', { static: true })
|
||||
private _viewer: ElementRef;
|
||||
|
||||
@ -58,12 +54,16 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _router: Router,
|
||||
private readonly _watermarksMapService: WatermarksMapService,
|
||||
) {
|
||||
this._loadingService.start();
|
||||
const obs$: Observable<Partial<IWatermark>> = this.#watermarkId
|
||||
? _watermarksMapService.watch$(this.#dossierTemplateId, this.#watermarkId)
|
||||
: of(DEFAULT_WATERMARK);
|
||||
this.watermark$ = obs$.pipe(tap(wm => this._initForm(wm)));
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
for (const key of Object.keys(this._watermark)) {
|
||||
for (const key of Object.keys(this.form.getRawValue())) {
|
||||
if (this._watermark[key] !== this.form.get(key)?.value) {
|
||||
return true;
|
||||
}
|
||||
@ -78,18 +78,19 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
return this.form.valid;
|
||||
}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await firstValueFrom(this._loadWatermark());
|
||||
}
|
||||
|
||||
@Debounce()
|
||||
async configChanged() {
|
||||
await this._drawWatermark();
|
||||
}
|
||||
|
||||
async save(): Promise<void> {
|
||||
const watermark: IWatermark = this.form.getRawValue();
|
||||
|
||||
const watermark: IWatermark = {
|
||||
id: this._watermark.id,
|
||||
enabled: this._watermark.id ? this._watermark.enabled : true,
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
...this.form.getRawValue(),
|
||||
};
|
||||
this._loadingService.start();
|
||||
try {
|
||||
await firstValueFrom(
|
||||
this._watermarkService.saveWatermark(watermark).pipe(
|
||||
@ -98,11 +99,11 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
watermark.id ? _('watermark-screen.action.change-success') : _('watermark-screen.action.created-success'),
|
||||
);
|
||||
}),
|
||||
tap(async () => {
|
||||
tap(async updatedWatermark => {
|
||||
if (!watermark.id) {
|
||||
await this._router.navigate([`/main/admin/dossier-templates/${this.#dossierTemplateId}/watermarks`]);
|
||||
} else {
|
||||
await firstValueFrom(this._loadWatermark());
|
||||
await this._router.navigate([
|
||||
`/main/admin/dossier-templates/${this.#dossierTemplateId}/watermarks/${updatedWatermark.id}`,
|
||||
]);
|
||||
}
|
||||
}),
|
||||
),
|
||||
@ -110,15 +111,14 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
} catch (error) {
|
||||
this._toaster.error(_('watermark-screen.action.error'));
|
||||
}
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
async revert() {
|
||||
this.form.setValue({ ...this._watermark });
|
||||
this.form.patchValue({ ...this._watermark });
|
||||
await this.configChanged();
|
||||
}
|
||||
|
||||
triggerChanges() {}
|
||||
|
||||
async setValue(type: 'fontType' | 'orientation' | 'hexColor', value: any) {
|
||||
if (!this.form.get(type).disabled) {
|
||||
this.form.get(type).setValue(value);
|
||||
@ -126,17 +126,11 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
private _loadWatermark(): Observable<IWatermark> {
|
||||
return this._watermarkService.getWatermark(this.#watermarkId).pipe(
|
||||
catchError(() => of(DEFAULT_WATERMARK)),
|
||||
tap(watermark => {
|
||||
this._watermark = watermark;
|
||||
this._watermark.dossierTemplateId = this.#dossierTemplateId;
|
||||
this.form.setValue({ ...watermark });
|
||||
this._loadViewer();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}),
|
||||
);
|
||||
private _initForm(watermark: Partial<IWatermark>) {
|
||||
this._watermark = { ...watermark, dossierTemplateId: this.#dossierTemplateId };
|
||||
this.form.patchValue({ ...watermark });
|
||||
this._loadViewer();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
private _loadViewer() {
|
||||
@ -207,26 +201,20 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
}
|
||||
|
||||
private _getForm(): UntypedFormGroup {
|
||||
const defaultValue = {
|
||||
value: null,
|
||||
disabled: !this.permissionsService.isAdmin(),
|
||||
};
|
||||
const defaultFormControl = [{ ...defaultValue }, Validators.required];
|
||||
|
||||
return this._formBuilder.group({
|
||||
id: [{ ...defaultValue }],
|
||||
name: [{ ...defaultFormControl }],
|
||||
enabled: [{ ...defaultValue }],
|
||||
dossierTemplateId: [{ ...defaultValue }],
|
||||
text: [{ ...defaultFormControl }],
|
||||
hexColor: [...defaultFormControl],
|
||||
opacity: [...defaultFormControl],
|
||||
fontSize: [...defaultFormControl],
|
||||
fontType: [...defaultFormControl],
|
||||
orientation: [...defaultFormControl],
|
||||
createdBy: [{ ...defaultValue }],
|
||||
dateAdded: [{ ...defaultValue }],
|
||||
dateModified: [{ ...defaultValue }],
|
||||
const form = this._formBuilder.group({
|
||||
name: [null],
|
||||
text: [null],
|
||||
hexColor: [null],
|
||||
opacity: [null],
|
||||
fontSize: [null],
|
||||
fontType: [null],
|
||||
orientation: [null],
|
||||
});
|
||||
|
||||
if (!this.permissionsService.isAdmin()) {
|
||||
form.disable();
|
||||
}
|
||||
|
||||
return form;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,11 +3,42 @@ import { CommonModule } from '@angular/common';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { WatermarkScreenComponent } from './watermark-screen/watermark-screen.component';
|
||||
import { WatermarksListingScreenComponent } from './watermarks-listing/watermarks-listing-screen.component';
|
||||
import { CompositeRouteGuard } from '@iqser/common-ui';
|
||||
import { AuthGuard } from '../../../auth/auth.guard';
|
||||
import { RedRoleGuard } from '../../../auth/red-role.guard';
|
||||
import { WATERMARK_ID } from '@red/domain';
|
||||
import { WatermarkExistsGuard } from '@guards/watermark-exists.guard';
|
||||
|
||||
const routes = [{ path: '', component: WatermarkScreenComponent }];
|
||||
const routes = [
|
||||
{
|
||||
path: '',
|
||||
component: WatermarksListingScreenComponent,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'create',
|
||||
component: WatermarkScreenComponent,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: `:${WATERMARK_ID}`,
|
||||
component: WatermarkScreenComponent,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard, WatermarkExistsGuard],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [WatermarkScreenComponent],
|
||||
declarations: [WatermarkScreenComponent, WatermarksListingScreenComponent],
|
||||
imports: [RouterModule.forChild(routes), CommonModule, SharedModule],
|
||||
})
|
||||
export class WatermarkModule {}
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
<div class="content-container">
|
||||
<iqser-table
|
||||
[headerTemplate]="headerTemplate"
|
||||
[itemSize]="80"
|
||||
[noDataText]="'watermarks-listing.no-data.title' | translate"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
emptyColumnWidth="1fr"
|
||||
noDataIcon="red:attribute"
|
||||
></iqser-table>
|
||||
</div>
|
||||
|
||||
<ng-template #headerTemplate>
|
||||
<div class="table-header-actions">
|
||||
<iqser-icon-button
|
||||
*ngIf="currentUser.isAdmin"
|
||||
[label]="'watermarks-listing.add-new' | translate"
|
||||
[routerLink]="getRouterLink()"
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:plus"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #tableItemTemplate let-entity="entity">
|
||||
<div>
|
||||
<div class="label cell">
|
||||
<span>{{ entity.name }}</span>
|
||||
</div>
|
||||
|
||||
<div class="center cell">
|
||||
<mat-slide-toggle (toggleChange)="toggleStatus(entity)" [checked]="entity.enabled" color="primary"></mat-slide-toggle>
|
||||
</div>
|
||||
|
||||
<div class="cell user-column">
|
||||
<redaction-initials-avatar
|
||||
[defaultValue]="'unknown' | translate"
|
||||
[user]="entity.createdBy || 'system'"
|
||||
></redaction-initials-avatar>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="small-label">
|
||||
{{ entity.dateAdded | date: 'd MMM yyyy' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="small-label">
|
||||
{{ entity.dateModified | date: 'd MMM yyyy' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="action-buttons">
|
||||
<iqser-circle-button
|
||||
[routerLink]="getRouterLink(entity)"
|
||||
[tooltip]="'watermarks-listing.action.edit' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openConfirmDeleteWatermarkDialog($event, entity)"
|
||||
[tooltip]="'watermarks-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
ConfirmationDialogInput,
|
||||
@ -15,15 +15,15 @@ import { getCurrentUser } from '@services/user.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { WatermarkService } from '@services/entity-services/watermark.service';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { AdminDialogService } from '../../../services/admin-dialog.service';
|
||||
import { WatermarksMapService } from '@services/entity-services/watermarks-map.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './watermarks-listing-screen.component.html',
|
||||
styleUrls: ['./watermarks-listing-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: listingProvidersFactory(WatermarksListingScreenComponent),
|
||||
})
|
||||
export class WatermarksListingScreenComponent extends ListingComponent<Watermark> implements OnInit {
|
||||
export class WatermarksListingScreenComponent extends ListingComponent<Watermark> {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = getCurrentUser();
|
||||
@ -40,62 +40,41 @@ export class WatermarksListingScreenComponent extends ListingComponent<Watermark
|
||||
constructor(
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _watermarkService: WatermarkService,
|
||||
private readonly _watermarksMapService: WatermarksMapService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _toaster: Toaster,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this._loadData();
|
||||
this.entitiesService.setEntities(this._watermarksMapService.get(this.#dossierTemplateId));
|
||||
}
|
||||
|
||||
async openConfirmDeleteWatermarkDialog($event: MouseEvent, watermark: Watermark): Promise<void> {
|
||||
const isUsed = await firstValueFrom(this._watermarkService.isWatermarkUsed(watermark.id));
|
||||
|
||||
if (!isUsed) {
|
||||
await this._deleteWatermark(watermark);
|
||||
return;
|
||||
}
|
||||
|
||||
const data = new ConfirmationDialogInput({
|
||||
question: _('watermarks-listing.watermark-is-used'),
|
||||
question: isUsed ? _('watermarks-listing.watermark-is-used') : null,
|
||||
});
|
||||
this._dialogService.openDialog('confirm', $event, data, async () => {
|
||||
await this._deleteWatermark(watermark);
|
||||
});
|
||||
}
|
||||
|
||||
async toggleStatus(watermark?: Watermark): Promise<void> {
|
||||
watermark.enabled = !watermark.enabled;
|
||||
async toggleStatus(watermark: Watermark): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._watermarkService.saveWatermark(watermark));
|
||||
const updatedWatermark = await firstValueFrom(this._watermarkService.saveWatermark({ ...watermark, enabled: !watermark.enabled }));
|
||||
this.entitiesService.replace(updatedWatermark);
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
getRouterLink(watermark: Watermark = null): string {
|
||||
return `/main/admin/dossier-templates/${this.#dossierTemplateId}/watermarks/${watermark ? watermark.id : 0}`;
|
||||
}
|
||||
|
||||
private async _loadData(): Promise<void> {
|
||||
this._loadingService.start();
|
||||
|
||||
try {
|
||||
const response = await firstValueFrom(this._watermarkService.getWatermarks(this.#dossierTemplateId));
|
||||
const watermarkConfig = response?.map(item => new Watermark(item)) || [];
|
||||
this.entitiesService.setEntities(watermarkConfig);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
this._loadingService.stop();
|
||||
return `/main/admin/dossier-templates/${this.#dossierTemplateId}/watermarks/${watermark ? watermark.id : 'create'}`;
|
||||
}
|
||||
|
||||
private async _deleteWatermark(watermark: Watermark): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._watermarkService.deleteWatermark(watermark.id));
|
||||
await firstValueFrom(this._watermarkService.deleteWatermark(this.#dossierTemplateId, watermark.id));
|
||||
this.entitiesService.setEntities(this._watermarksMapService.get(this.#dossierTemplateId));
|
||||
this._toaster.success(_('watermarks-listing.action.delete-success'));
|
||||
await this._loadData();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
<section>
|
||||
<div class="page-header">
|
||||
<redaction-dossier-template-breadcrumbs class="flex-1"></redaction-dossier-template-breadcrumbs>
|
||||
|
||||
<div class="actions flex-1">
|
||||
<redaction-dossier-template-actions></redaction-dossier-template-actions>
|
||||
|
||||
<iqser-circle-button
|
||||
[routerLink]="['../..']"
|
||||
[tooltip]="'common.close' | translate"
|
||||
icon="iqser:close"
|
||||
tooltipPosition="below"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-inner">
|
||||
<div class="overlay-shadow"></div>
|
||||
|
||||
<redaction-admin-side-nav type="dossierTemplates"></redaction-admin-side-nav>
|
||||
|
||||
<div class="content-container">
|
||||
<iqser-table
|
||||
[bulkActions]="bulkActions"
|
||||
[headerTemplate]="headerTemplate"
|
||||
[itemSize]="80"
|
||||
[noDataText]="'watermarks-listing.no-data.title' | translate"
|
||||
[selectionEnabled]="true"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
emptyColumnWidth="1fr"
|
||||
noDataIcon="red:attribute"
|
||||
></iqser-table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ng-template #headerTemplate>
|
||||
<div class="table-header-actions">
|
||||
<iqser-icon-button
|
||||
[routerLink]="getRouterLink()"
|
||||
*ngIf="currentUser.isAdmin"
|
||||
[label]="'watermarks-listing.add-new' | translate"
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:plus"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #bulkActions>
|
||||
<iqser-circle-button
|
||||
*ngIf="currentUser.isAdmin && (listingService.areSomeSelected$ | async)"
|
||||
[tooltip]="'watermarks-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
></iqser-circle-button>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #tableItemTemplate let-entity="entity">
|
||||
<div *ngIf="cast(entity) as watermark">
|
||||
<div class="label cell">
|
||||
<span>{{ watermark.name }}</span>
|
||||
</div>
|
||||
|
||||
<div class="center cell">
|
||||
<mat-slide-toggle (toggleChange)="toggleStatus(watermark)" [checked]="watermark.enabled" color="primary"></mat-slide-toggle>
|
||||
</div>
|
||||
|
||||
<div class="cell user-column">
|
||||
<redaction-initials-avatar
|
||||
[defaultValue]="'unknown' | translate"
|
||||
[user]="watermark.createdBy || 'system'"
|
||||
></redaction-initials-avatar>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="small-label">
|
||||
{{ watermark.dateAdded | date: 'd MMM yyyy' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="small-label">
|
||||
{{ watermark.dateModified | date: 'd MMM yyyy' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="action-buttons">
|
||||
<iqser-circle-button
|
||||
[routerLink]="getRouterLink(watermark)"
|
||||
[tooltip]="'watermarks-listing.action.edit' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openConfirmDeleteWatermarkDialog($event, watermark)"
|
||||
[tooltip]="'watermarks-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
@ -10,7 +10,6 @@ import { DossiersDialogService } from '../../../shared-dossiers/services/dossier
|
||||
@Component({
|
||||
selector: 'redaction-table-item [dossier]',
|
||||
templateUrl: './table-item.component.html',
|
||||
styleUrls: ['./table-item.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class TableItemComponent implements OnChanges {
|
||||
|
||||
@ -10,7 +10,6 @@ import { Router } from '@angular/router';
|
||||
@Component({
|
||||
selector: 'redaction-archived-dossiers-screen',
|
||||
templateUrl: './archived-dossiers-screen.component.html',
|
||||
styleUrls: ['./archived-dossiers-screen.component.scss'],
|
||||
providers: listingProvidersFactory(ArchivedDossiersScreenComponent),
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
|
||||
@ -26,7 +26,6 @@ import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
@Component({
|
||||
selector: 'redaction-dossier-overview-screen-header',
|
||||
templateUrl: './dossier-overview-screen-header.component.html',
|
||||
styleUrls: ['./dossier-overview-screen-header.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossierOverviewScreenHeaderComponent implements OnInit {
|
||||
|
||||
@ -1,14 +1,29 @@
|
||||
<div class="needs-work">
|
||||
<redaction-annotation-icon *ngIf="file.analysisRequired" [color]="analysisColor" label="A" type="square"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="file.analysisRequired"
|
||||
[color]="analysisColor$ | async"
|
||||
label="A"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="file.hasUpdates && file.assignee === userService.currentUser.id && !file.isApproved"
|
||||
[color]="updatedColor"
|
||||
[color]="updatedColor$ | async"
|
||||
label="U"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="file.hasRedactions" [color]="redactionColor" label="R" type="square"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="file.hasImages" [color]="imageColor" label="I" type="square"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="file.hintsOnly" [color]="hintColor" label="H" type="circle"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="file.hasSuggestions" [color]="suggestionColor" label="S" type="rhombus"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="file.hasRedactions"
|
||||
[color]="redactionColor$ | async"
|
||||
label="R"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="file.hasImages" [color]="imageColor$ | async" label="I" type="square"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="file.hintsOnly" [color]="hintColor$ | async" label="H" type="circle"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="file.hasSuggestions"
|
||||
[color]="suggestionColor$ | async"
|
||||
label="S"
|
||||
type="rhombus"
|
||||
></redaction-annotation-icon>
|
||||
<mat-icon *ngIf="file.hasAnnotationComments" svgIcon="red:comment"></mat-icon>
|
||||
</div>
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
||||
import { annotationDefaultColorConfig, DefaultBasedColorType, File } from '@red/domain';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-file-workload',
|
||||
@ -10,41 +11,35 @@ import { DefaultColorsService } from '@services/entity-services/default-colors.s
|
||||
styleUrls: ['./file-workload.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class FileWorkloadComponent {
|
||||
export class FileWorkloadComponent implements OnInit {
|
||||
@Input() file: File;
|
||||
|
||||
suggestionColor$: Observable<string>;
|
||||
imageColor$: Observable<string>;
|
||||
updatedColor$: Observable<string>;
|
||||
analysisColor$: Observable<string>;
|
||||
hintColor$: Observable<string>;
|
||||
redactionColor$: Observable<string>;
|
||||
|
||||
#dossierTemplateId: string;
|
||||
|
||||
constructor(
|
||||
readonly userService: UserService,
|
||||
private readonly _defaultColorsService: DefaultColorsService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
) {}
|
||||
|
||||
get suggestionColor() {
|
||||
return this._getDefaultColor('suggestion');
|
||||
ngOnInit() {
|
||||
this.#dossierTemplateId = this._dossiersService.find(this.file.dossierId).dossierTemplateId;
|
||||
this.suggestionColor$ = this.#getDefaultColor$('suggestion');
|
||||
this.imageColor$ = this.#getDefaultColor$('recommendation');
|
||||
this.updatedColor$ = this.#getDefaultColor$('updated');
|
||||
this.analysisColor$ = this.#getDefaultColor$('analysis');
|
||||
this.hintColor$ = this.#getDefaultColor$('hint');
|
||||
this.redactionColor$ = this.#getDefaultColor$('redaction');
|
||||
}
|
||||
|
||||
get imageColor() {
|
||||
return this._getDefaultColor('recommendation');
|
||||
}
|
||||
|
||||
get updatedColor() {
|
||||
return this._getDefaultColor('updated');
|
||||
}
|
||||
|
||||
get analysisColor() {
|
||||
return this._getDefaultColor('analysis');
|
||||
}
|
||||
|
||||
get hintColor() {
|
||||
return this._getDefaultColor('hint');
|
||||
}
|
||||
|
||||
get redactionColor() {
|
||||
return this._getDefaultColor('redaction');
|
||||
}
|
||||
|
||||
private _getDefaultColor(type: DefaultBasedColorType) {
|
||||
const dossierTemplateId = this._dossiersService.find(this.file.dossierId).dossierTemplateId;
|
||||
return this._defaultColorsService.getColor(dossierTemplateId, annotationDefaultColorConfig[type]);
|
||||
#getDefaultColor$(type: DefaultBasedColorType): Observable<string> {
|
||||
return this._defaultColorsService.getColor$(this.#dossierTemplateId, annotationDefaultColorConfig[type]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,7 +181,6 @@ export class ConfigService {
|
||||
) {
|
||||
const allDistinctWorkflowFileStatuses = new Set<WorkflowFileStatus>();
|
||||
const allDistinctPeople = new Set<string>();
|
||||
const allDistinctAddedDates = new Set<string>();
|
||||
const allDistinctNeedsWork = new Set<string>();
|
||||
const allDistinctProcessingTypes = new Set<ProcessingType>();
|
||||
|
||||
@ -192,7 +191,6 @@ export class ConfigService {
|
||||
entities.forEach(file => {
|
||||
allDistinctPeople.add(file.assignee);
|
||||
allDistinctWorkflowFileStatuses.add(file.workflowStatus);
|
||||
allDistinctAddedDates.add(dayjs(file.added).format('DD/MM/YYYY'));
|
||||
|
||||
if (file.analysisRequired) {
|
||||
allDistinctNeedsWork.add('analysis');
|
||||
@ -291,8 +289,8 @@ export class ConfigService {
|
||||
id: item,
|
||||
label: workloadTranslations[item],
|
||||
metadata: {
|
||||
color: this._defaultColorsService.getColor(dossierTemplateId, annotationDefaultColorConfig[item]),
|
||||
shape: AnnotationShapeMap[item],
|
||||
color$: this._defaultColorsService.getColor$(dossierTemplateId, annotationDefaultColorConfig[item]),
|
||||
},
|
||||
}),
|
||||
);
|
||||
@ -323,13 +321,14 @@ export class ConfigService {
|
||||
label: key,
|
||||
icon: 'red:template',
|
||||
filters: [...filterValue].map(
|
||||
(value: string) =>
|
||||
(value?: string) =>
|
||||
new NestedFilter({
|
||||
id: value,
|
||||
label: value === undefined ? this._translateService.instant('filters.empty') : value,
|
||||
// id shouldn't be undefined to work correctly
|
||||
id: value ?? 'empty',
|
||||
label: value ?? this._translateService.instant('filters.empty'),
|
||||
}),
|
||||
),
|
||||
checker: (input: File, filter: INestedFilter) => filter.id === input.fileAttributes.attributeIdToValue[id],
|
||||
checker: (input: File, filter: INestedFilter) => filter.id === (input.fileAttributes.attributeIdToValue[id] ?? 'empty'),
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import { List, StatusBarConfig } from '@iqser/common-ui';
|
||||
@Component({
|
||||
selector: 'redaction-dossier-documents-status',
|
||||
templateUrl: './dossier-documents-status.component.html',
|
||||
styleUrls: ['./dossier-documents-status.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossierDocumentsStatusComponent implements OnChanges {
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
<div class="needs-work">
|
||||
<redaction-annotation-icon
|
||||
*ngIf="dossierStats.hasRedactionsFilePresent"
|
||||
[color]="redactionColor"
|
||||
[color]="redactionColor$ | async"
|
||||
label="R"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
|
||||
<redaction-annotation-icon
|
||||
*ngIf="dossierStats.hasHintsNoRedactionsFilePresent"
|
||||
[color]="hintColor"
|
||||
[color]="hintColor$ | async"
|
||||
label="H"
|
||||
type="circle"
|
||||
></redaction-annotation-icon>
|
||||
|
||||
<redaction-annotation-icon
|
||||
*ngIf="dossierStats.hasSuggestionsFilePresent"
|
||||
[color]="suggestionColor"
|
||||
[color]="suggestionColor$ | async"
|
||||
label="S"
|
||||
type="rhombus"
|
||||
></redaction-annotation-icon>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { Dossier, DossierStats } from '@red/domain';
|
||||
import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core';
|
||||
import { DefaultColorType, Dossier, DossierStats } from '@red/domain';
|
||||
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
||||
import { BehaviorSubject, Observable, switchMap } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-workload-column',
|
||||
@ -8,21 +9,33 @@ import { DefaultColorsService } from '@services/entity-services/default-colors.s
|
||||
styleUrls: ['./dossier-workload-column.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossierWorkloadColumnComponent {
|
||||
export class DossierWorkloadColumnComponent implements OnChanges {
|
||||
@Input() dossier: Dossier;
|
||||
@Input() dossierStats: DossierStats;
|
||||
|
||||
constructor(private readonly _colorsService: DefaultColorsService) {}
|
||||
readonly suggestionColor$: Observable<string>;
|
||||
readonly hintColor$: Observable<string>;
|
||||
readonly redactionColor$: Observable<string>;
|
||||
|
||||
get suggestionColor() {
|
||||
return this._colorsService.getColor(this.dossier.dossierTemplateId, 'requestAddColor');
|
||||
readonly #dossierTemplateId$ = new BehaviorSubject<string>(null);
|
||||
|
||||
constructor(private readonly _defaultColorsService: DefaultColorsService) {
|
||||
this.suggestionColor$ = this.#dossierTemplateId$.pipe(
|
||||
switchMap(dossierTemplateId => this.#getColor$(dossierTemplateId, 'requestAddColor')),
|
||||
);
|
||||
this.hintColor$ = this.#dossierTemplateId$.pipe(switchMap(dossierTemplateId => this.#getColor$(dossierTemplateId, 'hintColor')));
|
||||
this.redactionColor$ = this.#dossierTemplateId$.pipe(
|
||||
switchMap(dossierTemplateId => this.#getColor$(dossierTemplateId, 'redactionColor')),
|
||||
);
|
||||
}
|
||||
|
||||
get hintColor() {
|
||||
return this._colorsService.getColor(this.dossier.dossierTemplateId, 'hintColor');
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes.dossier) {
|
||||
this.#dossierTemplateId$.next(this.dossier.dossierTemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
get redactionColor() {
|
||||
return this._colorsService.getColor(this.dossier.dossierTemplateId, 'redactionColor');
|
||||
#getColor$(dossierTemplateId: string, colorType: DefaultColorType): Observable<string> {
|
||||
return this._defaultColorsService.getColor$(dossierTemplateId, colorType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,6 @@ import { firstValueFrom } from 'rxjs';
|
||||
@Component({
|
||||
selector: 'redaction-dossiers-listing-actions',
|
||||
templateUrl: './dossiers-listing-actions.component.html',
|
||||
styleUrls: ['./dossiers-listing-actions.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossiersListingActionsComponent implements OnChanges {
|
||||
|
||||
@ -1,6 +1,14 @@
|
||||
import { Injectable, TemplateRef } from '@angular/core';
|
||||
import { ButtonConfig, IFilterGroup, INestedFilter, keyChecker, NestedFilter, TableColumnConfig } from '@iqser/common-ui';
|
||||
import { AnnotationShapeMap, Dossier, DossierTemplate, StatusSorter, User, WorkflowFileStatus } from '@red/domain';
|
||||
import {
|
||||
annotationDefaultColorConfig,
|
||||
AnnotationShapeMap,
|
||||
Dossier,
|
||||
DossierTemplate,
|
||||
StatusSorter,
|
||||
User,
|
||||
WorkflowFileStatus,
|
||||
} from '@red/domain';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
@ -12,6 +20,7 @@ import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
|
||||
import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { SharedDialogService } from '@shared/services/dialog.service';
|
||||
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
||||
|
||||
@Injectable()
|
||||
export class ConfigService {
|
||||
@ -23,6 +32,7 @@ export class ConfigService {
|
||||
private readonly _dossierStatesMapService: DossierStatesMapService,
|
||||
private readonly _dialogService: SharedDialogService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _defaultColorsService: DefaultColorsService,
|
||||
) {}
|
||||
|
||||
get tableConfig(): TableColumnConfig<Dossier>[] {
|
||||
@ -53,7 +63,7 @@ export class ConfigService {
|
||||
];
|
||||
}
|
||||
|
||||
filterGroups(entities: Dossier[], needsWorkFilterTemplate: TemplateRef<unknown>) {
|
||||
filterGroups(entities: Dossier[], needsWorkFilterTemplate: TemplateRef<unknown>, dossierTemplateId: string) {
|
||||
const allDistinctFileStatus = new Set<string>();
|
||||
const allDistinctPeople = new Set<string>();
|
||||
const allDistinctNeedsWork = new Set<string>();
|
||||
@ -145,7 +155,10 @@ export class ConfigService {
|
||||
new NestedFilter({
|
||||
id: type,
|
||||
label: workloadTranslations[type],
|
||||
metadata: { shape: AnnotationShapeMap[type] },
|
||||
metadata: {
|
||||
shape: AnnotationShapeMap[type],
|
||||
color$: this._defaultColorsService.getColor$(dossierTemplateId, annotationDefaultColorConfig[type]),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@ -62,7 +62,11 @@ export class DossiersListingScreenComponent extends ListingComponent<Dossier> im
|
||||
}
|
||||
|
||||
private _computeAllFilters() {
|
||||
const filterGroups = this._configService.filterGroups(this.entitiesService.all, this._needsWorkFilterTemplate);
|
||||
const filterGroups = this._configService.filterGroups(
|
||||
this.entitiesService.all,
|
||||
this._needsWorkFilterTemplate,
|
||||
this.dossierTemplate.id,
|
||||
);
|
||||
this.filterService.addFilterGroups(filterGroups);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ import { AnnotationsListingService } from '../../services/annotations-listing.se
|
||||
@Component({
|
||||
selector: 'redaction-annotation-reference [annotation]',
|
||||
templateUrl: './annotation-reference.component.html',
|
||||
styleUrls: ['./annotation-reference.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AnnotationReferenceComponent implements OnChanges {
|
||||
|
||||
@ -166,7 +166,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
|
||||
}
|
||||
|
||||
get #allPages() {
|
||||
return Array.from({ length: this.file?.numberOfPages }, (x, i) => i + 1);
|
||||
return Array.from({ length: this.file?.numberOfPages }, (_x, i) => i + 1);
|
||||
}
|
||||
|
||||
private static _scrollToFirstElement(elements: HTMLElement[], mode: 'always' | 'if-needed' = 'if-needed') {
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
*ngIf="(editingReviewer$ | async) === false"
|
||||
[user]="file.assignee"
|
||||
[withName]="!!file.assignee"
|
||||
id="assignee"
|
||||
tooltipPosition="below"
|
||||
></redaction-initials-avatar>
|
||||
|
||||
@ -34,8 +35,9 @@
|
||||
*ngIf="(canAssignOrUnassign$ | async) && !!file.assignee"
|
||||
[tooltip]="assignTooltip$ | async"
|
||||
icon="iqser:edit"
|
||||
tooltipPosition="below"
|
||||
id="change-assignee"
|
||||
iqserHelpMode="document_features_in_editor"
|
||||
tooltipPosition="below"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
|
||||
@ -10,7 +10,6 @@ import { firstValueFrom } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
templateUrl: './document-info-dialog.component.html',
|
||||
styleUrls: ['./document-info-dialog.component.scss'],
|
||||
})
|
||||
export class DocumentInfoDialogComponent extends BaseDialogComponent implements OnInit {
|
||||
form: UntypedFormGroup;
|
||||
|
||||
@ -4,20 +4,6 @@
|
||||
<div class="dialog-content">
|
||||
<div translate="import-redactions-dialog.details" class="mb-24"></div>
|
||||
<iqser-upload-file (fileChanged)="fileChanged($event)"></iqser-upload-file>
|
||||
<!-- <div class="only-for-pages" *ngIf="fileToImport">-->
|
||||
<!-- <mat-checkbox-->
|
||||
<!-- (change)="onlyForSpecificPages = !onlyForSpecificPages"-->
|
||||
<!-- [checked]="onlyForSpecificPages"-->
|
||||
<!-- class="filter-menu-checkbox"-->
|
||||
<!-- color="primary"-->
|
||||
<!-- >-->
|
||||
<!-- {{ 'import-redactions-dialog.only-for-specific-pages' | translate }}-->
|
||||
<!-- </mat-checkbox>-->
|
||||
|
||||
<!-- <div *ngIf="onlyForSpecificPages" class="iqser-input-group datepicker-wrapper">-->
|
||||
<!-- <input />-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
|
||||
@ -211,7 +211,8 @@ export class AnnotationActionsService {
|
||||
return this.convertRecommendationToAnnotation($event, [recommendation]);
|
||||
}
|
||||
|
||||
const text = annotation.rectangle ? annotation.value : annotation.isImage ? 'Image' : textAndPositions.text;
|
||||
const isImageText = annotation.isImage ? 'Image' : textAndPositions.text;
|
||||
const text = annotation.rectangle ? annotation.value : isImageText;
|
||||
const data = { annotation, text };
|
||||
|
||||
this._dialogService.openDialog('resizeAnnotation', $event, data, (result: { comment: string; updateDictionary: boolean }) => {
|
||||
|
||||
@ -8,6 +8,7 @@ import { annotationDefaultColorConfig, IViewedPage } from '@red/domain';
|
||||
import { FilePreviewStateService } from './file-preview-state.service';
|
||||
import { FileDataService } from './file-data.service';
|
||||
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class AnnotationProcessingService {
|
||||
@ -68,7 +69,7 @@ export class AnnotationProcessingService {
|
||||
// top level filter
|
||||
if (topLevelFilter) {
|
||||
this._createParentFilter(a.isHighlight ? a.filterKey : a.superType, filterMap, filters, a.isHighlight, {
|
||||
color: a.color,
|
||||
color$: of(a.color),
|
||||
shortLabel: a.isHighlight ? '' : null,
|
||||
shape: a.iconShape,
|
||||
});
|
||||
@ -78,7 +79,7 @@ export class AnnotationProcessingService {
|
||||
if (!parentFilter) {
|
||||
parentFilter = this._createParentFilter(a.superType, filterMap, filters, false, {
|
||||
shape: a.iconShape,
|
||||
color: this._defaultColorsService.getColor(
|
||||
color$: this._defaultColorsService.getColor$(
|
||||
this._state.dossierTemplateId,
|
||||
annotationDefaultColorConfig[a.superType],
|
||||
),
|
||||
@ -90,7 +91,7 @@ export class AnnotationProcessingService {
|
||||
checked: false,
|
||||
matches: 1,
|
||||
metadata: {
|
||||
color: a.color,
|
||||
color$: of(a.color),
|
||||
shape: a.iconShape,
|
||||
},
|
||||
skipTranslation: true,
|
||||
|
||||
@ -19,6 +19,7 @@ import { NGXLogger } from 'ngx-logger';
|
||||
import { MultiSelectService } from './multi-select.service';
|
||||
import { FilesService } from '@services/files/files.service';
|
||||
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
||||
import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service';
|
||||
|
||||
const DELTA_VIEW_TIME = 10 * 60 * 1000; // 10 minutes;
|
||||
|
||||
@ -38,6 +39,7 @@ export class FileDataService extends EntitiesService<AnnotationWrapper> {
|
||||
private readonly _viewModeService: ViewModeService,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _dictionariesMapService: DictionariesMapService,
|
||||
private readonly _dossierDictionariesMapService: DossierDictionariesMapService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _redactionLogService: RedactionLogService,
|
||||
private readonly _textHighlightsService: TextHighlightService,
|
||||
@ -69,7 +71,11 @@ export class FileDataService extends EntitiesService<AnnotationWrapper> {
|
||||
|
||||
get #annotations$() {
|
||||
return this.#redactionLog$.pipe(
|
||||
withLatestFrom(this._state.file$),
|
||||
withLatestFrom(
|
||||
this._state.file$,
|
||||
this._dictionariesMapService.get$(this._state.dossierTemplateId),
|
||||
this._dossierDictionariesMapService.get$(this._state.dossierId),
|
||||
),
|
||||
map(([redactionLog, file]) => this.#buildAnnotations(redactionLog, file)),
|
||||
tap(() => this.#checkMissingTypes()),
|
||||
map(annotations =>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { combineLatest, firstValueFrom, from, merge, Observable, of, pairwise, Subject, switchMap } from 'rxjs';
|
||||
import { Dictionary, Dossier, DOSSIER_ID, File, FILE_ID } from '@red/domain';
|
||||
import { Dictionary, Dossier, DOSSIER_ID, DOSSIER_TEMPLATE_ID, File, FILE_ID } from '@red/domain';
|
||||
import { Router } from '@angular/router';
|
||||
import { FilesMapService } from '@services/files/files-map.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
@ -11,11 +11,11 @@ import { dossiersServiceResolver } from '@services/entity-services/dossiers.serv
|
||||
import { wipeFilesCache } from '@iqser/cache';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
import { FilesService } from '@services/files/files.service';
|
||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||
import { HttpEvent, HttpEventType, HttpProgressEvent, HttpResponse } from '@angular/common/http';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DictionariesMapService } from '../../../services/entity-services/dictionaries-map.service';
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service';
|
||||
|
||||
const ONE_MEGABYTE = 1024 * 1024;
|
||||
|
||||
@ -40,7 +40,7 @@ export class FilePreviewStateService {
|
||||
readonly isWritable$: Observable<boolean>;
|
||||
|
||||
readonly dossierId: string = getParam(DOSSIER_ID);
|
||||
readonly dossierTemplateId: string;
|
||||
readonly dossierTemplateId: string = getParam(DOSSIER_TEMPLATE_ID);
|
||||
readonly fileId: string = getParam(FILE_ID);
|
||||
dossier: Dossier;
|
||||
dialogRef: MatDialogRef<unknown>;
|
||||
@ -56,15 +56,12 @@ export class FilePreviewStateService {
|
||||
private readonly _filesService: FilesService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _fileManagementService: FileManagementService,
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
private readonly _dossierDictionariesMapService: DossierDictionariesMapService,
|
||||
private readonly _dictionariesMapService: DictionariesMapService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
) {
|
||||
const dossiersService = dossiersServiceResolver(_injector, router);
|
||||
|
||||
this.dossierTemplateId = dossiersService.find(this.dossierId).dossierTemplateId;
|
||||
|
||||
this.dossier$ = dossiersService.getEntityChanged$(this.dossierId).pipe(tap(dossier => (this.dossier = dossier)));
|
||||
this.file$ = filesMapService.watch$(this.dossierId, this.fileId).pipe(tap(file => (this.file = file)));
|
||||
[this.isReadonly$, this.isWritable$] = boolFactory(
|
||||
@ -75,8 +72,8 @@ export class FilePreviewStateService {
|
||||
this.blob$ = this.#blob$;
|
||||
this.dossierFileChange$ = this.#dossierFilesChange$();
|
||||
|
||||
this._dictionaryService
|
||||
.getDossierDictionary(this.dossierTemplateId, this.dossierId)
|
||||
this._dossierDictionariesMapService
|
||||
.watch$(this.dossierId, 'dossier_redaction')
|
||||
.subscribe(dictionary => (this.#dossierDictionary = dictionary));
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,8 @@ import { type ManualRedactionEntryType } from '@models/file/manual-redaction-ent
|
||||
import { NGXLogger } from 'ngx-logger';
|
||||
|
||||
function getResponseType(error: boolean, isConflict: boolean) {
|
||||
return error ? (isConflict ? 'conflictError' : 'error') : 'success';
|
||||
const isConflictError = isConflict ? 'conflictError' : 'error';
|
||||
return error ? isConflictError : 'success';
|
||||
}
|
||||
|
||||
function getDictionaryMessage(action: DictionaryActions, error = false, isConflict = false): string {
|
||||
|
||||
@ -5,11 +5,10 @@ import { NGXLogger } from 'ngx-logger';
|
||||
import { ViewModeService } from './view-mode.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Core } from '@pdftron/webviewer';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { WatermarkService } from '@services/entity-services/watermark.service';
|
||||
import { PdfViewer } from '../../pdf-viewer/services/pdf-viewer.service';
|
||||
import { REDDocumentViewer } from '../../pdf-viewer/services/document-viewer.service';
|
||||
import { LicenseService } from '../../../services/license.service';
|
||||
import { LicenseService } from '@services/license.service';
|
||||
import { WatermarksMapService } from '@services/entity-services/watermarks-map.service';
|
||||
import PDFNet = Core.PDFNet;
|
||||
|
||||
@Injectable()
|
||||
@ -21,7 +20,7 @@ export class StampService {
|
||||
private readonly _logger: NGXLogger,
|
||||
private readonly _viewModeService: ViewModeService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _watermarkService: WatermarkService,
|
||||
private readonly _watermarksMapService: WatermarksMapService,
|
||||
private readonly _licenseService: LicenseService,
|
||||
) {}
|
||||
|
||||
@ -44,7 +43,7 @@ export class StampService {
|
||||
if (this._viewModeService.isRedacted) {
|
||||
const dossier = this._state.dossier;
|
||||
if (dossier.previewWatermarkId) {
|
||||
await this._stampPreview(pdfDoc, dossier.dossierTemplateId);
|
||||
await this._stampPreview(pdfDoc, dossier.dossierTemplateId, dossier.previewWatermarkId);
|
||||
}
|
||||
} else {
|
||||
await this._stampExcludedPages(pdfDoc, file.excludedPages);
|
||||
@ -70,8 +69,8 @@ export class StampService {
|
||||
}
|
||||
}
|
||||
|
||||
private async _stampPreview(document: PDFNet.PDFDoc, dossierTemplateId: string): Promise<void> {
|
||||
const watermark = await firstValueFrom(this._watermarkService.getWatermark(dossierTemplateId));
|
||||
private async _stampPreview(document: PDFNet.PDFDoc, dossierTemplateId: string, watermarkId: string): Promise<void> {
|
||||
const watermark = this._watermarksMapService.get(dossierTemplateId, watermarkId);
|
||||
await stampPDFPage(
|
||||
document,
|
||||
this._pdf.PDFNet,
|
||||
@ -81,7 +80,7 @@ export class StampService {
|
||||
watermark.orientation,
|
||||
watermark.opacity,
|
||||
watermark.hexColor,
|
||||
Array.from({ length: await document.getPageCount() }, (x, i) => i + 1),
|
||||
Array.from({ length: await document.getPageCount() }, (_x, i) => i + 1),
|
||||
this._licenseService.activeLicenseKey,
|
||||
);
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
@Component({
|
||||
selector: 'redaction-date-column [date]',
|
||||
templateUrl: './date-column.component.html',
|
||||
styleUrls: ['./date-column.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DateColumnComponent {
|
||||
|
||||
@ -20,7 +20,6 @@ class DialogData {
|
||||
|
||||
@Component({
|
||||
templateUrl: './assign-reviewer-approver-dialog.component.html',
|
||||
styleUrls: ['./assign-reviewer-approver-dialog.component.scss'],
|
||||
})
|
||||
export class AssignReviewerApproverDialogComponent {
|
||||
readonly form: UntypedFormGroup;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<section class="dialog">
|
||||
<div class="dialog-header heading-l">{{ 'dictionary-details.title' | translate }}</div>
|
||||
<div class="dialog-header heading-l">{{ 'dictionary-details.title' | translate: { readOnly: data.readOnly } }}</div>
|
||||
|
||||
<div class="dialog-content">
|
||||
<redaction-add-edit-entity
|
||||
|
||||
@ -7,7 +7,6 @@ import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-e
|
||||
|
||||
@Component({
|
||||
templateUrl: './dictionary-details-dialog.component.html',
|
||||
styleUrls: ['./dictionary-details-dialog.component.scss'],
|
||||
providers: [dossiersServiceProvider],
|
||||
})
|
||||
export class DictionaryDetailsDialogComponent extends BaseDialogComponent {
|
||||
|
||||
@ -83,6 +83,6 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
|
||||
|
||||
private async _updateDossierDictionary() {
|
||||
const { dossierId, dossierTemplateId } = this.dossier;
|
||||
this.dossierDictionary = await firstValueFrom(this._dictionaryService.getDossierDictionary(dossierTemplateId, dossierId));
|
||||
this.dossierDictionary = await firstValueFrom(this._dictionaryService.loadDossierDictionary(dossierTemplateId, dossierId));
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,13 +15,19 @@
|
||||
></redaction-select>
|
||||
</div>
|
||||
|
||||
<redaction-dossier-watermark-selector
|
||||
<redaction-watermark-selector
|
||||
[dossierTemplateId]="dossier.dossierTemplateId"
|
||||
[watermarkId]="form.get('watermarkId').value"
|
||||
[previewWatermarkId]="form.get('previewWatermarkId').value"
|
||||
(idsUpdate)="updateWatermarkIds($event)"
|
||||
[label]="'dossier-watermark-selector.watermark' | translate"
|
||||
formControlName="watermarkId"
|
||||
>
|
||||
</redaction-dossier-watermark-selector>
|
||||
</redaction-watermark-selector>
|
||||
|
||||
<redaction-watermark-selector
|
||||
[dossierTemplateId]="dossier.dossierTemplateId"
|
||||
[label]="'dossier-watermark-selector.preview' | translate"
|
||||
formControlName="previewWatermarkId"
|
||||
>
|
||||
</redaction-watermark-selector>
|
||||
</form>
|
||||
|
||||
<ng-template #reportTemplateOptionTemplate let-option="option">
|
||||
|
||||
@ -7,7 +7,6 @@ import { ReportTemplateService } from '@services/report-template.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
import { UpdateWatermarkIdsEvent } from '@components/dossier-watermark-selector/dossier-watermark-selector.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-dossier-download-package',
|
||||
@ -47,7 +46,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
|
||||
}
|
||||
|
||||
for (const key of Object.keys(this.form.getRawValue())) {
|
||||
if (key.startsWith('watermark') || key.startsWith('previewWatermark')) {
|
||||
if (key.toLowerCase().includes('watermark')) {
|
||||
if (this.dossier[key] !== this.form.get(key).value) {
|
||||
return true;
|
||||
}
|
||||
@ -107,8 +106,8 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
|
||||
this.form.reset({
|
||||
downloadFileTypes: this.dossier.downloadFileTypes,
|
||||
reportTemplateIds: this.dossier.reportTemplateIds,
|
||||
watermarkId: [this.dossier.watermarkId],
|
||||
previewWatermarkId: [this.dossier.previewWatermarkId],
|
||||
watermarkId: this.dossier.watermarkId,
|
||||
previewWatermarkId: this.dossier.previewWatermarkId,
|
||||
});
|
||||
}
|
||||
|
||||
@ -128,9 +127,4 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
updateWatermarkIds(event: UpdateWatermarkIdsEvent) {
|
||||
this.form.get('watermarkId').setValue(event.watermarkId);
|
||||
this.form.get('previewWatermarkId').setValue(event.previewWatermarkId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,7 +77,6 @@ export class AddEditEntityComponent extends BaseFormComponent implements OnInit
|
||||
try {
|
||||
if (this.entity) {
|
||||
// edit mode
|
||||
console.log({ dossierId: this.dossierId });
|
||||
await firstValueFrom(
|
||||
this._dictionaryService.updateDictionary(dictionary, this.dossierTemplateId, dictionary.type, this.dossierId),
|
||||
);
|
||||
@ -148,7 +147,7 @@ export class AddEditEntityComponent extends BaseFormComponent implements OnInit
|
||||
});
|
||||
}
|
||||
|
||||
if (this.entity?.hasDictionary) {
|
||||
if (this.entity?.hasDictionary || this.#isDossierRedaction) {
|
||||
Object.assign(controlsConfig, {
|
||||
addToDictionaryAction: [this.#addToDictionaryActionControl],
|
||||
});
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
<div class="flex-align-items-center space-between">
|
||||
<div class="iqser-input-group w-250">
|
||||
<mat-select [(ngModel)]="value" [placeholder]="'initials-avatar.unassigned' | translate">
|
||||
<mat-select [(ngModel)]="value" [placeholder]="'initials-avatar.unassigned' | translate" id="select-assignee">
|
||||
<mat-select-trigger>
|
||||
<ng-container *ngTemplateOutlet="avatar; context: getContext(value)"></ng-container>
|
||||
</mat-select-trigger>
|
||||
<mat-option *ngFor="let user of options" [value]="user">
|
||||
<mat-option *ngFor="let user of options" [id]="'assignee-option-' + user" [value]="user">
|
||||
<ng-container *ngTemplateOutlet="avatar; context: getContext(user)"></ng-container>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
@ -16,6 +16,7 @@
|
||||
[tooltip]="'assign-user.save' | translate"
|
||||
class="pl-1"
|
||||
icon="iqser:check"
|
||||
id="save-assignee"
|
||||
tooltipPosition="below"
|
||||
></iqser-circle-button>
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ import { firstValueFrom } from 'rxjs';
|
||||
@Component({
|
||||
selector: 'redaction-file-download-btn [files] [dossier]',
|
||||
templateUrl: './file-download-btn.component.html',
|
||||
styleUrls: ['./file-download-btn.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class FileDownloadBtnComponent implements OnChanges {
|
||||
|
||||
@ -16,9 +16,7 @@
|
||||
<mat-icon svgIcon="iqser:search"></mat-icon>
|
||||
</div>
|
||||
<div *ngIf="searchText.length > 0" class="with-input">
|
||||
<div class="search-match-text">
|
||||
{{ currentMatch + '/' + findMatches.length }}
|
||||
</div>
|
||||
{{ currentMatch + '/' + findMatches.length }}
|
||||
<mat-icon (click)="previousSearchMatch()" class="pointer" svgIcon="red:arrow-up"></mat-icon>
|
||||
<mat-icon (click)="nextSearchMatch()" class="pointer" svgIcon="iqser:arrow-down"></mat-icon>
|
||||
<mat-icon (click)="searchChanged(''); inputElement.focus()" class="pointer" svgIcon="iqser:close"></mat-icon>
|
||||
|
||||
@ -72,9 +72,6 @@ form {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.search-match-text {
|
||||
}
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
|
||||
@ -19,7 +19,6 @@ interface PartialDossier extends Partial<IDossier> {
|
||||
@Component({
|
||||
selector: 'redaction-dossier-name-column',
|
||||
templateUrl: './dossier-name-column.component.html',
|
||||
styleUrls: ['./dossier-name-column.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossierNameColumnComponent {
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
<div *ngIf="watermarks$ | async as watermarks" class="container">
|
||||
<div class="iqser-input-group watermark">
|
||||
<mat-checkbox (change)="changeChecked($event)" [checked]="!!value" [disabled]="disabled" color="primary">
|
||||
{{ label }}
|
||||
</mat-checkbox>
|
||||
|
||||
<mat-select (selectionChange)="selectWatermark($event.value)" *ngIf="!!value" [value]="value">
|
||||
<mat-select-trigger *ngIf="!!value">
|
||||
<mat-icon *ngIf="!watermarksMap.get(value)?.enabled" svgIcon="red:warning"></mat-icon>
|
||||
<span> {{ watermarksMap.get(value)?.name }} </span>
|
||||
</mat-select-trigger>
|
||||
|
||||
<mat-option *ngFor="let watermark of watermarks" [disabled]="!watermark.enabled" [value]="watermark.id">
|
||||
<mat-icon *ngIf="!watermark.enabled" svgIcon="red:warning"></mat-icon>
|
||||
{{ watermark.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,81 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { FormFieldComponent, shareLast } from '@iqser/common-ui';
|
||||
import { filter, map, tap } from 'rxjs/operators';
|
||||
import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { Watermark } from '@red/domain';
|
||||
import { WatermarksMapService } from '@services/entity-services/watermarks-map.service';
|
||||
import { MatCheckboxChange } from '@angular/material/checkbox';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-watermark-selector [dossierTemplateId] [label]',
|
||||
templateUrl: './watermark-selector.component.html',
|
||||
styleUrls: ['./watermark-selector.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
multi: true,
|
||||
useExisting: WatermarkSelectorComponent,
|
||||
},
|
||||
{
|
||||
provide: NG_VALIDATORS,
|
||||
multi: true,
|
||||
useExisting: WatermarkSelectorComponent,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class WatermarkSelectorComponent extends FormFieldComponent<string> implements OnChanges {
|
||||
@Input() dossierTemplateId: string;
|
||||
@Input() label: string;
|
||||
readonly watermarks$: Observable<Watermark[]>;
|
||||
watermarksMap = new Map<string, Watermark>();
|
||||
#watermarks: Watermark[] = [];
|
||||
readonly #dossierTemplateId$ = new BehaviorSubject<string>(null);
|
||||
|
||||
constructor(private readonly _watermarksMapService: WatermarksMapService) {
|
||||
super();
|
||||
this.watermarks$ = this.#dossierTemplateId$.pipe(
|
||||
filter(dossierTemplateId => !!dossierTemplateId),
|
||||
map(dossierTemplateId => this._watermarksMapService.get(dossierTemplateId)),
|
||||
tap(watermarks => {
|
||||
this.#watermarks = watermarks;
|
||||
this.watermarksMap.clear();
|
||||
watermarks.forEach(watermark => this.watermarksMap.set(watermark.id, watermark));
|
||||
}),
|
||||
tap(watermarks => {
|
||||
if (!watermarks.length) {
|
||||
this.selectWatermark(null);
|
||||
this.setDisabledState(true);
|
||||
} else {
|
||||
this.setDisabledState(false);
|
||||
if (this.value && this.touched) {
|
||||
this.selectWatermark(watermarks[0].id);
|
||||
}
|
||||
}
|
||||
}),
|
||||
shareLast(),
|
||||
);
|
||||
}
|
||||
|
||||
changeChecked($event: MatCheckboxChange): void {
|
||||
const { checked } = $event;
|
||||
if (!checked || this.#watermarks.length === 0) {
|
||||
this.selectWatermark(null);
|
||||
} else {
|
||||
this.selectWatermark(this.#watermarks[0].id);
|
||||
}
|
||||
}
|
||||
|
||||
selectWatermark(watermarkId: string): void {
|
||||
this.markAsTouched();
|
||||
this._value = watermarkId;
|
||||
this.onChange(this._value);
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes.dossierTemplateId) {
|
||||
this.#dossierTemplateId$.next(this.dossierTemplateId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,6 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
@Component({
|
||||
selector: 'redaction-file-stats',
|
||||
templateUrl: './file-stats.component.html',
|
||||
styleUrls: ['./file-stats.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class FileStatsComponent {
|
||||
|
||||
@ -5,9 +5,9 @@
|
||||
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.id !== 'comment'"
|
||||
[color]="color"
|
||||
[color]="filter.metadata.color$ | async"
|
||||
[label]="label"
|
||||
[type]="filter.metadata?.shape"
|
||||
[type]="filter.metadata.shape"
|
||||
></redaction-annotation-icon>
|
||||
</ng-container>
|
||||
|
||||
|
||||
@ -14,7 +14,6 @@ export class TypeFilterComponent implements OnChanges {
|
||||
@Input() dossierId: string;
|
||||
|
||||
label: string;
|
||||
color: string;
|
||||
|
||||
private _suggestionsKeys: string[] = [
|
||||
SuperTypes.SuggestionRemove,
|
||||
@ -40,7 +39,5 @@ export class TypeFilterComponent implements OnChanges {
|
||||
: this._suggestionsKeys.includes(this.filter.id)
|
||||
? 'S'
|
||||
: this.filter.id.charAt(0);
|
||||
|
||||
this.color = this.filter.metadata?.color || 'transparent';
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,8 +47,19 @@
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<redaction-dossier-watermark-selector [dossierTemplateId]="dossierTemplateId" (idsUpdate)="updateWatermarkIds($event)">
|
||||
</redaction-dossier-watermark-selector>
|
||||
<redaction-watermark-selector
|
||||
[dossierTemplateId]="dossierTemplateId"
|
||||
[label]="'dossier-watermark-selector.watermark' | translate"
|
||||
formControlName="watermarkId"
|
||||
>
|
||||
</redaction-watermark-selector>
|
||||
|
||||
<redaction-watermark-selector
|
||||
[dossierTemplateId]="dossierTemplateId"
|
||||
[label]="'dossier-watermark-selector.preview' | translate"
|
||||
formControlName="previewWatermarkId"
|
||||
>
|
||||
</redaction-watermark-selector>
|
||||
|
||||
<div class="due-date">
|
||||
<mat-checkbox (change)="hasDueDate = !hasDueDate" [checked]="hasDueDate" class="filter-menu-checkbox" color="primary">
|
||||
@ -92,10 +103,10 @@
|
||||
<iqser-icon-button
|
||||
(action)="save({ addMembers: true })"
|
||||
[disabled]="disabled"
|
||||
[id]="'createDossierEditTeamButton'"
|
||||
[label]="'add-dossier-dialog.actions.save-and-add-members' | translate"
|
||||
[type]="iconButtonTypes.dark"
|
||||
icon="red:assign"
|
||||
[id]="'createDossierEditTeamButton'"
|
||||
></iqser-icon-button>
|
||||
|
||||
<iqser-help-button helpButtonKey="new_dossier_button"></iqser-help-button>
|
||||
|
||||
@ -11,7 +11,6 @@ import { firstValueFrom } from 'rxjs';
|
||||
import dayjs from 'dayjs';
|
||||
import { Router } from '@angular/router';
|
||||
import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service';
|
||||
import { UpdateWatermarkIdsEvent } from '@components/dossier-watermark-selector/dossier-watermark-selector.component';
|
||||
|
||||
interface DialogData {
|
||||
readonly dossierTemplateId?: string;
|
||||
@ -67,17 +66,11 @@ export class AddDossierDialogComponent extends BaseDialogComponent implements On
|
||||
}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
this.dossierTemplateId = this.form.get('dossierTemplateId').value;
|
||||
await this.dossierTemplateChanged(this.dossierTemplateId);
|
||||
await this.dossierTemplateChanged(this.form.get('dossierTemplateId').value);
|
||||
}
|
||||
|
||||
reportTemplateValueMapper = (reportTemplate: IReportTemplate) => reportTemplate.templateId;
|
||||
|
||||
updateWatermarkIds(event: UpdateWatermarkIdsEvent) {
|
||||
this.form.get('watermarkId').setValue(event.watermarkId);
|
||||
this.form.get('previewWatermarkId').setValue(event.previewWatermarkId);
|
||||
}
|
||||
|
||||
async save(options?: SaveOptions) {
|
||||
this._loadingService.start();
|
||||
const savedDossier = await firstValueFrom(this._activeDossiersService.createOrUpdate(this._formToObject()));
|
||||
@ -94,7 +87,9 @@ export class AddDossierDialogComponent extends BaseDialogComponent implements On
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
async dossierTemplateChanged(dossierTemplateId) {
|
||||
async dossierTemplateChanged(dossierTemplateId: string) {
|
||||
this.dossierTemplateId = dossierTemplateId;
|
||||
|
||||
// get current selected dossierTemplate
|
||||
const dossierTemplate = this.dossierTemplates.find(r => r.dossierTemplateId === dossierTemplateId);
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ function getInitials(name: string) {
|
||||
|
||||
const splittedName = name.split(' ').filter(value => value !== ' ' && value !== '');
|
||||
return splittedName
|
||||
.filter((value, index) => index < 2)
|
||||
.filter((_value, index) => index < 2)
|
||||
.map(str => str[0])
|
||||
.join('');
|
||||
}
|
||||
|
||||
@ -23,20 +23,20 @@ import { TypeFilterComponent } from './components/type-filter/type-filter.compon
|
||||
import { TeamMembersComponent } from './components/team-members/team-members.component';
|
||||
import { EditorComponent } from './components/editor/editor.component';
|
||||
import { ExpandableFileActionsComponent } from './components/expandable-file-actions/expandable-file-actions.component';
|
||||
import { ProcessingIndicatorComponent } from '@shared/components/processing-indicator/processing-indicator.component';
|
||||
import { DossierStateComponent } from '@shared/components/dossier-state/dossier-state.component';
|
||||
import { ProcessingIndicatorComponent } from './components/processing-indicator/processing-indicator.component';
|
||||
import { DossierStateComponent } from './components/dossier-state/dossier-state.component';
|
||||
import { FileStatsComponent } from './components/file-stats/file-stats.component';
|
||||
import { FileNameColumnComponent } from '@shared/components/file-name-column/file-name-column.component';
|
||||
import { DossierNameColumnComponent } from '@shared/components/dossier-name-column/dossier-name-column.component';
|
||||
import { FileNameColumnComponent } from './components/file-name-column/file-name-column.component';
|
||||
import { DossierNameColumnComponent } from './components/dossier-name-column/dossier-name-column.component';
|
||||
import { MAT_DATE_FORMATS } from '@angular/material/core';
|
||||
import { DossiersTypeSwitchComponent } from '@shared/components/dossiers-type-switch/dossiers-type-switch.component';
|
||||
import { DossiersTypeSwitchComponent } from './components/dossiers-type-switch/dossiers-type-switch.component';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AddDossierDialogComponent } from '@shared/dialogs/add-dossier-dialog/add-dossier-dialog.component';
|
||||
import { SharedDialogService } from '@shared/services/dialog.service';
|
||||
import { DossierWatermarkSelectorComponent } from '@components/dossier-watermark-selector/dossier-watermark-selector.component';
|
||||
import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-edit-entity.component';
|
||||
import { AddDossierDialogComponent } from './dialogs/add-dossier-dialog/add-dossier-dialog.component';
|
||||
import { SharedDialogService } from './services/dialog.service';
|
||||
import { AddEditEntityComponent } from './components/add-edit-entity/add-edit-entity.component';
|
||||
import { ColorPickerModule } from 'ngx-color-picker';
|
||||
import { WatermarkSelectorComponent } from './components/dossier-watermark-selector/watermark-selector.component';
|
||||
|
||||
const buttons = [FileDownloadBtnComponent, UserButtonComponent];
|
||||
|
||||
@ -58,7 +58,7 @@ const components = [
|
||||
FileNameColumnComponent,
|
||||
DossiersTypeSwitchComponent,
|
||||
AddDossierDialogComponent,
|
||||
DossierWatermarkSelectorComponent,
|
||||
WatermarkSelectorComponent,
|
||||
AddEditEntityComponent,
|
||||
|
||||
...buttons,
|
||||
|
||||
@ -17,7 +17,6 @@ import { TrashDialogService } from '../services/trash-dialog.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './trash-screen.component.html',
|
||||
styleUrls: ['./trash-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: listingProvidersFactory({
|
||||
entitiesService: TrashService,
|
||||
|
||||
@ -9,7 +9,6 @@ import { DOSSIER_ID } from '../../../tokens';
|
||||
|
||||
@Component({
|
||||
templateUrl: './file-drop.component.html',
|
||||
styleUrls: ['./file-drop.component.scss'],
|
||||
})
|
||||
export class FileDropComponent {
|
||||
constructor(
|
||||
|
||||
@ -9,6 +9,7 @@ import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DictionaryService } from '../entity-services/dictionary.service';
|
||||
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
||||
import { WatermarkService } from '@services/entity-services/watermark.service';
|
||||
|
||||
const DOSSIER_TEMPLATE_CONFLICT_MSG = _('dossier-templates-listing.error.conflict');
|
||||
const GENERIC_MSG = _('dossier-templates-listing.error.generic');
|
||||
@ -26,6 +27,7 @@ export class DossierTemplatesService extends EntitiesService<IDossierTemplate, D
|
||||
private readonly _dossierTemplateStatsService: DossierTemplateStatsService,
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
private readonly _defaultColorsService: DefaultColorsService,
|
||||
private readonly _watermarksService: WatermarkService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@ -45,6 +47,7 @@ export class DossierTemplatesService extends EntitiesService<IDossierTemplate, D
|
||||
...getAttributes(templates),
|
||||
this._dictionaryService.loadDictionaryData(dossierTemplateIds(templates)),
|
||||
this._defaultColorsService.loadAll(dossierTemplateIds(templates)),
|
||||
this._watermarksService.loadAll(dossierTemplateIds(templates)),
|
||||
]).pipe(map(() => templates));
|
||||
}
|
||||
return of(templates);
|
||||
|
||||
@ -15,6 +15,13 @@ export class DefaultColorsService extends EntitiesService<IDefaultColors, Defaul
|
||||
return this.find(dossierTemplateId)[colorType];
|
||||
}
|
||||
|
||||
getColor$(dossierTemplateId: string, colorType: DefaultColorType, fallback = 'transparent'): Observable<string> {
|
||||
return this.getEntityChanged$(dossierTemplateId).pipe(
|
||||
map(c => c[colorType]),
|
||||
map(c => c || fallback),
|
||||
);
|
||||
}
|
||||
|
||||
loadAll(dossierTemplateIds: string[]): Observable<DefaultColors[]> {
|
||||
return forkJoin(dossierTemplateIds.map(id => super.getFor<IDefaultColors>(id))).pipe(
|
||||
mapEach(defaultColors => new DefaultColors(defaultColors)),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { firstValueFrom, forkJoin, Observable, throwError } from 'rxjs';
|
||||
import { forkJoin, Observable, throwError } from 'rxjs';
|
||||
import { EntitiesService, List, QueryParam, RequiredParam, Toaster, Validate } from '@iqser/common-ui';
|
||||
import { Dictionary, DictionaryEntryType, DictionaryEntryTypes, IDictionary, IUpdateDictionary, SuperTypes } from '@red/domain';
|
||||
import { catchError, map, switchMap, tap } from 'rxjs/operators';
|
||||
@ -8,6 +8,7 @@ import { DossierTemplateStatsService } from './dossier-template-stats.service';
|
||||
import { DictionariesMapService } from './dictionaries-map.service';
|
||||
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
||||
import { FALLBACK_COLOR } from '@utils/constants';
|
||||
import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service';
|
||||
|
||||
const MIN_WORD_LENGTH = 2;
|
||||
|
||||
@ -22,6 +23,7 @@ export class DictionaryService extends EntitiesService<IDictionary, Dictionary>
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _dossierTemplateStatsService: DossierTemplateStatsService,
|
||||
private readonly _dictionariesMapService: DictionariesMapService,
|
||||
private readonly _dossierDictionariesMapService: DossierDictionariesMapService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@ -144,7 +146,7 @@ export class DictionaryService extends EntitiesService<IDictionary, Dictionary>
|
||||
async getDictionariesOptions(dossierTemplateId: string, dossierId: string): Promise<Dictionary[]> {
|
||||
const possibleDictionaries: Dictionary[] = [];
|
||||
|
||||
const dossierDictionary: Dictionary = await firstValueFrom(this.getDossierDictionary(dossierTemplateId, dossierId));
|
||||
const dossierDictionary: Dictionary = this._dossierDictionariesMapService.get(dossierId, 'dossier_redaction');
|
||||
|
||||
for (const dictionary of this._dictionariesMapService.get(dossierTemplateId)) {
|
||||
if (!dictionary.virtual && dictionary.addToDictionaryAction) {
|
||||
@ -161,7 +163,7 @@ export class DictionaryService extends EntitiesService<IDictionary, Dictionary>
|
||||
return possibleDictionaries;
|
||||
}
|
||||
|
||||
getDossierDictionary(dossierTemplateId: string, dossierId: string): Observable<Dictionary> {
|
||||
loadDossierDictionary(dossierTemplateId: string, dossierId: string): Observable<Dictionary> {
|
||||
return this.getForType(dossierTemplateId, 'dossier_redaction', dossierId).pipe(
|
||||
map(
|
||||
dictionary =>
|
||||
@ -170,6 +172,9 @@ export class DictionaryService extends EntitiesService<IDictionary, Dictionary>
|
||||
type: 'dossier_redaction',
|
||||
}),
|
||||
),
|
||||
tap(dictionary => {
|
||||
this._dossierDictionariesMapService.set(dossierId, [dictionary]);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Dictionary, DOSSIER_ID, IDictionary } from '@red/domain';
|
||||
import { EntitiesMapService } from '@iqser/common-ui';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class DossierDictionariesMapService extends EntitiesMapService<Dictionary, IDictionary> {
|
||||
protected readonly _primaryKey = DOSSIER_ID;
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { GenericService, QueryParam, RequiredParam, Validate } from '@iqser/common-ui';
|
||||
import { IWatermark } from '@red/domain';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { GenericService, mapEach, QueryParam, RequiredParam, Validate } from '@iqser/common-ui';
|
||||
import { IWatermark, Watermark } from '@red/domain';
|
||||
import { forkJoin, Observable } from 'rxjs';
|
||||
import { map, switchMap, tap } from 'rxjs/operators';
|
||||
import { WatermarksMapService } from '@services/entity-services/watermarks-map.service';
|
||||
|
||||
interface IsUsedResponse {
|
||||
value: boolean;
|
||||
@ -14,25 +15,40 @@ interface IsUsedResponse {
|
||||
export class WatermarkService extends GenericService<IWatermark> {
|
||||
protected readonly _defaultModelPath = 'watermark';
|
||||
|
||||
@Validate()
|
||||
saveWatermark(@RequiredParam() body: IWatermark) {
|
||||
return this._post(body, `${this._defaultModelPath}`);
|
||||
constructor(private readonly _watermarksMapService: WatermarksMapService) {
|
||||
super();
|
||||
}
|
||||
|
||||
@Validate()
|
||||
deleteWatermark(@RequiredParam() watermarkId: string) {
|
||||
return super.delete({}, `${this._defaultModelPath}/${watermarkId}`);
|
||||
deleteWatermark(@RequiredParam() dossierTemplateId: string, @RequiredParam() watermarkId: string): Observable<Watermark[]> {
|
||||
return super
|
||||
.delete(null, `${this._defaultModelPath}/${watermarkId}`)
|
||||
.pipe(switchMap(() => this.loadForDossierTemplate(dossierTemplateId)));
|
||||
}
|
||||
|
||||
@Validate()
|
||||
getWatermark(@RequiredParam() watermarkId: string) {
|
||||
return this._getOne([watermarkId]);
|
||||
saveWatermark(@RequiredParam() body: IWatermark): Observable<Watermark> {
|
||||
return this._post(body, `${this._defaultModelPath}`).pipe(
|
||||
switchMap(watermark =>
|
||||
this.loadForDossierTemplate(watermark.dossierTemplateId).pipe(
|
||||
map(() => this._watermarksMapService.get(watermark.dossierTemplateId, watermark.id.toString())),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@Validate()
|
||||
getWatermarks(@RequiredParam() dossierTemplateId: string): Observable<IWatermark[]> {
|
||||
loadForDossierTemplate(@RequiredParam() dossierTemplateId: string): Observable<Watermark[]> {
|
||||
const queryParams: QueryParam[] = [{ key: 'dossierTemplateId', value: dossierTemplateId }];
|
||||
return this.getAll<IWatermark[]>(this._defaultModelPath, queryParams);
|
||||
return this.getAll(this._defaultModelPath, queryParams).pipe(
|
||||
mapEach(entity => new Watermark(entity)),
|
||||
tap(entities => this._watermarksMapService.set(dossierTemplateId, entities.sort(this.sortByStatusFn))),
|
||||
);
|
||||
}
|
||||
|
||||
@Validate()
|
||||
loadAll(@RequiredParam() dossierTemplateIds: string[]): Observable<Watermark[]> {
|
||||
return forkJoin(dossierTemplateIds.map(id => this.loadForDossierTemplate(id))).pipe(map(arrays => [].concat(...arrays)));
|
||||
}
|
||||
|
||||
@Validate()
|
||||
@ -40,4 +56,11 @@ export class WatermarkService extends GenericService<IWatermark> {
|
||||
const queryParams: QueryParam[] = [{ key: 'watermarkId', value: watermarkId }];
|
||||
return this.getAll<IsUsedResponse>(`${this._defaultModelPath}/used`, queryParams).pipe(map(result => result.value));
|
||||
}
|
||||
|
||||
sortByStatusFn = (a: Watermark, b: Watermark) => {
|
||||
if (a.enabled === b.enabled) {
|
||||
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
||||
}
|
||||
return a.enabled ? -1 : 1;
|
||||
};
|
||||
}
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { DOSSIER_TEMPLATE_ID, IWatermark, Watermark } from '@red/domain';
|
||||
import { EntitiesMapService } from '@iqser/common-ui';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class WatermarksMapService extends EntitiesMapService<Watermark, IWatermark> {
|
||||
protected readonly _primaryKey = DOSSIER_TEMPLATE_ID;
|
||||
}
|
||||
@ -3,7 +3,6 @@ import { MissingTranslationHandler, MissingTranslationHandlerParams } from '@ngx
|
||||
export class REDMissingTranslationHandler implements MissingTranslationHandler {
|
||||
handle(params: MissingTranslationHandlerParams): any {
|
||||
const missingKey = params.key;
|
||||
// console.error('Missing translation: ' + missingKey);
|
||||
return `?${missingKey}?`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"ADMIN_CONTACT_NAME": null,
|
||||
"ADMIN_CONTACT_URL": null,
|
||||
"API_URL": "https://dev-05.iqser.cloud/redaction-gateway-v1",
|
||||
"API_URL": "https://dev-08.iqser.cloud/redaction-gateway-v1",
|
||||
"APP_NAME": "RedactManager",
|
||||
"AUTO_READ_TIME": 3,
|
||||
"BACKEND_APP_VERSION": "4.4.40",
|
||||
@ -11,7 +11,7 @@
|
||||
"MAX_RETRIES_ON_SERVER_ERROR": 3,
|
||||
"OAUTH_CLIENT_ID": "redaction",
|
||||
"OAUTH_IDP_HINT": null,
|
||||
"OAUTH_URL": "https://dev-05.iqser.cloud/auth/realms/redaction",
|
||||
"OAUTH_URL": "https://dev-08.iqser.cloud/auth/realms/redaction",
|
||||
"RECENT_PERIOD_IN_HOURS": 24,
|
||||
"SELECTION_MODE": "structural",
|
||||
"MANUAL_BASE_URL": "https://docs.redactmanager.com/preview"
|
||||
|
||||
@ -627,7 +627,7 @@
|
||||
"cancel": "Cancel",
|
||||
"save": "Save"
|
||||
},
|
||||
"title": "Edit Dossier Dictionary"
|
||||
"title": "{readOnly, select, false{Edit } other{}}Dossier Dictionary"
|
||||
},
|
||||
"dictionary-overview": {
|
||||
"compare": {
|
||||
@ -799,7 +799,7 @@
|
||||
"total-people": "Total users"
|
||||
},
|
||||
"table-col-names": {
|
||||
"documents-status": "Documents Status",
|
||||
"documents-status": "Documents State",
|
||||
"dossier-state": "Dossier State",
|
||||
"last-modified": "Last modified",
|
||||
"name": "Name",
|
||||
@ -1413,7 +1413,7 @@
|
||||
},
|
||||
"filters": {
|
||||
"assigned-people": "Assignee(s)",
|
||||
"documents-status": "Documents Status",
|
||||
"documents-status": "Documents State",
|
||||
"dossier-state": "Dossier State",
|
||||
"dossier-templates": "Dossier Templates",
|
||||
"empty": "Empty",
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 345454be9d260a3fbb27e9e5b57902dda2e350e0
|
||||
Subproject commit d3e45f5c9868f5ada0af084d93b42f9e92d68c5e
|
||||
@ -15,7 +15,6 @@ export class Dictionary extends Entity<IDictionary> implements IDictionary {
|
||||
readonly rank?: number;
|
||||
readonly recommendation: boolean;
|
||||
readonly type: string;
|
||||
readonly typeId?: string;
|
||||
readonly hasDictionary?: boolean;
|
||||
readonly systemManaged?: boolean;
|
||||
|
||||
@ -40,7 +39,6 @@ export class Dictionary extends Entity<IDictionary> implements IDictionary {
|
||||
this.rank = entity.rank;
|
||||
this.recommendation = !!entity.recommendation;
|
||||
this.type = entity.type;
|
||||
this.typeId = entity.typeId;
|
||||
this.hasDictionary = entity.hasDictionary;
|
||||
this.systemManaged = entity.systemManaged;
|
||||
}
|
||||
|
||||
@ -24,7 +24,6 @@ export interface IDictionary {
|
||||
* The nonnull entry type.
|
||||
*/
|
||||
readonly type: string;
|
||||
readonly typeId?: string;
|
||||
/**
|
||||
* The list of dictionary entries of an entry type.
|
||||
*/
|
||||
|
||||
@ -19,8 +19,8 @@ export class Dossier implements IDossier, IListable {
|
||||
readonly hardDeletedTime?: string;
|
||||
readonly softDeletedTime?: string;
|
||||
readonly startDate?: string;
|
||||
readonly watermarkId: number;
|
||||
readonly previewWatermarkId: number;
|
||||
readonly watermarkId: string;
|
||||
readonly previewWatermarkId: string;
|
||||
readonly archivedTime: string;
|
||||
readonly hasReviewers: boolean;
|
||||
readonly routerLink: string;
|
||||
|
||||
@ -56,9 +56,9 @@ export interface IDossierRequest {
|
||||
/**
|
||||
* Watermark id that will be applied to the redacted files.
|
||||
*/
|
||||
readonly watermarkId?: number;
|
||||
readonly watermarkId?: string;
|
||||
/**
|
||||
* Watermark id that will be applied to the preview files.
|
||||
*/
|
||||
readonly previewWatermarkId?: number;
|
||||
readonly previewWatermarkId?: string;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user