From cb68631511720035b63f9446286f3741fcb6f2fe Mon Sep 17 00:00:00 2001 From: Mike Kotikov <54106407+mikekotikov@users.noreply.github.com> Date: Mon, 30 Oct 2023 10:57:06 +0100 Subject: [PATCH 01/22] FIO-7429: Remove columns component settings(pull, offset, push) (#5384) --- .../columns/editForm/Columns.edit.display.js | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/components/columns/editForm/Columns.edit.display.js b/src/components/columns/editForm/Columns.edit.display.js index a19b1151c1..b4424b1c05 100644 --- a/src/components/columns/editForm/Columns.edit.display.js +++ b/src/components/columns/editForm/Columns.edit.display.js @@ -84,24 +84,6 @@ export default [ key: 'width', defaultValue: 6, label: 'Width' - }, - { - type: 'number', - key: 'offset', - defaultValue: 0, - label: 'Offset' - }, - { - type: 'number', - key: 'push', - defaultValue: 0, - label: 'Push' - }, - { - type: 'number', - key: 'pull', - defaultValue: 0, - label: 'Pull' } ] }, From 69bce855a0a32cdf5b041945541eec8686a527ff Mon Sep 17 00:00:00 2001 From: TanyaGashtold <61136841+TanyaGashtold@users.noreply.github.com> Date: Mon, 30 Oct 2023 12:57:41 +0300 Subject: [PATCH 02/22] Update Changelog.md --- Changelog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 79fe813aa7..53a1ffa1c8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -29,7 +29,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - FIO-7146: formiojs-circleci-to-ghactions - FIO-6859: update-s3-to-accept-headers-from-signer-presign - FIO 7239: support for AWS S3 Multipart Upload - - FIO-7239: add polyfill and include token in abort and complete requests for multipart upload + - FIO-7239: add polyfill and include token in abort and complete requests for multipart upload2 + - FIO-7429: removed columns component settings(pull, offset, push) ## 5.0.0-rc.26 ### Changed From 2209bc1b92253e3fd8ec2412d9b47b528e1c35b3 Mon Sep 17 00:00:00 2001 From: alexandraRamanenka <60643585+alexandraRamanenka@users.noreply.github.com> Date: Tue, 31 Oct 2023 10:36:17 +0200 Subject: [PATCH 03/22] FIO-7466: Fixed an issue where code inside tolltips will be executed (#5392) * FIO-7466: Fixed an issue where code inside tolltips/descriptions will be executed * Removed console.log --- .../_classes/component/Component.js | 2 +- .../_classes/component/Component.unit.js | 14 +++++++++++ .../_classes/component/fixtures/comp5.js | 24 +++++++++++++++++++ .../_classes/component/fixtures/index.js | 3 ++- 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/components/_classes/component/fixtures/comp5.js diff --git a/src/components/_classes/component/Component.js b/src/components/_classes/component/Component.js index c64abaa4eb..1e15ff96ef 100644 --- a/src/components/_classes/component/Component.js +++ b/src/components/_classes/component/Component.js @@ -1223,7 +1223,7 @@ export default class Component extends Element { placement: 'right', zIndex: 10000, interactive: true, - content: this.t(tooltipText, { _userInput: true }), + content: this.t(this.sanitize(tooltipText), { _userInput: true }), }); } }); diff --git a/src/components/_classes/component/Component.unit.js b/src/components/_classes/component/Component.unit.js index 7726f1b97c..46606065f2 100644 --- a/src/components/_classes/component/Component.unit.js +++ b/src/components/_classes/component/Component.unit.js @@ -9,6 +9,7 @@ import { comp1 } from './fixtures'; import _merge from 'lodash/merge'; import comp3 from './fixtures/comp3'; import comp4 from './fixtures/comp4'; +import comp5 from './fixtures/comp5'; describe('Component', () => { it('Should create a Component', (done) => { @@ -356,4 +357,17 @@ describe('Component', () => { .catch(done); }); }); + + it('Should not execute code inside Tooltips/Description', (done) => { + const formElement = document.createElement('div'); + const form = new Webform(formElement); + + form.setForm(comp5).then(() => { + setTimeout(() => { + assert.equal(window._ee, undefined, 'Should not execute code inside Tooltips/Description'); + done(); + }, 200); + }) + .catch(done); + }); }); diff --git a/src/components/_classes/component/fixtures/comp5.js b/src/components/_classes/component/fixtures/comp5.js new file mode 100644 index 0000000000..68806c95d7 --- /dev/null +++ b/src/components/_classes/component/fixtures/comp5.js @@ -0,0 +1,24 @@ +export default { + type: 'form', + display: 'form', + components: [ + { + label: 'Text Field', + description: "", + tooltip: " Date: Tue, 31 Oct 2023 11:36:58 +0300 Subject: [PATCH 04/22] Update Changelog.md --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 53a1ffa1c8..b541b48a17 100644 --- a/Changelog.md +++ b/Changelog.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - FIO 7239: support for AWS S3 Multipart Upload - FIO-7239: add polyfill and include token in abort and complete requests for multipart upload2 - FIO-7429: removed columns component settings(pull, offset, push) + - FIO-7466: fixed an issue where code inside tolltips will be executed ## 5.0.0-rc.26 ### Changed From 4f58085e0c66f245ab18d9ec890aa41fb725cadd Mon Sep 17 00:00:00 2001 From: antonSoftensity <61691723+antonSoftensity@users.noreply.github.com> Date: Thu, 2 Nov 2023 09:02:10 +0200 Subject: [PATCH 05/22] FIO-7355 Fixed issue with HTML5 select flickering on initial click (#5366) * FIO-7355 Fixed issue with HTML5 select flickering on initial click * FIO-7355 Reworked the fix for HTML5 Select flickering issue --- src/components/select/Select.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/select/Select.js b/src/components/select/Select.js index 9e651ee580..f976dbf96d 100644 --- a/src/components/select/Select.js +++ b/src/components/select/Select.js @@ -943,7 +943,11 @@ export default class SelectComponent extends ListComponent { } this.focusableElement = input; - this.addEventListener(input, 'focus', () => this.update()); + + if (this.component.dataSrc === 'custom') { + this.addEventListener(input, 'focus', () => this.updateCustomItems()); + } + this.addEventListener(input, 'keydown', (event) => { const { key } = event; From 6627908117863247f0b87c0e746fde803b37578a Mon Sep 17 00:00:00 2001 From: TanyaGashtold <61136841+TanyaGashtold@users.noreply.github.com> Date: Thu, 2 Nov 2023 10:02:56 +0300 Subject: [PATCH 06/22] Update Changelog.md --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index b541b48a17..4471aa4964 100644 --- a/Changelog.md +++ b/Changelog.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - FIO-7239: add polyfill and include token in abort and complete requests for multipart upload2 - FIO-7429: removed columns component settings(pull, offset, push) - FIO-7466: fixed an issue where code inside tolltips will be executed + - FIO-7355: fixed issue with HTML5 select flickering on initial click ## 5.0.0-rc.26 ### Changed From 663ecd0b6028d5afe00222e9db28c99fbccc75f6 Mon Sep 17 00:00:00 2001 From: Rolf Date: Fri, 3 Nov 2023 17:04:56 +0100 Subject: [PATCH 07/22] Add capability for adding sanitize profiles through sanitizeConfig in options With this modification we can allow Formio to display svg and mathml by including the below (works in sandbox): { "sanitizeConfig": { "useProfiles": { "mathMl": true, "svg": true } } } --- src/utils/utils.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/utils/utils.js b/src/utils/utils.js index 473ba571b3..d308e8d313 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -1304,6 +1304,12 @@ export function sanitize(string, options) { ADD_ATTR: ['ref', 'target'], USE_PROFILES: { html: true } }; + // Use profiles + if (options.sanitizeConfig && options.sanitizeConfig.useProfiles) { + Object.keys(options.sanitizeConfig.useProfiles).forEach(key => { + sanitizeOptions.USE_PROFILES[key] = options.sanitizeConfig.useProfiles[key]; + }); + } // Add attrs if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addAttr) && options.sanitizeConfig.addAttr.length > 0) { options.sanitizeConfig.addAttr.forEach((attr) => { From 357fcab36e184f504c31344678df9401becb0a7d Mon Sep 17 00:00:00 2001 From: Brendan Bond Date: Tue, 7 Nov 2023 10:43:05 -0500 Subject: [PATCH 08/22] Update Changelog.md --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index 4471aa4964..028434c70c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -33,6 +33,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - FIO-7429: removed columns component settings(pull, offset, push) - FIO-7466: fixed an issue where code inside tolltips will be executed - FIO-7355: fixed issue with HTML5 select flickering on initial click + +### Changed + - Add capability for adding sanitize profiles through sanitizeConfig in options ## 5.0.0-rc.26 ### Changed From 3edd00c79b9cc9cfe6cdea275e5633886db20130 Mon Sep 17 00:00:00 2001 From: TanyaGashtold <61136841+TanyaGashtold@users.noreply.github.com> Date: Tue, 7 Nov 2023 19:27:20 +0300 Subject: [PATCH 09/22] FIO--7530: added ability to pass onSetItems component setting as a string (needed for builder mode) (#5397) --- src/components/select/Select.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/select/Select.js b/src/components/select/Select.js index f976dbf96d..d41a252c6d 100644 --- a/src/components/select/Select.js +++ b/src/components/select/Select.js @@ -400,8 +400,10 @@ export default class SelectComponent extends ListComponent { } // Allow js processing (needed for form builder) - if (this.component.onSetItems && typeof this.component.onSetItems === 'function') { - const newItems = this.component.onSetItems(this, items); + if (this.component.onSetItems) { + const newItems = typeof this.component.onSetItems === 'function' + ? this.component.onSetItems(this, items) + : this.evaluate(this.component.onSetItems, { items: items }, 'items'); if (newItems) { items = newItems; } From c6504223aeb73607874f1c75a03429be363c4e75 Mon Sep 17 00:00:00 2001 From: lane-formio Date: Tue, 7 Nov 2023 10:28:34 -0600 Subject: [PATCH 10/22] Revert "FIO-4405: fixed an issue where walidation error displays with empty value even if it is not required (#4746)" (#5398) This reverts commit 3a8d7d6be224dac2bfc0e0b1dc31ddd2f89075a3. --- src/components/_classes/component/Component.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/_classes/component/Component.js b/src/components/_classes/component/Component.js index 1e15ff96ef..05dfb83227 100644 --- a/src/components/_classes/component/Component.js +++ b/src/components/_classes/component/Component.js @@ -3321,8 +3321,6 @@ export default class Component extends Element { shouldSkipValidation(data, dirty, row) { const rules = [ - // Do not check custom validation for empty data if it is not required - () => this.component.validate.custom && !this.dataValue && !this.component.validate.required, // Force valid if component is read-only () => this.options.readOnly, // Do not check validations if component is not an input component. From e73f8f0b9b42738df43d62b55e651d334fb1e6ed Mon Sep 17 00:00:00 2001 From: lane-formio Date: Tue, 7 Nov 2023 10:35:29 -0600 Subject: [PATCH 11/22] Update Changelog.md --- Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index 028434c70c..f8c1e76081 100644 --- a/Changelog.md +++ b/Changelog.md @@ -33,6 +33,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - FIO-7429: removed columns component settings(pull, offset, push) - FIO-7466: fixed an issue where code inside tolltips will be executed - FIO-7355: fixed issue with HTML5 select flickering on initial click + - FIO-7530: added ability to pass onSetItems component setting as a string (needed for builder mode) + - FIO-7528: Revert FIO-4405: fixed an issue where walidation error displays with empty value even if it is not required (#4746) ### Changed - Add capability for adding sanitize profiles through sanitizeConfig in options From 38f4d53fa373531a0b5c8f13a3bc40cabba38a0e Mon Sep 17 00:00:00 2001 From: lane-formio Date: Tue, 7 Nov 2023 10:44:40 -0600 Subject: [PATCH 12/22] Update Changelog.md --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index f8c1e76081..ec14e0a513 100644 --- a/Changelog.md +++ b/Changelog.md @@ -31,7 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - FIO 7239: support for AWS S3 Multipart Upload - FIO-7239: add polyfill and include token in abort and complete requests for multipart upload2 - FIO-7429: removed columns component settings(pull, offset, push) - - FIO-7466: fixed an issue where code inside tolltips will be executed + - FIO-7466: Tooltips fix - FIO-7355: fixed issue with HTML5 select flickering on initial click - FIO-7530: added ability to pass onSetItems component setting as a string (needed for builder mode) - FIO-7528: Revert FIO-4405: fixed an issue where walidation error displays with empty value even if it is not required (#4746) From cf541c341c815853a4107558a04a3e911b2dbcc6 Mon Sep 17 00:00:00 2001 From: alexandraRamanenka <60643585+alexandraRamanenka@users.noreply.github.com> Date: Tue, 14 Nov 2023 16:59:39 +0200 Subject: [PATCH 13/22] FIO-7547: Container hidden with conditional logic still appears in submission (#5401) * FIO-7547: Container hidden with conditional logic still appears in submission * Fixed tests --- .../_classes/nested/NestedComponent.js | 2 +- src/components/container/Container.unit.js | 22 +++++++++- src/components/container/fixtures/comp4.js | 43 +++++++++++++++++++ src/components/container/fixtures/index.js | 3 +- src/components/select/Select.unit.js | 2 +- 5 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 src/components/container/fixtures/comp4.js diff --git a/src/components/_classes/nested/NestedComponent.js b/src/components/_classes/nested/NestedComponent.js index c2697a031e..dfee7555a1 100644 --- a/src/components/_classes/nested/NestedComponent.js +++ b/src/components/_classes/nested/NestedComponent.js @@ -617,7 +617,7 @@ export default class NestedComponent extends Field { clearOnHide(show) { super.clearOnHide(show); if (this.component.clearOnHide) { - if (this.allowData && !this.hasValue()) { + if (this.allowData && !this.hasValue() && !(this.options.server && !this.visible)) { this.dataValue = this.defaultValue; } if (this.hasValue()) { diff --git a/src/components/container/Container.unit.js b/src/components/container/Container.unit.js index 0cebca0600..ee17fc74e9 100644 --- a/src/components/container/Container.unit.js +++ b/src/components/container/Container.unit.js @@ -6,7 +6,8 @@ import ContainerComponent from './Container'; import { comp1, comp2, - comp3 + comp3, + comp4, } from './fixtures'; import { Formio } from '../../Formio'; @@ -77,4 +78,23 @@ describe('Container Component', () => { }, 100); }).catch(done); }); + + it('Should not set the default value when clearOnHide during the server-side validation', (done) => { + const form = _.cloneDeep(comp4); + const element = document.createElement('div'); + + Formio.createForm(element, form, { server: true, noDefaults: true }).then(form => { + form.setValue({ data: { checkbox: false } }, { + sanitize: true, + }, true); + + form.checkConditions(); + form.clearOnHide(); + + setTimeout(() => { + assert.deepEqual(form._data, { checkbox: false }, 'Should not add Container\'s key'); + done(); + }, 200); + }).catch(done); + }); }); diff --git a/src/components/container/fixtures/comp4.js b/src/components/container/fixtures/comp4.js new file mode 100644 index 0000000000..c48b94e359 --- /dev/null +++ b/src/components/container/fixtures/comp4.js @@ -0,0 +1,43 @@ +export default { + type: 'form', + display: 'form', + components: [ + { + label: 'Checkbox', + tableView: false, + key: 'checkbox', + type: 'checkbox', + input: true, + }, + { + label: 'Container', + tableView: false, + key: 'container', + conditional: { + show: true, + when: 'checkbox', + eq: 'true', + }, + type: 'container', + input: true, + components: [ + { + label: 'Text Field', + applyMaskOn: 'change', + tableView: true, + key: 'textField', + type: 'textfield', + input: true, + }, + ], + }, + { + type: 'button', + label: 'Submit', + key: 'submit', + disableOnInvalid: true, + input: true, + tableView: false, + }, + ], +}; diff --git a/src/components/container/fixtures/index.js b/src/components/container/fixtures/index.js index 63f18da5cf..f1a58d4b03 100644 --- a/src/components/container/fixtures/index.js +++ b/src/components/container/fixtures/index.js @@ -1,4 +1,5 @@ import comp1 from './comp1'; import comp2 from './comp2'; import comp3 from './comp3'; -export { comp1, comp2, comp3 }; +import comp4 from './comp4'; +export { comp1, comp2, comp3, comp4 }; diff --git a/src/components/select/Select.unit.js b/src/components/select/Select.unit.js index e775fdde29..51bb3f06fa 100644 --- a/src/components/select/Select.unit.js +++ b/src/components/select/Select.unit.js @@ -42,7 +42,7 @@ describe('Select Component', () => { assert.equal(component.dataValue.value, 'a'); assert.equal(typeof component.dataValue , 'object'); done(); - }, 100); + }, 300); }); }); From cfcdcca99094174e01b032328130453e4edcc5e4 Mon Sep 17 00:00:00 2001 From: lane-formio Date: Tue, 14 Nov 2023 09:19:39 -0600 Subject: [PATCH 14/22] Fixing choices css issue (#5404) --- gulpfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index fa4b8277e3..d0bd609d64 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -75,7 +75,7 @@ gulp.task('styles-builder', function builderStyles() { }); gulp.task('styles-full', gulp.series('builder-fonts', function fullStyles() { return compileStyles([ - './node_modules/@formio/choices.js/public/assets/styles/choices.min.css', + './node_modules/@formio/choices.js/public/assets/styles/choices.css', './node_modules/tippy.js/dist/tippy.css', './node_modules/dialog-polyfill/dialog-polyfill.css', './node_modules/dragula/dist/dragula.css', From 3d1d0d174a8e77768da02764b4b2550f0bea5927 Mon Sep 17 00:00:00 2001 From: lane-formio Date: Tue, 14 Nov 2023 09:30:44 -0600 Subject: [PATCH 15/22] Update Changelog.md --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index ec14e0a513..91aaa1ade7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - FIO-7355: fixed issue with HTML5 select flickering on initial click - FIO-7530: added ability to pass onSetItems component setting as a string (needed for builder mode) - FIO-7528: Revert FIO-4405: fixed an issue where walidation error displays with empty value even if it is not required (#4746) + - FIO-7547: Container hidden with conditional logic still appears in submission #5401 ### Changed - Add capability for adding sanitize profiles through sanitizeConfig in options From 1eccbafefd34fd820740e3ba889c49a7dccb686e Mon Sep 17 00:00:00 2001 From: lane-formio Date: Tue, 14 Nov 2023 09:43:01 -0600 Subject: [PATCH 16/22] Update Changelog.md --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 91aaa1ade7..9e328328b9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - FIO-7530: added ability to pass onSetItems component setting as a string (needed for builder mode) - FIO-7528: Revert FIO-4405: fixed an issue where walidation error displays with empty value even if it is not required (#4746) - FIO-7547: Container hidden with conditional logic still appears in submission #5401 + - FIO-7550: Fixing choices css issue ### Changed - Add capability for adding sanitize profiles through sanitizeConfig in options From dedc49a5a17872fb9cb4a67e9cb22a6108d75c77 Mon Sep 17 00:00:00 2001 From: alexandraRamanenka <60643585+alexandraRamanenka@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:46:33 +0200 Subject: [PATCH 17/22] FIO-7074/FIO-7379: Fixes some issues caused by Wizzard was not always setting _data to submission data (#5396) --- src/Wizard.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Wizard.js b/src/Wizard.js index b514d19121..49f54eec5a 100644 --- a/src/Wizard.js +++ b/src/Wizard.js @@ -897,25 +897,23 @@ export default class Wizard extends Webform { } setValue(submission, flags = {}, ignoreEstablishment) { - this._submission = submission; - if ( - (flags && flags.fromSubmission && (this.options.readOnly || this.editMode) && !this.isHtmlRenderMode()) || - (flags && flags.fromSubmission && (this.prefixComps.length || this.suffixComps.length) && submission._id) || - (this.options.server && (this.prefixComps.length || this.suffixComps.length)) - ) { - this._data = submission.data; - } - - if (!ignoreEstablishment) { - this.establishPages(submission.data); - } const changed = this.getPages({ all: true }).reduce((changed, page) => { return this.setNestedValue(page, submission.data, flags, changed) || changed; }, false); + this.mergeData(this.data, submission.data); + if (changed) { this.pageFieldLogic(this.page); } + + submission.data = this.data; + this._submission = submission; + + if (!ignoreEstablishment) { + this.establishPages(submission.data); + } + this.setEditMode(submission); return changed; From 7faa182acf1aeb3942613c2c21a34424c190848a Mon Sep 17 00:00:00 2001 From: TanyaGashtold <61136841+TanyaGashtold@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:47:10 +0300 Subject: [PATCH 18/22] Update Changelog.md --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 9e328328b9..3723d64c1f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - FIO-7528: Revert FIO-4405: fixed an issue where walidation error displays with empty value even if it is not required (#4746) - FIO-7547: Container hidden with conditional logic still appears in submission #5401 - FIO-7550: Fixing choices css issue + - FIO-7074/FIO-7379: Fixes some issues caused by Wizzard was not always setting _data to submission data ### Changed - Add capability for adding sanitize profiles through sanitizeConfig in options From ca7509a597d759d2a22ee1167f0f24c671b89ef5 Mon Sep 17 00:00:00 2001 From: TanyaGashtold <61136841+TanyaGashtold@users.noreply.github.com> Date: Thu, 16 Nov 2023 13:12:26 +0300 Subject: [PATCH 19/22] FIO-7112: fixed an issue where value component still shows calendar widget after the condition base component is changed to the component without widget (#5402) --- src/components/_classes/component/Component.js | 7 ++++++- src/components/textfield/TextField.js | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/components/_classes/component/Component.js b/src/components/_classes/component/Component.js index 05dfb83227..e03c56d624 100644 --- a/src/components/_classes/component/Component.js +++ b/src/components/_classes/component/Component.js @@ -211,7 +211,12 @@ export default class Component extends Element { return { operators: ['isEqual', 'isNotEqual', 'isEmpty', 'isNotEmpty'], valueComponent() { - return { type: 'textfield' }; + return { + type: 'textfield', + widget: { + type: 'input' + } + }; } }; } diff --git a/src/components/textfield/TextField.js b/src/components/textfield/TextField.js index 22f82c1f12..08871db25b 100644 --- a/src/components/textfield/TextField.js +++ b/src/components/textfield/TextField.js @@ -44,6 +44,12 @@ export default class TextFieldComponent extends Input { return { ...super.conditionOperatorsSettings, operators: [...super.conditionOperatorsSettings.operators, 'includes', 'notIncludes', 'endsWith', 'startsWith'], + valueComponent(classComp) { + return { + ...classComp, + type: 'textfield', + }; + } }; } From 327515e778c03c811a0d197c3c386f2de659f405 Mon Sep 17 00:00:00 2001 From: antonSoftensity <61691723+antonSoftensity@users.noreply.github.com> Date: Mon, 20 Nov 2023 21:31:19 +0100 Subject: [PATCH 20/22] FIO-7406 Fixed plain Textarea interpolating data in readonly mode (#5383) --- src/components/textarea/TextArea.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/textarea/TextArea.js b/src/components/textarea/TextArea.js index bfe2ad4b12..3639aedafe 100644 --- a/src/components/textarea/TextArea.js +++ b/src/components/textarea/TextArea.js @@ -342,10 +342,10 @@ export default class TextAreaComponent extends TextFieldComponent { if (this.options.readOnly || this.disabled) { if (this.refs.input && this.refs.input[index]) { if (this.component.inputFormat === 'plain') { - this.refs.input[index].innerText = this.interpolate(value, {}, { noeval: true }); + this.refs.input[index].innerText = this.isPlain ? value : this.interpolate(value, {}, { noeval: true }); } else { - this.setContent(this.refs.input[index], this.interpolate(value, {}, { noeval: true }), this.shouldSanitizeValue); + this.setContent(this.refs.input[index], this.isPlain ? value : this.interpolate(value, {}, { noeval: true }), this.shouldSanitizeValue); } } } From d0e9b94f1285417066d341a0c6f786e99ff7f168 Mon Sep 17 00:00:00 2001 From: alexandraRamanenka <60643585+alexandraRamanenka@users.noreply.github.com> Date: Mon, 20 Nov 2023 22:32:17 +0200 Subject: [PATCH 21/22] FIO-7208: Moved Tree component to the contrib library (#5359) * FIO-7208: Moved Tree component to the contrib library * Removed Tree component from tests --- src/components/builder.js | 2 - src/components/index.js | 2 - src/components/tree/Node.js | 227 -------- src/components/tree/Tree.form.js | 15 - src/components/tree/Tree.js | 520 ------------------ src/components/tree/Tree.unit.js | 207 ------- .../tree/editForm/Tree.edit.data.js | 7 - .../tree/editForm/Tree.edit.display.js | 10 - src/components/tree/fixtures/comp1.js | 23 - src/components/tree/fixtures/comp2.js | 80 --- src/components/tree/fixtures/comp3.js | 23 - src/components/tree/fixtures/comp4.js | 45 -- src/components/tree/fixtures/index.js | 5 - src/sass/formio.form.scss | 21 - .../testBasicComponentSettings/form.js | 14 - 15 files changed, 1201 deletions(-) delete mode 100644 src/components/tree/Node.js delete mode 100644 src/components/tree/Tree.form.js delete mode 100644 src/components/tree/Tree.js delete mode 100644 src/components/tree/Tree.unit.js delete mode 100644 src/components/tree/editForm/Tree.edit.data.js delete mode 100644 src/components/tree/editForm/Tree.edit.display.js delete mode 100644 src/components/tree/fixtures/comp1.js delete mode 100644 src/components/tree/fixtures/comp2.js delete mode 100644 src/components/tree/fixtures/comp3.js delete mode 100644 src/components/tree/fixtures/comp4.js delete mode 100644 src/components/tree/fixtures/index.js diff --git a/src/components/builder.js b/src/components/builder.js index 3884eacd90..c953dce0ff 100644 --- a/src/components/builder.js +++ b/src/components/builder.js @@ -37,7 +37,6 @@ import TagsForm from './tags/Tags.form'; import TextAreaForm from './textarea/TextArea.form'; import TextfieldForm from './textfield/TextField.form'; import TimeForm from './time/Time.form'; -import TreeForm from './tree/Tree.form'; import UnknownForm from './unknown/Unknown.form'; import UrlForm from './url/Url.form'; import WellForm from './well/Well.form'; @@ -80,7 +79,6 @@ Components.tags.editForm = TagsForm; Components.textarea.editForm = TextAreaForm; Components.textfield.editForm = TextfieldForm; Components.time.editForm = TimeForm; -Components.tree.editForm = TreeForm; Components.unknown.editForm = UnknownForm; Components.url.editForm = UrlForm; Components.well.editForm = WellForm; diff --git a/src/components/index.js b/src/components/index.js index 5ec679e647..9df2ad255a 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -42,7 +42,6 @@ import TagsComponent from './tags/Tags'; import TextAreaComponent from './textarea/TextArea'; import TextFieldComponent from './textfield/TextField'; import TimeComponent from './time/Time'; -import TreeComponent from './tree/Tree'; import UnknownComponent from './unknown/Unknown'; import UrlComponent from './url/Url'; import WellComponent from './well/Well'; @@ -93,7 +92,6 @@ export default { textarea: TextAreaComponent, textfield: TextFieldComponent, time: TimeComponent, - tree: TreeComponent, unknown: UnknownComponent, url: UrlComponent, well: WellComponent, diff --git a/src/components/tree/Node.js b/src/components/tree/Node.js deleted file mode 100644 index 58db7167b8..0000000000 --- a/src/components/tree/Node.js +++ /dev/null @@ -1,227 +0,0 @@ -import _ from 'lodash'; - -export default class Node { - constructor( - parent, - { - data = {}, - children = [], - } = {}, - { - checkNode, - createComponents, - isNew = true, - removeComponents, - parentPath = '' - } = {}, - ) { - this.parent = parent; - this.previousData = {}; - this.persistentData = _.cloneDeep(data); - this.new = isNew; - this.createComponents = createComponents; - this.checkNode = checkNode; - this.removeComponents = removeComponents; - this.revertAvailable = false; - this.editing = false; - this.collapsed = false; - this.components = []; - this.children = []; - this.parentPath = parentPath; - - this.resetData(); - this.children = children.map((child, index) => new Node(this, child, { - checkNode, - createComponents, - isNew: false, - removeComponents, - parentPath: this.getChildrenPath(index), - })); -} - - get value() { - return this.new - ? null // Check the special case for empty root node. - : { - data: _.cloneDeep(this.persistentData), - children: this.children.filter((child) => !child.new).map((child) => child.value), - }; - } - - get isRoot() { - return this.parent === null; - } - - get changing() { - return this.new || this.editing; - } - - get hasChangingChildren() { - return this.changin || this.children.some((child) => child.hasChangingChildren); - } - - get hasData() { - return !_.isEmpty(this.persistentData); - } - - get hasChildren() { - return Array.isArray(this.children) && this.children.length > 0; - } - - getChildrenPath(index) { - return this.parentPath ? `${this.parentPath}.children[${index}]` : ''; - } - - eachChild(iteratee) { - iteratee(this); - this.children.forEach((child) => child.eachChild(iteratee)); - return this; - } - - getComponents() { - return this.children.reduce( - (components, child) => components.concat(child.getComponents()), - this.components, - ); - } - - validateNode() { - let valid = true; - this.getComponents().forEach(comp => { - comp.setPristine(false); - valid &= comp.checkValidity(null, false, this.persistentData); - }); - return valid; - } - - addChild() { - if (this.new) { - return null; - } - - const child = new Node(this, {}, { - checkNode: this.checkNode, - createComponents: this.createComponents, - isNew: true, - removeComponents: this.removeComponents, - parentPath: this.getChildrenPath(this.children.length), - }); - this.children = this.children.concat(child); - return child; - } - - removeChild(childToRemove) { - if (!this.new) { - this.children = this.children.filter((child) => child !== childToRemove); - } - - return this; - } - - edit() { - if (this.new) { - return this; - } - - this.editing = true; - return this.resetData(); - } - - save() { - const isValid = this.validateNode(); - if (this.changing && isValid) { - if (this.new) { - this.new = false; - } - else { - this.editing = false; - this.revertAvailable = true; - } - this.commitData(); - } - - return isValid; - } - - cancel() { - if (this.new) { - this.remove(); - } - else if (this.editing) { - this.editing = false; - this.resetData(); - } - - return this; - } - - remove() { - this.parent.removeChild(this); - this.parent = null; - this.clearComponents(); - return this; - } - - revert() { - if (!this.revertAvailable) { - return this; - } - - this.data = this.previousData; - return this.commitData(); - } - - commitData() { - this.previousData = this.persistentData; - this.persistentData = _.cloneDeep(this.data); - this.clearComponents(); - return this; - } - - resetData() { - this.data = _.cloneDeep(this.persistentData); - this.updateComponentsContext(); - return this; - } - - updateComponentsContext() { - if (this.changing) { - this.instantiateComponents(); - } - else { - this.clearComponents(); - } - - return this; - } - - instantiateComponents() { - this.components = this.createComponents(this.data, this); - this.components.forEach((component) => { - if (this.parentPath) { - const path = this.calculateComponentPath(component); - component.path = path; - } - }); - this.checkNode(this); - } - - clearComponents() { - this.removeComponents(this.components); - this.components = []; - } - - /** - * Return a path of component's value. - * - * @param {Object} component - The component instance. - * @return {string} - The component's value path. - */ - calculateComponentPath(component) { - let path = ''; - if (component.component.key) { - path = `${this.parentPath}.data.${component.component.key}`; - } - return path; - } -} diff --git a/src/components/tree/Tree.form.js b/src/components/tree/Tree.form.js deleted file mode 100644 index 2fe5c9a19b..0000000000 --- a/src/components/tree/Tree.form.js +++ /dev/null @@ -1,15 +0,0 @@ -import componentEditForm from '../_classes/component/Component.form'; -import TreeEditData from './editForm/Tree.edit.data'; -import TreeDisplayData from './editForm/Tree.edit.display'; -export default function(...extend) { - return componentEditForm([ - { - key: 'display', - components: TreeDisplayData, - }, - { - key: 'data', - components: TreeEditData, - }, - ], ...extend); -} diff --git a/src/components/tree/Tree.js b/src/components/tree/Tree.js deleted file mode 100644 index 67a5e7c683..0000000000 --- a/src/components/tree/Tree.js +++ /dev/null @@ -1,520 +0,0 @@ -import _ from 'lodash'; -import Component from '../_classes/component/Component'; -import Components from '../Components'; -import NestedDataComponent from '../_classes/nesteddata/NestedDataComponent'; -import Node from './Node'; - -export default class TreeComponent extends NestedDataComponent { - static schema(...extend) { - return NestedDataComponent.schema({ - label: 'Tree', - key: 'tree', - type: 'tree', - clearOnHide: true, - input: true, - tree: true, - components: [], - multiple: false, - }, ...extend); - } - - static get builderInfo() { - return { - title: 'Tree', - icon: 'indent', - weight: 40, - documentation: '/userguide/form-building/data-components#tree', - showPreview: false, - schema: TreeComponent.schema(), - }; - } - - constructor(...args) { - super(...args); - this.type = 'tree'; - } - - get emptyValue() { - return {}; - } - - get viewComponents() { - if (!this.viewComponentsInstantiated) { - this.viewComponentsInstantiated = true; - this._viewComponents = this.createComponents({}); - } - - return this._viewComponents; - } - - init() { - if (this.builderMode) { - return super.init(); - } - - this.components = []; - this.componentOptions = { - ...this.options, - parent: this, - root: this.root || this, - }; - this.disabled = this.shouldDisabled; - this.setRoot(); - this.viewComponentsInstantiated = false; - this._viewComponents = []; - } - - get disabled() { - return super.disabled; - } - - set disabled(disabled) { - super.disabled = disabled; - this.viewComponents.forEach((component) => component.parentDisabled = disabled); - } - - get isDefaultValueComponent() { - return !!this.options.editComponent && !!this.options.editForm && this.component.key === 'defaultValue'; - } - - destroy(all = false) { - if (!this.builderMode) { - this.removeComponents(this._viewComponents, all); - } - super.destroy(all); - } - - createComponents(data, node) { - const components = this.componentComponents.map( - (component) => { - const componentInstance = Components.create(component, this.componentOptions, data); - componentInstance.init(); - componentInstance.parentDisabled = this.disabled; - return componentInstance; - }, - ); - - if (node) { - this.checkNode(this.data, node); - } - - return components; - } - - removeComponents(components, all = false) { - return components.map((component) => component.destroy(all)); - } - - render() { - if (this.builderMode) { - return super.render(); - } - - return super.render(this.renderTree(this.treeRoot)); - } - - renderTree(node = {}, odd = true) { - const childNodes = (node.hasChildren && !node.collapsed) - ? this.renderChildNodes(node.children, !odd) - : []; - const content = node.changing - ? this.renderEdit(node) - : this.renderView(node); - - return this.renderTemplate('tree', { - odd, - childNodes, - content, - node, - }); - } - - renderChildNodes(nodes = [], odd) { - return nodes.map((node) => this.renderTree(node, odd)); - } - - renderEdit(node = {}) { - return this.renderTemplate('treeEdit', { - children: this.renderComponents(node.components), - node, - }); - } - - renderView(node = {}) { - return this.renderTemplate('treeView', { - values: this.viewComponents.map((component) => { - component.data = node.data; - component.checkComponentConditions(node.data); - return component.getView(component.dataValue); - }), - nodeData: node.data, - node, - }); - } - - attach(element) { - if (this.builderMode) { - return super.attach(element); - } - - this.loadRefs(element, { - root: 'single', - }); - - return Promise.all([ - super.attach(element), - this.attachNode(this.refs.root, this.treeRoot), - ]); - } - - attachNode(element, node) { - if (!element) { - return Promise.resolve(); - } - - let componentsPromise = Promise.resolve(); - let childrenPromise = Promise.resolve(); - - node.refs = _.reduce( - element.children, - (refs, child) => ( - child.hasAttribute('ref') - ? { - ...refs, - [child.getAttribute('ref')]: child, - } - : refs - ), - {}, - ); - - if (node.refs.content) { - this.attachActions(node); - componentsPromise = this.attachComponents(node); - } - - if (node.refs.childNodes) { - childrenPromise = this.attachChildren(node); - } - - return Promise.all([ - componentsPromise, - childrenPromise, - ]); - } - - attachActions(node) { - if (!node.editing) { - this.loadRefs.call(node, node.refs.content, { - addChild: 'single', - editNode: 'single', - removeNode: 'single', - revertNode: 'single', - toggleNode: 'single', - }); - } - - //load refs correctly (if there is nested tree) - this.loadRefs.call(node, node.refs.content.children[0]?.children[1] || node.refs.content, { - cancelNode: 'single', - saveNode: 'single', - }); - - if (node.refs.addChild) { - this.addEventListener(node.refs.addChild, 'click', () => { - this.addChild(node); - }); - } - - if (node.refs.cancelNode) { - this.addEventListener(node.refs.cancelNode, 'click', () => { - this.cancelNode(node); - }); - } - - if (node.refs.editNode) { - this.addEventListener(node.refs.editNode, 'click', () => { - this.editNode(node); - }); - } - - if (node.refs.removeNode) { - this.addEventListener(node.refs.removeNode, 'click', () => { - this.removeNode(node); - }); - } - - if (node.refs.revertNode) { - this.addEventListener(node.refs.revertNode, 'click', () => { - this.revertNode(node); - }); - } - - if (node.refs.saveNode) { - this.addEventListener(node.refs.saveNode, 'click', () => { - this.saveNode(node); - }); - } - - if (node.refs.toggleNode) { - this.addEventListener(node.refs.toggleNode, 'click', () => { - this.toggleNode(node); - }); - } - } - - attachComponents(node, ...args) { - if (this.builderMode) { - return super.attachComponents.call(this, node, ...args); - } - - this.loadRefs.call(node, node.refs.content, { - nodeEdit: 'single', - }); - - return node.refs.nodeEdit - ? super.attachComponents(node.refs.nodeEdit, node.components) - : Promise.resolve(); - } - - attachChildren(node) { - const childElements = node.refs.childNodes.children; - - return Promise.all( - _.map( - childElements, - (childElement, index) => this.attachNode(childElement, node.children[index]), - ), - ); - } - - setValue(value, flags = {}) { - const changed = this.updateValue(value, flags); - this.setRoot(); - return changed; - } - - addChild(parent) { - if (this.options.readOnly || parent.new) { - return; - } - - this.hook('tree.addChild', { - parent, - component: this, - }, () => { - const child = parent.addChild(); - this.redraw(); - - return child; - }); - } - - cancelNode(node) { - if (this.options.readOnly) { - return; - } - - this.hook('tree.cancelNode', { - node, - component: this, - }, () => { - if (node.isRoot) { - if (node.persistentData && !_.isEmpty(node.persistentData)) { - node.cancel(); - this.redraw(); - } - else { - this.removeRoot(); - } - } - else { - node.cancel(); - this.redraw(); - } - - return node; - }); - } - - editNode(node) { - if (this.options.readOnly || node.new) { - return; - } - - this.hook('tree.editNode', { - node, - component: this, - }, () => { - node.edit(); - this.redraw(); - - return node; - }); - } - - removeNode(node) { - if (this.options.readOnly || node.new) { - return; - } - - this.hook('tree.removeNode', { - node, - component: this, - }, () => { - if (node.isRoot) { - this.removeRoot(); - } - else { - node.remove(); - this.updateTree(); - } - - return node; - }); - } - - revertNode(node) { - if (this.options.readOnly || !node.revertAvailable) { - return; - } - - this.hook('tree.revertNode', { - node, - component: this, - }, () => { - node.revert(); - this.updateTree(); - - return node; - }); - } - - saveNode(node) { - if (this.options.readOnly) { - return; - } - - this.hook('tree.saveNode', { - node, - component: this, - }, () => { - const isSaved = node.save(); - if (isSaved) { - this.updateTree(); - } - - return node; - }); - } - - toggleNode(node) { - this.hook('tree.toggleNode', { - node, - component: this, - }, () => { - node.collapsed = !node.collapsed; - this.redraw(); - - return node; - }); - } - - removeRoot() { - if (this.options.readOnly) { - return; - } - - this.dataValue = this.defaultValue; - this.setRoot(); - this.redraw(); - } - - setRoot() { - const value = this.getValue(); - this.treeRoot = new Node(null, value, { - isNew: this.builderMode ? true : !value.data, - createComponents: this.createComponents.bind(this), - checkNode: this.checkNode.bind(this, this.data), - removeComponents: this.removeComponents, - parentPath: this.isDefaultValueComponent ? (this.path || this.component.key) : null, - }); - this.hook('tree.setRoot', { - root: this.treeRoot, - component: this, - }); - this.redraw(); - } - - getValue() { - return this.dataValue || {}; - } - - updateTree() { - this.updateValue(this.treeRoot.value); - this.redraw(); - } - - checkData(data, flags, row) { - return this.checkNode(data, this.treeRoot, flags, row); - } - - checkNode(data, node, flags, row) { - return node.children.reduce( - (result, child) => this.checkNode(data, child, flags, row) && result, - super.checkData(data, flags, node.data, node.components) && !node.editing && !node.new, - ); - } - - getComponents() { - return this.treeRoot && (this.isDefaultValueComponent || (!this.isDefaultValueComponent && !this.builderMode)) - ? this.treeRoot.getComponents() - : super.getComponents(); - } - - getValueAsString(value, options) { - const getChildAsString = (value) => { - let result = (` - - - `); - result += ` - - `; - result += Object.keys(value.data).map((k) => (` - ${k} - - ${value.data[k]} - - `)); - - if (value.children?.length !== 0) { - value.children?.forEach((v) => { - result += getChildAsString(v); - }); - } - - result += ` - - - `; - - result += (` - - - `); - - return result; - }; - - if (options?.email) { - let result = ''; - result += getChildAsString(value); - return result; - } - - return super.getValueAsString(value, options); - } -} - -TreeComponent.prototype.hasChanged = Component.prototype.hasChanged; diff --git a/src/components/tree/Tree.unit.js b/src/components/tree/Tree.unit.js deleted file mode 100644 index f1c94e7812..0000000000 --- a/src/components/tree/Tree.unit.js +++ /dev/null @@ -1,207 +0,0 @@ -import assert from 'power-assert'; -import Harness from '../../../test/harness'; -import TreeComponent from './Tree'; -import { - comp1, - comp2, - comp3, - comp4 -} from './fixtures'; -import Webform from '../../Webform'; -import _ from 'lodash'; -import { Formio } from '../../Formio'; - -describe('Tree Component', () => { - it('Should set and render values in readOnly mode', function(done) { - Harness.testCreate(TreeComponent, comp1).then((component) => { - component.setValue({ - data: { - number: 111, - }, - children: [{ - data: { - number: 222, - }, - children: [{ - data: { - number: 333, - }, - children: [] - }] - }] - }); - - assert.equal(component.element.querySelectorAll('.tree__node-content').length, 3); - assert.equal(component.element.querySelectorAll('.editNode').length, 3); - - component.options.readOnly = true; - component.redraw(); - - const valueContainers = component.element.querySelectorAll('.col-sm-2'); - - assert.equal(component.element.querySelectorAll('.tree__node-content').length, 3); - assert.equal(component.element.querySelectorAll('.editNode').length, 0); - assert.equal(valueContainers[0].innerHTML.trim(), '111'); - assert.equal(valueContainers[1].innerHTML.trim(), '222'); - assert.equal(valueContainers[2].innerHTML.trim(), '333'); - - done(); - }); - }); - it('Should render tree and allow to save node with basic, layout and data component inside', function(done) { - Harness.testCreate(TreeComponent, comp2).then((component) => { - assert.equal(!!component.treeRoot.refs.content, true); - assert.equal(!!component.treeRoot.refs.cancelNode, true); - assert.equal(!!component.treeRoot.refs.saveNode, true); - assert.equal(!!component.treeRoot.refs.addChild, false); - assert.equal(!!component.treeRoot.refs.editNode, false); - assert.equal(!!component.treeRoot.refs.removeNode, false); - - const value = { - data: { - dataGrid: [{ textField: 'data grid 1st row text' }], - number: 3333, - select: '', - textArea: 'text area text', - }, - children: [] - }; - - const inputFields = { - 'data[tree][dataGrid][0][textField]': value.data.dataGrid[0].textField, - 'data[tree][number]':value.data.number, - 'data[tree][textArea]': value.data.textArea - }; - - const inputEvent = new Event('input'); - _.each(inputFields, (value, fieldName)=> { - const input = component.element.querySelector(`[name="${fieldName}"]`); - input.value = value; - input.dispatchEvent(inputEvent); - }); - - setTimeout(() => { - const clickEvent = new Event('click'); - component.treeRoot.refs.saveNode.dispatchEvent(clickEvent); - setTimeout(() => { - assert.equal(!!component.treeRoot.refs.content, true); - assert.equal(!!component.treeRoot.refs.cancelNode, false); - assert.equal(!!component.treeRoot.refs.saveNode, false); - assert.equal(!!component.treeRoot.refs.addChild, true); - assert.equal(!!component.treeRoot.refs.editNode, true); - assert.equal(!!component.treeRoot.refs.removeNode, true); - assert.deepEqual(component.getValue(), value, 'setvalue'); - - done(); - }); - }); - }); - }); - it('Should keep the node of parent tree opened when saving the node of a child tree', function(done) { - Harness.testCreate(TreeComponent, comp3).then((component) => { - assert.equal(!!component.treeRoot.refs.cancelNode, true); - assert.equal(!!component.treeRoot.refs.saveNode, true); - assert.equal(!!component.treeRoot.refs.editNode, false); - - const clickEvent = new Event('click'); - const childSaveNodeBtn = component.element.querySelector('.formio-component-tree1').querySelector('[ref="saveNode"]'); - - childSaveNodeBtn.dispatchEvent(clickEvent); - - setTimeout(() => { - assert.equal(!!component.treeRoot.refs.cancelNode, true); - assert.equal(!!component.treeRoot.refs.saveNode, true); - assert.equal(!!component.treeRoot.refs.editNode, false); - - const childTree = component.element.querySelector('.formio-component-tree1'); - const saveBtn = childTree.querySelector('[ref="saveNode"]'); - const editBtn = childTree.querySelector('[ref="editNode"]'); - - assert.equal(!!saveBtn, false); - assert.equal(!!editBtn, true); - - done(); - }); - }); - }); - it('Should allow to open node of a child tree for editing after opening parent tree node', function(done) { - Harness.testCreate(TreeComponent, comp3).then((component) => { - assert.equal(!!component.treeRoot.refs.cancelNode, true, 'Should show cancel btn for parent tree'); - assert.equal(!!component.treeRoot.refs.saveNode, true, 'Should show save btn for parent tree'); - assert.equal(!!component.treeRoot.refs.editNode, false, 'Should not show edit btn for parent node in editing tree'); - - assert.equal(!!component.treeRoot.components[0].treeRoot.refs.cancelNode, true, 'Should show cancel btn for child tree'); - assert.equal(!!component.treeRoot.components[0].treeRoot.refs.saveNode, true, 'Should show save btn for child tree'); - assert.equal(!!component.treeRoot.components[0].treeRoot.refs.editNode, false, 'Should not show edit btn for child tree in editing tree'); - - const clickEvent = new Event('click'); - const childSaveNodeBtn = component.treeRoot.components[0].treeRoot.refs.saveNode; - const parentSaveNodeBtn = component.treeRoot.refs.saveNode; - childSaveNodeBtn.dispatchEvent(clickEvent); - parentSaveNodeBtn.dispatchEvent(clickEvent); - - setTimeout(() => { - assert.equal(!!component.treeRoot.refs.cancelNode, false, 'Should not show cancel btn for parent tree'); - assert.equal(!!component.treeRoot.refs.saveNode, false, 'Should not show save btn for parent tree'); - assert.equal(!!component.treeRoot.refs.editNode, true, 'Should show edit btn for parent tree'); - - const parentEditNodeBtn = component.treeRoot.refs.editNode; - - parentEditNodeBtn.dispatchEvent(clickEvent); - - setTimeout(() => { - assert.equal(!!component.treeRoot.components[0].treeRoot.refs.saveNode, false, 'Should not show save btn for child tree'); - assert.equal(!!component.treeRoot.components[0].treeRoot.refs.editNode, true, 'Should show edit btn for child tree'); - - const childEditNodeBtn = component.treeRoot.components[0].treeRoot.refs.editNode; - - childEditNodeBtn.dispatchEvent(clickEvent); - - assert.equal(component.treeRoot.components[0].treeRoot.editing, true, 'Should set editing mode for child tree'); - assert.equal(!!component.treeRoot.components[0].treeRoot.refs.saveNode, true, 'Should show save btn for child tree'); - - done(); - }); - }); - }); - }); - - it('Should stop the submission if component didn\'t saved and has required fields', (done) => { - const formElement = document.createElement('div'); - const form = new Webform(formElement); - form.setForm(comp4).then(() => { - const submitButton = form.getComponent(['submit']); - assert.equal(submitButton.disabled, true, 'Submit button should being disabled'); - const tree = form.getComponent(['tree']); - const textField = tree.getComponents()[0].getComponent(['textField']); - textField.setValue('123'); - - setTimeout(() => { - assert.equal(submitButton.disabled, true, 'Submit button should being disabled'); - tree.saveNode(tree.treeRoot); - - setTimeout(() => { - assert.equal(submitButton.disabled, false, 'Submit button should being disabled'); - done(); - }, 300); - }, 300); - }).catch(done); - }); - - it('Should work with empty data and no defaults', (done) => { - const formElement = document.createElement('div'); - Formio.createForm(formElement, { - type: 'form', - components: [comp1], - display: 'form', - }, { noDefaults: true }) - .then((form) => { - setTimeout(() => { - const tree = form.getComponent(['tree']); - assert.equal(tree.treeRoot.new, true); - done(); - }, 300); - }) - .catch(done); - }); -}); diff --git a/src/components/tree/editForm/Tree.edit.data.js b/src/components/tree/editForm/Tree.edit.data.js deleted file mode 100644 index 296b37f4b5..0000000000 --- a/src/components/tree/editForm/Tree.edit.data.js +++ /dev/null @@ -1,7 +0,0 @@ -export default [ - { - key: 'multiple', - ignore: true - }, -]; -/* eslint-enable max-len */ diff --git a/src/components/tree/editForm/Tree.edit.display.js b/src/components/tree/editForm/Tree.edit.display.js deleted file mode 100644 index 5c563e9853..0000000000 --- a/src/components/tree/editForm/Tree.edit.display.js +++ /dev/null @@ -1,10 +0,0 @@ -export default [ - { - key: 'treeInfo', - weight: -10, - type: 'htmlelement', - tag: 'div', - className: 'alert alert-danger', - content: 'This component has been deprecated and will be removed in a future version of Formio.js.', - } -]; diff --git a/src/components/tree/fixtures/comp1.js b/src/components/tree/fixtures/comp1.js deleted file mode 100644 index 9e698b57be..0000000000 --- a/src/components/tree/fixtures/comp1.js +++ /dev/null @@ -1,23 +0,0 @@ -export default { - 'label': 'Tree', - 'tableView': true, - 'calculateServer': false, - 'key': 'tree', - 'type': 'tree', - 'input': true, - 'tree': true, - 'components': [{ - 'label': 'Number', - 'mask': false, - 'spellcheck': true, - 'tableView': false, - 'delimiter': false, - 'requireDecimal': false, - 'inputFormat': 'plain', - 'calculateServer': false, - 'key': 'number', - 'type': 'number', - 'input': true - }] -}; - diff --git a/src/components/tree/fixtures/comp2.js b/src/components/tree/fixtures/comp2.js deleted file mode 100644 index d7b1f9b358..0000000000 --- a/src/components/tree/fixtures/comp2.js +++ /dev/null @@ -1,80 +0,0 @@ -export default { - 'label': 'Tree', - 'tableView': false, - 'key': 'tree', - 'type': 'tree', - 'input': true, - 'tree': true, - 'components': [{ - 'label': 'Text Area', - 'autoExpand': false, - 'tableView': true, - 'key': 'textArea', - 'type': 'textarea', - 'input': true - }, { - 'label': 'Select', - 'widget': 'choicesjs', - 'tableView': true, - 'data': { - 'values': [{ - 'label': 'a', - 'value': 'a' - }, { - 'label': 'b', - 'value': 'b' - }, { - 'label': 'c', - 'value': 'c' - }] - }, - 'selectThreshold': 0.3, - 'validate': { - 'onlyAvailableItems': false - }, - 'key': 'select', - 'type': 'select', - 'indexeddb': { - 'filter': {} - }, - 'input': true - }, { - 'collapsible': false, - 'key': 'panel', - 'type': 'panel', - 'label': 'Panel', - 'input': false, - 'tableView': false, - 'components': [{ - 'label': 'Number', - 'mask': false, - 'spellcheck': true, - 'tableView': false, - 'delimiter': false, - 'requireDecimal': false, - 'inputFormat': 'plain', - 'key': 'number', - 'type': 'number', - 'input': true - }] - }, { - 'label': 'Data Grid', - 'reorder': false, - 'addAnotherPosition': 'bottom', - 'layoutFixed': false, - 'enableRowGroups': false, - 'initEmpty': false, - 'tableView': false, - 'defaultValue': [{}], - 'key': 'dataGrid', - 'type': 'datagrid', - 'input': true, - 'components': [{ - 'label': 'Text Field', - 'tableView': true, - 'key': 'textField', - 'type': 'textfield', - 'input': true - }] - }] -}; diff --git a/src/components/tree/fixtures/comp3.js b/src/components/tree/fixtures/comp3.js deleted file mode 100644 index 922cdb4503..0000000000 --- a/src/components/tree/fixtures/comp3.js +++ /dev/null @@ -1,23 +0,0 @@ -export default { - 'label': 'Tree', - 'tableView': false, - 'key': 'tree', - 'type': 'tree', - 'input': true, - 'tree': true, - 'components': [{ - 'label': 'Tree', - 'tableView': false, - 'key': 'tree1', - 'type': 'tree', - 'input': true, - 'tree': true, - 'components': [{ - 'label': 'Text Field', - 'tableView': true, - 'key': 'textField', - 'type': 'textfield', - 'input': true - }] - }] -}; diff --git a/src/components/tree/fixtures/comp4.js b/src/components/tree/fixtures/comp4.js deleted file mode 100644 index 46ad419ca9..0000000000 --- a/src/components/tree/fixtures/comp4.js +++ /dev/null @@ -1,45 +0,0 @@ -export default { - type: 'form', - owner: null, - components: [ - { - label: 'Tree', - tableView: false, - key: 'tree', - type: 'tree', - input: true, - tree: true, - components: [ - { - title: 'Required validation', - collapsible: false, - key: 'panel', - type: 'panel', - label: 'Panel', - input: false, - tableView: false, - components: [ - { - label: 'Text Field', - tableView: true, - validate: { - required: true, - }, - key: 'textField', - type: 'textfield', - input: true, - }, - ], - }, - ], - }, - { - type: 'button', - label: 'Submit', - key: 'submit', - disableOnInvalid: true, - input: true, - tableView: false, - }, - ], -}; diff --git a/src/components/tree/fixtures/index.js b/src/components/tree/fixtures/index.js deleted file mode 100644 index f1a58d4b03..0000000000 --- a/src/components/tree/fixtures/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import comp1 from './comp1'; -import comp2 from './comp2'; -import comp3 from './comp3'; -import comp4 from './comp4'; -export { comp1, comp2, comp3, comp4 }; diff --git a/src/sass/formio.form.scss b/src/sass/formio.form.scss index dea8b35bcb..8070768fa1 100644 --- a/src/sass/formio.form.scss +++ b/src/sass/formio.form.scss @@ -859,10 +859,6 @@ body.formio-dialog-open { overflow-wrap: break-word; } -.tree-listgroup { - flex-direction: row; -} - .formio-component-submit button[disabled]+.has-error { display: block; } @@ -1105,23 +1101,6 @@ body.formio-dialog-open { color: inherit; } -.tree { - &__level { - &_even { - background-color: #f6f6f6; - } - } - - &__node-content { - margin-bottom: 10px; - overflow-wrap: break-word; - } - - &__node-children { - margin: 0; - } -} - .formio-select-autocomplete-input { /* we can't use display: none or visibility: hidden because autocomplete won't work on hidden field */ opacity: 0; diff --git a/test/forms/helpers/testBasicComponentSettings/form.js b/test/forms/helpers/testBasicComponentSettings/form.js index 7043dac5b6..060f36b979 100644 --- a/test/forms/helpers/testBasicComponentSettings/form.js +++ b/test/forms/helpers/testBasicComponentSettings/form.js @@ -652,20 +652,6 @@ export default { "type": "textfield", "input": true }] - }, { - "label": "Tree", - "tableView": false, - "key": "tree", - "type": "tree", - "input": true, - "tree": true, - "components": [{ - "label": "Text Field Tree", - "tableView": true, - "key": "textFieldTree", - "type": "textfield", - "input": true - }] }, { "label": "Upload", "tableView": false, From f67428026dd5f40b478dc8ab1eeb7f05f67b3c11 Mon Sep 17 00:00:00 2001 From: lane-formio Date: Mon, 20 Nov 2023 15:49:04 -0600 Subject: [PATCH 22/22] Update Changelog.md --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index 3723d64c1f..9a393ad05c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -38,6 +38,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - FIO-7547: Container hidden with conditional logic still appears in submission #5401 - FIO-7550: Fixing choices css issue - FIO-7074/FIO-7379: Fixes some issues caused by Wizzard was not always setting _data to submission data + - FIO-7208: Moved Tree component to the contrib library + - FIO-7406 Fixed plain Textarea interpolating data in readonly mode [#5396](https://github.com/formio/formio.js/pull/5383) + - FIO-7112: fixed issues with calendar widget display for value components in new simple conditionals ui ### Changed - Add capability for adding sanitize profiles through sanitizeConfig in options