diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 0a60bd7233..b64fe93787 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -242,7 +242,14 @@ "submit": "Submit", "cancel": "Cancel", "search": "Search", + "search-help": "Click here to looking for an existing correspondence", "remove": "Remove", + "clear": "Clear", + "clear-help": "Click here to remove the selected value", + "edit": "Edit", + "edit-help": "Click here to edit the selected value", + "save": "Save", + "save-help": "Save changes", "first-name": "First name", "last-name": "Last name", "loading": "Loading...", @@ -251,7 +258,9 @@ "group-collapse": "Collapse", "group-expand": "Expand", "group-collapse-help": "Click here to collapse", - "group-expand-help": "Click here to expand and add more elements" + "group-expand-help": "Click here to expand and add more element", + "other-information": { + } }, "login": { "title": "Login", diff --git a/src/app/core/integration/models/authority.value.ts b/src/app/core/integration/models/authority.value.ts index 583356d011..997b1e7904 100644 --- a/src/app/core/integration/models/authority.value.ts +++ b/src/app/core/integration/models/authority.value.ts @@ -23,4 +23,8 @@ export class AuthorityValue extends IntegrationModel { hasValue(): boolean { return isNotEmpty(this.value); } + + hasOtherInformation(): boolean { + return isNotEmpty(this.otherInformation); + } } diff --git a/src/app/core/submission/models/workspaceitem-sections.model.ts b/src/app/core/submission/models/workspaceitem-sections.model.ts index 657dc85a4b..01c1c79eb9 100644 --- a/src/app/core/submission/models/workspaceitem-sections.model.ts +++ b/src/app/core/submission/models/workspaceitem-sections.model.ts @@ -1,15 +1,13 @@ import { WorkspaceitemSectionFormObject } from './workspaceitem-section-form.model'; import { WorkspaceitemSectionLicenseObject } from './workspaceitem-section-license.model'; import { WorkspaceitemSectionUploadObject } from './workspaceitem-section-upload.model'; -import { isNotEmpty, isNotNull } from '../../../shared/empty.util'; -import { FormFieldLanguageValueObject } from '../../../shared/form/builder/models/form-field-language-value.model'; +import { isNotNull } from '../../../shared/empty.util'; import { WorkspaceitemSectionRecycleObject } from './workspaceitem-section-recycle.model'; import { WorkspaceitemSectionDetectDuplicateObject } from './workspaceitem-section-deduplication.model'; import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model'; export class WorkspaceitemSectionsObject { [name: string]: WorkspaceitemSectionDataType; - } export function isServerFormValue(obj: any): boolean { @@ -28,18 +26,16 @@ export function normalizeSectionData(obj: any) { if (typeof obj === 'object' && isServerFormValue(obj)) { // If authority property is set normalize as a FormFieldMetadataValueObject object /* NOTE: Data received from server could have authority property equal to null, but into form - field's model is required a FormFieldMetadataValueObject object as field value, so double-check in - field's parser and eventually instantiate it */ - // if (isNotEmpty(obj.authority)) { - // result = new FormFieldMetadataValueObject(obj.value, obj.language, obj.authority, (obj.display || obj.value), obj.place, obj.confidence); - // } else if (isNotEmpty(obj.language)) { - // const languageValue = new FormFieldLanguageValueObject(obj.value, obj.language); - // result = languageValue; - // } else { - // // Normalize as a string value - // result = obj.value; - // } - result = new FormFieldMetadataValueObject(obj.value, obj.language, obj.authority, (obj.display || obj.value), obj.place, obj.confidence); + field's model is required a FormFieldMetadataValueObject object as field value, so instantiate it */ + result = new FormFieldMetadataValueObject( + obj.value, + obj.language, + obj.authority, + (obj.display || obj.value), + obj.place, + obj.confidence, + obj.otherInformation + ); } else if (Array.isArray(obj)) { result = []; obj.forEach((item, index) => { diff --git a/src/app/shared/chips/chips.component.html b/src/app/shared/chips/chips.component.html index 3e10839f22..8e6ca4ebc9 100644 --- a/src/app/shared/chips/chips.component.html +++ b/src/app/shared/chips/chips.component.html @@ -1,7 +1,12 @@
-
+ +
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts index f8539f3032..04fdf9ae76 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/dynamic-group/dynamic-group.components.ts @@ -9,8 +9,11 @@ import { Output, ViewChild } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { Subscription } from 'rxjs/Subscription'; import { Observable } from 'rxjs/Observable'; +import { filter, flatMap, map, mergeMap, scan } from 'rxjs/operators'; import { DynamicFormControlModel, DynamicFormGroupModel, DynamicInputModel } from '@ng-dynamic-forms/core'; import { isEqual } from 'lodash'; @@ -25,11 +28,10 @@ import { shrinkInOut } from '../../../../../animations/shrink'; import { ChipsItem } from '../../../../../chips/models/chips-item.model'; import { GlobalConfig } from '../../../../../../../config/global-config.interface'; import { GLOBAL_CONFIG } from '../../../../../../../config'; -import { FormGroup } from '@angular/forms'; -import { Subscription } from 'rxjs/Subscription'; import { hasOnlyEmptyProperties } from '../../../../../object.util'; -import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; -import { AuthorityValue } from '../../../../../../core/integration/models/authority.value'; +import { IntegrationSearchOptions } from '../../../../../../core/integration/models/integration-options.model'; +import { AuthorityService } from '../../../../../../core/integration/authority.service'; +import { IntegrationData } from '../../../../../../core/integration/integration-data'; @Component({ selector: 'ds-dynamic-group', @@ -59,6 +61,7 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit { @ViewChild('formRef') private formRef: FormComponent; constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, + private authorityService: AuthorityService, private formBuilderService: FormBuilderService, private formService: FormService, private cdr: ChangeDetectorRef) { @@ -75,7 +78,6 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit { } else { this.expandForm(); } - // this.formCollapsed = (isNotEmpty(value) && !(value.length === 1 && hasOnlyEmptyProperties(value[0]))) ? Observable.of(true) : Observable.of(false); }); this.formId = this.formService.getUniqueId(this.model.id); @@ -85,30 +87,10 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit { {}, this.model.submissionScope, this.model.readOnly); - const initChipsValue = this.model.isEmpty() ? [] : this.model.value; - this.chips = new Chips( - initChipsValue, - 'value', - this.model.mandatoryField, - this.EnvConfig.submission.metadata.icons); - this.subs.push( - this.chips.chipsItems - .subscribe((subItems: any[]) => { - const items = this.chips.getChipsItems(); - // Does not emit change if model value is equal to the current value - if (!isEqual(items, this.model.value)) { - // if ((isNotEmpty(items) && !this.model.isEmpty()) || (isEmpty(items) && !this.model.isEmpty())) { - if (!(isEmpty(items) && this.model.isEmpty())) { - this.model.valueUpdates.next(items); - this.change.emit(); - } - } - }), - ) + this.initChipsFromModelValue(); } isMandatoryFieldEmpty() { - // formModel[0].group[0].value == null let res = true; this.formModel.forEach((row) => { const modelRow = row as DynamicFormGroupModel; @@ -136,11 +118,6 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit { || this.selectedChipItem.item[model.name].value === PLACEHOLDER_PARENT_METADATA) ? null : this.selectedChipItem.item[model.name]; - // if (value instanceof FormFieldMetadataValueObject || value instanceof AuthorityValueModel) { - // model.valueUpdates.next(value.display); - // } else { - // model.valueUpdates.next(value); - // } model.valueUpdates.next(value); }); }); @@ -226,6 +203,91 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit { return item; } + private initChipsFromModelValue() { + + let initChipsValue$: Observable; + if (this.model.isEmpty()) { + this.initChips([]); + } else { + initChipsValue$ = Observable.of(this.model.value); + + // If authority + this.subs.push(initChipsValue$.pipe( + flatMap((valueModel) => { + const returnList: Array> = []; + valueModel.forEach((valueObj) => { + let returnObj = Object.create({}); + returnObj = Object.keys(valueObj).map((fieldName) => { + let return$: Observable; + if (valueObj[fieldName].hasAuthority() && isNotEmpty(valueObj[fieldName].authority)) { + const fieldId = fieldName.replace(/\./g, '_'); + const model = this.formBuilderService.findById(fieldId, this.formModel); + const searchOptions: IntegrationSearchOptions = new IntegrationSearchOptions( + (model as any).authorityOptions.scope, + (model as any).authorityOptions.name, + (model as any).authorityOptions.metadata, + valueObj[fieldName].authority, + (model as any).maxOptions, + 1); + + return$ = this.authorityService.getEntryByValue(searchOptions) + .map((result: IntegrationData) => result.payload[0]); + } else { + return$ = Observable.of(valueObj[fieldName]); + } + return return$.map((entry) => ({[fieldName]: entry})); + }); + + returnList.push(Observable.combineLatest(returnObj)); + }); + return returnList; + }), + mergeMap((valueListObj: Observable, index: number) => { + return valueListObj.pipe( + map((valueObj: any) => ({ + index: index, value: valueObj.reduce( + (acc: any, value: any) => Object.assign({}, acc, value) + ) + }) + ) + ) + }), + scan((acc: any[], valueObj: any) => { + if (acc.length === 0) { + acc.push(valueObj.value); + } else { + acc.splice(valueObj.index, 0, valueObj.value); + } + return acc; + }, []), + filter((modelValues: any[]) => this.model.value.length === modelValues.length) + ).subscribe((modelValue) => { + this.initChips(modelValue); + })); + } + } + + private initChips(initChipsValue) { + this.chips = new Chips( + initChipsValue, + 'value', + this.model.mandatoryField, + this.EnvConfig.submission.metadata.icons); + this.subs.push( + this.chips.chipsItems + .subscribe((subItems: any[]) => { + const items = this.chips.getChipsItems(); + // Does not emit change if model value is equal to the current value + if (!isEqual(items, this.model.value)) { + if (!(isEmpty(items) && this.model.isEmpty())) { + this.model.valueUpdates.next(items); + this.change.emit(); + } + } + }), + ) + } + private resetForm() { if (this.formRef) { this.formService.resetForm(this.formRef.formGroup, this.formModel, this.formId); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.html index 009dc411c0..c8c34997f5 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.html @@ -75,14 +75,31 @@ *ngIf="optionsList && optionsList.length == 0" (click)="$event.stopPropagation(); clearFields(); sdRef.close();">{{'form.no-results' | translate}} -

{{'form.loading' | translate}}

- + + + + + + + + diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.scss index 485cfe3e29..6d3923441e 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.scss +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.scss @@ -20,11 +20,11 @@ /* align fa-spin */ .left-addon .fa-spin { - left: 0px; + left: 0; } .right-addon .fa-spin { - right: 0px; + right: 0; } /* add padding */ @@ -55,3 +55,7 @@ div { overflow: visible; } + +.lookup-item { + border-bottom: $dropdown-border-width solid $dropdown-border-color; +} diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.html index 2d5eca2f16..fcfc4751ef 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/typeahead/dynamic-typeahead.component.html @@ -1,6 +1,25 @@ - - {{ r.display}} + + + + + + + + + + + +