From 0c1c68372f0aaf08889fb05e405cc575e79ca718 Mon Sep 17 00:00:00 2001 From: amentis Date: Tue, 18 Jun 2024 10:09:40 +0300 Subject: [PATCH] json import ui --- .../services/dmp/dmp-blueprint.service.ts | 41 +++++++++- .../src/app/core/services/dmp/dmp.service.ts | 24 +++--- .../start-new-dmp-dialog.component.ts | 4 +- .../dmp-upload-dialog.component.html | 44 +++++++--- .../dmp-upload-dialog.component.ts | 80 +++++++++++++++---- .../dmp-upload-dialog.module.ts | 4 + dmp-frontend/src/assets/i18n/en.json | 7 ++ 7 files changed, 163 insertions(+), 41 deletions(-) diff --git a/dmp-frontend/src/app/core/services/dmp/dmp-blueprint.service.ts b/dmp-frontend/src/app/core/services/dmp/dmp-blueprint.service.ts index e0f718c71..729e94b96 100644 --- a/dmp-frontend/src/app/core/services/dmp/dmp-blueprint.service.ts +++ b/dmp-frontend/src/app/core/services/dmp/dmp-blueprint.service.ts @@ -1,7 +1,7 @@ import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { IsActive } from '@app/core/common/enum/is-active.enum'; -import { DmpBlueprint, DmpBlueprintDefinitionSection, DmpBlueprintPersist, NewVersionDmpBlueprintPersist } from '@app/core/model/dmp-blueprint/dmp-blueprint'; +import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection, DmpBlueprintPersist, NewVersionDmpBlueprintPersist } from '@app/core/model/dmp-blueprint/dmp-blueprint'; import { DmpBlueprintLookup } from '@app/core/query/dmp-blueprint.lookup'; import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; @@ -18,13 +18,15 @@ import { BaseHttpV2Service } from '../http/base-http-v2.service'; import { DmpBlueprintStatus } from '@app/core/common/enum/dmp-blueprint-status'; import { error } from 'console'; import { DmpBlueprintVersionStatus } from '@app/core/common/enum/dmp-blueprint-version-status'; +import { TranslateService } from '@ngx-translate/core'; @Injectable() export class DmpBlueprintService { private headers = new HttpHeaders(); - constructor(private http: BaseHttpV2Service, private httpClient: HttpClient, private configurationService: ConfigurationService, private filterService: FilterService) { + constructor(private http: BaseHttpV2Service, private httpClient: HttpClient, private configurationService: ConfigurationService, private filterService: FilterService, private language: TranslateService, + ) { } private get apiBase(): string { return `${this.configurationService.server}dmp-blueprint`; } @@ -141,6 +143,41 @@ export class DmpBlueprintService { return lookup; } + // Finalized Blueprint with definitions Single AutoComplete + singleAutocompleteBlueprintConfiguration: SingleAutoCompleteConfiguration = { + initialItems: (data?: any) => this.query(this.buildAutocompleteWithDefinitonLookup(null, null, null, [DmpBlueprintStatus.Finalized])).pipe(map(x => x.items)), + filterFn: (searchQuery: string, data?: any) => this.query(this.buildAutocompleteWithDefinitonLookup(searchQuery, null, null, [DmpBlueprintStatus.Finalized])).pipe(map(x => x.items)), + getSelectedItem: (selectedItem: any) => this.query(this.buildAutocompleteWithDefinitonLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])), + displayFn: (item: DmpBlueprint) => item.label, + subtitleFn: (item: DmpBlueprint) => this.language.instant('DMP-EDITOR.FIELDS.DMP-BLUEPRINT-VERSION') + ' '+ item.version, + titleFn: (item: DmpBlueprint) => item.label, + valueAssign: (item: DmpBlueprint) => item.id, + }; + + public buildAutocompleteWithDefinitonLookup(like?: string, excludedIds?: Guid[], ids?: Guid[], statuses?: DmpBlueprintStatus[]): DmpBlueprintLookup { + const lookup: DmpBlueprintLookup = new DmpBlueprintLookup(); + lookup.page = { size: 100, offset: 0 }; + if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; } + if (ids && ids.length > 0) { lookup.ids = ids; } + lookup.isActive = [IsActive.Active]; + lookup.statuses = statuses; + lookup.project = { + fields: [ + nameof(x => x.id), + nameof(x => x.label), + nameof(x => x.version), + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.id)].join('.'), + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.label)].join('.'), + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.hasTemplates)].join('.'), + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.descriptionTemplates), nameof(x => x.descriptionTemplateGroupId)].join('.'), + ] + }; + lookup.order = { items: [nameof(x => x.label)] }; + lookup.versionStatuses = [DmpBlueprintVersionStatus.Previous, DmpBlueprintVersionStatus.Current]; + if (like) { lookup.like = this.filterService.transformLike(like); } + return lookup; + } + // // // UI Helpers diff --git a/dmp-frontend/src/app/core/services/dmp/dmp.service.ts b/dmp-frontend/src/app/core/services/dmp/dmp.service.ts index a3bc640f3..4f311f0d9 100644 --- a/dmp-frontend/src/app/core/services/dmp/dmp.service.ts +++ b/dmp-frontend/src/app/core/services/dmp/dmp.service.ts @@ -20,6 +20,7 @@ import { AuthService } from '../auth/auth.service'; import { ConfigurationService } from '../configuration/configuration.service'; import { BaseHttpV2Service } from '../http/base-http-v2.service'; import { DmpValidationResult } from '@app/ui/dmp/dmp-finalize-dialog/dmp-finalize-dialog.component'; +import { DmpCommonModelConfig, PreprocessingDmpModel } from '@app/core/model/dmp/dmp-import'; @Injectable() export class DmpService { @@ -197,26 +198,25 @@ export class DmpService { catchError((error: any) => throwError(error)));; } - uploadJson(file: File, label: string, repositoryId: string, format: string, reqFields: string[] = []): Observable { - const url = `${this.apiBase}/json/import`; + preprocessingDmp(fileId: Guid, repositoryId: string): Observable { + const url = `${this.apiBase}/json/preprocessing`; const params = new BaseHttpParams(); params.interceptorContext = { excludedInterceptors: [InterceptorType.JSONContentType] }; const formData = new FormData(); - formData.append('file', file); - formData.append('label', label); + formData.append('fileId', fileId.toString()); formData.append('repositoryId', repositoryId); - formData.append('format', format); - - if (reqFields.length > 0){ - for (var i = 0; i < reqFields.length; i++) { - formData.append('field[]', reqFields[i]); - } - } - return this.http.post(url, formData, { params: params }).pipe(catchError((error: any) => throwError(error))); + return this.http.post(url, formData, { params: params }).pipe(catchError((error: any) => throwError(error))); + } + + uploadJson(item: DmpCommonModelConfig, reqFields: string[] = []): Observable { + const url = `${this.apiBase}/json/import`; + + return this.http.post(url, item).pipe(catchError((error: any) => throwError(error))); + } // diff --git a/dmp-frontend/src/app/ui/dmp/new/start-new-dmp-dialogue/start-new-dmp-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/new/start-new-dmp-dialogue/start-new-dmp-dialog.component.ts index e28c66d41..48146ff0e 100644 --- a/dmp-frontend/src/app/ui/dmp/new/start-new-dmp-dialogue/start-new-dmp-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/new/start-new-dmp-dialogue/start-new-dmp-dialog.component.ts @@ -79,8 +79,8 @@ export class StartNewDmpDialogComponent extends BaseComponent { }, (error) => this.onCallbackImportFail(error.error) ); - } else if (file?.type.includes('/json')){ - this.dmpService.uploadJson(result.fileList[0], result.dmpTitle, 'rda-file-transformer', 'json') + } else if (file?.type.includes('/json') && result.dmpCommonModelConfig){ + this.dmpService.uploadJson(result.dmpCommonModelConfig) .pipe(takeUntil(this._destroyed)) .subscribe( (complete) => { diff --git a/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.component.html b/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.component.html index 6c9e3038a..78ba37074 100644 --- a/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.component.html +++ b/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.component.html @@ -9,8 +9,8 @@
- - + +
@@ -30,14 +30,38 @@
- + + + + + +
+ + {{ description.get('label').value }} + + + {{'DMP-UPLOAD.FIELDS.DESCRIPTION-TEMPLATE' | translate}} + + {{description.get('templateId').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + {{'DMP-UPLOAD.FIELDS.SECTION' | translate}} + + + + {{ section.label }} + + + + +
+
+
@@ -46,7 +70,7 @@
- +
diff --git a/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.component.ts index 746643e21..e7b79efe2 100644 --- a/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.component.ts @@ -2,12 +2,22 @@ import { HttpClient } from '@angular/common/http'; import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog'; import { DescriptionTemplate } from '@app/core/model/description-template/description-template'; +import { DmpBlueprint, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint'; +import { DmpBlueprintService } from '@app/core/services/dmp/dmp-blueprint.service'; import { DmpService } from '@app/core/services/dmp/dmp.service'; import { AnalyticsService } from '@app/core/services/matomo/analytics-service'; import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; import { BaseComponent } from '@common/base/base.component'; import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { map, takeUntil } from 'rxjs/operators'; +import { DmpImportRdaConfigEditorModel } from './dmp-common-model-config.editor.model'; +import { UntypedFormArray, UntypedFormGroup } from '@angular/forms'; +import { DescriptionTemplateService } from '@app/core/services/description-template/description-template.service'; +import { FormService } from '@common/forms/form-service'; +import { DmpCommonModelConfig } from '@app/core/model/dmp/dmp-import'; +import { StorageFileService } from '@app/core/services/storage-file/storage-file.service'; +import { IsActive } from '@notification-service/core/enum/is-active.enum'; +import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; @Component({ selector: 'dmp-upload-dialog', @@ -18,13 +28,17 @@ export class DmpUploadDialogComponent extends BaseComponent { dmpTitle: string; dmpBlueprints: any[] = []; files: File[] = []; + selectedBlueprintSections: DmpBlueprintDefinitionSection[]; + formGroup: UntypedFormGroup; - profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { - filterFn: this.filterProfiles.bind(this), - initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - subtitleFn: (item) => item['description'], + descriptionTemplateSingleAutocompleteConfiguration: SingleAutoCompleteConfiguration = { + initialItems: (data?: any) => this.descriptionTemplateService.query(this.descriptionTemplateService.buildDescriptionTempalteGroupAutocompleteLookup([IsActive.Active])).pipe(map(x => x.items)), + filterFn: (searchQuery: string, data?: any) => this.descriptionTemplateService.query(this.descriptionTemplateService.buildDescriptionTempalteGroupAutocompleteLookup([IsActive.Active], searchQuery)).pipe(map(x => x.items)), + getSelectedItem: (selectedItem: any) => this.descriptionTemplateService.query(this.descriptionTemplateService.buildDescriptionTempalteGroupAutocompleteLookup([IsActive.Active, IsActive.Inactive], null, null, [selectedItem])).pipe(map(x => x.items[0])), + displayFn: (item: DescriptionTemplate) => item.label, + titleFn: (item: DescriptionTemplate) => item.label, + subtitleFn: (item: DescriptionTemplate) => item.description, + valueAssign: (item: DescriptionTemplate) => item.id, popupItemActionIcon: 'visibility' }; @@ -35,6 +49,11 @@ export class DmpUploadDialogComponent extends BaseComponent { private dialog: MatDialog, private httpClient: HttpClient, private analyticsService: AnalyticsService, + private formService: FormService, + public descriptionTemplateService: DescriptionTemplateService, + public dmpBlueprintService: DmpBlueprintService, + private dmpService: DmpService, + private storageFileStorage: StorageFileService, @Inject(MAT_DIALOG_DATA) public data: any, ) { @@ -58,9 +77,20 @@ export class DmpUploadDialogComponent extends BaseComponent { this.data.success = true; this.data.dmpTitle = this.dmpTitle; this.data.dmpBlueprints = this.dmpBlueprints; + + if (this.files.length > 0 && this.files[0].type.includes('/json') && this.formGroup && this.formGroup.valid){ + this.data.dmpCommonModelConfig = this.formService.getValue(this.formGroup.value) as DmpCommonModelConfig; + this.data.dmpCommonModelConfig.file = this.files[0]; + } this.dialogRef.close(this.data); } + disableConfirmButton(){ + if (this.data.fileList.length === 0 || this.files.length === 0) return true; + if (this.files.length > 0 && this.files[0].type.includes('/json') && this.formGroup && this.formGroup.invalid) return true; + return false; + } + uploadFile(event) { const fileList: FileList = event.target.files this.data.fileList = fileList; @@ -71,6 +101,26 @@ export class DmpUploadDialogComponent extends BaseComponent { this.files.splice(0, 1); } this.files.push(...event.target.files); + + if (this.files.length > 0 && this.files[0].type.includes('/json')){ + this.storageFileStorage.uploadTempFiles(fileList[0]) + .pipe(takeUntil(this._destroyed)) + .subscribe( + (storageFile) => { + if (storageFile.length >0 ){ + this.dmpService.preprocessingDmp(storageFile[0].id, 'rda-file-transformer') + .pipe(takeUntil(this._destroyed)) + .subscribe( + (preprocessingData) => { + this.formGroup = new DmpImportRdaConfigEditorModel().fromModel(preprocessingData, storageFile[0].id,).buildForm(); + } + ); + } + + } + ); + + } } selectFile(event) { @@ -90,14 +140,14 @@ export class DmpUploadDialogComponent extends BaseComponent { this.dmpTitle = null; } - filterProfiles(value: string): Observable { - // TODO refactor - // const request = new DataTableRequest(null, null, { fields: ['+label'] }); - // const criteria = new DatasetProfileCriteria(); - // criteria.like = value; - // request.criteria = criteria; - // return this._service.searchDmpBlueprints(request); - return null; + selectedBlueprintChanged(item: DmpBlueprint): void{ + this.selectedBlueprintSections = item.definition?.sections?.filter(x => x.hasTemplates) || null; + if (this.formGroup){ + const descriptionsFormArray = this.formGroup.get('descriptions') as UntypedFormArray; + descriptionsFormArray.controls.forEach( control =>{ + control.get('sectionId').patchValue(null); + }) + } } hasFile(): boolean { diff --git a/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.module.ts b/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.module.ts index 5f28e6c37..09b4ee30a 100644 --- a/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.module.ts +++ b/dmp-frontend/src/app/ui/dmp/new/upload-dialogue/dmp-upload-dialog.module.ts @@ -4,12 +4,16 @@ import { CommonFormsModule } from '@common/forms/common-forms.module'; import { CommonUiModule } from '@common/ui/common-ui.module'; import { NgxDropzoneModule } from 'ngx-dropzone'; import { DmpUploadDialogComponent } from './dmp-upload-dialog.component'; +import { ReactiveFormsModule } from '@angular/forms'; +import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; @NgModule({ imports: [ CommonUiModule, CommonFormsModule, FormattingModule, + ReactiveFormsModule, + AutoCompleteModule, NgxDropzoneModule ], declarations: [ diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 1cd00ab1e..c18948868 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -699,6 +699,13 @@ "DMP-UPLOAD": { "TITLE": "Import Plan", "UPLOAD-SUCCESS": "Import was Successful", + "FIELDS": { + "BLUEPRINT-PLACEHOLDER": "Select Plan Blueprint", + "DESCRIPTION-TEMPLATE": "Description Template", + "DESCRIPTION-TEMPLATE-PLACHOLDER": "Select description template", + "SECTION": "Plan Section", + "SECTION-PLACEHOLDER": "Select plan section" + }, "ACTIONS": { "IMPORT": "Import", "CANCEL": "Cancel"