import { COMMA, ENTER } from '@angular/cdk/keycodes'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, SimpleChanges } from '@angular/core'; import { UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { MatDialog } from "@angular/material/dialog"; import { DescriptionTemplateFieldType } from '@app/core/common/enum/description-template-field-type'; import { DescriptionTemplateFieldValidationType } from '@app/core/common/enum/description-template-field-validation-type'; import { DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplateLabelAndMultiplicityData, DescriptionTemplateUploadData } from '@app/core/model/description-template/description-template'; import { FetcherReference } from '@app/core/model/reference/reference'; import { DmpService } from '@app/core/services/dmp/dmp.service'; import { SnackBarNotificationLevel, UiNotificationService } from "@app/core/services/notification/ui-notification-service"; import { ReferenceService } from '@app/core/services/reference/reference.service'; import { FileUtils } from '@app/core/services/utilities/file-utils.service'; import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; import { VisibilityRulesService } from '@app/ui/description/editor/description-form/visibility-rules/visibility-rules.service'; import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-description-form-field', templateUrl: './form-field.component.html', styleUrls: ['./form-field.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) export class DescriptionFormFieldComponent extends BaseComponent implements OnInit { @Input() field: DescriptionTemplateField; @Input() fieldSet: DescriptionTemplateFieldSet; @Input() propertiesFormGroup: UntypedFormGroup; @Input() visibilityRulesService: VisibilityRulesService; isRequired: boolean = false; // @Input() field: Field; // @Input() form: UntypedFormGroup; @Input() datasetProfileId: any; @Input() isChild: Boolean = false; visible: boolean = true; // change: Subscription; // trackByFn = (index, item) => item ? item['id'] : null; descriptionTemplateFieldTypeEnum = DescriptionTemplateFieldType; public singleAutoCompleteConfiguration: SingleAutoCompleteConfiguration; public multipleAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; tagsAutoCompleteConfiguration: SingleAutoCompleteConfiguration; currencyAutoCompleteConfiguration: SingleAutoCompleteConfiguration; multipleReferenceAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; readonly separatorKeysCodes: number[] = [ENTER, COMMA]; // tags: ExternalTagEditorModel[] = []; datasetIdInitialized: boolean = false; validationIcon; readonly datasetIdTypes: any[] = [ { name: 'Handle', value: 'handle' }, { name: 'DOI', value: 'doi' }, { name: 'Ark', value: 'ark' }, { name: 'Url', value: 'url' }, { name: 'Other', value: 'other' } ]; readonly validationTypes: any[] = [ { name: 'Zenodo', value: 'zenodo' } ]; filesToUpload: FileList; constructor( private language: TranslateService, private dmpService: DmpService, private cdr: ChangeDetectorRef, private uiNotificationService: UiNotificationService, public dialog: MatDialog, private fileUtils: FileUtils, private referenceService: ReferenceService ) { super(); } ngOnChanges(changes: SimpleChanges) { if (changes['form']) { } } ngOnInit() { // this.visibilityRulesService.getElementVisibilityMapObservable().pipe(takeUntil(this._destroyed)).subscribe(x => { // // console.log('getElementVisibilityMapObservable form field set'); // if (x[this.field.id]) { // this.visible = x[this.field.id]; // } else { // this.visible = true; // } // }); //TODO: validate that this logic is correct. Validation contenxt path might need to be fixed. // if (this.propertiesFormGroup.get(this.field.id).get('value') == null) { // const item: DescriptionFieldEditorModel = new DescriptionFieldEditorModel(); // item.key = this.field.id; // this.propertiesFormGroup.addControl(this.field.id, item.buildForm()); // } // if (this.propertiesFormGroup.get(this.field.id).get('value').value) { // this.visibilityRulesService.updateValueAndVisibility(this.field?.id, this.propertiesFormGroup.get(this.field.id).get('value').value); // } this.isRequired = this.field.validations?.includes(DescriptionTemplateFieldValidationType.Required); //TODO: refactor // if (this.field?.data?.fieldType === DescriptionTemplateFieldType.SELECT) { // if ((this.field.data as DescriptionTemplateSelectData).multipleSelect) { // const originalValue = this.propertiesFormGroup.get(this.field.id).get('value').value; // if (originalValue !== null && typeof originalValue === 'string') { // let values = (this.propertiesFormGroup.get(this.field.id).get('value').value).slice(1, -1).split(', ').filter((value) => !value.includes('"')); // let specialValue = (this.propertiesFormGroup.get(this.field.id).get('value').value).split('"').filter((value) => !value.startsWith('[') && !value.endsWith(']') && !values.includes(value) && value !== ', '); // specialValue.forEach(value => values.push(value)); // if (!originalValue.startsWith('[') && !originalValue.endsWith(']')) { // values = undefined; // values = [originalValue]; // } // this.propertiesFormGroup.get(this.field.id).get('value').patchValue(values); // values.forEach(element => { // this.visibilityRulesService.updateValueAndVisibility(this.field?.id, element); // }); // } // } // } switch (this.field?.data?.fieldType) { case DescriptionTemplateFieldType.EXTERNAL_DATASETS: //TODO: refactor // this.multipleReferenceAutoCompleteConfiguration = { // filterFn: this.filterOrganisations.bind(this), // initialItems: (excludedItems: any[]) => this.filterOrganisations('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), // displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, // titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, // subtitleFn: (item) => { try { return item['tag'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) } catch { return '' } }, // valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } } // }; break; case DescriptionTemplateFieldType.TAGS: this.tagsAutoCompleteConfiguration = { filterFn: this.filterTags.bind(this), initialItems: (excludedItems: any[]) => this.filterTags('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => { try { return this.showTag(item) } catch { return '' } }, titleFn: (item) => { try { return item['name'] } catch { return '' } }, valueAssign: (item) => { try { return this.addTag(item) } catch { return '' } } }; this.parseTags(); break; case DescriptionTemplateFieldType.DATASET_IDENTIFIER: // const value = this.propertiesFormGroup.get(this.field.id).get('value').value; // const disabled = this.propertiesFormGroup.get(this.field.id).disabled; //TODO: Refactor this. // this.form.removeControl('value'); // this.form.addControl('value', new DatasetIdModel(value).buildForm()); // if (disabled) { // this.form.disable(); // } this.datasetIdInitialized = true; break; case DescriptionTemplateFieldType.CURRENCY: this.currencyAutoCompleteConfiguration = { filterFn: this.searchCurrency.bind(this), initialItems: () => this.searchCurrency(''), displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } } }; break; case DescriptionTemplateFieldType.VALIDATION: // const value1 = this.propertiesFormGroup.get(this.field.id).get('value').value; // const disabled1 = this.propertiesFormGroup.get(this.field.id).disabled; //TODO: Refactor this. // this.form.removeControl('value'); // this.form.addControl('value', new DatasetIdModel(value1).buildForm()); // if (disabled1) { // this.form.disable(); // } break; case DescriptionTemplateFieldType.INTERNAL_ENTRIES_DESCRIPTIONS: this.makeAutocompleteConfiguration(this.searchDatasets.bind(this), "label"); break; case DescriptionTemplateFieldType.INTERNAL_ENTRIES_DMPS: this.makeAutocompleteConfiguration(this.searchDmps.bind(this), "label"); break; } // this.form = this.visibilityRulesService.getFormGroup(this.field.id); //TODO: refactor // this.propertiesFormGroup.get(this.field.id).get('value').valueChanges // .pipe( // takeUntil(this._destroyed), // distinctUntilChanged() // ) // .subscribe(item => { // // if (this.field?.data?.fieldType === DescriptionTemplateFieldType.ComboBox && this.form.get('data').value.type === DatasetProfileComboBoxType.Select && this.form.get('data').value.multipleSelect) { // // item.forEach(element => { // // this.visibilityRulesService.updateValueAndVisibility(this.field?.id, element); // // }); // // } else { // this.visibilityRulesService.updateValueAndVisibility(this.field?.id, item); // // } // }); } // _optionRemove(event) { // const array = JSON.parse(this.propertiesFormGroup.get(this.field.id).get('value').value); // if (array) { // const index = array.map(x => x.id).indexOf(event.id); // if (index >= 0) { // array.splice(index, 1); // } // this.propertiesFormGroup.get(this.field.id).get('value').patchValue(JSON.stringify(array)); // } // } searchFromAutocomplete(query: string) { //TODO refactor return null; // if (this.autocompleteOptions) { // const autocompleteRequestItem: RequestItem = new RequestItem(); // autocompleteRequestItem.criteria = new DatasetExternalAutocompleteOptionsCriteria(); // //TODO: refactor this // //autocompleteRequestItem.criteria.sources = this.autocompleteOptions; // // autocompleteRequestItem.criteria.like = query; // // return this.datasetExternalAutocompleteService.queryApi(autocompleteRequestItem); // return null; // } // else { // const autocompleteRequestItem: RequestItem = new RequestItem(); // autocompleteRequestItem.criteria = new DatasetExternalAutocompleteCriteria(); // let parseIdArray: string[] = this.field?.id.split('_'); // if (parseIdArray.length > 1) { // autocompleteRequestItem.criteria.fieldID = parseIdArray[parseIdArray.length - 1]; // } else { // autocompleteRequestItem.criteria.fieldID = this.field?.id; // } // if (typeof this.datasetProfileId === 'string') { // autocompleteRequestItem.criteria.profileID = this.datasetProfileId; // } // else if (this.datasetProfileId != null) { // autocompleteRequestItem.criteria.profileID = this.datasetProfileId.id; // } // autocompleteRequestItem.criteria.like = query; // //TODO: refactor this // // return this.datasetExternalAutocompleteService.queryAutocomplete(autocompleteRequestItem); // return null; // } } searchResearchers(query: string) { //TODO refactor return null; // const reasearcherAutocompleteRequestItem: RequestItem = new RequestItem(); // reasearcherAutocompleteRequestItem.criteria = new ResearcherCriteria; // reasearcherAutocompleteRequestItem.criteria.name = query; // return this.externalSourcesService.searchDMPResearchers(reasearcherAutocompleteRequestItem); } searchDatasets(query: string) { //TODO refactor return null; // let fields: Array = new Array(); // const datasetsAutocompleteRequestItem: DataTableRequest = new DataTableRequest(0, 25, { fields: fields }); // datasetsAutocompleteRequestItem.criteria = new DatasetCriteria(); // datasetsAutocompleteRequestItem.criteria.like = query; // //TODO: refactor this // // return this.datasetService.getPaged(datasetsAutocompleteRequestItem).pipe(map(item => item.data)); // return null; } searchDmps(query: string) { //TODO refactor return null; // let fields: Array = new Array(); // const dmpsAutocompleteRequestItem: DataTableRequest = new DataTableRequest(0, 25, { fields: fields }); // dmpsAutocompleteRequestItem.criteria = new DmpCriteria(); // dmpsAutocompleteRequestItem.criteria.like = query; // return this.dmpService.getPaged(dmpsAutocompleteRequestItem).pipe(map(item => item.data)); } makeAutocompleteConfiguration(myfunc: Function, title: string, subtitle?: string): void { if (!((this.field.data as DescriptionTemplateLabelAndMultiplicityData).multipleSelect)) { this.singleAutoCompleteConfiguration = { filterFn: myfunc.bind(this), initialItems: (extraData) => myfunc(''), displayFn: (item) => { try { return (item != null && item.length > 1) ? JSON.parse(item)[title] : item[title] } catch { return '' } }, titleFn: (item) => { try { return item[title] } catch { return '' } }, valueAssign: (item) => JSON.stringify(item), subtitleFn: (item) => { try { return item[subtitle] } catch { return '' } } }; } else { this.multipleAutoCompleteConfiguration = { filterFn: myfunc.bind(this), initialItems: (extraData) => myfunc(''), displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)[title] : item[title] } catch { return '' } }, titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)[title] : item[title] } catch { return '' } }, valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } }, subtitleFn: (item) => { try { return item[subtitle] } catch { return '' } } } } } searchDatasetExternalRegistries(query: string): Observable { //TODO refactor return null; // const requestItem: RequestItem = new RequestItem(); // requestItem.criteria = new RegistryCriteria(); // requestItem.criteria.like = query; // requestItem.criteria.type = ''; // return this.externalSourcesService.listExternal(ReferenceType.Registries, requestItem.criteria.like, requestItem.criteria.type); } searchDatasetExternalServices(query: string): Observable { //TODO refactor return null; // const requestItem: RequestItem = new RequestItem(); // requestItem.criteria = new ServiceCriteria(); // requestItem.criteria.like = query; // requestItem.criteria.type = ''; // return this.externalSourcesService.listExternal(ReferenceType.Services, requestItem.criteria.like, requestItem.criteria.type); } searchDatasetTags(query: string): Observable { //TODO refactor return null; // const requestItem: RequestItem = new RequestItem(); // requestItem.criteria = new TagCriteria(); // requestItem.criteria.like = query; // requestItem.criteria.type = ''; // return this.externalSourcesService.searchDatasetTags(requestItem); } parseTags() { try { let stringValue = this.propertiesFormGroup.get(this.field.id).get('value').value; if (typeof stringValue === 'string') { stringValue = (stringValue).replace(new RegExp('{', 'g'), '{"').replace(new RegExp('=', 'g'), '":"').replace(new RegExp(',', 'g'), '",').replace(new RegExp(', ', 'g'), ', "').replace(new RegExp('}', 'g'), '"}'); stringValue = stringValue.replace(new RegExp('}"', 'g'), '}').replace(new RegExp('"{', 'g'), '{'); } else if (stringValue instanceof Array) { const tempArray = new Array(); for (let stringTag of stringValue) { tempArray.push(JSON.parse(stringTag)); } stringValue = JSON.stringify(tempArray); } const tagArray = JSON.parse(stringValue); this.propertiesFormGroup.get(this.field.id).get('value').patchValue(tagArray); } catch (e) { console.warn('Could not parse tags'); } } filterTags(value: string): Observable { //TODO refactor return null; // const requestItem: RequestItem = new RequestItem(); // const criteria: TagCriteria = new TagCriteria(); // criteria.like = value; // requestItem.criteria = criteria; // return this.externalSourcesService.searchDatasetTags(requestItem); } showTag(ev: any) { if (typeof ev === 'string') { return ev; } else { return ev.name; } } addTag(ev: any) { // let item: ExternalTagEditorModel; // //this.filteredTags = this.formGroup.get('tags').value; // if (typeof ev === 'string') { // item = new ExternalTagEditorModel('', ev); // } else { // item = ev; // } // if (item.name !== '') { // return item; // } } getDatasetIdControl(name: string): UntypedFormControl { return this.propertiesFormGroup.get(this.field.id).get(name) as UntypedFormControl; } searchCurrency(query: string): Observable { //TODO refactor return null; // return this.currencyService.get(query); } validateId() { //TODO refactor return null; // const identifier = this.getDatasetIdControl('identifier').value; // const type = this.getDatasetIdControl('type').value; // this.validationIcon = 'loading'; // this.externalSourcesService.validateIdentifier(identifier, type).pipe(takeUntil(this._destroyed)).subscribe(result => { // this.validationIcon = result === true ? 'done' : 'clear'; // }); } public upload() { //TODO: refactor this // this.fileService.upload(this.filesToUpload[0], this.datasetProfileId.id, this.form.value.id).subscribe((fileId: string) => { // this.form.get("value").patchValue( // { "name": this.filesToUpload[0].name, "id": fileId + "", "type": this.filesToUpload[0].type }); // this.cdr.detectChanges(); // }, error => { // this.onCallbackUploadFail(error.error); // }) } private onCallbackUploadFail(error: any) { this.makeFilesNull(); this.uiNotificationService.snackBarNotification(this.language.instant(error.message), SnackBarNotificationLevel.Error); } fileChangeEvent(fileInput: any, dropped: boolean = false) { //TODO: refactor this // if (this.form.value.value) { // this.onRemove(false); // } // if (dropped) { // this.filesToUpload = fileInput.addedFiles; // } else { // this.filesToUpload = fileInput.target.files; // } // let messages: string[] = []; // if (this.filesToUpload.length == 0) { // messages.push(this.language.instant('DATASET-WIZARD.MESSAGES.NO-FILES-SELECTED')); // return; // } else { // let fileToUpload = this.filesToUpload[0]; // if (this.form.get("data") && this.form.get("data").value.types // && this.form.get("data").value.types.map(type => type.value).includes(fileToUpload.type) // && this.form.get("data").value.maxFileSizeInMB // && this.form.get("data").value.maxFileSizeInMB * 1048576 >= fileToUpload.size) { // this.upload(); // } else { // this.filesToUpload = null; // messages.push(this.language.instant('DATASET-WIZARD.MESSAGES.LARGE-FILE-OR-UNACCEPTED-TYPE')); // messages.push(this.language.instant('DATASET-WIZARD.MESSAGES.MAX-FILE-SIZE', { 'maxfilesize': this.form.get("data").value.maxFileSizeInMB })); // messages.push(this.language.instant('DATASET-WIZARD.MESSAGES.ACCEPTED-FILE-TRANSFOMER') + this.form.get("data").value.types.map(type => type.value).join(", ")); // } // if (messages && messages.length > 0) { // this.dialog.open(FormValidationErrorsDialogComponent, { // data: { // errorMessages: messages // } // }) // } // } } onRemove(makeFilesNull: boolean = true) { //TODO: refactor this // delete from tmp folder - subscribe call // this.fileService.deleteFromTempFolder(this.form.value.value.id).subscribe(res => { // if (makeFilesNull) { // this.makeFilesNull(); // } // this.cdr.detectChanges(); // }, error => { // if (makeFilesNull) { // this.makeFilesNull(); // } // }) } makeFilesNull() { //TODO: refactor this // this.filesToUpload = null; // this.form.value.value = null; // this.form.get("value").patchValue(null); } typesToString() { return (this.field.data as DescriptionTemplateUploadData).types.map(type => type.value).toString(); } download(): void { //TODO: refactor this // this.fileService.download(this.form.value.value.id) // .pipe(takeUntil(this._destroyed)) // .subscribe(response => { // const blob = new Blob([response.body], { type: this.form.value.value.type }); // const filename = this.fileUtils.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); // FileSaver.saveAs(blob, filename); // }); } }