RED-3800 SCM Theming and i18n - cleanup

This commit is contained in:
Timo Bejan 2022-11-29 13:29:21 +02:00
parent 24a3343665
commit 3500cb12cb
32 changed files with 161 additions and 106 deletions

View File

@ -1,4 +1,4 @@
<iqser-help-mode></iqser-help-mode> <iqser-help-mode *ngIf="!permissionsService.has(roles.getRss)"></iqser-help-mode>
<div class="top-bar"> <div class="top-bar">
<ng-template #menuPlaceholder> <ng-template #menuPlaceholder>
@ -27,7 +27,7 @@
[placeholder]="'search.placeholder' | translate" [placeholder]="'search.placeholder' | translate"
></redaction-spotlight-search> ></redaction-spotlight-search>
<iqser-help-button [iqserHelpMode]="'help_mode'"></iqser-help-button> <iqser-help-button [iqserHelpMode]="'help_mode'" *ngIf="!permissionsService.has(roles.getRss)"></iqser-help-button>
<redaction-notifications [iqserHelpMode]="'open_notifications'"></redaction-notifications> <redaction-notifications [iqserHelpMode]="'open_notifications'"></redaction-notifications>
</div> </div>

View File

@ -43,19 +43,19 @@ export class BaseScreenComponent {
id: 'admin', id: 'admin',
name: _('top-bar.navigation-items.my-account.children.admin'), name: _('top-bar.navigation-items.my-account.children.admin'),
routerLink: '/main/admin', routerLink: '/main/admin',
show: (this.currentUser.isManager || this.currentUser.isUserAdmin) && this._permissionsService.has([ROLES.templates.read]), show: (this.currentUser.isManager || this.currentUser.isUserAdmin) && this.permissionsService.has([ROLES.templates.read]),
}, },
{ {
id: 'downloads', id: 'downloads',
name: _('top-bar.navigation-items.my-account.children.downloads'), name: _('top-bar.navigation-items.my-account.children.downloads'),
routerLink: '/main/downloads', routerLink: '/main/downloads',
show: this.currentUser.isUser && this._permissionsService.has(ROLES.readDownloadStatus), show: this.currentUser.isUser && this.permissionsService.has(ROLES.readDownloadStatus),
}, },
{ {
id: 'trash', id: 'trash',
name: _('top-bar.navigation-items.my-account.children.trash'), name: _('top-bar.navigation-items.my-account.children.trash'),
routerLink: '/main/trash', routerLink: '/main/trash',
show: this.currentUser.isUser && this._permissionsService.has([ROLES.dossiers.read, ROLES.files.readStatus]), show: this.currentUser.isUser && this.permissionsService.has([ROLES.dossiers.read, ROLES.files.readStatus]),
}, },
]; ];
readonly searchActions: readonly SpotlightSearchAction[] = [ readonly searchActions: readonly SpotlightSearchAction[] = [
@ -89,7 +89,7 @@ export class BaseScreenComponent {
private readonly _router: Router, private readonly _router: Router,
private readonly _translateService: TranslateService, private readonly _translateService: TranslateService,
private readonly _featuresService: FeaturesService, private readonly _featuresService: FeaturesService,
private readonly _permissionsService: IqserPermissionsService, readonly permissionsService: IqserPermissionsService,
readonly userService: UserService, readonly userService: UserService,
readonly userPreferenceService: UserPreferenceService, readonly userPreferenceService: UserPreferenceService,
readonly titleService: Title, readonly titleService: Title,

View File

@ -95,7 +95,10 @@
<button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button type="button"> <button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button type="button">
{{ 'add-edit-clone-dossier-template.save' | translate }} {{ 'add-edit-clone-dossier-template.save' | translate }}
</button> </button>
<iqser-help-button *ngIf="dossierTemplate" helpButtonKey="edit_clone_delete_dossier_templates"></iqser-help-button> <iqser-help-button
helpButtonKey="edit_clone_delete_dossier_templates"
*ngIf="dossierTemplate && !permissionsService.has(roles.getRss)"
></iqser-help-button>
</div> </div>
</form> </form>

View File

@ -4,12 +4,13 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { applyIntervalConstraints } from '@utils/date-inputs-utils'; import { applyIntervalConstraints } from '@utils/date-inputs-utils';
import { downloadTypesTranslations } from '@translations/download-types-translations'; import { downloadTypesTranslations } from '@translations/download-types-translations';
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
import { BaseDialogComponent } from '@iqser/common-ui'; import { BaseDialogComponent, IqserPermissionsService } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { DossierTemplate, DownloadFileType, IDossierTemplate } from '@red/domain'; import { DossierTemplate, DownloadFileType, IDossierTemplate } from '@red/domain';
import { HttpStatusCode } from '@angular/common/http'; import { HttpStatusCode } from '@angular/common/http';
import { firstValueFrom } from 'rxjs'; import { firstValueFrom } from 'rxjs';
import dayjs, { Dayjs } from 'dayjs'; import dayjs, { Dayjs } from 'dayjs';
import { ROLES } from '@users/roles';
interface EditCloneTemplateData { interface EditCloneTemplateData {
dossierTemplateId: string; dossierTemplateId: string;
@ -21,6 +22,7 @@ interface EditCloneTemplateData {
styleUrls: ['./add-edit-clone-dossier-template-dialog.component.scss'], styleUrls: ['./add-edit-clone-dossier-template-dialog.component.scss'],
}) })
export class AddEditCloneDossierTemplateDialogComponent extends BaseDialogComponent { export class AddEditCloneDossierTemplateDialogComponent extends BaseDialogComponent {
readonly roles = ROLES;
hasValidFrom: boolean; hasValidFrom: boolean;
hasValidTo: boolean; hasValidTo: boolean;
downloadTypesEnum: DownloadFileType[] = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED']; downloadTypesEnum: DownloadFileType[] = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'];
@ -35,6 +37,7 @@ export class AddEditCloneDossierTemplateDialogComponent extends BaseDialogCompon
private _lastValidTo: Dayjs; private _lastValidTo: Dayjs;
constructor( constructor(
readonly permissionsService: IqserPermissionsService,
private readonly _dossierTemplatesService: DossierTemplatesService, private readonly _dossierTemplatesService: DossierTemplatesService,
protected readonly _dialogRef: MatDialogRef<AddEditCloneDossierTemplateDialogComponent>, protected readonly _dialogRef: MatDialogRef<AddEditCloneDossierTemplateDialogComponent>,
@Inject(MAT_DIALOG_DATA) readonly data: EditCloneTemplateData, @Inject(MAT_DIALOG_DATA) readonly data: EditCloneTemplateData,

View File

@ -16,7 +16,7 @@
<button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button type="button"> <button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button type="button">
{{ 'add-entity.save' | translate }} {{ 'add-entity.save' | translate }}
</button> </button>
<iqser-help-button helpButtonKey="create_new_entity"></iqser-help-button> <iqser-help-button helpButtonKey="create_new_entity" *ngIf="!permissionsService.has(roles.getRss)"></iqser-help-button>
</div> </div>
<iqser-circle-button (click)="close()" class="dialog-close" icon="iqser:close"></iqser-circle-button> <iqser-circle-button (click)="close()" class="dialog-close" icon="iqser:close"></iqser-circle-button>

View File

@ -1,7 +1,8 @@
import { ChangeDetectionStrategy, Component, Inject, ViewChild } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, ViewChild } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-edit-entity.component'; import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-edit-entity.component';
import { BaseDialogComponent } from '@iqser/common-ui'; import { BaseDialogComponent, IqserPermissionsService } from '@iqser/common-ui';
import { ROLES } from '@users/roles';
interface DialogData { interface DialogData {
readonly dossierTemplateId: string; readonly dossierTemplateId: string;
@ -13,12 +14,14 @@ interface DialogData {
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class AddEntityDialogComponent extends BaseDialogComponent { export class AddEntityDialogComponent extends BaseDialogComponent {
readonly roles = ROLES;
readonly dossierTemplateId = this._data.dossierTemplateId; readonly dossierTemplateId = this._data.dossierTemplateId;
@ViewChild(AddEditEntityComponent, { static: true }) private readonly _addEditEntityComponent: AddEditEntityComponent; @ViewChild(AddEditEntityComponent, { static: true }) private readonly _addEditEntityComponent: AddEditEntityComponent;
constructor( constructor(
protected readonly _dialogRef: MatDialogRef<AddEntityDialogComponent>, protected readonly _dialogRef: MatDialogRef<AddEntityDialogComponent>,
readonly permissionsService: IqserPermissionsService,
@Inject(MAT_DIALOG_DATA) private readonly _data: DialogData, @Inject(MAT_DIALOG_DATA) private readonly _data: DialogData,
) { ) {
super(_dialogRef, false); super(_dialogRef, false);

View File

@ -88,7 +88,7 @@
<div class="cell center"> <div class="cell center">
<redaction-annotation-icon <redaction-annotation-icon
[color]="dict.hexColor" [color]="dict.hexColor"
[label]="dict.hint ? 'H' : 'R'" [label]="dict.hint ? 'H' : ('redaction-abbreviation' | translate)"
[type]="dict.hint ? 'circle' : 'square'" [type]="dict.hint ? 'circle' : 'square'"
></redaction-annotation-icon> ></redaction-annotation-icon>
</div> </div>

View File

@ -23,7 +23,7 @@
</button> </button>
<div (click)="revert()" [translate]="'entity.info.actions.revert'" class="all-caps-label cancel"></div> <div (click)="revert()" [translate]="'entity.info.actions.revert'" class="all-caps-label cancel"></div>
<iqser-help-button helpButtonKey="edit_delete_entities"></iqser-help-button> <iqser-help-button helpButtonKey="edit_delete_entities" *ngIf="!iqserPermissionsService.has(roles.getRss)"></iqser-help-button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -5,8 +5,9 @@ import { ActivatedRoute } from '@angular/router';
import { getCurrentUser } from '@users/user.service'; import { getCurrentUser } from '@users/user.service';
import { PermissionsService } from '@services/permissions.service'; import { PermissionsService } from '@services/permissions.service';
import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-edit-entity.component'; import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-edit-entity.component';
import { IqserEventTarget } from '@iqser/common-ui'; import { IqserEventTarget, IqserPermissionsService } from '@iqser/common-ui';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { ROLES } from '@users/roles';
@Component({ @Component({
selector: 'redaction-entity-info', selector: 'redaction-entity-info',
@ -18,9 +19,15 @@ export class EntityInfoComponent {
readonly currentUser = getCurrentUser(); readonly currentUser = getCurrentUser();
readonly entity$: Observable<Dictionary>; readonly entity$: Observable<Dictionary>;
readonly dossierTemplateId: string; readonly dossierTemplateId: string;
readonly roles = ROLES;
@ViewChild(AddEditEntityComponent) private readonly _addEditEntityComponent: AddEditEntityComponent; @ViewChild(AddEditEntityComponent) private readonly _addEditEntityComponent: AddEditEntityComponent;
constructor(route: ActivatedRoute, dictionariesMapService: DictionariesMapService, readonly permissionsService: PermissionsService) { constructor(
route: ActivatedRoute,
dictionariesMapService: DictionariesMapService,
readonly iqserPermissionsService: IqserPermissionsService,
readonly permissionsService: PermissionsService,
) {
this.dossierTemplateId = route.parent.snapshot.paramMap.get(DOSSIER_TEMPLATE_ID); this.dossierTemplateId = route.parent.snapshot.paramMap.get(DOSSIER_TEMPLATE_ID);
const entityType = route.parent.snapshot.paramMap.get(ENTITY_TYPE); const entityType = route.parent.snapshot.paramMap.get(ENTITY_TYPE);
this.entity$ = dictionariesMapService.watch$(this.dossierTemplateId, entityType); this.entity$ = dictionariesMapService.watch$(this.dossierTemplateId, entityType);

View File

@ -1,7 +1,7 @@
<div class="details"> <div class="details">
<redaction-annotation-icon <redaction-annotation-icon
[color]="annotation.color" [color]="annotation.color"
[label]="annotation.isEarmark ? '' : annotation.superType[0].toUpperCase()" [label]="annotation.isEarmark ? '' : (annotationTypesTranslations[annotation.superType] | translate)[0].toUpperCase()"
[type]="annotation.iconShape" [type]="annotation.iconShape"
class="mt-6 mr-10" class="mt-6 mr-10"
></redaction-annotation-icon> ></redaction-annotation-icon>

View File

@ -1,6 +1,7 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { MultiSelectService } from '../../services/multi-select.service'; import { MultiSelectService } from '../../services/multi-select.service';
import { annotationTypesTranslations } from '@translations/annotation-types-translations';
@Component({ @Component({
selector: 'redaction-annotation-card', selector: 'redaction-annotation-card',
@ -9,6 +10,7 @@ import { MultiSelectService } from '../../services/multi-select.service';
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class AnnotationCardComponent { export class AnnotationCardComponent {
annotationTypesTranslations = annotationTypesTranslations;
@Input() annotation: AnnotationWrapper; @Input() annotation: AnnotationWrapper;
@Input() isSelected = false; @Input() isSelected = false;

View File

@ -11,6 +11,7 @@
<button <button
(click)="switchView(viewModes.DELTA)" (click)="switchView(viewModes.DELTA)"
*ngIf="!permissionsService.has(roles.getRss)"
[class.active]="viewMode === viewModes.DELTA" [class.active]="viewMode === viewModes.DELTA"
[disabled]="(canSwitchToDeltaView$ | async) === false" [disabled]="(canSwitchToDeltaView$ | async) === false"
[iqserHelpMode]="'views'" [iqserHelpMode]="'views'"
@ -22,6 +23,7 @@
<button <button
(click)="switchView(viewModes.REDACTED)" (click)="switchView(viewModes.REDACTED)"
*ngIf="!permissionsService.has(roles.getRss)"
[class.active]="viewMode === viewModes.REDACTED" [class.active]="viewMode === viewModes.REDACTED"
[disabled]="(canSwitchToRedactedView$ | async) === false" [disabled]="(canSwitchToRedactedView$ | async) === false"
[iqserHelpMode]="'views'" [iqserHelpMode]="'views'"
@ -33,6 +35,7 @@
<button <button
(click)="switchView(viewModes.TEXT_HIGHLIGHTS)" (click)="switchView(viewModes.TEXT_HIGHLIGHTS)"
*ngIf="!permissionsService.has(roles.getRss)"
[class.active]="viewMode === viewModes.TEXT_HIGHLIGHTS" [class.active]="viewMode === viewModes.TEXT_HIGHLIGHTS"
[disabled]="(canSwitchToEarmarksView$ | async) === false" [disabled]="(canSwitchToEarmarksView$ | async) === false"
[iqserHelpMode]="'views'" [iqserHelpMode]="'views'"

View File

@ -5,10 +5,11 @@ import { FilePreviewStateService } from '../../services/file-preview-state.servi
import { combineLatest, Observable } from 'rxjs'; import { combineLatest, Observable } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { FileDataService } from '../../services/file-data.service'; import { FileDataService } from '../../services/file-data.service';
import { BASE_HREF, ConfirmationDialogInput, ConfirmOptions, Toaster } from '@iqser/common-ui'; import { BASE_HREF, ConfirmationDialogInput, ConfirmOptions, IqserPermissionsService, Toaster } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { UserPreferenceService } from '@users/user-preference.service'; import { UserPreferenceService } from '@users/user-preference.service';
import { FilePreviewDialogService } from '../../services/file-preview-dialog.service'; import { FilePreviewDialogService } from '../../services/file-preview-dialog.service';
import { ROLES } from '@users/roles';
@Component({ @Component({
selector: 'redaction-view-switch', selector: 'redaction-view-switch',
@ -21,10 +22,12 @@ export class ViewSwitchComponent {
readonly canSwitchToDeltaView$: Observable<boolean>; readonly canSwitchToDeltaView$: Observable<boolean>;
readonly canSwitchToRedactedView$: Observable<boolean>; readonly canSwitchToRedactedView$: Observable<boolean>;
readonly canSwitchToEarmarksView$: Observable<boolean>; readonly canSwitchToEarmarksView$: Observable<boolean>;
readonly roles = ROLES;
constructor( constructor(
@Inject(BASE_HREF) private readonly _baseHref: string, @Inject(BASE_HREF) private readonly _baseHref: string,
readonly viewModeService: ViewModeService, readonly viewModeService: ViewModeService,
readonly permissionsService: IqserPermissionsService,
private readonly _stateService: FilePreviewStateService, private readonly _stateService: FilePreviewStateService,
private readonly _fileDataService: FileDataService, private readonly _fileDataService: FileDataService,
private readonly _userPreferenceService: UserPreferenceService, private readonly _userPreferenceService: UserPreferenceService,

View File

@ -34,7 +34,7 @@
{{ translations[data.operation].save | translate }} {{ translations[data.operation].save | translate }}
</button> </button>
<div class="all-caps-label cancel" mat-dialog-close translate="highlight-action-dialog.actions.cancel"></div> <div class="all-caps-label cancel" mat-dialog-close translate="highlight-action-dialog.actions.cancel"></div>
<iqser-help-button helpButtonKey="highlights"></iqser-help-button> <iqser-help-button helpButtonKey="highlights" *ngIf="!permissionsService.has(roles.getRss)"></iqser-help-button>
</div> </div>
</form> </form>

View File

@ -2,11 +2,12 @@ import { Component, Inject } from '@angular/core';
import { UntypedFormGroup, Validators } from '@angular/forms'; import { UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { EarmarkOperation, EarmarkOperationPages } from '@red/domain'; import { EarmarkOperation, EarmarkOperationPages } from '@red/domain';
import { BaseDialogComponent, DetailsRadioOption } from '@iqser/common-ui'; import { BaseDialogComponent, DetailsRadioOption, IqserPermissionsService } from '@iqser/common-ui';
import { EarmarksService } from '@services/files/earmarks.service'; import { EarmarksService } from '@services/files/earmarks.service';
import { firstValueFrom } from 'rxjs'; import { firstValueFrom } from 'rxjs';
import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { highlightsTranslations } from '@translations/highlights-translations'; import { highlightsTranslations } from '@translations/highlights-translations';
import { ROLES } from '@users/roles';
export interface HighlightActionData { export interface HighlightActionData {
readonly operation: EarmarkOperation; readonly operation: EarmarkOperation;
@ -24,6 +25,7 @@ export interface HighlightActionData {
export class HighlightActionDialogComponent extends BaseDialogComponent { export class HighlightActionDialogComponent extends BaseDialogComponent {
readonly translations = highlightsTranslations; readonly translations = highlightsTranslations;
readonly #operation = this.data.operation; readonly #operation = this.data.operation;
readonly roles = ROLES;
readonly options: DetailsRadioOption<EarmarkOperationPages>[] = [ readonly options: DetailsRadioOption<EarmarkOperationPages>[] = [
{ {
@ -39,6 +41,7 @@ export class HighlightActionDialogComponent extends BaseDialogComponent {
]; ];
constructor( constructor(
readonly permissionsService: IqserPermissionsService,
protected readonly _dialogRef: MatDialogRef<HighlightActionDialogComponent>, protected readonly _dialogRef: MatDialogRef<HighlightActionDialogComponent>,
private readonly _textHighlightService: EarmarksService, private readonly _textHighlightService: EarmarksService,
@Inject(MAT_DIALOG_DATA) readonly data: HighlightActionData, @Inject(MAT_DIALOG_DATA) readonly data: HighlightActionData,

View File

@ -4,7 +4,7 @@
<hr /> <hr />
<div class="dialog-content"> <div class="dialog-content">
<div *ngIf="rssData$ | async as rssEntry"> <div *ngIf="rssData$ | async as rssEntry">
<div *ngFor="let entry of rssEntry.result | keyvalue" class="rss-row"> <div *ngFor="let entry of rssEntry.result | keyvalue: originalOrder" class="rss-row">
<div class="rss-key">{{ entry.key }}:</div> <div class="rss-key">{{ entry.key }}:</div>
<div class="rss-value">{{ entry.value }}</div> <div class="rss-value">{{ entry.value }}</div>
</div> </div>

View File

@ -7,6 +7,7 @@ import { firstValueFrom, Observable } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { FilesMapService } from '@services/files/files-map.service'; import { FilesMapService } from '@services/files/files-map.service';
import { UserPreferenceService } from '@users/user-preference.service'; import { UserPreferenceService } from '@users/user-preference.service';
import { KeyValue } from '@angular/common';
interface RssData { interface RssData {
file: IFile; file: IFile;
@ -19,6 +20,8 @@ interface RssData {
export class RssDialogComponent extends BaseDialogComponent { export class RssDialogComponent extends BaseDialogComponent {
rssData$: Observable<IRssEntry>; rssData$: Observable<IRssEntry>;
originalOrder = (a: KeyValue<string, string>, b: KeyValue<string, string>): number => 0;
constructor( constructor(
protected readonly _dialogRef: MatDialogRef<RssDialogComponent>, protected readonly _dialogRef: MatDialogRef<RssDialogComponent>,
private readonly _rssService: RssService, private readonly _rssService: RssService,

View File

@ -25,14 +25,6 @@
<div class="vertical-line"></div> <div class="vertical-line"></div>
<redaction-file-actions
[dossier]="dossier"
[file]="file"
[minWidth]="width"
fileActionsHelpModeKey="document_features_in_editor"
type="file-preview"
></redaction-file-actions>
<iqser-circle-button <iqser-circle-button
(action)="openRSSView(file)" (action)="openRSSView(file)"
*allow="roles.getRss" *allow="roles.getRss"
@ -42,6 +34,14 @@
tooltipPosition="below" tooltipPosition="below"
></iqser-circle-button> ></iqser-circle-button>
<redaction-file-actions
[dossier]="dossier"
[file]="file"
[minWidth]="width"
fileActionsHelpModeKey="document_features_in_editor"
type="file-preview"
></redaction-file-actions>
<iqser-circle-button <iqser-circle-button
(action)="toggleFullScreen()" (action)="toggleFullScreen()"
[icon]="fullScreen ? 'red:exit-fullscreen' : 'red:fullscreen'" [icon]="fullScreen ? 'red:exit-fullscreen' : 'red:fullscreen'"

View File

@ -48,7 +48,9 @@ export class PdfProxyService {
readonly #visibilityOffIcon = this._convertPath('/assets/icons/general/visibility-off.svg'); readonly #visibilityOffIcon = this._convertPath('/assets/icons/general/visibility-off.svg');
readonly #visibilityIcon = this._convertPath('/assets/icons/general/visibility.svg'); readonly #visibilityIcon = this._convertPath('/assets/icons/general/visibility.svg');
readonly #falsePositiveIcon = this._convertPath('/assets/icons/general/pdftron-action-false-positive.svg'); readonly #falsePositiveIcon = this._convertPath('/assets/icons/general/pdftron-action-false-positive.svg');
readonly #addRedactionIcon = this._convertPath('/assets/icons/general/pdftron-action-add-redaction.svg'); readonly #addRedactionIcon = this._iqserPermissionsService.has(ROLES.getRss)
? this._convertPath('/assets/icons/general/pdftron-action-add-component.svg')
: this._convertPath('/assets/icons/general/pdftron-action-add-redaction.svg');
readonly #addDictIcon = this._convertPath('/assets/icons/general/pdftron-action-add-dict.svg'); readonly #addDictIcon = this._convertPath('/assets/icons/general/pdftron-action-add-dict.svg');
constructor( constructor(

View File

@ -247,7 +247,7 @@ export class ViewerHeaderService {
], ],
]; ];
groups.forEach(group => this._pushGroup(enabledItems, group)); groups.forEach(group => this._pushGroup(enabledItems, group));
header.getItems().splice(8, header.getItems().length - 13, ...enabledItems); header.getItems().splice(10, header.getItems().length - 14, ...enabledItems);
}); });
this._pdf.instance.UI.updateElement('selectToolButton', { this._pdf.instance.UI.updateElement('selectToolButton', {

View File

@ -1,64 +1,62 @@
<div> <div class="cell filename">
<div class="cell filename"> <div [matTooltip]="item.filename" class="table-item-title heading" matTooltipPosition="above">
<div [matTooltip]="item.filename" class="table-item-title heading" matTooltipPosition="above"> <span
<span *ngIf="item.highlights.filename; else defaultFilename"
*ngIf="item.highlights.filename; else defaultFilename" [innerHTML]="sanitize(item.highlights.filename[0])"
[innerHTML]="sanitize(item.highlights.filename[0])" class="highlights"
class="highlights" ></span>
></span> <ng-template #defaultFilename>{{ item.filename }}</ng-template>
<ng-template #defaultFilename>{{ item.filename }}</ng-template>
</div>
<ng-container *ngIf="item.highlights['sections.text'] as highlights">
<div *ngIf="highlights.length > 0" class="small-label">
<span [innerHTML]="sanitize(highlights[0])" class="highlights"></span>
</div>
<div *ngIf="highlights.length > 1" class="small-label">
<span [innerHTML]="sanitize(highlights[1])" class="highlights"></span>
</div>
</ng-container>
<div *ngIf="item.unmatched?.length && item.unmatched as unmatched" class="small-label">
<span>
{{ 'search-screen.missing' | translate }}:<span *ngFor="let term of unmatched"
>&nbsp;<s>{{ term }}</s></span
>.&nbsp;{{ 'search-screen.must-contain' | translate }}:
<span (click)="$event.stopPropagation(); mustContain.emit(term)" *ngFor="let term of unmatched"
>&nbsp;<u>{{ term }}</u></span
>
</span>
</div>
</div> </div>
<div class="cell"> <ng-container *ngIf="item.highlights['sections.text'] as highlights">
<iqser-initials-avatar [user]="item.assignee" [withName]="true"></iqser-initials-avatar> <div *ngIf="highlights.length > 0" class="small-label">
</div> <span [innerHTML]="sanitize(highlights[0])" class="highlights"></span>
<div class="cell">
<iqser-status-bar
[configs]="[
{
color: item.status,
label: fileStatusTranslations[item.status] | translate,
length: 1,
cssClass: 'all-caps-label'
}
]"
[small]="true"
></iqser-status-bar>
</div>
<div class="cell small-label stats-subtitle">
<div>
<mat-icon *ngIf="item.archived" svgIcon="red:archive"></mat-icon>
{{ item.dossierName }}
</div> </div>
</div> <div *ngIf="highlights.length > 1" class="small-label">
<span [innerHTML]="sanitize(highlights[1])" class="highlights"></span>
<div class="cell small-label stats-subtitle">
<div>
<mat-icon svgIcon="iqser:pages"></mat-icon>
{{ item.numberOfPages }}
</div> </div>
</ng-container>
<div *ngIf="item.unmatched?.length && item.unmatched as unmatched" class="small-label">
<span>
{{ 'search-screen.missing' | translate }}:<span *ngFor="let term of unmatched"
>&nbsp;<s>{{ term }}</s></span
>.&nbsp;{{ 'search-screen.must-contain' | translate }}:
<span (click)="$event.stopPropagation(); mustContain.emit(term)" *ngFor="let term of unmatched"
>&nbsp;<u>{{ term }}</u></span
>
</span>
</div>
</div>
<div class="cell">
<iqser-initials-avatar [user]="item.assignee" [withName]="true"></iqser-initials-avatar>
</div>
<div class="cell">
<iqser-status-bar
[configs]="[
{
color: item.status,
label: fileStatusTranslations[item.status] | translate,
length: 1,
cssClass: 'all-caps-label'
}
]"
[small]="true"
></iqser-status-bar>
</div>
<div class="cell small-label stats-subtitle">
<div>
<mat-icon *ngIf="item.archived" svgIcon="red:archive"></mat-icon>
{{ item.dossierName }}
</div>
</div>
<div class="cell small-label stats-subtitle">
<div>
<mat-icon svgIcon="iqser:pages"></mat-icon>
{{ item.numberOfPages }}
</div> </div>
</div> </div>

View File

@ -16,6 +16,7 @@ import {
CircleButtonType, CircleButtonType,
CircleButtonTypes, CircleButtonTypes,
ConfirmationDialogInput, ConfirmationDialogInput,
IqserPermissionsService,
IqserTooltipPosition, IqserTooltipPosition,
LoadingService, LoadingService,
Toaster, Toaster,
@ -37,6 +38,7 @@ import { PageRotationService } from '../../../pdf-viewer/services/page-rotation.
import { FileAssignService } from '../../services/file-assign.service'; import { FileAssignService } from '../../services/file-assign.service';
import { ViewerHeaderService } from '../../../pdf-viewer/services/viewer-header.service'; import { ViewerHeaderService } from '../../../pdf-viewer/services/viewer-header.service';
import { ROTATION_ACTION_BUTTONS } from '../../../pdf-viewer/utils/constants'; import { ROTATION_ACTION_BUTTONS } from '../../../pdf-viewer/utils/constants';
import { ROLES } from '@users/roles';
@Component({ @Component({
selector: 'redaction-file-actions [file] [type] [dossier]', selector: 'redaction-file-actions [file] [type] [dossier]',
@ -97,6 +99,7 @@ export class FileActionsComponent implements OnChanges {
private readonly _fileAssignService: FileAssignService, private readonly _fileAssignService: FileAssignService,
private readonly _reanalysisService: ReanalysisService, private readonly _reanalysisService: ReanalysisService,
private readonly _permissionsService: PermissionsService, private readonly _permissionsService: PermissionsService,
private readonly _iqserPermissionsService: IqserPermissionsService,
private readonly _pageRotationService: PageRotationService, private readonly _pageRotationService: PageRotationService,
private readonly _viewerHeaderService: ViewerHeaderService, private readonly _viewerHeaderService: ViewerHeaderService,
private readonly _activeDossiersService: ActiveDossiersService, private readonly _activeDossiersService: ActiveDossiersService,
@ -150,7 +153,7 @@ export class FileActionsComponent implements OnChanges {
action: ($event: MouseEvent) => this._openImportRedactionsDialog($event), action: ($event: MouseEvent) => this._openImportRedactionsDialog($event),
tooltip: _('dossier-overview.import-redactions'), tooltip: _('dossier-overview.import-redactions'),
icon: 'red:import_redactions', icon: 'red:import_redactions',
show: this.showImportRedactions, show: this.showImportRedactions && !this._iqserPermissionsService.has(ROLES.getRss),
}, },
{ {
type: ActionTypes.downloadBtn, type: ActionTypes.downloadBtn,
@ -177,7 +180,8 @@ export class FileActionsComponent implements OnChanges {
show: show:
!!this._excludedPagesService && !!this._excludedPagesService &&
!this.file.excluded && !this.file.excluded &&
this._permissionsService.canExcludePages(this.file, this.dossier), this._permissionsService.canExcludePages(this.file, this.dossier) &&
!this._iqserPermissionsService.has(ROLES.getRss),
}, },
{ {
type: ActionTypes.circleBtn, type: ActionTypes.circleBtn,

View File

@ -73,7 +73,7 @@
</iqser-icon-button> </iqser-icon-button>
<div (click)="revert()" class="all-caps-label cancel" id="revert" translate="edit-dossier-dialog.actions.revert"></div> <div (click)="revert()" class="all-caps-label cancel" id="revert" translate="edit-dossier-dialog.actions.revert"></div>
<iqser-help-button [dialogButton]="true"></iqser-help-button> <iqser-help-button [dialogButton]="true" *ngIf="!iqserPermissionsService.has(roles.getRss)"></iqser-help-button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -40,6 +40,7 @@ interface NavItem {
providers: [dossiersServiceProvider], providers: [dossiersServiceProvider],
}) })
export class EditDossierDialogComponent extends BaseDialogComponent implements AfterViewInit { export class EditDossierDialogComponent extends BaseDialogComponent implements AfterViewInit {
readonly roles = ROLES;
navItems: NavItem[] = []; navItems: NavItem[] = [];
readonly iconButtonTypes = IconButtonTypes; readonly iconButtonTypes = IconButtonTypes;
activeNav: Section; activeNav: Section;
@ -53,9 +54,9 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A
private _dossier: Dossier; private _dossier: Dossier;
constructor( constructor(
readonly iqserPermissionsService: IqserPermissionsService,
private readonly _dossiersService: DossiersService, private readonly _dossiersService: DossiersService,
private readonly _permissionsService: PermissionsService, private readonly _permissionsService: PermissionsService,
private readonly _iqserPermissionsService: IqserPermissionsService,
protected readonly _dialogRef: MatDialogRef<EditDossierDialogComponent>, protected readonly _dialogRef: MatDialogRef<EditDossierDialogComponent>,
@Inject(MAT_DIALOG_DATA) @Inject(MAT_DIALOG_DATA)
private readonly _data: { private readonly _data: {
@ -99,7 +100,7 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A
return ( return (
(['members'].includes(this.activeNav) && (['members'].includes(this.activeNav) &&
this.#currentUser.isManager && this.#currentUser.isManager &&
this._iqserPermissionsService.has(ROLES.dossiers.edit)) || this.iqserPermissionsService.has(ROLES.dossiers.edit)) ||
this._permissionsService.canEditDossier(this._dossier) this._permissionsService.canEditDossier(this._dossier)
); );
} }

View File

@ -21,6 +21,8 @@
.mat-chip-list-wrapper { .mat-chip-list-wrapper {
height: 100%; height: 100%;
align-items: flex-start;
flex-direction: column;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
@include common-mixins.scroll-bar(); @include common-mixins.scroll-bar();

View File

@ -2,6 +2,7 @@ import { Component, Input, OnChanges } from '@angular/core';
import { INestedFilter } from '@iqser/common-ui'; import { INestedFilter } from '@iqser/common-ui';
import { SuperTypes } from '@red/domain'; import { SuperTypes } from '@red/domain';
import { DefaultColorsService } from '@services/entity-services/default-colors.service'; import { DefaultColorsService } from '@services/entity-services/default-colors.service';
import { TranslateService } from '@ngx-translate/core';
@Component({ @Component({
selector: 'redaction-type-filter [dossierTemplateId]', selector: 'redaction-type-filter [dossierTemplateId]',
@ -26,7 +27,7 @@ export class TypeFilterComponent implements OnChanges {
]; ];
private _needsAnalysisKeys: string[] = ['remove-only-here', 'analysis']; private _needsAnalysisKeys: string[] = ['remove-only-here', 'analysis'];
constructor(private readonly _defaultColorsService: DefaultColorsService) {} constructor(private readonly _defaultColorsService: DefaultColorsService, private readonly _translateService: TranslateService) {}
ngOnChanges(): void { ngOnChanges(): void {
this.label = this.label =
@ -38,6 +39,8 @@ export class TypeFilterComponent implements OnChanges {
? 'A' ? 'A'
: this._suggestionsKeys.includes(this.filter.id) : this._suggestionsKeys.includes(this.filter.id)
? 'S' ? 'S'
: this.filter.id.charAt(0); : this.filter.skipTranslation
? this.filter.label.charAt(0)
: this._translateService.instant(this.filter.label).charAt(0);
} }
} }

View File

@ -109,7 +109,7 @@
icon="red:assign" icon="red:assign"
></iqser-icon-button> ></iqser-icon-button>
<iqser-help-button [helpButtonKey]="'new_dossier_button'"></iqser-help-button> <iqser-help-button [helpButtonKey]="'new_dossier_button'" *ngIf="!permissionsService.has(roles.getRss)"></iqser-help-button>
</div> </div>
</form> </form>

View File

@ -3,7 +3,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DOSSIER_TEMPLATE_ID, DownloadFileType, IDossierRequest, IDossierTemplate, IReportTemplate } from '@red/domain'; import { DOSSIER_TEMPLATE_ID, DownloadFileType, IDossierRequest, IDossierTemplate, IReportTemplate } from '@red/domain';
import { UntypedFormGroup, Validators } from '@angular/forms'; import { UntypedFormGroup, Validators } from '@angular/forms';
import { downloadTypesTranslations } from '@translations/download-types-translations'; import { downloadTypesTranslations } from '@translations/download-types-translations';
import { BaseDialogComponent, IconButtonTypes, SaveOptions } from '@iqser/common-ui'; import { BaseDialogComponent, IconButtonTypes, IqserPermissionsService, SaveOptions } from '@iqser/common-ui';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
import { ReportTemplateService } from '@services/report-template.service'; import { ReportTemplateService } from '@services/report-template.service';
@ -11,6 +11,7 @@ import { firstValueFrom } from 'rxjs';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service'; import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service';
import { ROLES } from '@users/roles';
interface DialogData { interface DialogData {
readonly dossierTemplateId?: string; readonly dossierTemplateId?: string;
@ -21,20 +22,26 @@ interface DialogData {
styleUrls: ['./add-dossier-dialog.component.scss'], styleUrls: ['./add-dossier-dialog.component.scss'],
}) })
export class AddDossierDialogComponent extends BaseDialogComponent implements OnInit { export class AddDossierDialogComponent extends BaseDialogComponent implements OnInit {
readonly roles = ROLES;
readonly iconButtonTypes = IconButtonTypes; readonly iconButtonTypes = IconButtonTypes;
hasDueDate = false; hasDueDate = false;
downloadTypes: { key: DownloadFileType; label: string }[] = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map( downloadTypes: { key: DownloadFileType; label: string }[] = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED']
(type: DownloadFileType) => ({ .map((type: DownloadFileType) => ({
key: type, key: type,
label: downloadTypesTranslations[type], label: downloadTypesTranslations[type],
}), }))
); .filter(
element =>
!this.permissionsService.has(ROLES.getRss) ||
(this.permissionsService.has(ROLES.getRss) && !['DELTA_PREVIEW', 'REDACTED'].includes(element.key)),
);
dossierTemplates: IDossierTemplate[]; dossierTemplates: IDossierTemplate[];
availableReportTypes = []; availableReportTypes = [];
dossierTemplateId: string; dossierTemplateId: string;
constructor( constructor(
readonly permissionsService: IqserPermissionsService,
private readonly _activeDossiersService: ActiveDossiersService, private readonly _activeDossiersService: ActiveDossiersService,
private readonly _dossierTemplatesService: DossierTemplatesService, private readonly _dossierTemplatesService: DossierTemplatesService,
private readonly _reportTemplateController: ReportTemplateService, private readonly _reportTemplateController: ReportTemplateService,

View File

@ -15,8 +15,7 @@
"RECENT_PERIOD_IN_HOURS": 24, "RECENT_PERIOD_IN_HOURS": 24,
"SELECTION_MODE": "structural", "SELECTION_MODE": "structural",
"MANUAL_BASE_URL": "https://docs.redactmanager.com/preview", "MANUAL_BASE_URL": "https://docs.redactmanager.com/preview",
"RSS_ENABLED": true,
"ANNOTATIONS_THRESHOLD": 1000, "ANNOTATIONS_THRESHOLD": 1000,
"THEME": "theme-template", "THEME": "scm",
"BASE_TRANSLATIONS_DIRECTORY": "/assets/i18n/redact/" "BASE_TRANSLATIONS_DIRECTORY": "/assets/i18n/scm/"
} }

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" version="1.1" viewBox="0 0 16 16" width="16px"
xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd" id="Redacted" stroke="none" stroke-width="1">
<rect fill="#283241" height="16" id="Rectangle" width="16" x="0" y="0"></rect>
<text fill="#FFFFFF" font-family="Inter-SemiBold, Inter" font-size="11" font-weight="500"
id="H">
<tspan x="4.421875" y="12">C</tspan>
</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 519 B

View File

@ -17,7 +17,6 @@ OAUTH_URL="${OAUTH_URL:-/auth}"
RECENT_PERIOD_IN_HOURS="${RECENT_PERIOD_IN_HOURS:-24}" RECENT_PERIOD_IN_HOURS="${RECENT_PERIOD_IN_HOURS:-24}"
SELECTION_MODE="${SELECTION_MODE:-structural}" SELECTION_MODE="${SELECTION_MODE:-structural}"
MANUAL_BASE_URL="${MANUAL_BASE_URL:-https://docs.redactmanager.com/preview}" MANUAL_BASE_URL="${MANUAL_BASE_URL:-https://docs.redactmanager.com/preview}"
RSS_ENABLED="${RSS_ENABLED:-false}"
ANNOTATIONS_THRESHOLD="${ANNOTATIONS_THRESHOLD:-1000}" ANNOTATIONS_THRESHOLD="${ANNOTATIONS_THRESHOLD:-1000}"
BASE_TRANSLATIONS_DIRECTORY="${BASE_TRANSLATIONS_DIRECTORY:-/assets/i18n/redact/}" BASE_TRANSLATIONS_DIRECTORY="${BASE_TRANSLATIONS_DIRECTORY:-/assets/i18n/redact/}"
THEME="${THEME:-theme-template}" THEME="${THEME:-theme-template}"
@ -41,7 +40,6 @@ echo '{
"RECENT_PERIOD_IN_HOURS":"'"$RECENT_PERIOD_IN_HOURS"'", "RECENT_PERIOD_IN_HOURS":"'"$RECENT_PERIOD_IN_HOURS"'",
"SELECTION_MODE":"'"$SELECTION_MODE"'", "SELECTION_MODE":"'"$SELECTION_MODE"'",
"MANUAL_BASE_URL":"'"$MANUAL_BASE_URL"'", "MANUAL_BASE_URL":"'"$MANUAL_BASE_URL"'",
"RSS_ENABLED":"'"$RSS_ENABLED"'",
"BASE_TRANSLATIONS_DIRECTORY":"'"$BASE_TRANSLATIONS_DIRECTORY"'", "BASE_TRANSLATIONS_DIRECTORY":"'"$BASE_TRANSLATIONS_DIRECTORY"'",
"THEME":"'"$THEME"'", "THEME":"'"$THEME"'",
"ANNOTATIONS_THRESHOLD":"'"$ANNOTATIONS_THRESHOLD"'" "ANNOTATIONS_THRESHOLD":"'"$ANNOTATIONS_THRESHOLD"'"

View File

@ -133,7 +133,7 @@ export class File extends Entity<IFile> implements IFile {
this.numberOfOCRedPages = file.numberOfOCRedPages ?? 0; this.numberOfOCRedPages = file.numberOfOCRedPages ?? 0;
this.statusSort = StatusSorter[this.workflowStatus]; this.statusSort = StatusSorter[this.workflowStatus];
this.cacheIdentifier = btoa(this.fileManipulationDate ?? ''); this.cacheIdentifier = btoa(`${this.fileManipulationDate}${file.lastOCRTime}${file.ocrEndTime}`);
this.hintsOnly = this.hasHints && !this.hasRedactions; this.hintsOnly = this.hasHints && !this.hasRedactions;
this.hasNone = !this.hasRedactions && !this.hasHints && !this.hasSuggestions; this.hasNone = !this.hasRedactions && !this.hasHints && !this.hasSuggestions;
this.isProcessing = isProcessingStatuses.includes(this.processingStatus); this.isProcessing = isProcessingStatuses.includes(this.processingStatus);