argos/dmp-frontend/src/app/ui/description/editor/description-form/components/form-field/form-field.component.ts

525 lines
21 KiB
TypeScript

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 = <string>this.propertiesFormGroup.get(this.field.id).get('value').value;
// if (originalValue !== null && typeof originalValue === 'string') {
// let values = (<string>this.propertiesFormGroup.get(this.field.id).get('value').value).slice(1, -1).split(', ').filter((value) => !value.includes('"'));
// let specialValue = (<string>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<DatasetExternalAutocompleteOptionsCriteria> = 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<DatasetExternalAutocompleteCriteria> = 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<ResearcherCriteria> = 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<string> = new Array();
// const datasetsAutocompleteRequestItem: DataTableRequest<DatasetCriteria> = 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<string> = new Array();
// const dmpsAutocompleteRequestItem: DataTableRequest<DmpCriteria> = 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<FetcherReference[]> {
//TODO refactor
return null;
// const requestItem: RequestItem<RegistryCriteria> = 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<FetcherReference[]> {
//TODO refactor
return null;
// const requestItem: RequestItem<ServiceCriteria> = 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<any[]> {
//TODO refactor
return null;
// const requestItem: RequestItem<TagCriteria> = 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 = (<string>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<any[]> {
//TODO refactor
return null;
// const requestItem: RequestItem<TagCriteria> = 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<any[]> {
//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);
// });
}
}