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] 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 = (` -
${k} | -
- ${value.data[k]}
- - `)); - - if (value.children?.length !== 0) { - value.children?.forEach((v) => { - result += getChildAsString(v); - }); - } - - result += ` - |
-
---|