Editable input & some dossier dictionary updates

This commit is contained in:
Adina Țeudan 2021-08-11 22:27:20 +03:00
parent ac0114f5d0
commit 0308d6c88f
20 changed files with 124 additions and 225 deletions

View File

@ -1,7 +1,7 @@
<iqser-table-header
[bulkActions]="bulkActions"
[selectionEnabled]="true"
[hasEmptyColumn]="true"
[selectionEnabled]="true"
[tableColumnConfigs]="tableColumnConfigs"
[tableHeaderLabel]="tableHeaderLabel"
></iqser-table-header>
@ -22,42 +22,19 @@
<div (click)="toggleEntitySelected($event, field)" class="selection-column">
<iqser-round-checkbox [active]="isSelected(field)"></iqser-round-checkbox>
</div>
<div [class.editing]="field.editingName" class="name">
<div *ngIf="!field.editingName">
{{ field.name }}
</div>
<form (submit)="field.editingName = false; field.name = field.temporaryName" *ngIf="field.editingName">
<div class="red-input-group w-200">
<input [(ngModel)]="field.temporaryName" name="name" />
</div>
</form>
<iqser-circle-button
(action)="field.editingName = true"
*ngIf="!field.editingName"
[tooltip]="'file-attributes-csv-import.action.edit-name' | translate"
class="edit-name-button"
icon="red:edit"
[type]="circleButtonTypes.dark"
></iqser-circle-button>
<ng-container *ngIf="field.editingName">
<iqser-circle-button
(action)="field.editingName = false; field.name = field.temporaryName"
[tooltip]="'file-attributes-csv-import.action.save-name' | translate"
icon="red:check"
[type]="circleButtonTypes.dark"
></iqser-circle-button>
<iqser-circle-button
(action)="field.editingName = false; field.temporaryName = field.name"
[tooltip]="'file-attributes-csv-import.action.cancel-edit-name' | translate"
icon="red:close"
[type]="circleButtonTypes.dark"
></iqser-circle-button>
</ng-container>
<div>
<iqser-editable-input
(save)="field.name = $event"
[buttonsType]="circleButtonTypes.dark"
[cancelTooltip]="'file-attributes-csv-import.action.cancel-edit-name' | translate"
[class]="'w-200'"
[editTooltip]="'file-attributes-csv-import.action.edit-name' | translate"
[saveTooltip]="'file-attributes-csv-import.action.save-name' | translate"
[value]="field.name"
></iqser-editable-input>
</div>
<div>
<div class="red-input-group">
<mat-form-field class="no-label">
@ -84,8 +61,8 @@
(action)="field.primaryAttribute = false; toggleFieldActive.emit(field)"
[removeTooltip]="true"
[tooltip]="'file-attributes-csv-import.action.remove' | translate"
icon="red:trash"
[type]="circleButtonTypes.dark"
icon="red:trash"
></iqser-circle-button>
</div>
</div>
@ -98,15 +75,15 @@
<iqser-circle-button
[matMenuTriggerFor]="readOnlyMenu"
[tooltip]="'file-attributes-csv-import.table-header.actions.read-only' | translate"
icon="red:read-only"
[type]="circleButtonTypes.dark"
icon="red:read-only"
></iqser-circle-button>
<iqser-circle-button
(action)="deactivateSelection()"
[tooltip]="'file-attributes-csv-import.table-header.actions.remove-selected' | translate"
icon="red:trash"
[type]="circleButtonTypes.dark"
icon="red:trash"
></iqser-circle-button>
<div class="separator"></div>

View File

