RED-9201 - UI for Component Mapping Tables

This commit is contained in:
Valentin Mihai 2024-06-05 00:09:32 +03:00
parent d3f293f622
commit a960b837df
12 changed files with 308 additions and 9 deletions

View File

@ -0,0 +1,66 @@
<section class="dialog">
<div
[innerHTML]="'add-edit-component-mapping.dialog.title' | translate: { type: data.mapping ? 'edit' : 'add' }"
class="dialog-header heading-l"
></div>
<form (submit)="save()" [formGroup]="form">
<div class="dialog-content">
<div class="row">
<div class="iqser-input-group required w-300">
<label translate="add-edit-component-mapping.form.name"></label>
<input
[placeholder]="'add-edit-component-mapping.form.name-placeholder' | translate"
formControlName="name"
name="label"
type="text"
/>
</div>
<div class="iqser-input-group w-100 version" *ngIf="data?.mapping?.version">
<label translate="add-edit-component-mapping.form.version"></label>
<span> {{ data.mapping.version }} </span>
<!-- <input [placeholder]="'add-edit-component-mapping.form.name-placeholder' | translate" formControlName="name" name="label" type="text" />-->
</div>
</div>
<div class="iqser-input-group required">
<label translate="add-edit-component-mapping.form.file"></label>
<iqser-upload-file (fileChanged)="fileChanged($event)" />
</div>
<div class="row">
<div class="iqser-input-group required w-150">
<label translate="add-edit-component-mapping.form.delimiter"></label>
<input
[placeholder]="'add-edit-component-mapping.form.delimiter-placeholder' | translate"
formControlName="delimiter"
name="delimiter"
type="text"
/>
</div>
<div class="iqser-input-group required w-150">
<label translate="add-edit-component-mapping.form.encoding-type"></label>
<mat-form-field>
<mat-select formControlName="encodingType">
<mat-option *ngFor="let type of encodingTypeOptions" [value]="type">
{{ translations[type] | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div class="dialog-actions">
<iqser-icon-button
(action)="save()"
[disabled]="disabled"
[label]="'add-edit-component-mapping.actions.save' | translate"
[type]="iconButtonTypes.primary"
></iqser-icon-button>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
</section>

View File

@ -0,0 +1,21 @@
.row {
display: flex;
margin-top: 14px;
> *:not(:last-child) {
margin-right: 16px;
}
.iqser-input-group {
margin-top: 0;
}
.version {
margin-left: 50px;
span {
margin-top: 10px;
font-size: 15px;
}
}
}

View File

@ -0,0 +1,81 @@
import { Component } from '@angular/core';
import { CircleButtonComponent, IconButtonComponent, IconButtonTypes, IqserDialogComponent, IqserUploadFileModule } from '@iqser/common-ui';
import { FileAttributeEncodingTypes, IComponentMapping } from '@red/domain';
import { FormBuilder, ReactiveFormsModule, UntypedFormGroup, Validators } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { NgForOf, NgIf } from '@angular/common';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDialogClose } from '@angular/material/dialog';
import { MatOption } from '@angular/material/autocomplete';
import { MatSelect } from '@angular/material/select';
import { fileAttributeEncodingTypesTranslations } from '@translations/file-attribute-encoding-types-translations';
interface DialogData {
mapping: IComponentMapping;
}
interface DialogResult {}
@Component({
templateUrl: './add-edit-component-mapping-dialog.component.html',
styleUrls: ['./add-edit-component-mapping-dialog.component.scss'],
standalone: true,
imports: [
TranslateModule,
ReactiveFormsModule,
NgIf,
MatFormFieldModule,
NgForOf,
CircleButtonComponent,
MatDialogClose,
IqserUploadFileModule,
MatOption,
MatSelect,
IconButtonComponent,
],
})
export class AddEditComponentMappingDialogComponent extends IqserDialogComponent<
AddEditComponentMappingDialogComponent,
DialogData,
DialogResult
> {
protected readonly encodingTypeOptions = Object.keys(FileAttributeEncodingTypes);
protected readonly translations = fileAttributeEncodingTypesTranslations;
protected readonly iconButtonTypes = IconButtonTypes;
form!: UntypedFormGroup;
constructor(private readonly _formBuilder: FormBuilder) {
super();
this.form = this.#getForm();
}
get file() {
return this.form.get('file').value;
}
fileChanged(file: Blob | null) {
if (file) {
const fileReader = new FileReader();
fileReader.onload = () => {
const binaryContent = <string>fileReader.result;
this.form.get('file').setValue(binaryContent);
};
fileReader.readAsBinaryString(file as Blob);
} else {
this.form.controls['file'].setValue('');
}
}
save() {
this.dialogRef.close({ ...this.data.mapping, ...this.form.getRawValue() });
}
#getForm(): UntypedFormGroup {
return this._formBuilder.group({
name: [this.data?.mapping?.name, Validators.required],
file: [this.data?.mapping?.file, Validators.required],
delimiter: [this.data?.mapping?.delimiter ?? ',', Validators.required],
encodingType: this.encodingTypeOptions.find(e => e === this.data?.mapping?.encodingType) ?? this.encodingTypeOptions[0],
});
}
}

