summaryrefslogtreecommitdiffstats
path: root/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInputChild.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'client/js/app/src/app/pages/querybuilder/Components/Text/QueryInputChild.jsx')
-rw-r--r--client/js/app/src/app/pages/querybuilder/Components/Text/QueryInputChild.jsx194
1 files changed, 194 insertions, 0 deletions
diff --git a/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInputChild.jsx b/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInputChild.jsx
new file mode 100644
index 00000000000..0440d6ef1ba
--- /dev/null
+++ b/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInputChild.jsx
@@ -0,0 +1,194 @@
+import React, { useContext } from 'react';
+import AddPropertyButton from '../Buttons/AddPropertyButton';
+import { QueryInputContext } from '../Contexts/QueryInputContext';
+import QueryDropdownForm from './QueryDropDownForm';
+import SimpleForm from './SimpleForm';
+import { OverlayTrigger, Tooltip } from 'react-bootstrap';
+import SimpleButton from '../Buttons/SimpleButton';
+
+export default function QueryInputChild({ id }) {
+ const { inputs, setInputs, childMap } = useContext(QueryInputContext);
+
+ let index = inputs.findIndex((element) => element.id === id);
+ let childArray = inputs[index].children;
+ let currentTypes = inputs[index].type;
+
+ /**
+ * Update the state of inputs to reflect what is written into the form.
+ * @param {Event} e Event containing the new input.
+ */
+ const updateInput = (e) => {
+ e.preventDefault();
+ let newInputs = inputs.slice();
+ let iterId = e.target.id.replace('v', '');
+ let currentId = iterId.substring(0, 1);
+ let index = newInputs.findIndex((element) => element.id === currentId);
+ let children = newInputs[index].children;
+ const traversedChildren = traverseChildren(iterId, children, '');
+ children = traversedChildren.children;
+ index = children.findIndex((element) => element.id === iterId);
+ children[index].input = e.target.value;
+ setInputs(newInputs);
+ };
+
+ /**
+ * Returns a placeholder text for a SimpleForm component.
+ * @param {String} id The id of the SimpleForm component.
+ * @returns {String} The placeholder text
+ */
+ const setPlaceHolder = (id) => {
+ let currentId = id.substring(0, 1);
+ let index = inputs.findIndex((element) => element.id === currentId);
+ let combinedType = inputs[index].type;
+ let children = inputs[index].children;
+ if (id.length > 3) {
+ const traversedChildren = traverseChildren(id, children, combinedType);
+ combinedType = traversedChildren.combinedType;
+ children = traversedChildren.children;
+ const currentChoice = childMap[combinedType];
+ index = children.findIndex((element) => element.id === id);
+ combinedType = children[index].type;
+ return currentChoice[combinedType].type;
+ } else {
+ const currentChoice = childMap[combinedType];
+ index = children.findIndex((element) => element.id === id);
+ combinedType = children[index].type;
+ return currentChoice[combinedType].type;
+ }
+ };
+
+ /**
+ * Removes the row with the provided id.
+ * @param {String} id Id of row.
+ */
+ const removeRow = (id) => {
+ let newInputs = inputs.slice();
+ let currentId = id.substring(0, 1);
+ let index = newInputs.findIndex((element) => element.id === currentId);
+ let children = newInputs[index].children;
+ const traversedChildren = traverseChildren(id, children, '');
+ index = traversedChildren.children.findIndex((element) => element === id);
+ traversedChildren.children.splice(index, 1);
+ setInputs(newInputs);
+ };
+
+ /**
+ * Traverses the children until a child with the provided id is reached.
+ * @param {String} id Id of the innermost child.
+ * @param {Array} children Array containing serveral child objects.
+ * @param {String} combinedType The combined type of all traversed children
+ * @returns {Object} An object containing the children of the child with the provided id and the combined type.
+ */
+ function traverseChildren(id, children, combinedType) {
+ let currentId;
+ let index;
+ for (let i = 3; i < id.length; i += 2) {
+ currentId = id.substring(0, i);
+ index = children.findIndex((element) => element.id === currentId);
+ combinedType = combinedType + '_' + children[index].type;
+ children = children[index].children;
+ }
+ return { children: children, combinedType: combinedType };
+ }
+
+ const inputList = childArray.map((child) => {
+ return (
+ <div key={child.id} id={child.id}>
+ <QueryDropdownForm
+ choices={childMap[currentTypes]}
+ id={child.id}
+ child={true}
+ />
+ {child.hasChildren ? (
+ <>
+ <AddPropertyButton id={child.id} />
+ </>
+ ) : (
+ <SimpleForm
+ id={`v${child.id}`}
+ size="30"
+ onChange={updateInput}
+ placeholder={setPlaceHolder(child.id)}
+ />
+ )}
+ <OverlayTrigger
+ placement="right"
+ delay={{ show: 250, hide: 400 }}
+ overlay={<Tooltip id="button-tooltip">Remove row</Tooltip>}
+ >
+ <span>
+ <SimpleButton
+ id={`b${child.id}`}
+ className="removeRow"
+ onClick={() => removeRow(child.id)}
+ children="-"
+ ></SimpleButton>
+ </span>
+ </OverlayTrigger>
+ <br />
+ <Child
+ type={currentTypes + '_' + child.type}
+ child={child}
+ onChange={updateInput}
+ placeholder={setPlaceHolder}
+ removeRow={removeRow}
+ />
+ </div>
+ );
+ });
+
+ return <>{inputList}</>;
+}
+
+function Child({ child, type, onChange, placeholder, removeRow }) {
+ const { childMap } = useContext(QueryInputContext);
+
+ const nestedChildren = (child.children || []).map((child) => {
+ return (
+ <div key={child.id}>
+ <QueryDropdownForm
+ choices={childMap[type]}
+ id={child.id}
+ child={true}
+ />
+ {child.hasChildren ? (
+ <>
+ <AddPropertyButton id={child.id} />
+ </>
+ ) : (
+ <SimpleForm
+ id={`v${child.id}`}
+ size="30"
+ onChange={onChange}
+ placeholder={placeholder(child.id)}
+ />
+ )}
+ <OverlayTrigger
+ placement="right"
+ delay={{ show: 250, hide: 400 }}
+ overlay={<Tooltip id="button-tooltip">Remove row</Tooltip>}
+ >
+ <span>
+ <SimpleButton
+ id={`b${child.id}`}
+ className="removeRow"
+ onClick={() => removeRow(child.id)}
+ children="-"
+ ></SimpleButton>
+ </span>
+ </OverlayTrigger>
+ <br />
+ <Child
+ child={child}
+ id={child.id}
+ type={type + '_' + child.type}
+ onChange={onChange}
+ placeholder={placeholder}
+ removeRow={removeRow}
+ />
+ </div>
+ );
+ });
+
+ return <>{nestedChildren}</>;
+}