Confirmation dialogs with checkboxes

This commit is contained in:
Adina Țeudan 2022-03-02 17:07:24 +02:00
parent 42b7f83357
commit e4df3bb8b0
31 changed files with 194 additions and 463 deletions

View File

@ -2,7 +2,7 @@ import { Injectable, Injector, ProviderToken } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
import { FilesMapService } from '@services/entity-services/files-map.service';
import { DOSSIER_ID, FILE_ID } from '@utils/constants';
import { DossiersService } from '../services/entity-services/dossiers.service';
import { DossiersService } from '@services/entity-services/dossiers.service';
@Injectable({ providedIn: 'root' })
export class FilePreviewGuard implements CanActivate {

View File

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { firstValueFrom } from 'rxjs';
import { TrashDossiersService } from '../services/entity-services/trash-dossiers.service';
import { TrashDossiersService } from '@services/entity-services/trash-dossiers.service';
@Injectable({ providedIn: 'root' })
export class TrashDossiersGuard implements CanActivate {

View File

@ -15,7 +15,6 @@ import { ColorPickerModule } from 'ngx-color-picker';
import { AddEditFileAttributeDialogComponent } from './dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component';
import { AddEditDossierTemplateDialogComponent } from './dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component';
import { AddEditDictionaryDialogComponent } from './dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component';
import { ConfirmDeleteAttributeDialogComponent } from './dialogs/confirm-delete-attribute-dialog/confirm-delete-attribute-dialog.component';
import { EditColorDialogComponent } from './dialogs/edit-color-dialog/edit-color-dialog.component';
import { ComboChartComponent, ComboSeriesVerticalComponent } from './components/combo-chart';
import { NgxChartsModule } from '@swimlane/ngx-charts';
@ -24,7 +23,6 @@ import { GeneralConfigScreenComponent } from './screens/general-config/general-c
import { SmtpAuthDialogComponent } from './dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
import { AddEditUserDialogComponent } from './dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
import { UsersStatsComponent } from './components/users-stats/users-stats.component';
import { ConfirmDeleteUsersDialogComponent } from './dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component';
import { FileAttributesCsvImportDialogComponent } from './dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
import { ActiveFieldsListingComponent } from './dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component';
import { AdminSideNavComponent } from './admin-side-nav/admin-side-nav.component';
@ -55,11 +53,9 @@ const dialogs = [
AddEditDossierTemplateDialogComponent,
AddEditDictionaryDialogComponent,
AddEditFileAttributeDialogComponent,
ConfirmDeleteAttributeDialogComponent,
EditColorDialogComponent,
SmtpAuthDialogComponent,
AddEditUserDialogComponent,
ConfirmDeleteUsersDialogComponent,
FileAttributesConfigurationsDialogComponent,
FileAttributesCsvImportDialogComponent,
AddEditDossierAttributeDialogComponent,

View File

@ -4,7 +4,7 @@ import { AdminDialogService } from '../../../services/admin-dialog.service';
import { BaseFormComponent, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { rolesTranslations } from '../../../../../translations/roles-translations';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { User } from '@red/domain';
import { IProfileUpdateRequest, User } from '@red/domain';
import { UserService } from '@services/user.service';
import { HttpStatusCode } from '@angular/common/http';
import { firstValueFrom } from 'rxjs';
@ -83,7 +83,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
async save() {
this._loadingService.start();
const userData = { ...this.form.getRawValue(), roles: this.activeRoles };
const userData: IProfileUpdateRequest = { ...this.form.getRawValue(), roles: this.activeRoles };
if (!this.user) {
await firstValueFrom(this.userService.create(userData))
@ -105,9 +105,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
}
delete() {
this._dialogService.openDialog('deleteUsers', null, [this.user.id], () => {
this.closeDialog.emit(true);
});
this._dialogService.deleteUsers([this.user.id], null, () => this.closeDialog.emit(true));
}
private _getForm(): FormGroup {

View File

@ -1,39 +0,0 @@
<section class="dialog">
<div class="dialog-header heading-l">
{{ 'confirm-delete-file-attribute.title' | translate: translateArgs }}
</div>
<div *ngIf="showToast" class="inline-dialog-toast toast-error">
<div translate="confirm-delete-file-attribute.toast-error"></div>
<a (click)="showToast = false" class="toast-close-button">
<mat-icon svgIcon="iqser:close"></mat-icon>
</a>
</div>
<div class="dialog-content">
<div class="heading" translate="confirm-delete-file-attribute.warning"></div>
<ng-container *ngFor="let checkbox of checkboxes; let idx = index">
<mat-checkbox [(ngModel)]="checkbox.value" [class.error]="!checkbox.value && showToast" color="primary">
{{ checkbox.label }}
</mat-checkbox>
</ng-container>
<ul class="templates-container flex">
<li *ngFor="let template of data.templates" class="small-label">{{ template.fileName }}</li>
</ul>
</div>
<div class="dialog-actions">
<button (click)="deleteFileAttribute()" color="primary" mat-flat-button>
{{ 'confirm-delete-file-attribute.delete' | translate: { type: type } }}
</button>
<div
(click)="this.dialogRef.close()"
[translateParams]="{ type: type }"
[translate]="'confirm-delete-file-attribute.cancel'"
class="all-caps-label cancel"
></div>
</div>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
</section>

View File

@ -1,27 +0,0 @@
@use 'variables';
.dialog-header {
color: variables.$primary;
}
.heading {
margin-bottom: 24px;
}
mat-checkbox {
width: 100%;
&:not(:last-of-type) {
margin-bottom: 6px;
}
}
.templates-container {
padding: 0 45px;
margin-top: 0;
flex-direction: column;
li {
margin: 5px 0;
}
}

View File

@ -1,89 +0,0 @@
import { Component, Inject } from '@angular/core';
import { DossierAttributeConfig, FileAttributeConfig, IReportTemplate } from '@red/domain';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { TranslateService } from '@ngx-translate/core';
const isFileAttributeConfig = (value: DossierAttributeConfig | FileAttributeConfig): value is FileAttributeConfig =>
value instanceof FileAttributeConfig;
interface CheckBox {
value: boolean;
label: string;
}
interface DialogData {
attribute: FileAttributeConfig | DossierAttributeConfig;
templates: IReportTemplate[];
}
@Component({
selector: 'redaction-confirm-delete-attribute-dialog',
templateUrl: './confirm-delete-attribute-dialog.component.html',
styleUrls: ['./confirm-delete-attribute-dialog.component.scss'],
})
export class ConfirmDeleteAttributeDialogComponent {
checkboxes: CheckBox[];
showToast = false;
constructor(
private readonly _translateService: TranslateService,
readonly dialogRef: MatDialogRef<ConfirmDeleteAttributeDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: DialogData,
) {
this.checkboxes = this.checkBoxConfig;
}
get checkBoxConfig(): CheckBox[] {
const checkBoxes = isFileAttributeConfig(this.data.attribute) ? this._fileAttributeCheckboxes : this._dossierAttributeCheckboxes;
if (this.data.templates.length !== 0) {
checkBoxes.push({
value: false,
label: this._translateService.instant('confirm-delete-file-attribute.impacted-report', {
count: this.data.templates.length,
}),
});
}
return checkBoxes;
}
get valid() {
return this.checkboxes.reduce((acc, currentValue) => acc && currentValue.value, true);
}
get type(): 'bulk' | 'single' {
return this.data.attribute ? 'single' : 'bulk';
}
get translateArgs() {
return {
type: this.type,
name: this.data.attribute?.label,
};
}
private get _fileAttributeCheckboxes(): CheckBox[] {
return [
{
value: false,
label: this._translateService.instant('confirm-delete-file-attribute.file-impacted-documents', { type: this.type }),
},
{ value: false, label: this._translateService.instant('confirm-delete-file-attribute.file-lost-details') },
];
}
private get _dossierAttributeCheckboxes(): CheckBox[] {
return [
{ value: false, label: this._translateService.instant('confirm-delete-file-attribute.dossier-impacted-documents') },
{ value: false, label: this._translateService.instant('confirm-delete-file-attribute.dossier-lost-details') },
];
}
deleteFileAttribute() {
if (this.valid) {
this.dialogRef.close(true);
} else {
this.showToast = true;
}
}
}

View File

@ -1,47 +0,0 @@
<section class="dialog">
<div
[translateParams]="{ usersCount: userIds.length }"
[translate]="'confirm-delete-users.title'"
class="dialog-header heading-l"
></div>
<div *ngIf="showToast" class="inline-dialog-toast toast-error">
<div translate="confirm-delete-users.toast-error"></div>
<a (click)="showToast = false" class="toast-close-button">
<mat-icon svgIcon="iqser:close"></mat-icon>
</a>
</div>
<div class="dialog-content">
<div class="heading" translate="confirm-delete-users.warning"></div>
<mat-checkbox
*ngFor="let checkbox of checkboxes; let idx = index"
[(ngModel)]="checkbox.value"
[class.error]="!checkbox.value && showToast"
color="primary"
>
{{
checkbox.label
| translate
: {
dossiersCount: dossiersCount,
usersCount: userIds.length
}
}}
</mat-checkbox>
</div>
<div class="dialog-actions">
<button (click)="deleteUser()" color="primary" mat-flat-button>
{{ 'confirm-delete-users.delete' | translate: { usersCount: userIds.length } }}
</button>
<div
(click)="cancel()"
[translateParams]="{ usersCount: userIds.length }"
[translate]="'confirm-delete-users.cancel'"
class="all-caps-label cancel"
></div>
</div>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
</section>

View File

@ -1,17 +0,0 @@
@use 'variables';
.dialog-header {
color: variables.$primary;
}
.heading {
margin-bottom: 24px;
}
mat-checkbox {
width: 100%;
&:not(:last-of-type) {
margin-bottom: 6px;
}
}

View File

@ -1,55 +0,0 @@
import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { List, LoadingService } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { ActiveDossiersService } from '@services/entity-services/active-dossiers.service';
import { UserService } from '@services/user.service';
import { firstValueFrom } from 'rxjs';
@Component({
selector: 'redaction-confirm-delete-users-dialog',
templateUrl: './confirm-delete-users-dialog.component.html',
styleUrls: ['./confirm-delete-users-dialog.component.scss'],
})
export class ConfirmDeleteUsersDialogComponent {
readonly checkboxes = [
{ value: false, label: _('confirm-delete-users.impacted-dossiers') },
{ value: false, label: _('confirm-delete-users.impacted-documents') },
];
showToast = false;
dossiersCount: number;
constructor(
private readonly _userService: UserService,
private readonly _loadingService: LoadingService,
private readonly _activeDossiersService: ActiveDossiersService,
@Inject(MAT_DIALOG_DATA) readonly userIds: List<string>,
readonly dialogRef: MatDialogRef<ConfirmDeleteUsersDialogComponent>,
) {
this.dossiersCount = this._dossierCount;
}
get valid() {
return this.checkboxes[0].value && this.checkboxes[1].value;
}
private get _dossierCount(): number {
return this._activeDossiersService.all.filter(dw =>
this.userIds.reduce((prev, userId) => prev || dw.memberIds.includes(userId), false),
).length;
}
async deleteUser() {
if (this.valid) {
this._loadingService.start();
await firstValueFrom(this._userService.delete(this.userIds));
this.dialogRef.close(true);
} else {
this.showToast = true;
}
}
cancel() {
this.dialogRef.close();
}
}

View File

@ -65,6 +65,12 @@
</div>
</ng-template>
<ng-template #impactedTemplates let-data="data">
<ul class="templates-container flex">
<li *ngFor="let template of data.templates" class="small-label">{{ template.fileName }}</li>
</ul>
</ng-template>
<ng-template #tableItemTemplate let-entity="entity">
<div *ngIf="cast(entity) as attribute">
<div class="cell">
@ -89,7 +95,7 @@
></iqser-circle-button>
<iqser-circle-button
(action)="openConfirmDeleteAttributeDialog($event, attribute)"
(action)="openConfirmDeleteAttributeDialog($event, [attribute])"
[tooltip]="'dossier-attributes-listing.action.delete' | translate"
[type]="circleButtonTypes.dark"
icon="iqser:trash"

View File

@ -0,0 +1,9 @@
.templates-container {
padding: 0 45px;
margin-top: 0;
flex-direction: column;
li {
margin: 5px 0;
}
}

View File

@ -1,4 +1,4 @@
import { Component, forwardRef, Injector, OnInit } from '@angular/core';
import { Component, forwardRef, Injector, OnInit, TemplateRef, ViewChild } from '@angular/core';
import {
CircleButtonTypes,
DefaultListingServicesTmp,
@ -39,6 +39,7 @@ export class DossierAttributesListingScreenComponent extends ListingComponent<Do
{ label: _('dossier-attributes-listing.table-col-names.placeholder'), width: '2fr' },
{ label: _('dossier-attributes-listing.table-col-names.type'), sortByKey: 'type' },
];
@ViewChild('impactedTemplates') impactedTemplatesRef: TemplateRef<unknown>;
readonly #dossierTemplateId: string;
constructor(
@ -58,16 +59,11 @@ export class DossierAttributesListingScreenComponent extends ListingComponent<Do
await this._loadData();
}
async openConfirmDeleteAttributeDialog($event: MouseEvent, dossierAttribute?: DossierAttributeConfig) {
const dossierTemplateId = this.#dossierTemplateId;
const resp = await firstValueFrom(
this._reportTemplateService.getTemplatesByPlaceholder(dossierTemplateId, dossierAttribute.placeholder),
);
this._dialogService.openDialog('deleteAttribute', $event, { attribute: dossierAttribute, templates: resp }, async () => {
async openConfirmDeleteAttributeDialog($event: MouseEvent, attributes: DossierAttributeConfig[] = this.listingService.selected) {
await this._dialogService.deleteAttributes(attributes, this.#dossierTemplateId, this.impactedTemplatesRef, $event, async () => {
this._loadingService.start();
const ids = dossierAttribute ? [dossierAttribute.id] : this.listingService.selected.map(item => item.id);
await firstValueFrom(this._dossierAttributesService.delete(ids, dossierTemplateId));
const ids = attributes.map(a => a.id);
await firstValueFrom(this._dossierAttributesService.delete(ids, this.#dossierTemplateId));
await this._loadData();
});
}

View File

@ -37,6 +37,12 @@
</div>
</section>
<ng-template #impactedTemplates let-data="data">
<ul class="templates-container flex">
<li *ngFor="let template of data.templates" class="small-label">{{ template.fileName }}</li>
</ul>
</ng-template>
<ng-template #bulkActions>
<iqser-circle-button
(click)="openConfirmDeleteAttributeDialog($event)"
@ -126,7 +132,7 @@
icon="iqser:edit"
></iqser-circle-button>
<iqser-circle-button
(action)="openConfirmDeleteAttributeDialog($event, attribute)"
(action)="openConfirmDeleteAttributeDialog($event, [attribute])"
[tooltip]="'file-attributes-listing.action.delete' | translate"
[type]="circleButtonTypes.dark"
icon="iqser:trash"

View File

@ -1,4 +1,14 @@
import { ChangeDetectionStrategy, Component, ElementRef, forwardRef, Injector, OnDestroy, OnInit, ViewChild } from '@angular/core';
import {
ChangeDetectionStrategy,
Component,
ElementRef,
forwardRef,
Injector,
OnDestroy,
OnInit,
TemplateRef,
ViewChild,
} from '@angular/core';
import { AdminDialogService } from '../../services/admin-dialog.service';
import {
CircleButtonTypes,
@ -50,6 +60,7 @@ export class FileAttributesListingScreenComponent extends ListingComponent<FileA
rightIconTooltip: _('file-attributes-listing.table-col-names.primary-info-tooltip'),
},
];
@ViewChild('impactedTemplates') impactedTemplatesRef: TemplateRef<unknown>;
private _existingConfiguration: IFileAttributesConfig;
@ViewChild('fileInput') private _fileInput: ElementRef;
readonly #dossierTemplateId: string;
@ -93,25 +104,15 @@ export class FileAttributesListingScreenComponent extends ListingComponent<FileA
});
}
async openConfirmDeleteAttributeDialog($event: MouseEvent, fileAttribute?: FileAttributeConfig) {
const dossierTemplateId = this.#dossierTemplateId;
const resp = await firstValueFrom(
this._reportTemplateService.getTemplatesByPlaceholder(dossierTemplateId, fileAttribute.placeholder),
);
this._dialogService.openDialog('deleteAttribute', $event, { attribute: fileAttribute, templates: resp }, async () => {
async openConfirmDeleteAttributeDialog(
$event: MouseEvent,
attributes: FileAttributeConfig[] = this.listingService.selected,
): Promise<void> {
await this._dialogService.deleteAttributes(attributes, this.#dossierTemplateId, this.impactedTemplatesRef, $event, async () => {
this._loadingService.start();
if (fileAttribute) {
await firstValueFrom(this._fileAttributesService.deleteFileAttributes([fileAttribute.id], dossierTemplateId));
} else {
await firstValueFrom(
this._fileAttributesService.deleteFileAttributes(
this.listingService.selected.map(f => f.id),
dossierTemplateId,
),
);
}
await this._dossierTemplatesService.refreshDossierTemplate(dossierTemplateId);
const ids = attributes.map(a => a.id);
await firstValueFrom(this._fileAttributesService.deleteFileAttributes(ids, this.#dossierTemplateId));
await firstValueFrom(this._dossierTemplatesService.refreshDossierTemplate(this.#dossierTemplateId));
await this._loadData();
});
}
@ -148,7 +149,7 @@ export class FileAttributesListingScreenComponent extends ListingComponent<FileA
}
this._loadingService.stop();
});
await this._dossierTemplatesService.refreshDossierTemplate(this.#dossierTemplateId);
await firstValueFrom(this._dossierTemplatesService.refreshDossierTemplate(this.#dossierTemplateId));
await this._loadData();
}

View File

@ -80,7 +80,7 @@ export class UserListingScreenComponent extends ListingComponent<User> implement
}
openDeleteUsersDialog(userIds: string[], $event?: MouseEvent) {
this._dialogService.openDialog('deleteUsers', $event, userIds, async () => {
this._dialogService.deleteUsers(userIds, $event, async () => {
await this._loadData();
});
}

View File

@ -1,31 +1,42 @@
import { Injectable } from '@angular/core';
import { Injectable, TemplateRef } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { AddEditFileAttributeDialogComponent } from '../dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component';
import { AddEditDictionaryDialogComponent } from '../dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component';
import { AddEditDossierTemplateDialogComponent } from '../dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component';
import { ConfirmDeleteAttributeDialogComponent } from '../dialogs/confirm-delete-attribute-dialog/confirm-delete-attribute-dialog.component';
import { EditColorDialogComponent } from '../dialogs/edit-color-dialog/edit-color-dialog.component';
import { SmtpAuthDialogComponent } from '../dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
import { AddEditUserDialogComponent } from '../dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
import { ConfirmDeleteUsersDialogComponent } from '../dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component';
import { FileAttributesCsvImportDialogComponent } from '../dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
import { AddEditDossierAttributeDialogComponent } from '../dialogs/add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component';
import { ConfirmationDialogComponent, DialogConfig, DialogService, largeDialogConfig } from '@iqser/common-ui';
import {
ConfirmationDialogComponent,
ConfirmationDialogInput,
ConfirmOptions,
DialogConfig,
DialogService,
largeDialogConfig,
LoadingService,
TitleColors,
} from '@iqser/common-ui';
import { UploadDictionaryDialogComponent } from '../dialogs/upload-dictionary-dialog/upload-dictionary-dialog.component';
import { FileAttributesConfigurationsDialogComponent } from '../dialogs/file-attributes-configurations-dialog/file-attributes-configurations-dialog.component';
import { AddEditDossierStateDialogComponent } from '../dialogs/add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component';
import { ConfirmDeleteDossierStateDialogComponent } from '../dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { firstValueFrom, forkJoin } from 'rxjs';
import { ActiveDossiersService } from '@services/entity-services/active-dossiers.service';
import { UserService } from '../../../services/user.service';
import { IDossierAttributeConfig, IFileAttributeConfig, IReportTemplate } from '@red/domain';
import { ReportTemplateService } from '../../../services/report-template.service';
type DialogType =
| 'confirm'
| 'addEditDictionary'
| 'editColor'
| 'addEditFileAttribute'
| 'deleteAttribute'
| 'importFileAttributes'
| 'fileAttributesConfigurations'
| 'addEditUser'
| 'deleteUsers'
| 'smtpAuthConfig'
| 'addEditDossierTemplate'
| 'addEditDossierAttribute'
@ -52,10 +63,6 @@ export class AdminDialogService extends DialogService<DialogType> {
component: AddEditFileAttributeDialogComponent,
dialogConfig: { autoFocus: true },
},
deleteAttribute: {
component: ConfirmDeleteAttributeDialogComponent,
dialogConfig: { disableClose: false },
},
fileAttributesConfigurations: {
component: FileAttributesConfigurationsDialogComponent,
},
@ -63,10 +70,6 @@ export class AdminDialogService extends DialogService<DialogType> {
component: FileAttributesCsvImportDialogComponent,
dialogConfig: { ...largeDialogConfig, ...{ disableClose: false } },
},
deleteUsers: {
component: ConfirmDeleteUsersDialogComponent,
dialogConfig: { autoFocus: true, disableClose: false },
},
addEditUser: {
component: AddEditUserDialogComponent,
dialogConfig: { autoFocus: true },
@ -94,7 +97,88 @@ export class AdminDialogService extends DialogService<DialogType> {
},
};
constructor(protected readonly _dialog: MatDialog) {
constructor(
protected readonly _dialog: MatDialog,
private readonly _activeDossiersService: ActiveDossiersService,
private readonly _loadingService: LoadingService,
private readonly _userService: UserService,
private readonly _reportTemplateService: ReportTemplateService,
) {
super(_dialog);
}
deleteUsers(userIds: string[], $event?: MouseEvent, cb?: () => Promise<void> | void): void {
const data = new ConfirmationDialogInput({
title: _('confirm-delete-users.title'),
question: _('confirm-delete-users.warning'),
confirmationText: _('confirm-delete-users.delete'),
denyText: _('confirm-delete-users.cancel'),
titleColor: TitleColors.WARN,
translateParams: { usersCount: 1, dossiersCount: this._getUsersDossiersCount(userIds) },
checkboxes: [
{ value: false, label: _('confirm-delete-users.impacted-dossiers') },
{ value: false, label: _('confirm-delete-users.impacted-documents') },
],
toastMessage: _('confirm-delete-users.toast-error'),
});
this.openDialog('confirm', $event, data, async result => {
if (result === ConfirmOptions.CONFIRM) {
this._loadingService.start();
await firstValueFrom(this._userService.delete(userIds));
await cb();
this._loadingService.stop();
}
});
}
async deleteAttributes(
attributes: IFileAttributeConfig[] | IDossierAttributeConfig[],
dossierTemplateId: string,
impactedTemplatesRef: TemplateRef<unknown>,
$event?: MouseEvent,
cb?: () => Promise<void> | void,
): Promise<void> {
this._loadingService.start();
const templates$ = attributes
.map(a => a.placeholder)
.map(placeholder => this._reportTemplateService.getTemplatesByPlaceholder(dossierTemplateId, placeholder as string));
const templates: IReportTemplate[] = (await firstValueFrom(forkJoin(templates$))).flat();
const templateIds = new Set<string>(templates.map(t => t.templateId));
const uniqueTemplates = Array.from(templateIds).map(id => templates.find(t => t.templateId === id));
this._loadingService.stop();
const data = new ConfirmationDialogInput({
title: _('confirm-delete-file-attribute.title'),
question: _('confirm-delete-file-attribute.warning'),
confirmationText: _('confirm-delete-file-attribute.delete'),
denyText: _('confirm-delete-file-attribute.cancel'),
titleColor: TitleColors.WARN,
checkboxes: [
{
value: false,
label: 'confirm-delete-file-attribute.file-impacted-documents',
},
{ value: false, label: 'confirm-delete-file-attribute.file-lost-details' },
],
toastMessage: _('confirm-delete-file-attribute.toast-error'),
translateParams: { reportsCount: uniqueTemplates.length, count: attributes.length, name: attributes[0].label },
});
if (templates.length) {
data.checkboxes.push({
value: false,
label: _('confirm-delete-file-attribute.impacted-report'),
extraContent: impactedTemplatesRef,
extraContentData: { templates: uniqueTemplates },
});
}
this.openDialog('confirm', $event, data, async () => {
await cb();
});
}
private _getUsersDossiersCount(userIds: string[]): number {
return this._activeDossiersService.all.filter(dw => userIds.reduce((prev, userId) => prev || dw.memberIds.includes(userId), false))
.length;
}
}

View File

@ -1,32 +0,0 @@
<section class="dialog">
<div [translateParams]="dossier" [translate]="'confirm-archive-dossier.title'" class="dialog-header heading-l"></div>
<div *ngIf="showToast" class="inline-dialog-toast toast-error">
<div translate="confirm-archive-dossier.toast-error"></div>
<a (click)="showToast = false" class="toast-close-button">
<mat-icon svgIcon="iqser:close"></mat-icon>
</a>
</div>
<div class="dialog-content">
<div class="heading mb-8" translate="confirm-archive-dossier.warning"></div>
<div class="mb-24" translate="confirm-archive-dossier.details"></div>
<mat-checkbox
*ngFor="let checkbox of checkboxes; let idx = index"
[(ngModel)]="checkbox.value"
[class.error]="!checkbox.value && showToast"
color="primary"
>
{{ checkbox.label | translate }}
</mat-checkbox>
</div>
<div class="dialog-actions">
<button (click)="archiveDossier()" color="primary" mat-flat-button>
{{ 'confirm-archive-dossier.archive' | translate }}
</button>
<div (click)="cancel()" [translate]="'confirm-archive-dossier.cancel'" class="all-caps-label cancel"></div>
</div>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
</section>

View File

@ -1,13 +0,0 @@
@use 'variables';
.dialog-header {
color: variables.$primary;
}
mat-checkbox {
width: 100%;
&:not(:last-of-type) {
margin-bottom: 6px;
}
}

View File

@ -1,49 +0,0 @@
import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { LoadingService, Toaster } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { firstValueFrom } from 'rxjs';
import { Dossier } from '@red/domain';
import { ActiveDossiersService } from '@services/entity-services/active-dossiers.service';
import { ArchivedDossiersService } from '@services/entity-services/archived-dossiers.service';
import { Router } from '@angular/router';
@Component({
templateUrl: './confirm-archive-dossier-dialog.component.html',
styleUrls: ['./confirm-archive-dossier-dialog.component.scss'],
})
export class ConfirmArchiveDossierDialogComponent {
readonly checkboxes = [{ value: false, label: _('confirm-archive-dossier.checkbox.documents') }];
showToast = false;
constructor(
private readonly _loadingService: LoadingService,
private readonly _activeDossiersService: ActiveDossiersService,
private readonly _archivedDossiersService: ArchivedDossiersService,
private readonly _toaster: Toaster,
private readonly _router: Router,
@Inject(MAT_DIALOG_DATA) readonly dossier: Dossier,
readonly dialogRef: MatDialogRef<ConfirmArchiveDossierDialogComponent>,
) {}
get valid() {
return this.checkboxes[0].value;
}
async archiveDossier() {
if (this.valid) {
this._loadingService.start();
await firstValueFrom(this._archivedDossiersService.archive([this.dossier]));
await this._router.navigate(['main', 'dossiers']);
this._toaster.success(_('dossier-listing.archive.archive-succeeded'), { params: this.dossier });
this.dialogRef.close(true);
this._loadingService.stop();
} else {
this.showToast = true;
}
}
cancel() {
this.dialogRef.close();
}
}

View File

@ -8,7 +8,7 @@ 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 { ConfirmationDialogInput, IconButtonTypes, LoadingService, TitleColors, Toaster } from '@iqser/common-ui';
import { ConfirmationDialogInput, ConfirmOptions, IconButtonTypes, LoadingService, TitleColors, Toaster } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
@ -18,6 +18,7 @@ import { DOSSIER_TEMPLATE_ID } from '@utils/constants';
import { TranslateService } from '@ngx-translate/core';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { TrashDossiersService } from '@services/entity-services/trash-dossiers.service';
import { ArchivedDossiersService } from '@services/entity-services/archived-dossiers.service';
@Component({
selector: 'redaction-edit-dossier-general-info',
@ -49,6 +50,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
private readonly _toaster: Toaster,
private readonly _loadingService: LoadingService,
private readonly _translateService: TranslateService,
private readonly _archivedDossiersService: ArchivedDossiersService,
) {}
get changed(): boolean {
@ -128,7 +130,6 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
title: _('confirmation-dialog.delete-dossier.title'),
titleColor: TitleColors.WARN,
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'),
@ -148,8 +149,26 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
}
archiveDossier() {
this._dialogService.openDialog('archiveDossier', null, this.dossier, () => {
this._editDossierDialogRef.close();
const data = new ConfirmationDialogInput({
title: _('confirm-archive-dossier.title'),
details: _('confirm-archive-dossier.details'),
question: _('confirm-archive-dossier.warning'),
confirmationText: _('confirm-archive-dossier.archive'),
denyText: _('confirm-archive-dossier.cancel'),
titleColor: TitleColors.WARN,
translateParams: { ...this.dossier },
checkboxes: [{ value: false, label: _('confirm-archive-dossier.checkbox.documents') }],
toastMessage: _('confirm-archive-dossier.toast-error'),
});
this._dialogService.openDialog('confirm', null, data, async result => {
if (result === ConfirmOptions.CONFIRM) {
this._loadingService.start();
await firstValueFrom(this._archivedDossiersService.archive([this.dossier]));
await this._router.navigate(['main', 'dossiers']);
this._toaster.success(_('dossier-listing.archive.archive-succeeded'), { params: this.dossier });
this._editDossierDialogRef.close();
this._loadingService.stop();
}
});
}

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
import { DossierStats, StatusSorter } from '../../../../../../../../../../libs/red-domain/src';
import { DossierStats, StatusSorter } from '@red/domain';
import { List, StatusBarConfig } from '@iqser/common-ui';
@Component({

View File

@ -12,7 +12,7 @@ import { AnnotationReferencesService } from './services/annotation-references.se
import { FilterService } from '@iqser/common-ui';
import { ManualAnnotationService } from '../../services/manual-annotation.service';
import { AnnotationProcessingService } from '../../services/annotation-processing.service';
import { dossiersServiceProvider } from '../../../../services/entity-services/dossiers.service.provider';
import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider';
export const filePreviewScreenProviders = [
FilterService,

View File

@ -49,7 +49,7 @@ import { FilePreviewStateService } from './services/file-preview-state.service';
import { FileDataModel } from '../../../../models/file/file-data.model';
import { filePreviewScreenProviders } from './file-preview-providers';
import { ManualAnnotationService } from '../../services/manual-annotation.service';
import { DossiersService } from '../../../../services/entity-services/dossiers.service';
import { DossiersService } from '@services/entity-services/dossiers.service';
import Annotation = Core.Annotations.Annotation;
import PDFNet = Core.PDFNet;

View File

@ -10,7 +10,7 @@ import { IRectangle, ISectionGrid, ISectionRectangle } from '@red/domain';
import { SkippedService } from './skipped.service';
import { firstValueFrom } from 'rxjs';
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
import { DossiersService } from '../../../../../services/entity-services/dossiers.service';
import { DossiersService } from '@services/entity-services/dossiers.service';
import Annotation = Core.Annotations.Annotation;
@Injectable()

View File

@ -12,14 +12,12 @@ import { RecategorizeImageDialogComponent } from '../dialogs/recategorize-image-
import { ConfirmationDialogComponent, DialogConfig, DialogService, largeDialogConfig } from '@iqser/common-ui';
import { ResizeAnnotationDialogComponent } from '../dialogs/resize-annotation-dialog/resize-annotation-dialog.component';
import { HighlightActionDialogComponent } from '../screens/file-preview-screen/dialogs/highlight-action-dialog/highlight-action-dialog.component';
import { ConfirmArchiveDossierDialogComponent } from '../dialogs/confirm-archive-dossier-dialog/confirm-archive-dossier-dialog.component';
type DialogType =
| 'confirm'
| 'documentInfo'
| 'editDossier'
| 'addDossier'
| 'archiveDossier'
| 'assignFile'
| 'recategorizeImage'
| 'changeLegalBasis'
@ -48,10 +46,6 @@ export class DossiersDialogService extends DialogService<DialogType> {
component: AddDossierDialogComponent,
dialogConfig: { width: '900px', autoFocus: true },
},
archiveDossier: {
component: ConfirmArchiveDossierDialogComponent,
dialogConfig: { disableClose: false },
},
assignFile: {
component: AssignReviewerApproverDialogComponent,
dialogConfig: { disableClose: false },

View File

@ -8,7 +8,6 @@ import { DossiersDialogService } from '../services/dossiers-dialog.service';
import { DocumentInfoDialogComponent } from '../dialogs/document-info-dialog/document-info-dialog.component';
import { EditDossierDialogComponent } from '../dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
import { AddDossierDialogComponent } from '../dialogs/add-dossier-dialog/add-dossier-dialog.component';
import { ConfirmArchiveDossierDialogComponent } from '../dialogs/confirm-archive-dossier-dialog/confirm-archive-dossier-dialog.component';
import { AssignReviewerApproverDialogComponent } from '../dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
import { EditDossierGeneralInfoComponent } from '../dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component';
import { EditDossierDownloadPackageComponent } from '../dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component';
@ -27,12 +26,7 @@ const components = [
EditDossierTeamComponent,
EditDossierDeletedDocumentsComponent,
];
const dialogs = [
EditDossierDialogComponent,
AddDossierDialogComponent,
ConfirmArchiveDossierDialogComponent,
AssignReviewerApproverDialogComponent,
];
const dialogs = [EditDossierDialogComponent, AddDossierDialogComponent, AssignReviewerApproverDialogComponent];
const services = [DossiersDialogService, FileAssignService, RedactionImportService];
@NgModule({

View File

@ -16,10 +16,6 @@ export class FileAttributesService extends EntitiesService<FileAttributeConfig,
super(_injector, FileAttributeConfig, 'fileAttributes');
}
get fileAttributesConfig(): FileAttributesConfigMap {
return this._fileAttributesConfig$.value;
}
/**
* Get the file attributes that can be used at importing csv.
*/

View File

@ -400,16 +400,16 @@
},
"configurations": "Einstellungen",
"confirm-delete-file-attribute": {
"cancel": "{type, select, single{Attribut} bulk{Attribute} other{}} behalten",
"delete": "{type, select, single{Attribut} bulk{Attribute} other{}} löschen",
"file-impacted-documents": "Alle Dokumente {type, select, single{ist} bulk{sind} other{}} betroffen",
"cancel": "{count, plural, one{Attribut} other{Attribute}} behalten",
"delete": "{count, plural, one{Attribut} other{Attribute}} löschen",
"file-impacted-documents": "Alle Dokumente {count, plural, one{ist} other{sind}} betroffen",
"dossier-impacted-documents": "",
"file-lost-details": "Alle in die Dokumente eingegebenen Daten gehen verloren",
"dossier-lost-details": "",
"title": "{type, select, single{{name}} bulk{Datei-Attribute} other{}} löschen",
"title": "{count, plural, one{{name}} other{Datei-Attribute}} löschen",
"toast-error": "Bitte bestätigen Sie, dass Ihnen die Konsequenzen dieser Aktion bewusst sind!",
"warning": "Achtung: Diese Aktion kann nicht rückgängig gemacht werden!",
"impacted-report": "{count}"
"impacted-report": "{reportsCount}"
},
"confirm-delete-users": {
"cancel": "{usersCount, plural, one{Benutzer} other{Benutzer}} behalten",

View File

@ -451,14 +451,14 @@
"warning": "The {name} status is assigned to {count} {count, plural, one{Dossier} other{Dossiers}}."
},
"confirm-delete-file-attribute": {
"cancel": "Keep {type, select, single{Attribute} bulk{Attributes} other{}}",
"delete": "Delete {type, select, single{Attribute} bulk{Attributes} other{}}",
"cancel": "Keep {count, plural, one{Attribute} other{Attributes}}",
"delete": "Delete {count, plural, one{Attribute} other{Attributes}}",
"dossier-impacted-documents": "All dossiers based on this template will be affected",
"dossier-lost-details": "All values for this attribute will be lost",
"file-impacted-documents": "All documents {type, select, single{it is} bulk{they are} other{}} used on will be impacted",
"file-impacted-documents": "All documents {count, plural, one{it is} other{they are}} used on will be impacted",
"file-lost-details": "All inputted details on the documents will be lost",
"impacted-report": "{count} reports use the placeholder for this attribute and need to be adjusted",
"title": "Delete {type, select, single{{name}} bulk{File Attributes} other{}}",
"impacted-report": "{reportsCount} reports use the placeholder for this attribute and need to be adjusted",
"title": "Delete {count, plural, one{{name}} other{File Attributes}}",
"toast-error": "Please confirm that you understand the ramifications of your action!",
"warning": "Warning: this cannot be undone!"
},

@ -1 +1 @@
Subproject commit 4d045682ab46688934883450706e8aee8e2f1d02
Subproject commit 2cfe09a07083fb75ab070c5f428d2a1482213b7b