View File

@ -1,14 +1,23 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { ListingComponent, TableColumnConfig, listingProvidersFactory, LoadingService, IconButtonTypes } from '@iqser/common-ui';
import {
ListingComponent,
TableColumnConfig,
listingProvidersFactory,
LoadingService,
IconButtonTypes,
IqserDialog,
} from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { defaultColorsTranslations } from '@translations/default-colors-translations';
import { Roles } from '@users/roles';
import { getCurrentUser } from '@common-ui/users';
import { User } from '@red/domain';
import { ComponentMapping } from '@red/domain';
import { combineLatest } from 'rxjs';
import { combineLatest, firstValueFrom } from 'rxjs';
import { ComponentMappingsService } from '@services/entity-services/component-mappings.service';
import { tap } from 'rxjs/operators';
import { AddEditComponentMappingDialogComponent } from './add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component';
import { AdminDialogService } from '../../services/admin-dialog.service';
@Component({
templateUrl: './component-mappings-screen.component.html',
@ -30,6 +39,8 @@ export class ComponentMappingsScreenComponent extends ListingComponent<Component
constructor(
private readonly _loadingService: LoadingService,
private readonly _componentMappingService: ComponentMappingsService,
private readonly _iqserDialog: IqserDialog,
private readonly _dialogService: AdminDialogService,
) {
super();
this.context$ = combineLatest([this._componentMappingService.loadData()]).pipe(
@ -41,7 +52,22 @@ export class ComponentMappingsScreenComponent extends ListingComponent<Component
this._loadingService.stop();
}
openAddEditComponentMappingDialog(entity?: ComponentMapping) {}
async openAddEditComponentMappingDialog(mapping?: ComponentMapping) {
const dialog = this._iqserDialog.openDefault(AddEditComponentMappingDialogComponent, {
data: {
mapping,
},
});
const result = await dialog.result();
if (result) {
this._componentMappingService.saveData(result);
}
}
openDeleteComponentMappingDialog(entity?: ComponentMapping) {}
openDeleteComponentMappingDialog(entity?: ComponentMapping) {
this._dialogService.openDialog('confirm', null, async () => {
// this._loadingService.start();
// this._loadingService.stop();
});
}
}

View File

@ -7,36 +7,54 @@ const DATA = [
{
id: '1',
name: 'OECD Number',
file: 'some file name',
delimiter: ',',
encodingType: 'UTF-8',
version: 2,
searchKey: 'OECD Number',
},
{
id: '2',
name: 'Study Title',
file: 'some file name',
delimiter: ';',
encodingType: 'ASCII',
version: 1,
searchKey: 'Study Title',
},
{
id: '3',
name: 'Report Number',
file: 'some file name',
delimiter: '.',
encodingType: 'ISO',
version: 2,
searchKey: 'Report Number',
},
{
id: '4',
name: 'GLP Study',
file: 'some file name',
delimiter: '"',
encodingType: 'UTF-8',
version: 5,
searchKey: 'GLP Study',
},
{
id: '5',
name: 'Performing Laboratory',
file: 'some file name',
delimiter: ']',
encodingType: 'UTF-8',
version: 2,
searchKey: 'Performing Laboratory',
},
{
id: '6',
name: 'Test',
file: 'some file name',
delimiter: ';',
encodingType: 'UTF-8',
version: 3,
searchKey: 'Test',
},
@ -49,4 +67,14 @@ export class ComponentMappingsService extends EntitiesService<IComponentMapping,
loadData(): Observable<ComponentMapping[]> {
return of(DATA);
}
saveData(mapping: any): Observable<ComponentMapping> {
if (!mapping.id) {
mapping.id = (Number(DATA[DATA.length - 1].id) + 1).toString();
mapping.version = 1;
mapping.searchKey = mapping.name;
}
DATA.push(mapping);
return of(mapping);
}
}

View File

@ -1,9 +1,9 @@
{
"ADMIN_CONTACT_NAME": null,
"ADMIN_CONTACT_URL": null,
"API_URL": "https://dan.iqser.cloud",
"API_URL": "https://frontend2.iqser.cloud",
"APP_NAME": "RedactManager",
"IS_DOCUMINE": false,
"IS_DOCUMINE": true,
"RULE_EDITOR_DEV_ONLY": false,
"AUTO_READ_TIME": 3,
"BACKEND_APP_VERSION": "4.4.40",
@ -13,13 +13,13 @@
"MAX_RETRIES_ON_SERVER_ERROR": 3,
"OAUTH_CLIENT_ID": "redaction",
"OAUTH_IDP_HINT": null,
"OAUTH_URL": "https://dan.iqser.cloud/auth",
"OAUTH_URL": "https://frontend2.iqser.cloud/auth",
"RECENT_PERIOD_IN_HOURS": 24,
"SELECTION_MODE": "structural",
"MANUAL_BASE_URL": "https://docs.redactmanager.com/preview",
"ANNOTATIONS_THRESHOLD": 1000,
"THEME": "redact",
"BASE_TRANSLATIONS_DIRECTORY": "/assets/i18n/redact/",
"THEME": "scm",
"BASE_TRANSLATIONS_DIRECTORY": "/assets/i18n/scm/",
"AVAILABLE_NOTIFICATIONS_DAYS": 30,
"AVAILABLE_OLD_NOTIFICATIONS_MINUTES": 60,
"NOTIFICATIONS_THRESHOLD": 1000,

View File

@ -94,6 +94,23 @@
},
"save": "Dossier-Vorlage speichern"
},
"add-edit-component-mapping": {
"actions": {
"save": ""
},
"dialog": {
"title": ""
},
"form": {
"delimiter": "",
"delimiter-placeholder": "",
"encoding-type": "",
"file": "",
"name": "",
"name-placeholder": "",
"version": ""
}
},
"add-edit-dossier-attribute": {
"error": {
"generic": "Attribut konnte nicht gespeichert werden!"

View File

@ -94,6 +94,23 @@
},
"save": "Save dossier template"
},
"add-edit-component-mapping": {
"actions": {
"save": "Save mapping"
},
"dialog": {
"title": "{type, select, add{Add New} edit{Edit} other{}} Component Mapping"
},
"form": {
"delimiter": "",
"delimiter-placeholder": "",
"encoding-type": "",
"file": "Mapping file",
"name": "Mapping name",
"name-placeholder": "Mapping name",
"version": "Version"
}
},
"add-edit-dossier-attribute": {
"error": {
"generic": "Failed to save attribute"

View File

@ -94,6 +94,23 @@
},
"save": "Dossier-Vorlage speichern"
},
"add-edit-component-mapping": {
"actions": {
"save": ""
},
"dialog": {
"title": ""
},
"form": {
"delimiter": "",
"delimiter-placeholder": "",
"encoding-type": "",
"file": "",
"name": "",
"name-placeholder": "",
"version": ""
}
},
"add-edit-dossier-attribute": {
"error": {
"generic": "Attribut konnte nicht gespeichert werden!"

View File

@ -94,6 +94,23 @@
},
"save": "Save dossier template"
},
"add-edit-component-mapping": {
"actions": {
"save": "Save mapping"
},
"dialog": {
"title": "{type, select, add{Add New} edit{Edit} other{}} Component Mapping"
},
"form": {
"delimiter": "Delimiter",
"delimiter-placeholder": "Delimiter",
"encoding-type": "Encoding type",
"file": "Mapping file",
"name": "Mapping name",
"name-placeholder": "Mapping name",
"version": "Version"
}
},
"add-edit-dossier-attribute": {
"error": {
"generic": "Failed to save attribute!"

View File

@ -4,11 +4,17 @@ import { IListable } from '@iqser/common-ui';
export class ComponentMapping implements IComponentMapping, IListable {
readonly id: string;
readonly name: string;
readonly file: string;
readonly delimiter: string;
readonly encodingType: string;
readonly version: number;
constructor(componentMapping: IComponentMapping) {
this.id = componentMapping.id;
this.name = componentMapping.name;
this.file = componentMapping.file;
this.delimiter = componentMapping.delimiter;
this.encodingType = componentMapping.encodingType;
this.version = componentMapping.version;
}

View File

@ -1,5 +1,8 @@
export interface IComponentMapping {
id: string;
name: string;
file: string;
version: number;
delimiter: string;
encodingType: string;
}