Workflow initial

This commit is contained in:
Adina Țeudan 2021-09-21 15:44:49 +03:00
parent c975fc859f
commit b9ecec3e52
17 changed files with 340 additions and 88 deletions

View File

@ -14,12 +14,12 @@
border-radius: 4px;
width: 100%;
justify-content: flex-start;
padding: 0 8px;
padding: 4px 8px;
margin-left: -8px;
&.link-property {
cursor: pointer;
transition: background-color 0.2;
transition: background-color 0.2s;
&:hover {
background-color: $grey-6;

View File

@ -1,17 +1,26 @@
<div *ngIf="screen === 'dossier-overview'" class="action-buttons">
<div *ngIf="isDossierOverviewList" class="action-buttons">
<ng-container *ngTemplateOutlet="actions"></ng-container>
<iqser-status-bar *ngIf="isWorkable" [configs]="statusBarConfig"></iqser-status-bar>
<iqser-status-bar *ngIf="showStatusBar" [configs]="statusBarConfig"></iqser-status-bar>
</div>
<ng-container *ngIf="screen === 'file-preview'">
<ng-container *ngIf="isFilePreview || isDossierOverviewWorkflow">
<ng-container *ngTemplateOutlet="actions"></ng-container>
</ng-container>
<ng-template #actions>
<div class="file-actions" *ngIf="fileStatus">
<div *ngIf="fileStatus" class="file-actions">
<iqser-circle-button
(action)="openDocument()"
*ngIf="showOpenDocument"
[tooltipPosition]="tooltipPosition"
[tooltip]="'dossier-overview.open-document' | translate"
[type]="buttonType"
icon="red:collapse"
></iqser-circle-button>
<iqser-circle-button
(action)="openDeleteFileDialog($event)"
*ngIf="canDelete"
*ngIf="showDelete"
[tooltipPosition]="tooltipPosition"
[tooltip]="'dossier-overview.delete.action' | translate"
[type]="buttonType"
@ -20,7 +29,7 @@
<iqser-circle-button
(action)="assign($event)"
*ngIf="canAssign && screen === 'dossier-overview'"
*ngIf="showAssign"
[tooltipPosition]="tooltipPosition"
[tooltip]="assignTooltip | translate"
[type]="buttonType"
@ -29,7 +38,7 @@
<iqser-circle-button
(action)="assignToMe($event)"
*ngIf="canAssignToSelf && screen === 'dossier-overview'"
*ngIf="showAssignToSelf"
[tooltipPosition]="tooltipPosition"
[tooltip]="'dossier-overview.assign-me' | translate"
[type]="buttonType"
@ -47,7 +56,7 @@
<iqser-circle-button
(action)="toggleViewDocumentInfo()"
*ngIf="screen === 'file-preview'"
*ngIf="showDocumentInfo"
[attr.aria-expanded]="activeDocumentInfo"
[tooltip]="'file-preview.document-info' | translate"
icon="red:status-info"
@ -56,7 +65,7 @@
<iqser-circle-button
(action)="toggleExcludePages()"
*ngIf="screen === 'file-preview'"
*ngIf="showExcludePages"
[attr.aria-expanded]="activeExcludePages"
[showDot]="!!fileStatus.excludedPages?.length"
[tooltip]="'file-preview.exclude-pages' | translate"
@ -67,7 +76,7 @@
<!-- Ready for approval-->
<iqser-circle-button
(action)="setFileUnderApproval($event)"
*ngIf="canSetToUnderApproval"
*ngIf="showUnderApproval"
[tooltipPosition]="tooltipPosition"
[tooltip]="'dossier-overview.under-approval' | translate"
[type]="buttonType"
@ -77,7 +86,7 @@
<!-- Back to review -->
<iqser-circle-button
(action)="setFileUnderReview($event, true)"
*ngIf="canSetToUnderReview"
*ngIf="showUnderReview"
[tooltipPosition]="tooltipPosition"
[tooltip]="'dossier-overview.under-review' | translate"
[type]="buttonType"
@ -87,7 +96,7 @@
<!-- Approved-->
<iqser-circle-button
(action)="setFileApproved($event)"
*ngIf="readyForApproval"
*ngIf="showApprove"
[disabled]="!fileStatus.canBeApproved"
[tooltipPosition]="tooltipPosition"
[tooltip]="
@ -100,7 +109,7 @@
<!-- Back to approval -->
<iqser-circle-button
(action)="setFileUnderApproval($event)"
*ngIf="canUndoApproval"
*ngIf="showUndoApproval"
[tooltipPosition]="tooltipPosition"
[tooltip]="'dossier-overview.under-approval' | translate"
[type]="buttonType"
@ -109,7 +118,7 @@
<iqser-circle-button
(action)="ocrFile($event)"
*ngIf="fileStatus.canBeOCRed"
*ngIf="showOCR"
[tooltipPosition]="tooltipPosition"
[tooltip]="'dossier-overview.ocr-file' | translate"
[type]="buttonType"
@ -119,22 +128,22 @@
<!-- reanalyse file preview -->
<iqser-circle-button
(action)="reanalyseFile($event)"
*ngIf="canReanalyse && screen === 'file-preview'"
*ngIf="canReanalyse && isFilePreview"
[tooltip]="'file-preview.reanalyse-notification' | translate"
[type]="circleButtonTypes.warn"
icon="iqser:refresh"
tooltipClass="warn small"
tooltipPosition="below"
[type]="circleButtonTypes.warn"
></iqser-circle-button>
<!-- reanalyse file listing -->
<iqser-circle-button
(action)="reanalyseFile($event)"
*ngIf="canReanalyse && screen === 'dossier-overview'"
*ngIf="canReanalyse && isDossierOverview"
[tooltipPosition]="tooltipPosition"
[tooltip]="'dossier-overview.reanalyse.action' | translate"
icon="iqser:refresh"
[type]="circleButtonTypes.dark"
icon="iqser:refresh"
></iqser-circle-button>
<!-- exclude from redaction -->
@ -143,7 +152,7 @@
(change)="toggleAnalysis()"
(click)="$event.stopPropagation()"
[checked]="!fileStatus?.excluded"
[class.mr-24]="screen === 'dossier-overview'"
[class.mr-24]="isDossierOverviewList"
[disabled]="!canToggleAnalysis"
[matTooltipPosition]="tooltipPosition"
[matTooltip]="toggleTooltip | translate"

View File

@ -1,5 +1,9 @@
@import 'libs/common-ui/src/assets/styles/mixins';
.file-actions {
display: flex;
overflow-y: auto;
@include no-scroll-bar;
> *:not(:last-child) {
margin-right: 2px;

View File

@ -5,7 +5,7 @@ import { AppStateService } from '@state/app-state.service';
import { FileActionService } from '../../services/file-action.service';
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component';
import { AutoUnsubscribe, CircleButtonType, CircleButtonTypes, LoadingService, StatusBarConfig, Toaster } from '@iqser/common-ui';
import { AutoUnsubscribe, CircleButtonType, CircleButtonTypes, LoadingService, Required, StatusBarConfig, Toaster } from '@iqser/common-ui';
import { FileManagementControllerService, FileStatus } from '@redaction/red-ui-http';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { UserService } from '@services/user.service';
@ -23,25 +23,29 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
@Input() fileStatus: FileStatusWrapper;
@Input() activeDocumentInfo: boolean;
@Input() activeExcludePages: boolean;
@Input() @Required() type: 'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow';
@Output() actionPerformed = new EventEmitter<string>();
screen: 'file-preview' | 'dossier-overview';
statusBarConfig?: readonly StatusBarConfig<FileStatus.StatusEnum>[];
tooltipPosition?: 'below' | 'above';
toggleTooltip?: string;
assignTooltip?: string;
buttonType?: CircleButtonType;
isWorkable: boolean;
canUndoApproval: boolean;
canAssignToSelf: boolean;
canAssign: boolean;
canDelete: boolean;
showUndoApproval: boolean;
showAssignToSelf: boolean;
showAssign: boolean;
showDelete: boolean;
showOCR: boolean;
canReanalyse: boolean;
canSetToUnderReview: boolean;
canSetToUnderApproval: boolean;
readyForApproval: boolean;
showUnderReview: boolean;
showUnderApproval: boolean;
showApprove: boolean;
canToggleAnalysis: boolean;
showExcludePages: boolean;
showDocumentInfo: boolean;
showStatusBar: boolean;
showOpenDocument: boolean;
constructor(
readonly permissionsService: PermissionsService,
@ -56,6 +60,22 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
super();
}
get isDossierOverviewList(): boolean {
return this.type === 'dossier-overview-list';
}
get isDossierOverviewWorkflow(): boolean {
return this.type === 'dossier-overview-workflow';
}
get isFilePreview(): boolean {
return this.type === 'file-preview';
}
get isDossierOverview(): boolean {
return this.type.startsWith('dossier-overview-list');
}
private get _toggleTooltip(): string {
if (!this.currentUser.isManager) {
return _('file-preview.toggle-analysis.only-managers');
@ -65,13 +85,9 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
}
ngOnInit(): void {
if (this.fileStatus) {
this.screen = 'dossier-overview';
} else {
if (!this.fileStatus) {
this.fileStatus = this.appStateService.activeFile;
this.screen = 'file-preview';
}
this._setup();
this.addSubscription = this.appStateService.fileChanged$
.pipe(filter(file => file.fileId === this.fileStatus?.fileId))
@ -93,6 +109,10 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
this.actionPerformed.emit('view-exclude-pages');
}
openDocument() {
this.actionPerformed.emit('navigate');
}
openDeleteFileDialog($event: MouseEvent) {
this._dialogService.openDialog(
'confirm',
@ -194,22 +214,31 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
private _setup() {
this.statusBarConfig = [{ color: this.fileStatus.status, length: 1 }];
this.tooltipPosition = this.screen === 'file-preview' ? 'below' : 'above';
this.tooltipPosition = this.isFilePreview ? 'below' : 'above';
this.assignTooltip = this.fileStatus.isUnderApproval
? _('dossier-overview.assign-approver')
: _('dossier-overview.assign-reviewer');
this.buttonType = this.screen === 'file-preview' ? CircleButtonTypes.default : CircleButtonTypes.dark;
this.isWorkable = this.fileStatus.isWorkable;
this.buttonType = this.isFilePreview ? CircleButtonTypes.default : CircleButtonTypes.dark;
this.toggleTooltip = this._toggleTooltip;
this.canUndoApproval = this.permissionsService.canUndoApproval(this.fileStatus);
this.canAssignToSelf = this.permissionsService.canAssignToSelf(this.fileStatus);
this.canAssign = this.permissionsService.canAssignUser(this.fileStatus);
this.canDelete = this.permissionsService.canDeleteFile(this.fileStatus);
this.canReanalyse = this.permissionsService.canReanalyseFile(this.fileStatus);
this.canSetToUnderReview = this.permissionsService.canSetUnderReview(this.fileStatus);
this.canSetToUnderApproval = this.permissionsService.canSetUnderApproval(this.fileStatus);
this.readyForApproval = this.permissionsService.isReadyForApproval(this.fileStatus);
this.showUndoApproval = this.permissionsService.canUndoApproval(this.fileStatus) && !this.isDossierOverviewWorkflow;
this.showUnderReview = this.permissionsService.canSetUnderReview(this.fileStatus) && !this.isDossierOverviewWorkflow;
this.showUnderApproval = this.permissionsService.canSetUnderApproval(this.fileStatus) && !this.isDossierOverviewWorkflow;
this.showApprove = this.permissionsService.isReadyForApproval(this.fileStatus) && !this.isDossierOverviewWorkflow;
this.canToggleAnalysis = this.permissionsService.canToggleAnalysis(this.fileStatus);
this.showDelete = this.permissionsService.canDeleteFile(this.fileStatus);
this.showOCR = this.fileStatus.canBeOCRed;
this.canReanalyse = this.permissionsService.canReanalyseFile(this.fileStatus);
this.showStatusBar = this.fileStatus.isWorkable && this.isDossierOverviewList;
this.showAssignToSelf = this.permissionsService.canAssignToSelf(this.fileStatus) && this.isDossierOverview;
this.showAssign = this.permissionsService.canAssignUser(this.fileStatus) && this.isDossierOverview;
this.showOpenDocument = this.fileStatus.canBeOpened && this.isDossierOverviewWorkflow;
this.showExcludePages = this.isFilePreview;
this.showDocumentInfo = this.isFilePreview;
}
}

View File

@ -33,10 +33,10 @@
<ng-template #nameTemplate let-dossier="entity">
<div class="cell">
<div [matTooltip]="dossier.dossierName" class="table-item-title heading" matTooltipPosition="above">
<div [matTooltip]="dossier.dossierName" class="table-item-title heading mb-6" matTooltipPosition="above">
{{ dossier.dossierName }}
</div>
<div class="small-label stats-subtitle">
<div class="small-label stats-subtitle mb-6">
<div>
<mat-icon svgIcon="red:template"></mat-icon>
{{ dossier.dossierTemplateName }}

View File

@ -4,6 +4,7 @@
[actionConfigs]="actionConfigs"
[fileAttributeConfigs]="fileAttributeConfigs"
[showCloseButton]="true"
[viewModeSelection]="viewModeSelection"
>
<redaction-file-download-btn
[dossier]="currentDossier"
@ -37,6 +38,7 @@
<div [class.extended]="collapsedDetails" class="content-container">
<iqser-table
(noDataAction)="fileInput.click()"
*ngIf="(listingMode$ | async) === listingModes.table"
[bulkActions]="bulkActions"
[hasScrollButton]="true"
[itemSize]="80"
@ -49,6 +51,12 @@
noDataButtonIcon="red:upload"
noDataIcon="red:document"
></iqser-table>
<iqser-workflow
*ngIf="(listingMode$ | async) === listingModes.workflow"
[config]="workflowConfig"
[itemTemplate]="workflowItemTemplate"
></iqser-workflow>
</div>
<div [class.collapsed]="collapsedDetails" class="right-container" iqserHasScrollbar>
@ -74,34 +82,21 @@
<ng-template #filenameTemplate let-fileStatus="entity">
<div class="cell">
<div class="filename-wrapper">
<div [class.error]="fileStatus.isError" class="table-item-title text-overflow">
<div>
<div [class.error]="fileStatus.isError" class="table-item-title">
<span [matTooltip]="fileStatus.filename" matTooltipPosition="above">
{{ fileStatus.filename }}
</span>
</div>
</div>
<div *ngIf="fileStatus.primaryAttribute" class="small-label">
<div class="primary-attribute text-overflow">
<div class="primary-attribute">
<span [matTooltip]="fileStatus.primaryAttribute" matTooltipPosition="above">
{{ fileStatus.primaryAttribute }}
</span>
</div>
</div>
<div class="small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:pages"></mat-icon>
{{ fileStatus.numberOfPages }}
</div>
<div>
<mat-icon svgIcon="red:exclude-pages"></mat-icon>
{{ fileStatus.excludedPagesCount }}
</div>
<div *ngIf="fileStatus.lastOCRTime" [matTooltipPosition]="'above'" [matTooltip]="'dossier-overview.ocr-performed' | translate">
<mat-icon svgIcon="red:ocr"></mat-icon>
{{ fileStatus.lastOCRTime | date: 'mediumDate' }}
</div>
</div>
<ng-container *ngTemplateOutlet="statsTemplate; context: { entity: fileStatus }"></ng-container>
</div>
</ng-template>
@ -167,10 +162,71 @@
></iqser-status-bar>
<redaction-file-actions
(actionPerformed)="calculateData()"
(actionPerformed)="actionPerformed()"
*ngIf="!fileStatus.isProcessing"
[fileStatus]="fileStatus"
class="mr-4"
type="dossier-overview-list"
></redaction-file-actions>
</div>
</ng-template>
<ng-template #viewModeSelection>
<div class="view-mode-selection">
<div class="all-caps-label" translate="view-mode.view-as"></div>
<iqser-circle-button
(action)="listingMode = listingModes.workflow"
[attr.aria-expanded]="(listingMode$ | async) === listingModes.workflow"
[tooltip]="'view-mode.workflow' | translate"
icon="iqser:lanes"
></iqser-circle-button>
<iqser-circle-button
(action)="listingMode = listingModes.table"
[attr.aria-expanded]="(listingMode$ | async) === listingModes.table"
[tooltip]="'view-mode.list' | translate"
icon="iqser:list"
></iqser-circle-button>
</div>
</ng-template>
<ng-template #workflowItemTemplate let-fileStatus="entity">
<div class="workflow-item">
<div>
<div class="details">
<div class="filename">
<span [matTooltip]="fileStatus.filename" matTooltipPosition="above">
{{ fileStatus.filename }}
</span>
</div>
<ng-container *ngTemplateOutlet="statsTemplate; context: { entity: fileStatus }"></ng-container>
</div>
<div class="user">
<redaction-initials-avatar [userId]="fileStatus.currentReviewer"></redaction-initials-avatar>
</div>
</div>
<redaction-file-actions
(actionPerformed)="actionPerformed($event, fileStatus)"
*ngIf="!fileStatus.isProcessing"
[fileStatus]="fileStatus"
type="dossier-overview-workflow"
></redaction-file-actions>
</div>
</ng-template>
<ng-template #statsTemplate let-fileStatus="entity">
<div class="small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:pages"></mat-icon>
{{ fileStatus.numberOfPages }}
</div>
<div>
<mat-icon svgIcon="red:exclude-pages"></mat-icon>
{{ fileStatus.excludedPagesCount }}
</div>
<div *ngIf="fileStatus.lastOCRTime" [matTooltipPosition]="'above'" [matTooltip]="'dossier-overview.ocr-performed' | translate">
<mat-icon svgIcon="red:ocr"></mat-icon>
{{ fileStatus.lastOCRTime | date: 'mediumDate' }}
</div>
</div>
</ng-template>

View File

@ -1,4 +1,5 @@
@import '../../../../../assets/styles/variables';
@import 'libs/common-ui/src/assets/styles/mixins';
.file-upload-input {
display: none;
@ -27,6 +28,7 @@
.primary-attribute {
padding-top: 6px;
@include line-clamp(1);
}
&.extend-cols {
@ -63,3 +65,55 @@
background-color: inherit;
}
}
.view-mode-selection {
border-right: 1px solid $separator;
padding-right: 16px;
margin-right: 16px !important;
display: flex;
align-items: center;
> iqser-circle-button:not(:last-child) {
margin-right: 2px;
}
> div {
margin-right: 8px;
}
}
.workflow-item {
padding: 10px;
> div {
display: flex;
justify-content: space-between;
.details {
max-width: calc(100% - 28px);
.filename {
font-weight: 600;
@include line-clamp(1);
}
}
.user {
display: flex;
align-items: flex-end;
}
}
redaction-file-actions {
margin-top: 10px;
display: none;
}
&:hover redaction-file-actions {
display: block;
}
}
.stats-subtitle {
margin-top: 4px;
}

View File

@ -10,6 +10,7 @@ import {
TemplateRef,
ViewChild
} from '@angular/core';
import { FileAttributeConfig, FileStatus } from '@redaction/red-ui-http';
import { AppStateService } from '@state/app-state.service';
import { FileDropOverlayService } from '@upload-download/services/file-drop-overlay.service';
import { FileUploadModel } from '@upload-download/model/file-upload.model';
@ -34,11 +35,13 @@ import {
DefaultListingServices,
keyChecker,
ListingComponent,
ListingModes,
LoadingService,
NestedFilter,
TableColumnConfig,
TableComponent,
Toaster
Toaster,
WorkflowConfig
} from '@iqser/common-ui';
import { DossierAttributesService } from '@shared/services/controller-wrappers/dossier-attributes.service';
import { DossierAttributeWithValue } from '@models/dossier-attributes.model';
@ -49,8 +52,10 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { annotationFilterChecker } from '@utils/filter-utils';
import { PermissionsService } from '@services/permissions.service';
import { RouterHistoryService } from '@services/router-history.service';
import { FileAttributeConfig } from '@redaction/red-ui-http';
import { DossierWrapper } from '../../../../state/model/dossier.wrapper';
import { Router } from '@angular/router';
import { FileActionService } from '../../services/file-action.service';
import StatusEnum = FileStatus.StatusEnum;
@Component({
templateUrl: './dossier-overview-screen.component.html',
@ -58,6 +63,7 @@ import { DossierWrapper } from '../../../../state/model/dossier.wrapper';
providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => DossierOverviewScreenComponent) }]
})
export class DossierOverviewScreenComponent extends ListingComponent<FileStatusWrapper> implements OnInit, OnDestroy, OnDetach, OnAttach {
readonly listingModes = ListingModes;
readonly circleButtonTypes = CircleButtonTypes;
readonly currentUser = this._userService.currentUser;
currentDossier = this._appStateService.activeDossier;
@ -81,6 +87,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
@ViewChild('reviewerTemplate', { static: true }) reviewerTemplate: TemplateRef<never>;
@ViewChild('pagesTemplate', { static: true }) pagesTemplate: TemplateRef<never>;
@ViewChild('statusTemplate', { static: true }) statusTemplate: TemplateRef<never>;
readonly workflowConfig: WorkflowConfig<FileStatusWrapper, StatusEnum>;
protected readonly _primaryKey = 'filename';
@ViewChild(DossierDetailsComponent, { static: false })
private readonly _dossierDetailsComponent: DossierDetailsComponent;
@ -93,6 +100,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
constructor(
private readonly _toaster: Toaster,
protected readonly _injector: Injector,
private readonly _router: Router,
private readonly _userService: UserService,
readonly permissionsService: PermissionsService,
private readonly _loadingService: LoadingService,
@ -106,13 +114,49 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
private readonly _statusOverlayService: StatusOverlayService,
private readonly _userPreferenceService: UserPreferenceService,
private readonly _fileDropOverlayService: FileDropOverlayService,
private readonly _dossierAttributesService: DossierAttributesService
private readonly _dossierAttributesService: DossierAttributesService,
private readonly _fileActionService: FileActionService
) {
super(_injector);
this._loadEntitiesFromState();
this.fileAttributeConfigs = this._appStateService.getFileAttributeConfig(
this.currentDossier.dossierTemplateId
).fileAttributeConfigs;
this.listingMode = this.listingModes.workflow;
this.workflowConfig = {
key: 'status',
columns: [
{
label: fileStatusTranslations[StatusEnum.UNASSIGNED],
key: StatusEnum.UNASSIGNED,
enterFn: this.unassignFn,
enterPredicate: (entity: FileStatusWrapper) => !!entity,
color: '#D3D5DA'
},
{
label: fileStatusTranslations[StatusEnum.UNDERREVIEW],
enterFn: this.underReviewFn,
enterPredicate: (file: FileStatusWrapper) => this.permissionsService.canAssignUser(file),
key: StatusEnum.UNDERREVIEW,
color: '#FDBD00'
},
{
label: fileStatusTranslations[StatusEnum.UNDERAPPROVAL],
enterFn: this.underApprovalFn,
enterPredicate: (file: FileStatusWrapper) =>
this.permissionsService.canSetUnderApproval(file) || this.permissionsService.canUndoApproval(file),
key: StatusEnum.UNDERAPPROVAL,
color: '#374C81'
},
{
label: fileStatusTranslations[StatusEnum.APPROVED],
enterFn: this.approveFn,
enterPredicate: (file: FileStatusWrapper) => this.permissionsService.isReadyForApproval(file),
key: StatusEnum.APPROVED,
color: '#48C9F7'
}
]
};
}
get checkedRequiredFilters() {
@ -127,10 +171,46 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
return this.fileAttributeConfigs.filter(config => config.displayedInFileList);
}
unassignFn = async (file: FileStatusWrapper) => {
// TODO
console.log('unassign', file);
};
underReviewFn = (file: FileStatusWrapper) => {
this._fileActionService.assignFile('reviewer', null, file, () => this._loadingService.loadWhile(this.reloadDossiers()), true);
};
underApprovalFn = async (file: FileStatusWrapper) => {
if (this._appStateService.activeDossier.approverIds.length > 1) {
this._fileActionService.assignFile('approver', null, file, () => this._loadingService.loadWhile(this.reloadDossiers()), true);
} else {
this._loadingService.start();
await this._fileActionService.setFileUnderApproval(file).toPromise();
await this.reloadDossiers();
this._loadingService.stop();
}
};
approveFn = async (file: FileStatusWrapper) => {
this._loadingService.start();
await this._fileActionService.setFileApproved(file).toPromise();
await this.reloadDossiers();
this._loadingService.stop();
};
actionPerformed(action?: string, fileStatus?: FileStatusWrapper) {
this._calculateData();
if (action === 'navigate') {
this._router.navigate(this.routerLinkFn(fileStatus));
}
}
routerLinkFn = (fileStatus: FileStatusWrapper) =>
fileStatus.canBeOpened ? [`/main/dossiers/${this.currentDossier.dossierId}/file/${fileStatus.fileId}`] : [];
disabledFn = (fileStatus: FileStatusWrapper) => fileStatus.excluded;
lastOpenedFn = (fileStatus: FileStatusWrapper) => fileStatus.lastOpened;
async ngOnInit(): Promise<void> {
@ -139,7 +219,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
try {
this._fileDropOverlayService.initFileDropHandling();
this.calculateData();
this._calculateData();
this.addSubscription = timer(0, 7500).subscribe(async () => {
await this._appStateService.reloadActiveDossierFilesIfNecessary();
@ -147,7 +227,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
});
this.addSubscription = this._appStateService.fileChanged$.subscribe(() => {
this.calculateData();
this._calculateData();
});
this.addSubscription = this._appStateService.dossierTemplateChanged$.subscribe(() => {
@ -197,10 +277,10 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
async reloadDossiers() {
await this._appStateService.getFiles(this.currentDossier, false);
this.calculateData();
this._calculateData();
}
calculateData(): void {
_calculateData(): void {
if (!this._appStateService.activeDossierId) {
return;
}

View File

@ -91,6 +91,7 @@
(actionPerformed)="fileActionPerformed($event)"
[activeDocumentInfo]="viewDocumentInfo"
[activeExcludePages]="excludePages"
type="file-preview"
></redaction-file-actions>
<iqser-circle-button
@ -106,10 +107,10 @@
(action)="downloadOriginalFile()"
*ngIf="userPreferenceService.areDevFeaturesEnabled"
[tooltip]="'file-preview.download-original-file' | translate"
[type]="circleButtonTypes.primary"
class="ml-8"
icon="red:download"
tooltipPosition="below"
[type]="circleButtonTypes.primary"
></iqser-circle-button>
<!-- End Dev Mode Features-->

View File

@ -8,6 +8,7 @@ import { isArray } from 'rxjs/internal-compatibility';
import { DossiersDialogService } from './dossiers-dialog.service';
import { ConfirmationDialogInput } from '../../shared/dialogs/confirmation-dialog/confirmation-dialog.component';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { Observable } from 'rxjs';
@Injectable()
export class FileActionService {
@ -83,7 +84,7 @@ export class FileActionService {
);
}
setFileApproved(fileStatus: FileStatusWrapper | FileStatusWrapper[]) {
setFileApproved(fileStatus: FileStatusWrapper | FileStatusWrapper[]): Observable<any> {
if (!isArray(fileStatus)) {
fileStatus = [fileStatus];
}
@ -116,11 +117,7 @@ export class FileActionService {
assignFile(mode: 'reviewer' | 'approver', $event: MouseEvent, file?: FileStatusWrapper, callback?: Function, ignoreChanged = false) {
const files = file ? [file] : [this._appStateService.activeFile];
const data = { mode, files, ignoreChanged };
this._dialogService.openDialog('assignFile', $event, data, async () => {
if (callback) {
callback();
}
});
this._dialogService.openDialog('assignFile', $event, data, callback);
}
private async _assignReviewerToCurrentUser(fileStatus: FileStatusWrapper | FileStatusWrapper[], callback?: Function) {

View File

@ -15,7 +15,9 @@
<div (click)="resetFilters()" *ngIf="showResetFilters$ | async" class="reset-filters" translate="reset-filters"></div>
</div>
<div *ngIf="showCloseButton || actionConfigs || buttonConfigs" class="actions">
<div *ngIf="showCloseButton || actionConfigs || buttonConfigs || viewModeSelection" class="actions">
<ng-container [ngTemplateOutlet]="viewModeSelection"></ng-container>
<ng-container *ngFor="let config of buttonConfigs; trackBy: trackByLabel">
<iqser-icon-button
(action)="config.action($event)"
@ -53,10 +55,10 @@
<ng-template #searchBar>
<iqser-input-with-action
[(value)]="searchService.searchValue"
*ngIf="searchPlaceholder && searchService"
[(value)]="searchService.searchValue"
[class.mr-8]="searchPosition === searchPositions.beforeFilters"
[placeholder]="searchPlaceholder"
[width]="searchWidth"
[class.mr-8]="searchPosition === searchPositions.beforeFilters"
></iqser-input-with-action>
</ng-template>

View File

@ -1,3 +1,5 @@
@import '../../../../../assets/styles/variables';
.ml-6 {
margin-left: 6px;
}

View File

@ -1,7 +1,7 @@
import { Component, EventEmitter, Input, Optional, Output } from '@angular/core';
import { Component, EventEmitter, Input, Optional, Output, TemplateRef } from '@angular/core';
import { ActionConfig } from '@shared/components/page-header/models/action-config.model';
import { ButtonConfig } from '@shared/components/page-header/models/button-config.model';
import { FilterService, SearchService } from '@iqser/common-ui';
import { FilterService, IconButtonTypes, Listable, SearchService } from '@iqser/common-ui';
import { distinctUntilChanged, map } from 'rxjs/operators';
import { combineLatest, Observable, of } from 'rxjs';
import { SearchPosition, SearchPositions } from '@shared/components/page-header/models/search-positions.type';
@ -12,13 +12,15 @@ import { FileAttributeConfig } from '@redaction/red-ui-http';
templateUrl: './page-header.component.html',
styleUrls: ['./page-header.component.scss']
})
export class PageHeaderComponent<T> {
export class PageHeaderComponent<T extends Listable> {
readonly searchPositions = SearchPositions;
readonly iconButtonTypes = IconButtonTypes;
@Input() pageLabel: string;
@Input() showCloseButton: boolean;
@Input() actionConfigs: readonly ActionConfig[];
@Input() buttonConfigs: readonly ButtonConfig[];
@Input() viewModeSelection: TemplateRef<unknown>;
@Input() fileAttributeConfigs: readonly FileAttributeConfig[];
@Input() searchPlaceholder: string;
@Input() searchWidth: number | 'full';

View File

@ -680,6 +680,7 @@
},
"ocr-file": "OCR Document",
"ocr-performed": "OCR was performed for this file.",
"open-document": "Open Document",
"quick-filters": {
"assigned-to-me": "Assigned to me",
"assigned-to-others": "Assigned to others",
@ -1491,6 +1492,11 @@
"expand": "Show Details",
"title": "Users"
},
"view-mode": {
"list": "List",
"view-as": "View as:",
"workflow": "Workflow"
},
"watermark": "Watermark",
"watermark-screen": {
"action": {

View File

@ -81,6 +81,8 @@
mat-icon {
width: 10px;
height: 10px;
line-height: 13px;
margin-right: 6px;
}

View File

@ -241,10 +241,18 @@ section.settings {
margin-top: 32px;
}
.mb-6 {
margin-bottom: 6px;
}
.mb-8 {
margin-bottom: 8px !important;
}
.mb-12 {
margin-bottom: 12px !important;
}
.ml-8 {
margin-left: 8px;
}

@ -1 +1 @@
Subproject commit 6c0f123bd97148f8696038f63c9951c241b71990
Subproject commit cb8393c492ec1e2795d644009266cc71eeca11a7