Pull request #203: Move delete dossier action to edit modal

Merge in RED/ui from RED-1544 to master

* commit 'dc0f89441a645ecf9d94526e04a591173208dd8f':
  Move delete dossier action to edit modal
This commit is contained in:
Timo Bejan 2021-06-07 13:31:27 +02:00
commit 3c4d6b0bb3
21 changed files with 173 additions and 108 deletions

View File

@ -93,7 +93,3 @@
.mb-5 {
margin-bottom: 5px;
}
.mb-8 {
margin-bottom: 8px;
}

View File

@ -17,6 +17,7 @@ export enum AppConfigKey {
ADMIN_CONTACT_URL = 'ADMIN_CONTACT_URL',
AUTO_READ_TIME = 'AUTO_READ_TIME',
MAX_FILE_SIZE_MB = 'MAX_FILE_SIZE_MB',
DELETE_RETENTION_HOURS = 'DELETE_RETENTION_HOURS',
APP_NAME = 'APP_NAME',
// TODO

View File

@ -54,7 +54,3 @@
.mt-12 {
margin-top: 12px;
}
.mt-24 {
margin-top: 24px;
}

View File

@ -1,14 +1,5 @@
<redaction-status-bar [config]="getDossierStatusConfig(dossier)"></redaction-status-bar>
<div [class.active]="actionMenuOpen" class="action-buttons">
<redaction-circle-button
(action)="openDeleteDossierDialog($event, dossier)"
*ngIf="permissionsService.canDeleteDossier(dossier)"
icon="red:trash"
tooltip="dossier-listing.delete.action"
type="dark-bg"
>
</redaction-circle-button>
<redaction-circle-button
(action)="openEditDossierDialog($event, dossier)"
*ngIf="permissionsService.isManager()"

View File

@ -23,12 +23,6 @@ export class DossierListingActionsComponent {
private readonly _fileManagementControllerService: FileManagementControllerService
) {}
openDeleteDossierDialog($event: MouseEvent, dossier: DossierWrapper) {
this._dialogService.openDeleteDossierDialog($event, dossier, () => {
this.actionPerformed.emit();
});
}
openEditDossierDialog($event: MouseEvent, dossier: DossierWrapper) {
this._dialogService.openEditDossierDialog($event, dossier, () => {
this.actionPerformed.emit();

View File

@ -52,15 +52,13 @@
(updateDossier)="updatedDossier($event)"
*ngIf="activeNav === 'dossier-dictionary'"
[dossierWrapper]="dossierWrapper"
>
</redaction-edit-dossier-dictionary>
></redaction-edit-dossier-dictionary>
<redaction-edit-dossier-team-members
(updateDossier)="updatedDossier($event)"
*ngIf="activeNav === 'members'"
[dossierWrapper]="dossierWrapper"
>
</redaction-edit-dossier-team-members>
></redaction-edit-dossier-team-members>
</div>
<div class="dialog-actions">

View File

@ -41,11 +41,11 @@ export class EditDossierDialogComponent {
private readonly _notificationService: NotificationService,
private readonly _translateService: TranslateService,
private readonly _changeRef: ChangeDetectorRef,
public dialogRef: MatDialogRef<EditDossierDialogComponent>,
private readonly _dialogRef: MatDialogRef<EditDossierDialogComponent>,
@Inject(MAT_DIALOG_DATA)
public data: { dossierWrapper: DossierWrapper; afterSave: Function }
private readonly _data: { dossierWrapper: DossierWrapper; afterSave: Function }
) {
this.dossierWrapper = data.dossierWrapper;
this.dossierWrapper = _data.dossierWrapper;
}
get activeNavItem(): { key: string; title?: string } {
@ -67,13 +67,18 @@ export class EditDossierDialogComponent {
null,
NotificationType.SUCCESS
);
if (updatedDossier) {
this.dossierWrapper = updatedDossier;
}
this._changeRef.detectChanges();
if (this.data.afterSave) {
this.data.afterSave();
}
this.afterSave();
}
afterSave() {
if (this._data?.afterSave) this._data.afterSave();
}
async save() {

View File

@ -67,4 +67,14 @@
<mat-datepicker #picker></mat-datepicker>
</div>
</div>
<div class="dialog-actions">
<redaction-icon-button
(action)="openDeleteDossierDialog($event)"
*ngIf="permissionsService.canDeleteDossier(dossierWrapper)"
icon="red:trash"
text="dossier-listing.delete.action"
type="show-bg"
></redaction-icon-button>
</div>
</form>

View File

@ -16,3 +16,8 @@
margin-right: 16px;
}
}
.dialog-actions {
border-top: none;
padding: 0;
}

View File

@ -5,6 +5,16 @@ import { AppStateService } from '../../../../../state/app-state.service';
import * as moment from 'moment';
import { DossierWrapper } from '../../../../../state/model/dossier.wrapper';
import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
import { PermissionsService } from '../../../../../services/permissions.service';
import { Router } from '@angular/router';
import { MatDialogRef } from '@angular/material/dialog';
import { EditDossierDialogComponent } from '../edit-dossier-dialog.component';
import {
NotificationService,
NotificationType
} from '../../../../../services/notification.service';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'redaction-edit-dossier-general-info',
@ -14,15 +24,21 @@ import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSectionInterface {
dossierForm: FormGroup;
hasDueDate: boolean;
reportTypesEnum = Object.values(DossierTemplateModel.ReportTypesEnum);
readonly reportTypesEnum = Object.values(DossierTemplateModel.ReportTypesEnum);
dossierTemplates: DossierTemplateModel[];
@Input() dossierWrapper: DossierWrapper;
@Output() updateDossier = new EventEmitter<any>();
constructor(
readonly permissionsService: PermissionsService,
private readonly _appStateService: AppStateService,
private readonly _formBuilder: FormBuilder
private readonly _formBuilder: FormBuilder,
private readonly _dialogService: DossiersDialogService,
private readonly _router: Router,
private readonly _editDossierDialogRef: MatDialogRef<EditDossierDialogComponent>,
private readonly _notificationService: NotificationService,
private readonly _translateService: TranslateService
) {}
get changed() {
@ -96,6 +112,22 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
this.updateDossier.emit(updatedDossier);
}
openDeleteDossierDialog($event: MouseEvent) {
this._dialogService.openDeleteDossierDialog($event, this.dossierWrapper, () => {
this._editDossierDialogRef.componentInstance.afterSave();
this._editDossierDialogRef.close();
this._router.navigate(['main', 'dossiers']).then(() => this._notifyDossierDeleted());
});
}
private _notifyDossierDeleted() {
this._notificationService.showToastNotification(
this._translateService.instant('edit-dossier-dialog.delete-successful'),
null,
NotificationType.SUCCESS
);
}
private _filterInvalidDossierTemplates() {
this.dossierTemplates = this._appStateService.dossierTemplates.filter(r => {
if (this.dossierWrapper?.dossierTemplateId === r.dossierTemplateId) {

View File

@ -183,9 +183,9 @@ export class DossierListingScreenComponent
}
openAddDossierDialog(): void {
this._dialogService.openAddDossierDialog(addResponse => {
this._dialogService.openAddDossierDialog(async addResponse => {
this._calculateData();
this._router.navigate([`/main/dossiers/${addResponse.dossier.dossierId}`]);
await this._router.navigate([`/main/dossiers/${addResponse.dossier.dossierId}`]);
if (addResponse.addMembers) {
this.openAssignDossierOwnerDialog(null, addResponse.dossier);
}

View File

@ -46,14 +46,6 @@
tooltip="dossier-overview.header-actions.edit"
tooltipPosition="below"
></redaction-circle-button>
<!-- Commented because users miss-click this shit !-->
<!-- <redaction-circle-button-->
<!-- (action)="openDeleteDossierDialog($event)"-->
<!-- *ngIf="permissionsService.canDeleteDossier()"-->
<!-- icon="red:trash"-->
<!-- tooltip="dossier-overview.header-actions.delete"-->
<!-- tooltipPosition="below"-->
<!-- ></redaction-circle-button>-->
<redaction-file-download-btn
[disabled]="areSomeEntitiesSelected"

View File

@ -270,12 +270,6 @@ export class DossierOverviewScreenComponent
this._dialogService.openEditDossierDialog($event, this.activeDossier);
}
openDeleteDossierDialog($event: MouseEvent) {
this._dialogService.openDeleteDossierDialog($event, this.activeDossier, () => {
this._router.navigate(['/main/dossiers']);
});
}
openAssignDossierMembersDialog(): void {
this._dialogService.openAssignTeamMembersDialog(null, this.activeDossier, () => {
this.reloadDossiers();

View File

@ -14,7 +14,8 @@ import { ForceRedactionDialogComponent } from '../dialogs/force-redaction-dialog
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import {
ConfirmationDialogComponent,
ConfirmationDialogInput
ConfirmationDialogInput,
TitleColors
} from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component';
import { DossierWrapper } from '@state/model/dossier.wrapper';
import { DocumentInfoDialogComponent } from '../dialogs/document-info-dialog/document-info-dialog.component';
@ -28,6 +29,7 @@ import { EditDossierDialogComponent } from '../dialogs/edit-dossier-dialog/edit-
import { FileStatusWrapper } from '../../../models/file/file-status.wrapper';
import { AssignReviewerApproverDialogComponent } from '../dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
import { TeamMembersDialogComponent } from '../dialogs/team-members-dialog/team-members-dialog.component';
import { AppConfigService } from '../../app-config/app-config.service';
const dialogConfig = {
width: '662px',
@ -46,7 +48,8 @@ export class DossiersDialogService {
private readonly _fileManagementControllerService: FileManagementControllerService,
private readonly _notificationService: NotificationService,
private readonly _manualAnnotationService: ManualAnnotationService,
private readonly _manualRedactionControllerService: ManualRedactionControllerService
private readonly _manualRedactionControllerService: ManualRedactionControllerService,
private readonly _appConfigService: AppConfigService
) {}
openDeleteFilesDialog(
@ -192,11 +195,18 @@ export class DossiersDialogService {
cb?: Function
): MatDialogRef<ConfirmationDialogComponent> {
$event.stopPropagation();
const period = this._appConfigService.getConfig('DELETE_RETENTION_HOURS');
const ref = this._dialog.open(ConfirmationDialogComponent, {
...dialogConfig,
data: new ConfirmationDialogInput({
title: 'confirmation-dialog.delete-dossier.title',
question: 'confirmation-dialog.delete-dossier.question'
titleColor: TitleColors.PRIMARY,
question: 'confirmation-dialog.delete-dossier.question',
details: 'confirmation-dialog.delete-dossier.details',
confirmationText: 'confirmation-dialog.delete-dossier.confirmation-text',
requireInput: true,
denyText: 'confirmation-dialog.delete-dossier.deny-text',
translateParams: { dossierName: dossier.dossierName, period: period }
})
});

View File

@ -1,30 +1,30 @@
<section class="dialog">
<div class="dialog-header heading-l">
{{ confirmationDialogInput.title | translate: confirmationDialogInput.translateParams }}
<div [class.primary]="isDeleteAction" class="dialog-header heading-l">
{{ config.title }}
</div>
<div class="dialog-content">
<p
[innerHTML]="
confirmationDialogInput.question
| translate: confirmationDialogInput.translateParams
"
></p>
<p [class.heading]="isDeleteAction" [innerHTML]="config.question" class="mt-0 mb-8"></p>
<p *ngIf="config.details" [innerHTML]="config.details" class="mt-0"></p>
<div *ngIf="config.requireInput" class="red-input-group required w-300 mt-24">
<label>{{ inputLabel }}</label>
<input [(ngModel)]="inputValue" />
</div>
</div>
<div class="dialog-actions">
<button (click)="confirm()" color="primary" mat-flat-button>
{{
confirmationDialogInput.confirmationText
| translate: confirmationDialogInput.translateParams
}}
</button>
<button (click)="deny()" color="primary" mat-flat-button>
{{
confirmationDialogInput.denyText
| translate: confirmationDialogInput.translateParams
}}
<button
(click)="confirm()"
[disabled]="config.requireInput && confirmationDoesNotMatch()"
color="primary"
mat-flat-button
>
{{ config.confirmationText }}
</button>
<div (click)="deny()" class="all-caps-label cancel">
{{ config.denyText }}
</div>
</div>
<redaction-circle-button

View File

@ -1,56 +1,80 @@
import { Component, Inject } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { TranslateService } from '@ngx-translate/core';
export type TitleColor = 'default' | 'primary';
export enum TitleColors {
DEFAULT = 'default',
PRIMARY = 'primary'
}
export class ConfirmationDialogInput {
title?: string;
titleColor?: TitleColor;
question?: string;
details?: string;
confirmationText?: string;
requireInput?: boolean;
denyText?: string;
translateParams?: Record<string, unknown>;
constructor(options: ConfirmationDialogInput) {
this.title = options.title || ConfirmationDialogInput.default().title;
this.question = options.question || ConfirmationDialogInput.default().question;
this.confirmationText =
options.confirmationText || ConfirmationDialogInput.default().confirmationText;
this.denyText = options.denyText || ConfirmationDialogInput.default().denyText;
this.translateParams =
options.translateParams || ConfirmationDialogInput.default().translateParams;
}
static default() {
return new ConfirmationDialogInput({
title: 'common.confirmation-dialog.title',
question: 'common.confirmation-dialog.description',
confirmationText: 'common.confirmation-dialog.confirm',
denyText: 'common.confirmation-dialog.deny',
translateParams: {}
});
constructor(options?: ConfirmationDialogInput) {
this.title = options?.title || 'common.confirmation-dialog.title';
this.titleColor = options?.titleColor || TitleColors.DEFAULT;
this.question = options?.question || 'common.confirmation-dialog.description';
this.details = options?.details || '';
this.confirmationText = options?.confirmationText || 'common.confirmation-dialog.confirm';
this.requireInput = options?.requireInput || false;
this.denyText = options?.denyText || 'common.confirmation-dialog.deny';
this.translateParams = options?.translateParams || {};
}
}
@Component({
selector: 'redaction-confirmation-dialog',
templateUrl: './confirmation-dialog.component.html',
styleUrls: ['./confirmation-dialog.component.scss']
})
export class ConfirmationDialogComponent {
config: ConfirmationDialogInput;
inputValue = '';
readonly inputLabel: string;
private readonly _inputLabelKey = 'confirmation-dialog.delete-dossier.input-label';
constructor(
private readonly _dialogRef: MatDialogRef<ConfirmationDialogComponent>,
private readonly _translateService: TranslateService,
public dialogRef: MatDialogRef<ConfirmationDialogComponent>,
@Inject(MAT_DIALOG_DATA) public confirmationDialogInput: ConfirmationDialogInput
@Inject(MAT_DIALOG_DATA) private readonly _confirmationDialogInput: ConfirmationDialogInput
) {
if (!confirmationDialogInput) {
this.confirmationDialogInput = ConfirmationDialogInput.default();
}
this.config = _confirmationDialogInput ?? new ConfirmationDialogInput();
this.config = this.translate(this.config);
this.inputLabel =
this.translate(this._inputLabelKey) + ` '${this.config.confirmationText}'`;
}
deny() {
this.dialogRef.close();
get isDeleteAction() {
return this.config?.titleColor === TitleColors.PRIMARY;
}
confirm() {
this.dialogRef.close(true);
confirmationDoesNotMatch(): boolean {
return this.inputValue.toLowerCase() !== this.config.confirmationText.toLowerCase();
}
deny(): void {
this._dialogRef.close();
}
confirm(): void {
this._dialogRef.close(true);
}
translate<T extends ConfirmationDialogInput | string>(obj: T): T {
if (typeof obj === 'string')
return this._translateService.instant(obj, this.config.translateParams);
const stringKeys = Object.keys(obj).filter(key => typeof key === 'string' && !!obj[key]);
stringKeys.forEach(key => (obj[key] = this.translate(obj[key])));
return obj;
}
}

View File

@ -10,5 +10,6 @@
"LICENSE_START": "01-01-2021",
"LICENSE_END": "31-12-2021",
"LICENSE_PAGE_COUNT": 1000000,
"MAX_FILE_SIZE_MB": 100
"MAX_FILE_SIZE_MB": 100,
"DELETE_RETENTION_HOURS": 96
}

View File

@ -614,8 +614,9 @@
"question": "Möchten Sie fortfahren?"
},
"delete-dossier": {
"title": "Dossier löschen",
"question": "Möchten Sie fortfahren?"
"title": "Dossier {{dossierName}}",
"question": "Möchten Sie fortfahren?",
"confirmation-text": "Lösche Dossier"
}
},
"add-edit-file-attribute": {

View File

@ -200,7 +200,8 @@
"entries": "{{length}} entries"
},
"unsaved-changes": "You have unsaved changes. Save or revert before changing the tab.",
"change-successful": "Dossier was updated."
"change-successful": "Dossier was updated.",
"delete-successful": "Dossier was deleted."
},
"dossier-details": {
"title": "Dossier Details",
@ -657,8 +658,12 @@
"question": "Do you wish to proceed?"
},
"delete-dossier": {
"title": "Delete Dossier",
"question": "Do you wish to proceed?"
"title": "Delete {{dossierName}}",
"question": "Are you sure you want to delete this dossier?",
"details": "Deleted dossiers are sent to trash. They can be restored up to {{period}} days from their deletion.",
"input-label": "To proceed please type below",
"confirmation-text": "Delete Dossier",
"deny-text": "Keep Dossier"
}
},
"add-edit-file-attribute": {

View File

@ -241,10 +241,18 @@ section.settings {
margin-top: 20px;
}
.mt-24 {
margin-top: 24px;
}
.mt-32 {
margin-top: 32px;
}
.mb-8 {
margin-bottom: 8px !important;
}
.pb-24 {
padding-bottom: 24px;
}

View File

@ -9,6 +9,7 @@ ADMIN_CONTACT_NAME="${ADMIN_CONTACT_NAME:-}"
ADMIN_CONTACT_URL="${ADMIN_CONTACT_URL:-}"
AUTO_READ_TIME="${AUTO_READ_TIME:-1.5}"
MAX_FILE_SIZE_MB="${MAX_FILE_SIZE_MB:-50}"
DELETE_RETENTION_HOURS="${DELETE_RETENTION_HOURS:-96}"
BACKEND_APP_VERSION="${BACKEND_APP_VERSION:-4.7.0}"
@ -34,6 +35,7 @@ echo '{
"APP_NAME":"'"$APP_NAME"'",
"AUTO_READ_TIME":'"$AUTO_READ_TIME"',
"MAX_FILE_SIZE_MB":"'"$MAX_FILE_SIZE_MB"'",
"DELETE_RETENTION_HOURS":"'"$DELETE_RETENTION_HOURS"'",
"API_URL":"'"$API_URL"'"
}' > /usr/share/nginx/html/ui/assets/config/config.json