diff options
author | Erlend <erlendniko@hotmail.com> | 2022-06-28 13:51:18 +0200 |
---|---|---|
committer | Erlend <erlendniko@hotmail.com> | 2022-06-28 13:51:18 +0200 |
commit | 137c2d051fc2a27295058eff56a9ea7340a09c44 (patch) | |
tree | 275467e26b66bc6803aa0c5b4777b42160c9f329 /client | |
parent | b820ad627ee0a9b0cf8d81b4c87622bb3529b6f7 (diff) |
QueryInputChild now properly displays children
Diffstat (limited to 'client')
7 files changed, 238 insertions, 66 deletions
diff --git a/client/js/app/src/app/pages/querybuilder/Components/Buttons/AddPropertyButton.jsx b/client/js/app/src/app/pages/querybuilder/Components/Buttons/AddPropertyButton.jsx new file mode 100644 index 00000000000..b205c693652 --- /dev/null +++ b/client/js/app/src/app/pages/querybuilder/Components/Buttons/AddPropertyButton.jsx @@ -0,0 +1,43 @@ +import React, { useContext, useState } from 'react'; +import { QueryInputContext } from '../Contexts/QueryInputContext'; +import SimpleButton from './SimpleButton'; + +export default function AddPropertyButton({ id }) { + const { inputs, setInputs } = useContext(QueryInputContext); + const [childId, setChildId] = useState(1); + + const addChildProperty = () => { + const newInputs = inputs.slice(); + //this is needed because substring() is exclusive the last parameter + const iterId = id + '.'; + //TODO: the id can be of type 1.1.2, need to iterate over it to go through the tree of children. + let currentId = iterId.substring(0, 1); + let index = newInputs.findIndex((element) => element.id === currentId); //get the index of the root parent + let children = newInputs[index].children; + for (let i = 3; i < iterId.length; i += 2) { + currentId = iterId.substring(0, i); + index = children.findIndex((element) => element.id === currentId); + children = children[index].children; + } + children.push({ + id: id + '.' + childId, + type: newInputs[index].type, + input: '', + hasChildren: false, + children: [], + }); + setInputs(newInputs); + setChildId((childId) => childId + 1); + console.log('BUTTON CLICK'); + }; + + return ( + <SimpleButton + id={`propb${id}`} + className={'addpropsbutton'} + onClick={addChildProperty} + > + + Add property + </SimpleButton> + ); +} diff --git a/client/js/app/src/app/pages/querybuilder/Components/Buttons/AddQueryInputButton.jsx b/client/js/app/src/app/pages/querybuilder/Components/Buttons/AddQueryInputButton.jsx index 5af361a85d1..feb0be7cd57 100644 --- a/client/js/app/src/app/pages/querybuilder/Components/Buttons/AddQueryInputButton.jsx +++ b/client/js/app/src/app/pages/querybuilder/Components/Buttons/AddQueryInputButton.jsx @@ -10,7 +10,13 @@ export default function AddQueryInput() { setId((id) => id + 1); setInputs((prevInputs) => [ ...prevInputs, - { id: id + 1, type: '', input: '', hasChildren: false, children: [] }, + { + id: `${id + 1}`, + type: 'yql', + input: '', + hasChildren: false, + children: [], + }, ]); }; diff --git a/client/js/app/src/app/pages/querybuilder/Components/Contexts/QueryInputContext.jsx b/client/js/app/src/app/pages/querybuilder/Components/Contexts/QueryInputContext.jsx index 572fc7b5aa5..9aea9f7a89c 100644 --- a/client/js/app/src/app/pages/querybuilder/Components/Contexts/QueryInputContext.jsx +++ b/client/js/app/src/app/pages/querybuilder/Components/Contexts/QueryInputContext.jsx @@ -45,92 +45,92 @@ export const QueryInputProvider = (prop) => { // Children of the levelZeroParameters that has attributes const childMap = { collapse: { - summary: { child: 'summary', type: 'String', hasChildren: false }, + summary: { name: 'summary', type: 'String', hasChildren: false }, }, metrics: { - ignore: { child: 'ignore', type: 'Boolean', hasChildren: false }, + ignore: { name: 'ignore', type: 'Boolean', hasChildren: false }, }, model: { defaultIndex: { - child: 'defaultIndex', + name: 'defaultIndex', type: 'String', hasChildren: false, }, - encoding: { child: 'encoding', type: 'String', hasChildren: false }, - language: { child: 'language', type: 'String', hasChildren: false }, - queryString: { child: 'queryString', type: 'String', hasChildren: false }, - restrict: { child: 'restrict', type: 'List', hasChildren: false }, - searchPath: { child: 'searchPath', type: 'String', hasChildren: false }, - sources: { child: 'sources', type: 'List', hasChildren: false }, - type: { child: 'type', type: 'String', hasChildren: false }, + encoding: { name: 'encoding', type: 'String', hasChildren: false }, + language: { name: 'language', type: 'String', hasChildren: false }, + queryString: { name: 'queryString', type: 'String', hasChildren: false }, + restrict: { name: 'restrict', type: 'List', hasChildren: false }, + searchPath: { name: 'searchPath', type: 'String', hasChildren: false }, + sources: { name: 'sources', type: 'List', hasChildren: false }, + type: { name: 'type', type: 'String', hasChildren: false }, }, pos: { - ll: { child: 'll', type: 'String', hasChildren: false }, - radius: { child: 'radius', type: 'String', hasChildren: false }, - bb: { child: 'bb', type: 'List', hasChildren: false }, - attribute: { child: 'attribute', type: 'String', hasChildren: false }, + ll: { name: 'll', type: 'String', hasChildren: false }, + radius: { name: 'radius', type: 'String', hasChildren: false }, + bb: { name: 'bb', type: 'List', hasChildren: false }, + attribute: { name: 'attribute', type: 'String', hasChildren: false }, }, presentation: { - bolding: { child: 'bolding', type: 'Boolean', hasChildren: false }, - format: { child: 'format', type: 'String', hasChildren: false }, - summary: { child: 'summary', type: 'String', hasChildren: false }, - template: { child: 'template', type: 'String', hasChildren: false }, - timing: { child: 'timing', type: 'Boolean', hasChildren: false }, + bolding: { name: 'bolding', type: 'Boolean', hasChildren: false }, + format: { name: 'format', type: 'String', hasChildren: false }, + summary: { name: 'summary', type: 'String', hasChildren: false }, + template: { name: 'template', type: 'String', hasChildren: false }, + timing: { name: 'timing', type: 'Boolean', hasChildren: false }, }, ranking: { - location: { child: 'location', type: 'String', hasChildren: false }, - features: { child: 'features', type: 'String', hasChildren: false }, + location: { name: 'location', type: 'String', hasChildren: false }, + features: { name: 'features', type: 'String', hasChildren: false }, listFeatures: { - child: 'listFeatures', + name: 'listFeatures', type: 'Boolean', hasChildren: false, }, - profile: { child: 'profile', type: 'String', hasChildren: false }, - properties: { child: 'properties', type: 'String', hasChildren: false }, - sorting: { child: 'sorting', type: 'String', hasChildren: false }, - freshness: { child: 'freshness', type: 'String', hasChildren: false }, - queryCache: { child: 'queryCache', type: 'Boolean', hasChildren: false }, - matchPhase: { child: 'matchPhase', type: 'Parent', hasChildren: true }, + profile: { name: 'profile', type: 'String', hasChildren: false }, + properties: { name: 'properties', type: 'String', hasChildren: false }, + sorting: { name: 'sorting', type: 'String', hasChildren: false }, + freshness: { name: 'freshness', type: 'String', hasChildren: false }, + queryCache: { name: 'queryCache', type: 'Boolean', hasChildren: false }, + matchPhase: { name: 'matchPhase', type: 'Parent', hasChildren: true }, }, ranking_matchPhase: { - maxHits: { child: 'maxHits', type: 'Long', hasChildren: false }, - attribute: { child: 'attribute', type: 'String', hasChildren: false }, - ascending: { child: 'ascending', type: 'Boolean', hasChildren: false }, - diversity: { child: 'diversity', type: 'Parent', hasChildren: true }, + maxHits: { name: 'maxHits', type: 'Long', hasChildren: false }, + attribute: { name: 'attribute', type: 'String', hasChildren: false }, + ascending: { name: 'ascending', type: 'Boolean', hasChildren: false }, + diversity: { name: 'diversity', type: 'Parent', hasChildren: true }, }, ranking_matchPhase_diversity: { - attribute: { child: 'attribute', type: 'String', hasChildren: false }, - minGroups: { child: 'minGroups', type: 'Long', hasChildren: false }, + attribute: { name: 'attribute', type: 'String', hasChildren: false }, + minGroups: { name: 'minGroups', type: 'Long', hasChildren: false }, }, rules: { - off: { child: 'off', type: 'Boolean', hasChildren: false }, - rulebase: { child: 'rulebase', type: 'String', hasChildren: false }, + off: { name: 'off', type: 'Boolean', hasChildren: false }, + rulebase: { name: 'rulebase', type: 'String', hasChildren: false }, }, streaming: { - userid: { child: 'userid', type: 'Integer', hasChildren: false }, - groupname: { child: 'groupname', type: 'String', hasChildren: false }, - selection: { child: 'selection', type: 'String', hasChildren: false }, - priority: { child: 'priority', type: 'String', hasChildren: false }, + userid: { name: 'userid', type: 'Integer', hasChildren: false }, + groupname: { name: 'groupname', type: 'String', hasChildren: false }, + selection: { name: 'selection', type: 'String', hasChildren: false }, + priority: { name: 'priority', type: 'String', hasChildren: false }, maxbucketspervisitor: { - child: 'maxbucketspervisitor', + name: 'maxbucketspervisitor', type: 'Integer', hasChildren: false, }, }, trace: { - timestamps: { child: 'timestamps', type: 'Boolean', hasChildren: false }, + timestamps: { name: 'timestamps', type: 'Boolean', hasChildren: false }, }, tracelevel: { - rules: { child: 'rules', type: 'Integer', hasChildren: false }, + rules: { name: 'rules', type: 'Integer', hasChildren: false }, }, }; const firstChoice = levelZeroParameters[Object.keys(levelZeroParameters)[0]].name; - // inputs reflect the state of the individual QueryInputs + const [inputs, setInputs] = useState([ { - id: 1, + id: '1', type: firstChoice, input: '', hasChildren: false, diff --git a/client/js/app/src/app/pages/querybuilder/Components/Text/QueryDropDownForm.jsx b/client/js/app/src/app/pages/querybuilder/Components/Text/QueryDropDownForm.jsx index 30cafac08fc..79e7cf8cfc0 100644 --- a/client/js/app/src/app/pages/querybuilder/Components/Text/QueryDropDownForm.jsx +++ b/client/js/app/src/app/pages/querybuilder/Components/Text/QueryDropDownForm.jsx @@ -2,8 +2,8 @@ import { QueryInputContext } from '../Contexts/QueryInputContext'; import React, { useContext, useEffect } from 'react'; import SimpleDropDownForm from './SimpleDropDownForm'; -export default function QueryDropdownFormn({ choices, id }) { - const { inputs, setInputs, levelZeroParameters } = +export default function QueryDropdownForm({ choices, id, child = false }) { + const { inputs, setInputs, levelZeroParameters, childMap } = useContext(QueryInputContext); // Update the state of the QueryInput to reflect the chosen method @@ -11,20 +11,63 @@ export default function QueryDropdownFormn({ choices, id }) { e.preventDefault(); const newType = e.target.value; const newInputs = inputs.slice(); - const index = newInputs.findIndex((element) => element.id === id); - newInputs[index].type = newType; - let hasChildren = levelZeroParameters[newType].hasChildren; - newInputs[index].hasChildren = hasChildren; + if (child) { + //this is needed because substring() is exclusive the last parameter + let iterId = id + '.'; + let currentId = iterId.slice(0, 1); + let index = newInputs.findIndex((element) => element.id === currentId); // get the index of the root parent + let children = newInputs[index].children; + let parentTypes = newInputs[index].type; + let childChoices = childMap[parentTypes]; + for (let i = 3; i < iterId.length - 2; i += 2) { + console.log('GOT HERE'); + currentId = iterId.slice(0, i); + index = children.findIndex((element) => element.id === currentId); + let child = children[index]; + parentTypes = parentTypes + '_' + child.name; + childChoices = childMap[parentTypes]; + console.log(parentTypes); + console.log(childChoices); + children = child.children; + } + index = children.findIndex( + (element) => element.id === iterId.slice(0, iterId.length - 1) + ); + children[index].type = newType; + children[index].hasChildren = childChoices[newType].hasChildren; + } else { + const index = newInputs.findIndex((element) => element.id === id); + newInputs[index].type = newType; + let hasChildren = levelZeroParameters[newType].hasChildren; + newInputs[index].hasChildren = hasChildren; + } setInputs(newInputs); }; // On start set the type of the first QueryInput to the first in the list of choices useEffect(() => { const newInputs = inputs.slice(); - const index = newInputs.findIndex((element) => element.id === id); const key = Object.keys(choices)[0]; - newInputs[index].type = choices[key].name; - setInputs(inputs); + if (child) { + let iterId = id + '.'; + let currentId = iterId.slice(0, 1); + let index = newInputs.findIndex((element) => element.id === currentId); + let children = newInputs[index].children; + for (let i = 3; i < iterId.length - 2; i += 2) { + currentId = iterId.slice(0, i); + console.log(iterId); + index = children.findIndex((element) => element.id === currentId); + children = children[index].children; + } + index = children.findIndex( + (element) => element.id === iterId.slice(0, iterId.length - 1) + ); + children[index].type = choices[key].name; + } else { + const index = newInputs.findIndex((element) => element.id === id); + newInputs[index].type = choices[key].name; + } + setInputs(newInputs); }, []); return ( diff --git a/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInput.jsx b/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInput.jsx index 9dc9ccc2911..e24774cd1f7 100644 --- a/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInput.jsx +++ b/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInput.jsx @@ -1,10 +1,11 @@ import React, { useContext } from 'react'; import SimpleButton from '../Buttons/SimpleButton'; -import Info from './Info'; import SimpleForm from './SimpleForm'; import { OverlayTrigger, Tooltip } from 'react-bootstrap'; import { QueryInputContext } from '../Contexts/QueryInputContext'; -import QueryDropdownFormn from './QueryDropDownForm'; +import QueryDropdownForm from './QueryDropDownForm'; +import AddPropertyButton from '../Buttons/AddPropertyButton'; +import QueryInputChild from './QueryInputChild'; export default function QueryInput() { const { inputs, setInputs, levelZeroParameters, childMap } = @@ -37,22 +38,19 @@ export default function QueryInput() { const inputList = inputs.map((value) => { return ( <div key={value.id} id={value.id} className="queryinput"> - <QueryDropdownFormn - choices={levelZeroParameters} - id={value.id} - ></QueryDropdownFormn> - <Info id={value.id} height="15" width="15" /> + <QueryDropdownForm choices={levelZeroParameters} id={value.id} /> {value.hasChildren ? ( - <SimpleButton id={`propb${value.id}`} className={'addpropsbutton'}> - + Add property - </SimpleButton> + <> + <AddPropertyButton id={value.id} /> + <QueryInputChild id={value.id} /> + </> ) : ( <SimpleForm id={`v${value.id}`} size="30" onChange={updateInput} placeholder={setPlaceholder(value.id)} - ></SimpleForm> + /> )} <OverlayTrigger placement="right" 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..2128e6acb7f --- /dev/null +++ b/client/js/app/src/app/pages/querybuilder/Components/Text/QueryInputChild.jsx @@ -0,0 +1,81 @@ +import React, { useContext, useEffect } from 'react'; +import AddPropertyButton from '../Buttons/AddPropertyButton'; +import { QueryInputContext } from '../Contexts/QueryInputContext'; +import QueryDropdownForm from './QueryDropDownForm'; +import SimpleForm from './SimpleForm'; + +export default function QueryInputChild({ id }) { + const { inputs, setInputs, childMap } = useContext(QueryInputContext); + + let childArray; + let parentType; + let index; + index = inputs.findIndex((element) => element.id === id); + parentType = inputs[index].type; + childArray = inputs[index].children; + + // const updateType = (e) => { + // e.preventDefault(); + // const newType = e.target.value; + // const newInputs =inputs.slice(); + // const children = newInputs[parentType].children; + // } + + // const updateInput = (e) => { + // e.preventDefault(); + // const fid = parseInt(e.target.id.replace("v", "")); + // const index = childArray.findIndex((element) => element.id === fid) + // childArray[index].input = e.target.value; + // const newInputs = inputs.slice(); + // setInputs(newInputs); + // } + + const inputList = childArray.map((child) => { + return ( + <div key={child.id} id={child.id}> + <QueryDropdownForm + choices={childMap[parentType]} + id={child.id} + child={true} + /> + {child.hasChildren ? ( + <> + <AddPropertyButton id={child.id} /> + </> + ) : ( + <SimpleForm id={`v${child.id}`} size="30" /> + )} + <Child id={child.id} type={parentType} child={child} /> + </div> + ); + }); + + return <>{inputList}</>; +} + +function Child({ child, id, type }) { + const { inputs, setInputs, childMap } = useContext(QueryInputContext); + console.log(child); + + const nestedChildren = (child.children || []).map((child) => { + return ( + <> + <QueryDropdownForm + choices={childMap[type]} + id={child.id} + child={true} + /> + {child.hasChildren ? ( + <> + <AddPropertyButton id={child.id} /> + </> + ) : ( + <SimpleForm id={`v${child.id}`} size="30" /> + )} + <Child key={child.id} child={child} id={child.id} type={child.type} /> + </> + ); + }); + + return <div>{nestedChildren}</div>; +} diff --git a/client/js/app/src/app/pages/querybuilder/Components/Text/SimpleDropDownForm.jsx b/client/js/app/src/app/pages/querybuilder/Components/Text/SimpleDropDownForm.jsx index 8fb283c54dd..3bb781ddb7a 100644 --- a/client/js/app/src/app/pages/querybuilder/Components/Text/SimpleDropDownForm.jsx +++ b/client/js/app/src/app/pages/querybuilder/Components/Text/SimpleDropDownForm.jsx @@ -11,6 +11,7 @@ export default function SimpleDropDownForm({ SimpleDropDownForm.defaultProps = { onChange: handleChange, }; + const { choice, setChoice } = useState(choices[0]); const options = Object.keys(choices).map((choice) => { |