Merge branch 'master' into VM/RED-3982
This commit is contained in:
commit
0962a2cb90
@ -28,10 +28,15 @@ export class CloneDossierTemplateDialogComponent {
|
|||||||
async save() {
|
async save() {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
try {
|
try {
|
||||||
await firstValueFrom(this._dossierTemplatesService.clone(this.dossierTemplateId, this.nameOfClonedDossierTemplate));
|
await firstValueFrom(
|
||||||
|
this._dossierTemplatesService.clone(this.dossierTemplateId, {
|
||||||
|
...this._dossierTemplate,
|
||||||
|
name: this.nameOfClonedDossierTemplate,
|
||||||
|
}),
|
||||||
|
);
|
||||||
this._dialogRef.close(true);
|
this._dialogRef.close(true);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this._toaster.error(_('clone-dossier-template.error.generic'), { error });
|
this._toaster.error(_('clone-dossier-template.error.generic'), { params: error });
|
||||||
}
|
}
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,8 +68,8 @@ export class ReportsScreenComponent implements OnInit {
|
|||||||
);
|
);
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
download(data, template.fileName);
|
download(data, template.fileName);
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
this._toaster.error(_('error.http.generic'));
|
this._toaster.error(_('error.http.generic'), { params: error });
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { RouterModule } from '@angular/router';
|
|||||||
import { SharedModule } from '../shared/shared.module';
|
import { SharedModule } from '../shared/shared.module';
|
||||||
import { TemplateStatsComponent } from './components/template-stats/template-stats.component';
|
import { TemplateStatsComponent } from './components/template-stats/template-stats.component';
|
||||||
import { BreadcrumbTypes } from '@red/domain';
|
import { BreadcrumbTypes } from '@red/domain';
|
||||||
|
import { SharedDossiersModule } from '../shared-dossiers/shared-dossiers.module';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@ -18,6 +19,6 @@ const routes = [
|
|||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [DashboardScreenComponent, TemplateStatsComponent],
|
declarations: [DashboardScreenComponent, TemplateStatsComponent],
|
||||||
imports: [RouterModule.forChild(routes), CommonModule, SharedModule],
|
imports: [RouterModule.forChild(routes), CommonModule, SharedModule, SharedDossiersModule],
|
||||||
})
|
})
|
||||||
export class DashboardModule {}
|
export class DashboardModule {}
|
||||||
|
|||||||
@ -170,8 +170,9 @@ export class DossierOverviewBulkActionsComponent implements OnChanges {
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true);
|
const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true);
|
||||||
|
const allFilesAreApproved = this.selectedFiles.reduce((acc, file) => acc && file.isApproved, true);
|
||||||
this.#allFilesAreExcluded = this.selectedFiles.reduce((acc, file) => acc && file.excluded, true);
|
this.#allFilesAreExcluded = this.selectedFiles.reduce((acc, file) => acc && file.excluded, true);
|
||||||
this.#canMoveToSameState = allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval;
|
this.#canMoveToSameState = allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval || allFilesAreApproved;
|
||||||
|
|
||||||
this.#canAssign =
|
this.#canAssign =
|
||||||
this.#canMoveToSameState &&
|
this.#canMoveToSameState &&
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Dossier, File } from '@red/domain';
|
import { Dossier, File, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
|
||||||
import { DossiersDialogService } from '../../shared-dossiers/services/dossiers-dialog.service';
|
import { DossiersDialogService } from '../../shared-dossiers/services/dossiers-dialog.service';
|
||||||
import { ConfirmationDialogInput, LoadingService } from '@iqser/common-ui';
|
import { ConfirmationDialogInput, LoadingService } from '@iqser/common-ui';
|
||||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||||
@ -26,7 +26,7 @@ export class BulkActionsService {
|
|||||||
const dossier = this._getDossier(files);
|
const dossier = this._getDossier(files);
|
||||||
// If more than 1 approver - show dialog and ask who to assign
|
// If more than 1 approver - show dialog and ask who to assign
|
||||||
if (dossier.approverIds.length > 1) {
|
if (dossier.approverIds.length > 1) {
|
||||||
this._assignFiles(files, 'approver', true);
|
this._assignFiles(files, WorkflowFileStatuses.UNDER_APPROVAL, true);
|
||||||
} else {
|
} else {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
await firstValueFrom(this._filesService.setUnderApprovalFor(files, dossier.id, dossier.approverIds[0]));
|
await firstValueFrom(this._filesService.setUnderApprovalFor(files, dossier.id, dossier.approverIds[0]));
|
||||||
@ -124,15 +124,15 @@ export class BulkActionsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assign(files: File[], mode: 'reviewer' | 'approver' = files[0].isUnderApproval ? 'approver' : 'reviewer') {
|
assign(files: File[]): void {
|
||||||
this._assignFiles(files, mode, false, true);
|
this._assignFiles(files, files[0].workflowStatus, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getDossier(files: File[]): Dossier {
|
private _getDossier(files: File[]): Dossier {
|
||||||
return this._activeDossiersService.find(files[0].dossierId);
|
return this._activeDossiersService.find(files[0].dossierId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _assignFiles(files: File[], mode: 'reviewer' | 'approver', ignoreChanged = false, withUnassignedOption = false) {
|
private _assignFiles(files: File[], targetStatus: WorkflowFileStatus, ignoreChanged = false, withUnassignedOption = false): void {
|
||||||
this._dialogService.openDialog('assignFile', null, { mode, files, ignoreChanged, withUnassignedOption });
|
this._dialogService.openDialog('assignFile', null, { targetStatus, files, ignoreChanged, withUnassignedOption });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,11 +102,11 @@ export class UserManagementComponent {
|
|||||||
const { dossierId, filename } = file;
|
const { dossierId, filename } = file;
|
||||||
this.loadingService.start();
|
this.loadingService.start();
|
||||||
|
|
||||||
if (!assigneeId) {
|
if (!assigneeId || file.isApproved) {
|
||||||
await firstValueFrom(this.filesService.setUnassigned([file], dossierId));
|
await firstValueFrom(this.filesService.setAssignee([file], dossierId, assigneeId));
|
||||||
} else if (file.isNew || file.isUnderReview) {
|
} else if (file.isNew || file.isUnderReview) {
|
||||||
await firstValueFrom(this.filesService.setReviewerFor([file], dossierId, assigneeId));
|
await firstValueFrom(this.filesService.setReviewerFor([file], dossierId, assigneeId));
|
||||||
} else if (file.isUnderApproval) {
|
} else {
|
||||||
await firstValueFrom(this.filesService.setUnderApprovalFor([file], dossierId, assigneeId));
|
await firstValueFrom(this.filesService.setUnderApprovalFor([file], dossierId, assigneeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -319,11 +319,11 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _assign($event: MouseEvent) {
|
private _assign($event: MouseEvent) {
|
||||||
const mode = this.file.isUnderApproval ? 'approver' : 'reviewer';
|
|
||||||
const files = [this.file];
|
const files = [this.file];
|
||||||
|
const targetStatus = this.file.workflowStatus;
|
||||||
const withCurrentUserAsDefault = true;
|
const withCurrentUserAsDefault = true;
|
||||||
const withUnassignedOption = true;
|
const withUnassignedOption = true;
|
||||||
this._dialogService.openDialog('assignFile', $event, { mode, files, withCurrentUserAsDefault, withUnassignedOption });
|
this._dialogService.openDialog('assignFile', $event, { targetStatus, files, withCurrentUserAsDefault, withUnassignedOption });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _assignToMe($event: MouseEvent) {
|
private async _assignToMe($event: MouseEvent) {
|
||||||
|
|||||||
@ -1,17 +1,11 @@
|
|||||||
<section class="dialog">
|
<section class="dialog">
|
||||||
<div
|
<div [translateParams]="{ type: mode }" [translate]="'assign-owner.dialog.title'" class="dialog-header heading-l"></div>
|
||||||
[translateParams]="{
|
|
||||||
type: data.mode
|
|
||||||
}"
|
|
||||||
[translate]="'assign-owner.dialog.title'"
|
|
||||||
class="dialog-header heading-l"
|
|
||||||
></div>
|
|
||||||
|
|
||||||
<form (submit)="save()" [formGroup]="form">
|
<form (submit)="save()" [formGroup]="form">
|
||||||
<div class="dialog-content">
|
<div class="dialog-content">
|
||||||
<div class="iqser-input-group w-300 required">
|
<div class="iqser-input-group w-300 required">
|
||||||
<mat-form-field floatLabel="always">
|
<mat-form-field floatLabel="always">
|
||||||
<mat-label>{{ 'assign-owner.dialog.label' | translate: { type: data.mode } }}</mat-label>
|
<mat-label>{{ 'assign-owner.dialog.label' | translate: { type: mode } }}</mat-label>
|
||||||
<mat-select [placeholder]="'initials-avatar.unassigned' | translate" formControlName="user">
|
<mat-select [placeholder]="'initials-avatar.unassigned' | translate" formControlName="user">
|
||||||
<mat-option *ngFor="let userId of userOptions" [value]="userId">
|
<mat-option *ngFor="let userId of userOptions" [value]="userId">
|
||||||
{{ userId | name: { defaultValue: 'initials-avatar.unassigned' | translate } }}
|
{{ userId | name: { defaultValue: 'initials-avatar.unassigned' | translate } }}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
|||||||
import { UserService } from '@services/user.service';
|
import { UserService } from '@services/user.service';
|
||||||
import { LoadingService, Toaster } from '@iqser/common-ui';
|
import { LoadingService, Toaster } from '@iqser/common-ui';
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { Dossier, File } from '@red/domain';
|
import { Dossier, File, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { FilesService } from '@services/files/files.service';
|
import { FilesService } from '@services/files/files.service';
|
||||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||||
@ -11,7 +11,7 @@ import { PermissionsService } from '@services/permissions.service';
|
|||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
|
|
||||||
class DialogData {
|
class DialogData {
|
||||||
mode: 'approver' | 'reviewer';
|
targetStatus: WorkflowFileStatus;
|
||||||
files: File[];
|
files: File[];
|
||||||
ignoreChanged?: boolean;
|
ignoreChanged?: boolean;
|
||||||
withUnassignedOption?: boolean;
|
withUnassignedOption?: boolean;
|
||||||
@ -24,6 +24,7 @@ class DialogData {
|
|||||||
})
|
})
|
||||||
export class AssignReviewerApproverDialogComponent {
|
export class AssignReviewerApproverDialogComponent {
|
||||||
readonly form: FormGroup;
|
readonly form: FormGroup;
|
||||||
|
readonly mode: 'reviewer' | 'approver';
|
||||||
dossier: Dossier;
|
dossier: Dossier;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -39,6 +40,10 @@ export class AssignReviewerApproverDialogComponent {
|
|||||||
) {
|
) {
|
||||||
this.dossier = this._activeDossiersService.find(this.data.files[0].dossierId);
|
this.dossier = this._activeDossiersService.find(this.data.files[0].dossierId);
|
||||||
this.form = this._getForm();
|
this.form = this._getForm();
|
||||||
|
this.mode =
|
||||||
|
data.targetStatus === WorkflowFileStatuses.UNDER_APPROVAL || data.targetStatus === WorkflowFileStatuses.APPROVED
|
||||||
|
? 'approver'
|
||||||
|
: 'reviewer';
|
||||||
}
|
}
|
||||||
|
|
||||||
get selectedUser(): string {
|
get selectedUser(): string {
|
||||||
@ -47,9 +52,10 @@ export class AssignReviewerApproverDialogComponent {
|
|||||||
|
|
||||||
get userOptions() {
|
get userOptions() {
|
||||||
const unassignUser = this._canUnassignFiles && this.data.withUnassignedOption ? [undefined] : [];
|
const unassignUser = this._canUnassignFiles && this.data.withUnassignedOption ? [undefined] : [];
|
||||||
return this.data.mode === 'approver'
|
if (!this.permissionsService.canAssignUser(this.data.files, this.dossier)) {
|
||||||
? [...this.dossier.approverIds, ...unassignUser]
|
return [...unassignUser];
|
||||||
: [...this.dossier.memberIds, ...unassignUser];
|
}
|
||||||
|
return this.mode === 'reviewer' ? [...this.dossier.memberIds, ...unassignUser] : [...this.dossier.approverIds, ...unassignUser];
|
||||||
}
|
}
|
||||||
|
|
||||||
get changed(): boolean {
|
get changed(): boolean {
|
||||||
@ -97,9 +103,9 @@ export class AssignReviewerApproverDialogComponent {
|
|||||||
async save() {
|
async save() {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
try {
|
try {
|
||||||
if (!this.selectedUser) {
|
if (!this.selectedUser || this.data.targetStatus === WorkflowFileStatuses.APPROVED) {
|
||||||
await firstValueFrom(this._filesService.setUnassigned(this.data.files, this.dossier.id));
|
await firstValueFrom(this._filesService.setAssignee(this.data.files, this.dossier.id, this.selectedUser));
|
||||||
} else if (this.data.mode === 'reviewer') {
|
} else if (this.mode === 'reviewer') {
|
||||||
await firstValueFrom(this._filesService.setReviewerFor(this.data.files, this.dossier.id, this.selectedUser));
|
await firstValueFrom(this._filesService.setReviewerFor(this.data.files, this.dossier.id, this.selectedUser));
|
||||||
} else {
|
} else {
|
||||||
await firstValueFrom(this._filesService.setUnderApprovalFor(this.data.files, this.dossier.id, this.selectedUser));
|
await firstValueFrom(this._filesService.setUnderApprovalFor(this.data.files, this.dossier.id, this.selectedUser));
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { UserService } from '@services/user.service';
|
import { UserService } from '@services/user.service';
|
||||||
import { Dossier, File, User } from '@red/domain';
|
import { Dossier, File, User, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
|
||||||
import { DossiersDialogService } from './dossiers-dialog.service';
|
import { DossiersDialogService } from './dossiers-dialog.service';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { FilesService } from '@services/files/files.service';
|
import { FilesService } from '@services/files/files.service';
|
||||||
@ -8,16 +8,6 @@ import { ConfirmationDialogInput, LoadingService, Toaster } from '@iqser/common-
|
|||||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
|
|
||||||
const changeReviewerDialogInput = new ConfirmationDialogInput({
|
|
||||||
title: _('confirmation-dialog.assign-file-to-me.title'),
|
|
||||||
question: _('confirmation-dialog.assign-file-to-me.question'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const changeApproverDialogInput = new ConfirmationDialogInput({
|
|
||||||
title: _('confirmation-dialog.assign-me-as-approver.title'),
|
|
||||||
question: _('confirmation-dialog.assign-me-as-approver.question'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const atLeastOneAssignee = (files: File[]) => files.reduce((acc, fs) => acc || !!fs.assignee, false);
|
const atLeastOneAssignee = (files: File[]) => files.reduce((acc, fs) => acc || !!fs.assignee, false);
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -35,76 +25,66 @@ export class FileAssignService {
|
|||||||
this.currentUser = userService.currentUser;
|
this.currentUser = userService.currentUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
async assignToMe(files: File[]) {
|
async assignToMe(files: File[]): Promise<unknown> {
|
||||||
const filesAreUnderApproval = files.reduce((acc, fs) => acc && fs.isUnderApproval, true);
|
const assignReq = async () => {
|
||||||
|
this._loadingService.start();
|
||||||
|
await firstValueFrom(this._filesService.setAssignee(files, files[0].dossierId, this.currentUser.id));
|
||||||
|
this._loadingService.stop();
|
||||||
|
};
|
||||||
|
if (atLeastOneAssignee(files)) {
|
||||||
|
const dialogInput = new ConfirmationDialogInput({
|
||||||
|
title: _('confirmation-dialog.assign-file-to-me.title'),
|
||||||
|
question: _('confirmation-dialog.assign-file-to-me.question'),
|
||||||
|
});
|
||||||
|
const ref = this._dialogService.openDialog('confirm', null, dialogInput, assignReq);
|
||||||
|
return firstValueFrom(ref.afterClosed());
|
||||||
|
}
|
||||||
|
|
||||||
return filesAreUnderApproval ? this.#assignMeAsApprover(files) : this.#assignMeAsReviewer(files);
|
return assignReq();
|
||||||
}
|
}
|
||||||
|
|
||||||
async assignReviewer($event: MouseEvent, file: File, ignoreChanged = false): Promise<void> {
|
async assignReviewer($event: MouseEvent, file: File, ignoreChanged = false): Promise<void> {
|
||||||
await this._assignFile('reviewer', $event, file, ignoreChanged);
|
await this._assignFile(WorkflowFileStatuses.UNDER_REVIEW, $event, file, ignoreChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
async assignApprover($event: MouseEvent, file: File, ignoreChanged = false): Promise<void> {
|
async assignApprover($event: MouseEvent, file: File, ignoreChanged = false): Promise<void> {
|
||||||
await this._assignFile('approver', $event, file, ignoreChanged);
|
await this._assignFile(WorkflowFileStatuses.UNDER_APPROVAL, $event, file, ignoreChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
#assignMeAsReviewer(files: File[]) {
|
private async _assignFile(targetStatus: WorkflowFileStatus, $event: MouseEvent, file: File, ignoreChanged = false): Promise<void> {
|
||||||
if (atLeastOneAssignee(files)) {
|
|
||||||
const cb = () => this.#assignReviewerToCurrentUser(files);
|
|
||||||
const ref = this._dialogService.openDialog('confirm', null, changeReviewerDialogInput, cb);
|
|
||||||
|
|
||||||
return firstValueFrom(ref.afterClosed());
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.#assignReviewerToCurrentUser(files);
|
|
||||||
}
|
|
||||||
|
|
||||||
#assignMeAsApprover(files: File[]) {
|
|
||||||
if (atLeastOneAssignee(files)) {
|
|
||||||
const cb = () => this.#assignApproverToCurrentUser(files);
|
|
||||||
const ref = this._dialogService.openDialog('confirm', null, changeApproverDialogInput, cb);
|
|
||||||
|
|
||||||
return firstValueFrom(ref.afterClosed());
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.#assignApproverToCurrentUser(files);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _assignFile(mode: 'reviewer' | 'approver', $event: MouseEvent, file: File, ignoreChanged = false): Promise<void> {
|
|
||||||
$event?.stopPropagation();
|
$event?.stopPropagation();
|
||||||
|
|
||||||
const currentUserId = this.currentUser.id;
|
const currentUserId = this.currentUser.id;
|
||||||
const currentDossier = this._activeDossiersService.find(file.dossierId);
|
const currentDossier = this._activeDossiersService.find(file.dossierId);
|
||||||
const eligibleUsersIds = this._getUserIds(mode, currentDossier);
|
const eligibleUsersIds = this._getUserIds(targetStatus, currentDossier);
|
||||||
|
|
||||||
if (file.isNew) {
|
if (file.isNew) {
|
||||||
await this._makeAssignFileRequest(currentUserId, mode, [file]);
|
await this._makeAssignFileRequest(currentUserId, targetStatus, [file]);
|
||||||
} else if (file.assignee === currentUserId) {
|
} else if (file.assignee === currentUserId) {
|
||||||
if (eligibleUsersIds.includes(currentUserId)) {
|
if (eligibleUsersIds.includes(currentUserId)) {
|
||||||
await this._makeAssignFileRequest(currentUserId, mode, [file]);
|
await this._makeAssignFileRequest(currentUserId, targetStatus, [file]);
|
||||||
} else if (eligibleUsersIds.length === 1) {
|
} else if (eligibleUsersIds.length === 1) {
|
||||||
await this._makeAssignFileRequest(eligibleUsersIds[0], mode, [file]);
|
await this._makeAssignFileRequest(eligibleUsersIds[0], targetStatus, [file]);
|
||||||
} else {
|
} else {
|
||||||
const data = { mode, files: [file], ignoreChanged };
|
const data = { targetStatus, files: [file], ignoreChanged };
|
||||||
this._dialogService.openDialog('assignFile', null, data);
|
this._dialogService.openDialog('assignFile', null, data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (eligibleUsersIds.length === 1) {
|
if (eligibleUsersIds.length === 1) {
|
||||||
await this._makeAssignFileRequest(eligibleUsersIds[0], mode, [file]);
|
await this._makeAssignFileRequest(eligibleUsersIds[0], targetStatus, [file]);
|
||||||
} else {
|
} else {
|
||||||
const data = { mode, files: [file], ignoreChanged, withCurrentUserAsDefault: true };
|
const data = { targetStatus, files: [file], ignoreChanged, withCurrentUserAsDefault: true };
|
||||||
this._dialogService.openDialog('assignFile', null, data);
|
this._dialogService.openDialog('assignFile', null, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _makeAssignFileRequest(userId: string, mode: 'reviewer' | 'approver', files: File[]) {
|
private async _makeAssignFileRequest(userId: string, targetStatus: WorkflowFileStatus, files: File[]) {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
try {
|
try {
|
||||||
if (!userId) {
|
if (!userId || targetStatus === WorkflowFileStatuses.APPROVED) {
|
||||||
await firstValueFrom(this._filesService.setUnassigned(files, files[0].dossierId));
|
await firstValueFrom(this._filesService.setAssignee(files, files[0].dossierId, userId));
|
||||||
} else if (mode === 'reviewer') {
|
} else if (targetStatus === WorkflowFileStatuses.UNDER_REVIEW) {
|
||||||
await firstValueFrom(this._filesService.setReviewerFor(files, files[0].dossierId, userId));
|
await firstValueFrom(this._filesService.setReviewerFor(files, files[0].dossierId, userId));
|
||||||
} else {
|
} else {
|
||||||
await firstValueFrom(this._filesService.setUnderApprovalFor(files, files[0].dossierId, userId));
|
await firstValueFrom(this._filesService.setUnderApprovalFor(files, files[0].dossierId, userId));
|
||||||
@ -115,21 +95,9 @@ export class FileAssignService {
|
|||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getUserIds(mode: 'reviewer' | 'approver', dossier: Dossier) {
|
private _getUserIds(targetStatus: WorkflowFileStatus, dossier: Dossier) {
|
||||||
return mode === 'approver' ? dossier.approverIds : dossier.memberIds;
|
return targetStatus === WorkflowFileStatuses.UNDER_APPROVAL || targetStatus === WorkflowFileStatuses.APPROVED
|
||||||
}
|
? dossier.approverIds
|
||||||
|
: dossier.memberIds;
|
||||||
async #assignReviewerToCurrentUser(files: File[]) {
|
|
||||||
this._loadingService.start();
|
|
||||||
const reviewer$ = this._filesService.setReviewerFor(files, files[0].dossierId, this.currentUser.id);
|
|
||||||
await firstValueFrom(reviewer$);
|
|
||||||
this._loadingService.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
async #assignApproverToCurrentUser(files: File[]) {
|
|
||||||
this._loadingService.start();
|
|
||||||
const approver$ = this._filesService.setUnderApprovalFor(files, files[0].dossierId, this.currentUser.id);
|
|
||||||
await firstValueFrom(approver$);
|
|
||||||
this._loadingService.stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,13 +3,13 @@ import { List } from '@iqser/common-ui';
|
|||||||
import { ActivatedRouteSnapshot, IsActiveMatchOptions, NavigationEnd, Router } from '@angular/router';
|
import { ActivatedRouteSnapshot, IsActiveMatchOptions, NavigationEnd, Router } from '@angular/router';
|
||||||
import { BehaviorSubject, Observable, of } from 'rxjs';
|
import { BehaviorSubject, Observable, of } from 'rxjs';
|
||||||
import { filter, pluck } from 'rxjs/operators';
|
import { filter, pluck } from 'rxjs/operators';
|
||||||
import { FilesMapService } from '@services/files/files-map.service';
|
import { FilesMapService } from './files/files-map.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { BreadcrumbTypes, DOSSIER_ID, DOSSIER_TEMPLATE_ID, DOSSIERS_ARCHIVE, FILE_ID } from '@red/domain';
|
import { BreadcrumbTypes, DOSSIER_ID, DOSSIER_TEMPLATE_ID, DOSSIERS_ARCHIVE, FILE_ID } from '@red/domain';
|
||||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
import { DossiersService } from './dossiers/dossiers.service';
|
||||||
import { dossiersServiceResolver } from '@services/entity-services/dossiers.service.provider';
|
import { dossiersServiceResolver } from './entity-services/dossiers.service.provider';
|
||||||
import { FeaturesService } from '@services/features.service';
|
import { FeaturesService } from './features.service';
|
||||||
import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service';
|
import { DashboardStatsService } from './dossier-templates/dashboard-stats.service';
|
||||||
|
|
||||||
export type RouterLinkActiveOptions = { exact: boolean } | IsActiveMatchOptions;
|
export type RouterLinkActiveOptions = { exact: boolean } | IsActiveMatchOptions;
|
||||||
export type BreadcrumbDisplayType = 'text' | 'dropdown';
|
export type BreadcrumbDisplayType = 'text' | 'dropdown';
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { Injectable, Injector } from '@angular/core';
|
|||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map, switchMap, tap } from 'rxjs/operators';
|
import { map, switchMap, tap } from 'rxjs/operators';
|
||||||
import { DossierStatesService } from '@services/entity-services/dossier-states.service';
|
import { DossierStatesService } from '../entity-services/dossier-states.service';
|
||||||
|
|
||||||
const templatesSorter = (a: DashboardStats, b: DashboardStats) => {
|
const templatesSorter = (a: DashboardStats, b: DashboardStats) => {
|
||||||
if (a.numberOfActiveDossiers > 0 && b.numberOfActiveDossiers === 0) {
|
if (a.numberOfActiveDossiers > 0 && b.numberOfActiveDossiers === 0) {
|
||||||
|
|||||||
@ -70,10 +70,8 @@ export class DossierTemplatesService extends EntitiesService<DossierTemplate, ID
|
|||||||
return this._post(body).pipe(switchMap(() => this.loadAll()));
|
return this._post(body).pipe(switchMap(() => this.loadAll()));
|
||||||
}
|
}
|
||||||
|
|
||||||
clone(dossierTemplateId: string, name: string) {
|
clone(dossierTemplateId: string, body: IDossierTemplate) {
|
||||||
return this._post(null, `${this._defaultModelPath}/${dossierTemplateId}/clone?nameOfClonedDossierTemplate=${name}`).pipe(
|
return this._post(body, `${this._defaultModelPath}/${dossierTemplateId}/clone`).pipe(switchMap(() => this.loadAll()));
|
||||||
switchMap(() => this.loadAll()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshDossierTemplate(dossierTemplateId: string): Observable<any> {
|
refreshDossierTemplate(dossierTemplateId: string): Observable<any> {
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
|||||||
import { ActiveDossiersService } from './active-dossiers.service';
|
import { ActiveDossiersService } from './active-dossiers.service';
|
||||||
import { DossiersService } from './dossiers.service';
|
import { DossiersService } from './dossiers.service';
|
||||||
import { FilesMapService } from '../files/files-map.service';
|
import { FilesMapService } from '../files/files-map.service';
|
||||||
import { FeaturesService } from '@services/features.service';
|
import { FeaturesService } from '../features.service';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class ArchivedDossiersService extends DossiersService {
|
export class ArchivedDossiersService extends DossiersService {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { DossierStatsService } from './dossier-stats.service';
|
|||||||
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service';
|
import { DashboardStatsService } from '../dossier-templates/dashboard-stats.service';
|
||||||
|
|
||||||
const CONFLICT_MSG = _('add-dossier-dialog.errors.dossier-already-exists');
|
const CONFLICT_MSG = _('add-dossier-dialog.errors.dossier-already-exists');
|
||||||
const GENERIC_MSG = _('add-dossier-dialog.errors.generic');
|
const GENERIC_MSG = _('add-dossier-dialog.errors.generic');
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import { Injectable, Injector } from '@angular/core';
|
|||||||
import { EntitiesService, mapEach, RequiredParam, Toaster, Validate } from '@iqser/common-ui';
|
import { EntitiesService, mapEach, RequiredParam, Toaster, Validate } from '@iqser/common-ui';
|
||||||
import { DossierState, IDossierState } from '@red/domain';
|
import { DossierState, IDossierState } from '@red/domain';
|
||||||
import { EMPTY, forkJoin, Observable, switchMap } from 'rxjs';
|
import { EMPTY, forkJoin, Observable, switchMap } from 'rxjs';
|
||||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
import { DossierTemplatesService } from '../dossier-templates/dossier-templates.service';
|
||||||
import { catchError, defaultIfEmpty, tap } from 'rxjs/operators';
|
import { catchError, defaultIfEmpty, tap } from 'rxjs/operators';
|
||||||
import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service';
|
import { DossierStatesMapService } from '../entity-services/dossier-states-map.service';
|
||||||
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
|
|
||||||
|
|||||||
@ -6,11 +6,11 @@ import { forkJoin, map, Observable, of } from 'rxjs';
|
|||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { ConfigService } from '../config.service';
|
import { ConfigService } from '../config.service';
|
||||||
import { PermissionsService } from '../permissions.service';
|
import { PermissionsService } from '../permissions.service';
|
||||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
import { ActiveDossiersService } from '../dossiers/active-dossiers.service';
|
||||||
import { UserService } from '@services/user.service';
|
import { UserService } from '../user.service';
|
||||||
import { flatMap } from 'lodash-es';
|
import { flatMap } from 'lodash-es';
|
||||||
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
|
import { DossierStatsService } from '../dossiers/dossier-stats.service';
|
||||||
import { FilesService } from '@services/files/files.service';
|
import { FilesService } from '../files/files.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
|
|||||||
@ -42,10 +42,10 @@ export class FilesService extends EntitiesService<File, IFile> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Validate()
|
@Validate()
|
||||||
setUnassigned(@RequiredParam() files: List<File>, @RequiredParam() dossierId: string) {
|
setAssignee(@RequiredParam() files: List<File>, @RequiredParam() dossierId: string, assigneeId: string) {
|
||||||
const url = `${this._defaultModelPath}/set-assignee/${dossierId}/bulk`;
|
const url = `${this._defaultModelPath}/set-assignee/${dossierId}/bulk`;
|
||||||
const fileIds = files.map(f => f.id);
|
const fileIds = files.map(f => f.id);
|
||||||
return this._post<unknown>(fileIds, url).pipe(switchMap(() => this.loadAll(dossierId)));
|
return this._post<unknown>(fileIds, url, [{ key: 'assigneeId', value: assigneeId }]).pipe(switchMap(() => this.loadAll(dossierId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Validate()
|
@Validate()
|
||||||
|
|||||||
@ -6,11 +6,11 @@ import { Dossier, INotification, Notification, NotificationTypes } from '@red/do
|
|||||||
import { map, switchMap, tap } from 'rxjs/operators';
|
import { map, switchMap, tap } from 'rxjs/operators';
|
||||||
import { notificationsTranslations } from '@translations/notifications-translations';
|
import { notificationsTranslations } from '@translations/notifications-translations';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { UserService } from '@services/user.service';
|
import { UserService } from './user.service';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
|
import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
|
||||||
import { BASE_HREF } from '../tokens';
|
import { BASE_HREF } from '../tokens';
|
||||||
import { DossiersCacheService } from '@services/dossiers/dossiers-cache.service';
|
import { DossiersCacheService } from './dossiers/dossiers-cache.service';
|
||||||
|
|
||||||
const INCLUDE_SEEN = false;
|
const INCLUDE_SEEN = false;
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,7 @@ export class PermissionsService {
|
|||||||
return this.isAdmin();
|
return this.isAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
isReviewerOrApprover(file: File, dossier: Dossier): boolean {
|
isAssigneeOrApprover(file: File, dossier: Dossier): boolean {
|
||||||
return this.isFileAssignee(file) || this.isApprover(dossier);
|
return this.isFileAssignee(file) || this.isApprover(dossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ export class PermissionsService {
|
|||||||
|
|
||||||
canSetUnderReview(file: File | File[], dossier: Dossier): boolean {
|
canSetUnderReview(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
return this.isApprover(dossier) && files.reduce((acc, _file) => this._canSetUnderReview(_file, dossier) && acc, true);
|
return files.reduce((acc, _file) => this._canSetUnderReview(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
canBeApproved(file: File | File[], dossier: Dossier): boolean {
|
canBeApproved(file: File | File[], dossier: Dossier): boolean {
|
||||||
@ -129,8 +129,9 @@ export class PermissionsService {
|
|||||||
return files.reduce((acc, _file) => this._canBeApproved(_file, dossier) && acc, true);
|
return files.reduce((acc, _file) => this._canBeApproved(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
isReadyForApproval(files: File | File[], dossier: Dossier): boolean {
|
isReadyForApproval(file: File | File[], dossier: Dossier): boolean {
|
||||||
return this.canSetUnderReview(files, dossier);
|
const files = file instanceof File ? [file] : file;
|
||||||
|
return files.reduce((acc, _file) => this._isReadyForApproval(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
canSetUnderApproval(file: File | File[], dossier: Dossier): boolean {
|
canSetUnderApproval(file: File | File[], dossier: Dossier): boolean {
|
||||||
@ -232,7 +233,7 @@ export class PermissionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canAddComment(file: File, dossier: Dossier): boolean {
|
canAddComment(file: File, dossier: Dossier): boolean {
|
||||||
return (this.isFileAssignee(file) || this.isApprover(dossier)) && !file.isApproved;
|
return this.isAssigneeOrApprover(file, dossier) && !file.isApproved;
|
||||||
}
|
}
|
||||||
|
|
||||||
canExcludePages(file: File, dossier: Dossier): boolean {
|
canExcludePages(file: File, dossier: Dossier): boolean {
|
||||||
@ -260,21 +261,19 @@ export class PermissionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _canSoftDeleteFile(file: File, dossier: Dossier): boolean {
|
private _canSoftDeleteFile(file: File, dossier: Dossier): boolean {
|
||||||
return (
|
return dossier.isActive && (this.isAssigneeOrApprover(file, dossier) || (!file.assignee && this.isDossierMember(dossier)));
|
||||||
dossier.isActive && (this.isApprover(dossier) || this.isFileAssignee(file) || (!file.assignee && this.isDossierMember(dossier)))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canRestoreFile(file: File, dossier: Dossier): boolean {
|
private _canRestoreFile(file: File, dossier: Dossier): boolean {
|
||||||
return this.isApprover(dossier) || this.isFileAssignee(file);
|
return this.isAssigneeOrApprover(file, dossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canHardDeleteFile(file: File, dossier: Dossier): boolean {
|
private _canHardDeleteFile(file: File, dossier: Dossier): boolean {
|
||||||
return this.isApprover(dossier) || this.isFileAssignee(file) || (!file.assignee && this.isDossierMember(dossier));
|
return this.isAssigneeOrApprover(file, dossier) || (!file.assignee && this.isDossierMember(dossier));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canReanalyseFile(file: File, dossier: Dossier): boolean {
|
private _canReanalyseFile(file: File, dossier: Dossier): boolean {
|
||||||
return dossier.isActive && this.isReviewerOrApprover(file, dossier) && file.analysisRequired;
|
return dossier.isActive && this.isAssigneeOrApprover(file, dossier) && file.analysisRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canEnableAutoAnalysis(file: File, dossier: Dossier): boolean {
|
private _canEnableAutoAnalysis(file: File, dossier: Dossier): boolean {
|
||||||
@ -285,32 +284,52 @@ export class PermissionsService {
|
|||||||
return dossier.isActive && !file.excludedFromAutomaticAnalysis && this.isFileAssignee(file) && !file.isApproved;
|
return dossier.isActive && !file.excludedFromAutomaticAnalysis && this.isFileAssignee(file) && !file.isApproved;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canAssignToSelf(file: File, dossier: Dossier): boolean {
|
/** UNDER_REVIEW => NEW */
|
||||||
const precondition =
|
private _canSetToNew(file: File, dossier: Dossier): boolean {
|
||||||
dossier.isActive && this.isDossierMember(dossier) && !this.isFileAssignee(file) && !file.isError && !file.isProcessing;
|
return dossier.isActive && file.isUnderReview && this.isDossierMember(dossier);
|
||||||
return precondition && (file.isNew || file.isUnderReview || (file.isUnderApproval && this.isApprover(dossier)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** UNDER_REVIEW => UNDER_APPROVAL */
|
||||||
private _canSetUnderApproval(file: File, dossier: Dossier): boolean {
|
private _canSetUnderApproval(file: File, dossier: Dossier): boolean {
|
||||||
return dossier.isActive && file.isUnderReview && this.isFileAssignee(file);
|
return dossier.isActive && file.isUnderReview && this.isDossierMember(dossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canUndoApproval(file: File, dossier: Dossier): boolean {
|
/** UNDER_APPROVAL => UNDER_REVIEW */
|
||||||
return dossier.isActive && file.isApproved && this.isFileAssignee(file);
|
private _canSetUnderReview(file: File, dossier: Dossier): boolean {
|
||||||
|
return dossier.isActive && file.isUnderApproval && this.isAssigneeOrApprover(file, dossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** UNDER_APPROVAL => APPROVED */
|
||||||
private _canBeApproved(file: File, dossier: Dossier): boolean {
|
private _canBeApproved(file: File, dossier: Dossier): boolean {
|
||||||
return dossier.isActive && file.canBeApproved && this.isFileAssignee(file);
|
return this._isReadyForApproval(file, dossier) && file.canBeApproved;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _isReadyForApproval(file: File, dossier: Dossier): boolean {
|
||||||
|
return dossier.isActive && file.isUnderApproval && this.isAssigneeOrApprover(file, dossier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** APPROVED => UNDER_APPROVAL */
|
||||||
|
private _canUndoApproval(file: File, dossier: Dossier): boolean {
|
||||||
|
return dossier.isActive && file.isApproved && this.isApprover(dossier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _assignmentPrecondition(file: File, dossier: Dossier): boolean {
|
||||||
|
return dossier.isActive && !file.isError && !file.isProcessing;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _canAssignToSelf(file: File, dossier: Dossier): boolean {
|
||||||
|
const precondition = this._assignmentPrecondition(file, dossier) && !this.isFileAssignee(file);
|
||||||
|
return precondition && (this.isApprover(dossier) || (this.isDossierMember(dossier) && (file.isNew || file.isUnderReview)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canAssignUser(file: File, dossier: Dossier) {
|
private _canAssignUser(file: File, dossier: Dossier) {
|
||||||
const precondition = dossier.isActive && !file.isProcessing && !file.isError && !file.isApproved && this.isApprover(dossier);
|
const precondition = this._assignmentPrecondition(file, dossier);
|
||||||
|
|
||||||
if (precondition) {
|
if (precondition) {
|
||||||
if ((file.isNew || file.isUnderReview) && dossier.hasReviewers) {
|
if ((file.isNew || file.isUnderReview) && dossier.hasReviewers && this.isDossierMember(dossier)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (file.isUnderApproval && dossier.approverIds.length > 1) {
|
if ((file.isUnderApproval || file.isApproved) && dossier.approverIds.length > 1 && this.isApprover(dossier)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,14 +337,6 @@ export class PermissionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _canUnassignUser(file: File, dossier: Dossier) {
|
private _canUnassignUser(file: File, dossier: Dossier) {
|
||||||
return dossier.isActive && (file.isUnderReview || file.isUnderApproval) && (this.isFileAssignee(file) || this.isApprover(dossier));
|
return this._assignmentPrecondition(file, dossier) && !!file.assignee && this.isAssigneeOrApprover(file, dossier);
|
||||||
}
|
|
||||||
|
|
||||||
private _canSetToNew(file: File, dossier: Dossier): boolean {
|
|
||||||
return dossier.isActive && file.isUnderReview && this.isFileAssignee(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _canSetUnderReview(file: File, dossier: Dossier): boolean {
|
|
||||||
return dossier.isActive && file.isUnderApproval && this.isFileAssignee(file);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"ADMIN_CONTACT_NAME": null,
|
"ADMIN_CONTACT_NAME": null,
|
||||||
"ADMIN_CONTACT_URL": null,
|
"ADMIN_CONTACT_URL": null,
|
||||||
"API_URL": "https://dev-08.iqser.cloud/redaction-gateway-v1",
|
"API_URL": "https://dev-05.iqser.cloud/redaction-gateway-v1",
|
||||||
"APP_NAME": "RedactManager",
|
"APP_NAME": "RedactManager",
|
||||||
"AUTO_READ_TIME": 3,
|
"AUTO_READ_TIME": 3,
|
||||||
"BACKEND_APP_VERSION": "4.4.40",
|
"BACKEND_APP_VERSION": "4.4.40",
|
||||||
@ -16,7 +16,7 @@
|
|||||||
"MAX_RETRIES_ON_SERVER_ERROR": 3,
|
"MAX_RETRIES_ON_SERVER_ERROR": 3,
|
||||||
"OAUTH_CLIENT_ID": "redaction",
|
"OAUTH_CLIENT_ID": "redaction",
|
||||||
"OAUTH_IDP_HINT": null,
|
"OAUTH_IDP_HINT": null,
|
||||||
"OAUTH_URL": "https://dev-08.iqser.cloud/auth/realms/redaction",
|
"OAUTH_URL": "https://dev-05.iqser.cloud/auth/realms/redaction",
|
||||||
"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"
|
||||||
|
|||||||
@ -554,10 +554,6 @@
|
|||||||
"question": "Dieses Dokument wird gerade von einer anderen Person geprüft. Möchten Sie Reviewer werden und sich selbst dem Dokument zuweisen?",
|
"question": "Dieses Dokument wird gerade von einer anderen Person geprüft. Möchten Sie Reviewer werden und sich selbst dem Dokument zuweisen?",
|
||||||
"title": "Neuen Reviewer zuweisen"
|
"title": "Neuen Reviewer zuweisen"
|
||||||
},
|
},
|
||||||
"assign-me-as-approver": {
|
|
||||||
"question": "",
|
|
||||||
"title": ""
|
|
||||||
},
|
|
||||||
"compare-file": {
|
"compare-file": {
|
||||||
"question": "<strong>Achtung!</strong> <br><br> Seitenzahl stimmt nicht überein, aktuelles Dokument hat <strong>{currentDocumentPageCount} Seite(n)</strong>. Das hochgeladene Dokument hat <strong>{compareDocumentPageCount} Seite(n)</strong>. <br><br> Möchten Sie fortfahren?",
|
"question": "<strong>Achtung!</strong> <br><br> Seitenzahl stimmt nicht überein, aktuelles Dokument hat <strong>{currentDocumentPageCount} Seite(n)</strong>. Das hochgeladene Dokument hat <strong>{compareDocumentPageCount} Seite(n)</strong>. <br><br> Möchten Sie fortfahren?",
|
||||||
"title": "Vergleichen mit: {fileName}"
|
"title": "Vergleichen mit: {fileName}"
|
||||||
|
|||||||
@ -551,13 +551,9 @@
|
|||||||
"title": "Warning!"
|
"title": "Warning!"
|
||||||
},
|
},
|
||||||
"assign-file-to-me": {
|
"assign-file-to-me": {
|
||||||
"question": "This document is currently reviewed by someone else. Do you want to become the reviewer and assign yourself to this document?",
|
"question": "At least one document is currently assigned to someone else. Are you sure you want to replace them and assign yourself to these documents?",
|
||||||
"title": "Re-assign user"
|
"title": "Re-assign user"
|
||||||
},
|
},
|
||||||
"assign-me-as-approver": {
|
|
||||||
"question": "This document is currently under approval by someone else. Do you want to become the approver and assign yourself to this document?",
|
|
||||||
"title": "Re-assign approver"
|
|
||||||
},
|
|
||||||
"compare-file": {
|
"compare-file": {
|
||||||
"question": "<strong>Warning!</strong> <br><br> Number of pages does not match, current document has <strong>{currentDocumentPageCount} page(s)</strong>. Uploaded document has <strong>{compareDocumentPageCount} page(s)</strong>. <br><br> Do you wish to proceed?",
|
"question": "<strong>Warning!</strong> <br><br> Number of pages does not match, current document has <strong>{currentDocumentPageCount} page(s)</strong>. Uploaded document has <strong>{compareDocumentPageCount} page(s)</strong>. <br><br> Do you wish to proceed?",
|
||||||
"title": "Compare with file: {fileName}"
|
"title": "Compare with file: {fileName}"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "redaction",
|
"name": "redaction",
|
||||||
"version": "3.492.0",
|
"version": "3.496.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user