From fdef3ff523df02a27cea7a7dbe7ad036f1cf0a36 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 12 Apr 2024 16:20:01 +0300 Subject: [PATCH 1/2] FIO-8091: added selectData calculation for url/resource select components --- src/components/select/Select.js | 4 + src/components/select/Select.unit.js | 122 ++++++++++++++++++ .../select/editForm/Select.edit.data.js | 62 ++++++++- 3 files changed, 187 insertions(+), 1 deletion(-) diff --git a/src/components/select/Select.js b/src/components/select/Select.js index 4fc820f0bc..19fe7539a5 100644 --- a/src/components/select/Select.js +++ b/src/components/select/Select.js @@ -254,6 +254,10 @@ export default class SelectComponent extends ListComponent { return super.shouldLoad; } + get selectData() { + return this.component.selectData || super.selectData; + } + isEntireObjectDisplay() { return this.component.dataSrc === 'resource' && this.valueProperty === 'data'; } diff --git a/src/components/select/Select.unit.js b/src/components/select/Select.unit.js index 59fdbefad8..85fc394107 100644 --- a/src/components/select/Select.unit.js +++ b/src/components/select/Select.unit.js @@ -8,6 +8,9 @@ import { expect } from 'chai'; import { Formio } from './../../Formio'; import _ from 'lodash'; +global.requestAnimationFrame = (cb) => cb(); +global.cancelAnimationFrame = () => { }; + import { comp1, comp2, @@ -1212,3 +1215,122 @@ describe('Select Component with Entire Object Value Property', () => { }); }); }); + +describe('Select Component selectData property', () => { + const originalMakeRequest = Formio.makeRequest; + + before((done) => { + Formio.makeRequest = (formio, type, url) => { + return new Promise(resolve => { + const values = [{ + label: 'Label 1', + value: 'value1', + }, { + label: 'Label 2', + value: 'value2', + }]; + + resolve(values); + }); + }; + Harness.builderBefore(done); + }); + afterEach(() => Harness.getBuilder().setForm({ display: 'form', components: [] })); + + it('Should calculate selectData property for url dataSource', (done) => { + const builder = Harness.getBuilder(); + builder.setForm({}).then(() => { + Harness.buildComponent('select'); + + setTimeout(() => { + const dataSrc = builder.editForm.getComponent('dataSrc'); + dataSrc.setValue('url'); + const url = builder.editForm.getComponent(['data.url']); + const valueProperty = builder.editForm.getComponent('valueProperty'); + url.setValue('htts//fakeurl.com'); + valueProperty.setValue('value'); + + setTimeout(() => { + const defaultValue = builder.editForm.getComponent('defaultValue'); + defaultValue.setValue('value1'); + defaultValue.updateItems(null, true); + + setTimeout(() => { + assert.deepEqual(builder.editForm.data.selectData, { + label: 'Label 1', + }); + Harness.saveComponent(); + setTimeout(() => { + done(); + }, 150); + }, 250); + }, 250); + }, 150); + }).catch(done); + }); + + it('Should calculate selectData property for resource dataSource', (done) => { + const builder = Harness.getBuilder(); + builder.setForm({}).then(() => { + Harness.buildComponent('select'); + + setTimeout(() => { + const dataSrc = builder.editForm.getComponent('dataSrc'); + dataSrc.setValue('resource'); + const resource = builder.editForm.getComponent(['data.resource']); + const valueProperty = builder.editForm.getComponent('valueProperty'); + resource.setValue('12345678'); + valueProperty.setValue('value'); + + setTimeout(() => { + const defaultValue = builder.editForm.getComponent('defaultValue'); + defaultValue.setValue('value1'); + defaultValue.updateItems(null, true); + + setTimeout(() => { + assert.deepEqual(builder.editForm.data.selectData, { + label: 'Label 1', + }); + Harness.saveComponent(); + setTimeout(() => { + done(); + }, 150); + }, 250); + }, 250); + }, 150); + }).catch(done); + }); + + it('Should not calculate selectData property without valueProperty', (done) => { + const builder = Harness.getBuilder(); + builder.setForm({}).then(() => { + Harness.buildComponent('select'); + + setTimeout(() => { + const dataSrc = builder.editForm.getComponent('dataSrc'); + dataSrc.setValue('url'); + const url = builder.editForm.getComponent(['data.url']); + url.setValue('https://fakeurl.com'); + + setTimeout(() => { + const defaultValue = builder.editForm.getComponent('defaultValue'); + defaultValue.setValue('value1'); + defaultValue.updateItems(null, true); + + setTimeout(() => { + assert.equal(builder.editForm.data.selectData, undefined); + Harness.saveComponent(); + setTimeout(() => { + done(); + }, 150); + }, 250); + }, 250); + }, 150); + }).catch(done); + }); + + after((done) => { + Formio.makeRequest = originalMakeRequest; + Harness.builderAfter(done); + }); +}); diff --git a/src/components/select/editForm/Select.edit.data.js b/src/components/select/editForm/Select.edit.data.js index df6ad3e1df..e860bf6d46 100644 --- a/src/components/select/editForm/Select.edit.data.js +++ b/src/components/select/editForm/Select.edit.data.js @@ -1,5 +1,33 @@ +import _ from 'lodash'; import { eachComponent } from '../../../utils/utils'; +const calculateSelectData = (context) => { + const { instance, data } = context; + const rawDefaultValue = instance.downloadedResources.find(resource => _.get(resource, data.valueProperty) === instance.getValue()); + const options = { data: {}, noeval: true }; + instance.interpolate(data.template, { + item: rawDefaultValue, + }, options); + return options.data.item; +}; + +const setSelectData = (context) => { + // Wait before downloadedResources will be set + setTimeout(() => { + const { instance, data } = context; + const selectDataComponent = instance?.root.getComponent('selectData'); + // nothing can set if don't have downloaded resources + if (!selectDataComponent || !instance.getValue() || !instance.downloadedResources?.length) { + return; + } + // if valueProperty is not provided, we have entire object + const shouldCalculateUrlData = data.dataSrc === 'url' && data.data.url && data.valueProperty; + const shouldCalculateResourceData = data.dataSrc === 'resource' && data.data.resource && data.valueProperty; + const newValue = shouldCalculateUrlData || shouldCalculateResourceData ? calculateSelectData(context) : undefined; + selectDataComponent.setValue(newValue); + }, 0); +}; + export default [ { key: 'dataSrc', @@ -625,5 +653,37 @@ export default [ key: 'useExactSearch', label: 'Use exact search', tooltip: 'Disables search algorithm threshold.', - } + }, + { + key: 'defaultValue', + onSetItems(component) { + setSelectData(component.evalContext()); + }, + onChange(context) { + if (context && context.flags && context.flags.modified) { + setSelectData(context); + } + }, + }, + { + key: 'selectData', + conditional: { + json: { 'and': [ + { '!==': [{ var: 'data.valueProperty' }, null] }, + { '!==': [{ var: 'data.valueProperty' }, ''] }, + ] }, + }, + }, + { + key: 'template', + onChange(context) { + if (context && context.flags && context.flags.modified) { + const defaultValueComponent = context.instance.root.getComponent('defaultValue'); + if (!defaultValueComponent) { + return; + } + setSelectData(defaultValueComponent.evalContext()); + } + }, + }, ]; From b8e8ad030644065725fdc35dee3ac85bd4e9df14 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 12 Apr 2024 20:54:19 +0300 Subject: [PATCH 2/2] fixed tests --- src/WebformBuilder.unit.js | 120 ++++++++++++++++++++++++++ src/components/select/Select.unit.js | 121 --------------------------- 2 files changed, 120 insertions(+), 121 deletions(-) diff --git a/src/WebformBuilder.unit.js b/src/WebformBuilder.unit.js index 5b3979ac16..33caeee583 100644 --- a/src/WebformBuilder.unit.js +++ b/src/WebformBuilder.unit.js @@ -2,6 +2,7 @@ import assert from 'power-assert'; import Harness from '../test/harness'; import WebformBuilder from './WebformBuilder'; import Builders from './builders'; +import { Formio } from './Formio'; import { uniqueApiKeys, uniqueApiKeysLayout, uniqueApiKeysSameLevel, columnsForm, resourceKeyCamelCase } from '../test/formtest'; import sameApiKeysLayoutComps from '../test/forms/sameApiKeysLayoutComps'; import testApiKeysUniquifying from '../test/forms/testApiKeysUniquifying'; @@ -269,3 +270,122 @@ describe('WebformBuilder tests', function() { }).catch(done); }); }); + +describe('Select Component selectData property', () => { + const originalMakeRequest = Formio.makeRequest; + + before((done) => { + Formio.makeRequest = () => { + return new Promise(resolve => { + const values = [{ + label: 'Label 1', + value: 'value1', + }, { + label: 'Label 2', + value: 'value2', + }]; + + resolve(values); + }); + }; + Harness.builderBefore(done); + }); + afterEach(() => Harness.getBuilder().setForm({ display: 'form', components: [] })); + + it('Should calculate selectData property for url dataSource', (done) => { + const builder = Harness.getBuilder(); + builder.setForm({}).then(() => { + Harness.buildComponent('select'); + + setTimeout(() => { + const dataSrc = builder.editForm.getComponent('dataSrc'); + dataSrc.setValue('url'); + const url = builder.editForm.getComponent(['data.url']); + const valueProperty = builder.editForm.getComponent('valueProperty'); + url.setValue('htts//fakeurl.com'); + valueProperty.setValue('value'); + + setTimeout(() => { + const defaultValue = builder.editForm.getComponent('defaultValue'); + defaultValue.setValue('value1'); + defaultValue.updateItems(null, true); + + setTimeout(() => { + assert.deepEqual(builder.editForm.data.selectData, { + label: 'Label 1', + }); + Harness.saveComponent(); + setTimeout(() => { + done(); + }, 150); + }, 250); + }, 250); + }, 150); + }).catch(done); + }); + + it('Should calculate selectData property for resource dataSource', (done) => { + const builder = Harness.getBuilder(); + builder.setForm({}).then(() => { + Harness.buildComponent('select'); + + setTimeout(() => { + const dataSrc = builder.editForm.getComponent('dataSrc'); + dataSrc.setValue('resource'); + const resource = builder.editForm.getComponent(['data.resource']); + const valueProperty = builder.editForm.getComponent('valueProperty'); + resource.setValue('12345678'); + valueProperty.setValue('value'); + + setTimeout(() => { + const defaultValue = builder.editForm.getComponent('defaultValue'); + defaultValue.setValue('value1'); + defaultValue.updateItems(null, true); + + setTimeout(() => { + assert.deepEqual(builder.editForm.data.selectData, { + label: 'Label 1', + }); + Harness.saveComponent(); + setTimeout(() => { + done(); + }, 150); + }, 250); + }, 250); + }, 150); + }).catch(done); + }); + + it('Should not calculate selectData property without valueProperty', (done) => { + const builder = Harness.getBuilder(); + builder.setForm({}).then(() => { + Harness.buildComponent('select'); + + setTimeout(() => { + const dataSrc = builder.editForm.getComponent('dataSrc'); + dataSrc.setValue('url'); + const url = builder.editForm.getComponent(['data.url']); + url.setValue('https://fakeurl.com'); + + setTimeout(() => { + const defaultValue = builder.editForm.getComponent('defaultValue'); + defaultValue.setValue('value1'); + defaultValue.updateItems(null, true); + + setTimeout(() => { + assert.equal(builder.editForm.data.selectData, undefined); + Harness.saveComponent(); + setTimeout(() => { + done(); + }, 150); + }, 250); + }, 250); + }, 150); + }).catch(done); + }); + + after((done) => { + Formio.makeRequest = originalMakeRequest; + Harness.builderAfter(done); + }); +}); diff --git a/src/components/select/Select.unit.js b/src/components/select/Select.unit.js index 85fc394107..30b1bc906a 100644 --- a/src/components/select/Select.unit.js +++ b/src/components/select/Select.unit.js @@ -8,9 +8,6 @@ import { expect } from 'chai'; import { Formio } from './../../Formio'; import _ from 'lodash'; -global.requestAnimationFrame = (cb) => cb(); -global.cancelAnimationFrame = () => { }; - import { comp1, comp2, @@ -1216,121 +1213,3 @@ describe('Select Component with Entire Object Value Property', () => { }); }); -describe('Select Component selectData property', () => { - const originalMakeRequest = Formio.makeRequest; - - before((done) => { - Formio.makeRequest = (formio, type, url) => { - return new Promise(resolve => { - const values = [{ - label: 'Label 1', - value: 'value1', - }, { - label: 'Label 2', - value: 'value2', - }]; - - resolve(values); - }); - }; - Harness.builderBefore(done); - }); - afterEach(() => Harness.getBuilder().setForm({ display: 'form', components: [] })); - - it('Should calculate selectData property for url dataSource', (done) => { - const builder = Harness.getBuilder(); - builder.setForm({}).then(() => { - Harness.buildComponent('select'); - - setTimeout(() => { - const dataSrc = builder.editForm.getComponent('dataSrc'); - dataSrc.setValue('url'); - const url = builder.editForm.getComponent(['data.url']); - const valueProperty = builder.editForm.getComponent('valueProperty'); - url.setValue('htts//fakeurl.com'); - valueProperty.setValue('value'); - - setTimeout(() => { - const defaultValue = builder.editForm.getComponent('defaultValue'); - defaultValue.setValue('value1'); - defaultValue.updateItems(null, true); - - setTimeout(() => { - assert.deepEqual(builder.editForm.data.selectData, { - label: 'Label 1', - }); - Harness.saveComponent(); - setTimeout(() => { - done(); - }, 150); - }, 250); - }, 250); - }, 150); - }).catch(done); - }); - - it('Should calculate selectData property for resource dataSource', (done) => { - const builder = Harness.getBuilder(); - builder.setForm({}).then(() => { - Harness.buildComponent('select'); - - setTimeout(() => { - const dataSrc = builder.editForm.getComponent('dataSrc'); - dataSrc.setValue('resource'); - const resource = builder.editForm.getComponent(['data.resource']); - const valueProperty = builder.editForm.getComponent('valueProperty'); - resource.setValue('12345678'); - valueProperty.setValue('value'); - - setTimeout(() => { - const defaultValue = builder.editForm.getComponent('defaultValue'); - defaultValue.setValue('value1'); - defaultValue.updateItems(null, true); - - setTimeout(() => { - assert.deepEqual(builder.editForm.data.selectData, { - label: 'Label 1', - }); - Harness.saveComponent(); - setTimeout(() => { - done(); - }, 150); - }, 250); - }, 250); - }, 150); - }).catch(done); - }); - - it('Should not calculate selectData property without valueProperty', (done) => { - const builder = Harness.getBuilder(); - builder.setForm({}).then(() => { - Harness.buildComponent('select'); - - setTimeout(() => { - const dataSrc = builder.editForm.getComponent('dataSrc'); - dataSrc.setValue('url'); - const url = builder.editForm.getComponent(['data.url']); - url.setValue('https://fakeurl.com'); - - setTimeout(() => { - const defaultValue = builder.editForm.getComponent('defaultValue'); - defaultValue.setValue('value1'); - defaultValue.updateItems(null, true); - - setTimeout(() => { - assert.equal(builder.editForm.data.selectData, undefined); - Harness.saveComponent(); - setTimeout(() => { - done(); - }, 150); - }, 250); - }, 250); - }, 150); - }).catch(done); - }); - - after((done) => { - Formio.makeRequest = originalMakeRequest; - Harness.builderAfter(done); - }); -});