@ -1,15 +1,10 @@
@import '../../../../../../assets/styles/variables';
iqser-table-column-name::ng-deep > div {
padding: 0 13px 0 10px !important;
&.name {
padding-left: 22px !important;
}
iqser-table-header::ng-deep iqser-table-column-name .name {
padding-left: 22px;
}
iqser-table-header::ng-deep .header-item {
padding: 0 24px 0 10px;
box-shadow: none;
border-top: 1px solid $separator;
@ -36,39 +31,26 @@ cdk-virtual-scroll-viewport {
::ng-deep.cdk-virtual-scroll-content-wrapper {
grid-template-columns: 30px minmax(0, 350px) 150px auto auto auto 11px;
.table-item {
> div {
height: 50px;
.table-item > div {
height: 50px;
&:not(.scrollbar-placeholder) {
padding-left: 10px;
&:not(.scrollbar-placeholder) {
padding-left: 10px;
&.center {
align-items: center;
}
}
&.name {
flex-direction: row;
&.center {
align-items: center;
justify-content: flex-start;
&:not(.editing) {
padding-left: 22px;
}
.edit-name-button {
display: none;
}
iqser-circle-button:first-of-type {
margin-left: 7px;
margin-right: 2px;
}
}
}
&:hover .name .edit-name-button {
iqser-editable-input:not(.editing) {
padding-left: 12px;
}
iqser-editable-input::ng-deep .edit-button {
display: none;
}
&:hover iqser-editable-input::ng-deep .edit-button {
display: block;
}
}

View File

@ -49,8 +49,8 @@
.csv-part {
display: flex;
min-height: calc(90vh - 240px);
max-height: calc(90vh - 240px);
min-height: calc(90vh - 241px);
max-height: calc(90vh - 241px);
.csv-part-header {
height: 50px;

View File

@ -16,8 +16,6 @@ export interface Field {
type: FileAttributeConfig.TypeEnum;
readonly: boolean;
primaryAttribute: boolean;
editingName?: boolean;
temporaryName?: string;
}
@Component({
@ -26,9 +24,7 @@ export interface Field {
providers: [...DefaultListingServices]
})
export class FileAttributesCsvImportDialogComponent extends ListingComponent<Field> {
protected readonly _primaryKey = 'csvColumn';
readonly tableColumnConfigs: TableColumnConfig<Field>[] = [];
parseResult: { data: any[]; errors: any[]; meta: any; fields: Field[] };
hoveredColumn: string;
activeFields: Field[] = [];
@ -39,6 +35,7 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent<Fie
keepPreview = false;
columnSample = [];
initialParseConfig: { delimiter?: string; encoding?: string } = {};
protected readonly _primaryKey = 'csvColumn';
constructor(
private readonly _toaster: Toaster,
@ -94,7 +91,6 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent<Fie
if (existing) {
entity.id = existing.id;
entity.name = existing.label;
entity.temporaryName = existing.label;
entity.type = existing.type;
entity.readonly = !existing.editable;
entity.primaryAttribute = existing.primaryAttribute;
@ -231,7 +227,6 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent<Fie
return {
csvColumn,
name: csvColumn,
temporaryName: csvColumn,
type: isNumber ? FileAttributeConfig.TypeEnum.NUMBER : FileAttributeConfig.TypeEnum.TEXT,
readonly: false,
primaryAttribute: false

View File

@ -1,24 +0,0 @@
<section class="dialog">
<div class="dialog-header heading-l" translate="dossier-dictionary-dialog.title"></div>
<form (submit)="saveDossierDictionary()">
<div class="dialog-content">
<redaction-dictionary-manager
#dictionaryManager
[canEdit]="canEdit"
[initialEntries]="dossier.type?.entries"
[withFloatingActions]="false"
></redaction-dictionary-manager>
</div>
<div class="dialog-actions">
<button [disabled]="!canEdit || !dictionaryManager.hasChanges" color="primary" mat-flat-button type="submit">
{{ 'dossier-dictionary-dialog.save-changes' | translate }}
</button>
<div class="all-caps-label pointer cancel" mat-dialog-close translate="dossier-dictionary-dialog.cancel"></div>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="red:close" mat-dialog-close></iqser-circle-button>
</section>

View File

@ -1,5 +0,0 @@
.dialog-content {
height: calc(90vh - 160px);
box-sizing: border-box;
padding-bottom: 24px;
}

View File

@ -1,44 +0,0 @@
import { Component, Inject, ViewChild } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DossierWrapper } from '@state/model/dossier.wrapper';
import { DictionaryManagerComponent } from '@shared/components/dictionary-manager/dictionary-manager.component';
import { DictionarySaveService } from '@shared/services/dictionary-save.service';
import { AppStateService } from '@state/app-state.service';
import { PermissionsService } from '@services/permissions.service';
@Component({
selector: 'redaction-dossier-dictionary-dialog',
templateUrl: './dossier-dictionary-dialog.component.html',
styleUrls: ['./dossier-dictionary-dialog.component.scss']
})
export class DossierDictionaryDialogComponent {
canEdit = false;
@ViewChild('dictionaryManager', { static: false })
private _dictionaryManager: DictionaryManagerComponent;
constructor(
public permissionsService: PermissionsService,
public dialogRef: MatDialogRef<DossierDictionaryDialogComponent>,
@Inject(MAT_DIALOG_DATA) public dossier: DossierWrapper,
private readonly _appStateService: AppStateService,
private readonly _dictionarySaveService: DictionarySaveService
) {
this.canEdit = this.permissionsService.isDossierMember(this.dossier) || this.permissionsService.isAdmin();
}
saveDossierDictionary() {
this._dictionarySaveService
.saveEntries(
this._dictionaryManager.currentEntries,
this._dictionaryManager.initialEntries,
this.dossier.dossierTemplateId,
'dossier_redaction',
this.dossier.dossierId
)
.subscribe(async () => {
await this._appStateService.reloadActiveDossierFiles();
this._appStateService.updateDossierDictionary(this.dossier.dossierTemplateId, this.dossier.dossierId);
this.dialogRef.close();
});
}
}

View File

@ -1,3 +1,28 @@
<div class="header-wrapper">
<div class="heading">
<div translate="edit-dossier-dialog.nav-items.dossier-dictionary"></div>
<div class="small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:entries"></mat-icon>
{{ 'edit-dossier-dialog.dictionary.entries' | translate: { length: (dossierWrapper.type?.entries || []).length } }}
</div>
</div>
</div>
<!-- <div class="display-name">-->
<!-- <div class="mr-16" translate="Display Name"></div>-->
<!-- <iqser-editable-input-->
<!-- (save)="field.name = $event"-->
<!-- [buttonsType]="circleButtonTypes.dark"-->
<!-- [cancelTooltip]="'file-attributes-csv-import.action.cancel-edit-name' | translate"-->
<!-- [class]="'w-200'"-->
<!-- [editTooltip]="'file-attributes-csv-import.action.edit-name' | translate"-->
<!-- [saveTooltip]="'file-attributes-csv-import.action.save-name' | translate"-->
<!-- [value]="field.name"-->
<!-- ></iqser-editable-input>-->
<!-- </div>-->
</div>
<redaction-dictionary-manager
[canEdit]="canEdit"
[initialEntries]="dossierWrapper.type?.entries || []"

View File

@ -0,0 +1,9 @@
.header-wrapper {
display: flex;
justify-content: space-between;
.display-name {
display: flex;
align-items: center;
}
}

View File

@ -5,6 +5,7 @@ import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { PermissionsService } from '@services/permissions.service';
import { DictionaryManagerComponent } from '@shared/components/dictionary-manager/dictionary-manager.component';
import { DictionarySaveService } from '@shared/services/dictionary-save.service';
import { FormBuilder } from '@angular/forms';
@Component({
selector: 'redaction-edit-dossier-dictionary',
@ -21,7 +22,8 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
constructor(
private readonly _appStateService: AppStateService,
private readonly _dictionarySaveService: DictionarySaveService,
private readonly _permissionsService: PermissionsService
private readonly _permissionsService: PermissionsService,
private readonly _formBuilder: FormBuilder
) {
this.canEdit = this._permissionsService.isDossierMember(this.dossierWrapper) || this._permissionsService.isAdmin();
}

View File

@ -17,16 +17,6 @@
<div [class.no-actions]="!showActionButtons" [class.no-padding]="noPaddingTab" class="content">
<div *ngIf="showHeading" class="heading">
{{ activeNavItem.title | translate }}
<div *ngIf="showSubtitle" class="small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:entries"></mat-icon>
{{
'edit-dossier-dialog.dictionary.entries'
| translate: { length: (dossierWrapper.type?.entries || []).length }
}}
</div>
</div>
</div>
<redaction-edit-dossier-general-info

View File

@ -72,7 +72,7 @@ export class EditDossierDialogComponent {
];
this.dossierWrapper = _data.dossierWrapper;
this.activeNav = _data.section || 'dossierInfo';
this.activeNav = _data.section || 'dossierDictionary';
}
get activeNavItem(): { key: string; title?: string } {
@ -95,11 +95,7 @@ export class EditDossierDialogComponent {
}
get showHeading(): boolean {
return !['dossierAttributes', 'deletedDocuments'].includes(this.activeNav);
}
get showSubtitle(): boolean {
return ['dossierDictionary'].includes(this.activeNav);
return !['dossierAttributes', 'dossierDictionary', 'deletedDocuments'].includes(this.activeNav);
}
get showActionButtons(): boolean {

View File

@ -34,7 +34,6 @@ import { PdfViewerDataService } from './services/pdf-viewer-data.service';
import { ManualAnnotationService } from './services/manual-annotation.service';
import { AnnotationDrawService } from './services/annotation-draw.service';
import { AnnotationProcessingService } from './services/annotation-processing.service';
import { DossierDictionaryDialogComponent } from './dialogs/dossier-dictionary-dialog/dossier-dictionary-dialog.component';
import { EditDossierDialogComponent } from './dialogs/edit-dossier-dialog/edit-dossier-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';
@ -62,7 +61,6 @@ const dialogs = [
RemoveAnnotationsDialogComponent,
DocumentInfoDialogComponent,
AssignReviewerApproverDialogComponent,
DossierDictionaryDialogComponent,
ChangeLegalBasisDialogComponent,
RecategorizeImageDialogComponent
];

View File

@ -163,20 +163,19 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
this.ngOnDestroy();
}
reanalyseDossier() {
return this._appStateService
.reanalyzeDossier()
.then(() => {
this.reloadDossiers();
this._toaster.success(_('dossier-overview.reanalyse-dossier.success'));
})
.catch(() => this._toaster.error(_('dossier-overview.reanalyse-dossier.error')));
async reanalyseDossier() {
try {
await this._appStateService.reanalyzeDossier();
await this.reloadDossiers();
this._toaster.success(_('dossier-overview.reanalyse-dossier.success'));
} catch (e) {
this._toaster.error(_('dossier-overview.reanalyse-dossier.error'));
}
}
reloadDossiers() {
this._appStateService.getFiles(this.currentDossier, false).then(() => {
this.calculateData();
});
async reloadDossiers() {
await this._appStateService.getFiles(this.currentDossier, false);
this.calculateData();
}
calculateData(): void {
@ -209,9 +208,9 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
return fileStatus.canBeOpened ? [`/main/dossiers/${this.currentDossier.dossierId}/file/${fileStatus.fileId}`] : [];
}
bulkActionPerformed() {
async bulkActionPerformed() {
this.entitiesService.setSelected([]);
this.reloadDossiers();
await this.reloadDossiers();
}
openEditDossierDialog($event: MouseEvent) {
@ -221,20 +220,14 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
}
openAssignDossierMembersDialog(): void {
this._dialogService.openDialog(
'editDossier',
null,
{
dossierWrapper: this.currentDossier,
section: 'members'
},
() => this.reloadDossiers()
);
const data = { dossierWrapper: this.currentDossier, section: 'members' };
this._dialogService.openDialog('editDossier', null, data, async () => await this.reloadDossiers());
}
openDossierDictionaryDialog() {
this._dialogService.openDialog('dossierDictionary', null, this.currentDossier, () => {
this.reloadDossiers();
const data = { dossierWrapper: this.currentDossier, section: 'dossierDictionary' };
this._dialogService.openDialog('editDossier', null, data, async () => {
await this.reloadDossiers();
});
}

View File

@ -8,7 +8,6 @@ import { DocumentInfoDialogComponent } from '../dialogs/document-info-dialog/doc
import { AppStateService } from '@state/app-state.service';
import { ManualAnnotationService } from './manual-annotation.service';
import { ManualAnnotationDialogComponent } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
import { DossierDictionaryDialogComponent } from '../dialogs/dossier-dictionary-dialog/dossier-dictionary-dialog.component';
import { EditDossierDialogComponent } from '../dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
import { AssignReviewerApproverDialogComponent } from '../dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
import { AppConfigService } from '@app-config/app-config.service';
@ -25,7 +24,6 @@ type DialogType =
| 'assignFile'
| 'recategorizeImage'
| 'changeLegalBasis'
| 'dossierDictionary'
| 'removeAnnotations'
| 'forceRedaction'
| 'manualAnnotation';
@ -64,10 +62,6 @@ export class DossiersDialogService extends DialogService<DialogType> {
changeLegalBasis: {
component: ChangeLegalBasisDialogComponent
},
dossierDictionary: {
component: DossierDictionaryDialogComponent,
dialogConfig: { width: '90vw', height: '90vh' }
},
removeAnnotations: {
component: RemoveAnnotationsDialogComponent
},

View File

@ -1,6 +1,6 @@
<div class="content-container">
<div class="actions-bar">
<div class="red-input-group w-450 mr-32">
<div class="red-input-group w-250 mr-32">
<input
#inputElement
(keyup)="searchChanged(searchText)"
@ -24,18 +24,20 @@
</div>
</div>
</div>
<div class="red-input-group mr-16">
<mat-checkbox [(ngModel)]="compare" color="primary">
{{ 'dictionary-overview.compare.compare' | translate }}
</mat-checkbox>
</div>
<div class="red-input-group w-200 mr-8">
<mat-select [(ngModel)]="dossier" [disabled]="!compare">
<mat-option [value]="selectDossier">{{ selectDossier.dossierName | translate }}</mat-option>
<mat-option *ngFor="let dossier of dossiers" [value]="dossier">
{{ dossier.dossierName }}
</mat-option>
</mat-select>
<div class="compare">
<div class="red-input-group mr-16">
<mat-checkbox [(ngModel)]="compare" color="primary">
{{ 'dictionary-overview.compare.compare' | translate }}
</mat-checkbox>
</div>
<div class="red-input-group w-200 mt-0">
<mat-select [(ngModel)]="dossier" [disabled]="!compare">
<mat-option [value]="selectDossier">{{ selectDossier.dossierName | translate }}</mat-option>
<mat-option *ngFor="let dossier of dossiers" [value]="dossier">
{{ dossier.dossierName }}
</mat-option>
</mat-select>
</div>
</div>
</div>
@ -65,8 +67,8 @@
<iqser-icon-button
(action)="saveDictionary.emit(currentEntries)"
[label]="'dictionary-overview.save-changes' | translate"
icon="red:check"
[type]="iconButtonTypes.primary"
icon="red:check"
></iqser-icon-button>
<div (click)="revert()" class="all-caps-label cancel" translate="dictionary-overview.revert-changes"></div>
</div>

View File

@ -50,6 +50,12 @@ ngx-monaco-editor {
display: flex;
align-items: center;
margin-bottom: 16px;
justify-content: space-between;
> .compare {
display: flex;
align-items: center;
}
.mr-32 {
margin-right: 32px;

View File

@ -282,7 +282,7 @@ export class AppStateService {
}
updateDossierDictionary(dossierTemplateId: string, dossierId: string) {
// dossier exists, load it's dictionary
// dossier exists, load its dictionary
this._dictionaryControllerService.getDictionaryForType(dossierTemplateId, 'dossier_redaction', dossierId).subscribe(
typeData => {
this.activeDossier.type = typeData;

View File

@ -1,10 +1,8 @@
@import 'variables';
@import 'red-mixins';
form {
.red-input-group:not(first-of-type) {
margin-top: 14px;
}
form .red-input-group:not(first-of-type) {
margin-top: 14px;
}
.red-input-group {
@ -103,13 +101,13 @@ form {
border-radius: 8px;
outline: none;
margin-top: 3px;
min-height: 34px;
min-height: 36px;
&.with-icon {
padding-right: 34px;
}
&:focus {
&:focus:not(:disabled):not(.mat-select-disabled) {
border-color: $accent;
}
@ -126,7 +124,8 @@ form {
}
}
&:disabled {
&:disabled,
&.mat-select-disabled {
background-color: $grey-2;
color: rgba($accent, 0.3);
}

View File

@ -42,6 +42,10 @@ export interface Dictionary {
* True if the type just for hint, not for redaction, default is false.
*/
hint?: boolean;
/**
* Label of the type
*/
label?: string;
/**
* The rank of this dictionary, higher rank means higher importance.
*/