diff --git a/src/create/createQuestion.tsx b/src/create/createQuestion.tsx index 110cb75d..bf3d3b62 100644 --- a/src/create/createQuestion.tsx +++ b/src/create/createQuestion.tsx @@ -16,7 +16,6 @@ interface Values { description: string; } - const types = [ {desc:"текст", value:"text"}, {desc:"селект", value:"select"}, @@ -40,6 +39,10 @@ export const TextField = (props: any) => { ); }; +//Для первого ознакомления рекомендую свернуть все функции и почитать их названия и описания + +//Заранее берётся поле children нужного родителя. Функция сама отделит все id от родительской части +//Вернёт число для текущего слоя вложенности (в случае чего надо будет ручками присоединить к строке родителя) const getFreeNumber = (array:Array):number => { // Для первого элемента в списке if (array.length === 0) { @@ -51,7 +54,13 @@ const getFreeNumber = (array:Array):number => { let indexes:any = [] //И берём только последние числа от строк, превращая их в числа for (let i = 0; i < array.length; i++) { - indexes.push(Number(array[i].id.slice(-1))) + //Строка состоит из чисел, разделённых пробелом. + + //Делим строку на массив чисел + let stringArr = array[i].id.split(" ") + //Берём последний элемент массива + stringArr = stringArr.slice(-1) + indexes.push(Number(stringArr[0])) } //Сортируем в порядке возрастания indexes.sort(function compare(a:any, b:any):any { @@ -83,6 +92,8 @@ const getFreeNumber = (array:Array):number => { } } } + +//Прохождение по полю children в поисках нужного id const getIndexById = (id:string, array:Array):number => { let index for (let i = 0; i <= array.length; i++) { @@ -101,54 +112,91 @@ const getIndexById = (id:string, array:Array):number => { } } + +//Извлечение информации из id для поиска пути к ребёнку. const getObjectFromId = (id:string, array:any):any => { - let indexes = id.split("") - //буфер содержит id всех родителей (от ребёнка до первого родителя) - let bufer = [] - for (let i = 0; i < indexes.length; i++) { - let val = (id.length - i) - bufer.push(id.substring(0, val)) - } - let parentObj = array - for (let i = 0; i < indexes.length - 1; i++) { - let id = bufer[bufer.length - i - 1] - parentObj = parentObj[getIndexById(id, parentObj)].children - } - if (parentObj.length > 1) { - parentObj = parentObj[Number(id.slice(-1))] - } - if (Array.isArray(parentObj)) { - return parentObj[0] - } else { - return parentObj + //Делим строку на массив чисел + let IDs = id.split(" ") + + // o o o o o <-- + // \ / \ / | Проходимся по каждому слою. Значит номер итерации укажет на количество элементов, + // o o o <-- кторые нужно добавить к строке currentIteration для получения id родителя на этом уровне вложенности. + // \ / / (наверное, проще её создавать с нуля, зная сколько нужно будет элементов) + // o <-- + + const getNewIdString = (index:number) => { + let id = "" + for (let i = 0; i < index ;i++) { + id = id + " " + IDs[i] + } + return id.slice(1) //убираем пробел в начале } + //Счётчик вложенности + let nestingCounter = 0 + //В пересчётах в каждом слое вложенности сюда сохраняется найденный объект + let bufferObject + + //Считаем до какого уровня вложенности нам вообще искать ребёнка + let stopIndex = IDs.length + + const searchId = (array:any) => { + if (nestingCounter === stopIndex) { + //Мы достигли нужного уровня вложенности + return + } else { + nestingCounter = nestingCounter + 1 + //Создаём строку id текущей вложенности, танцуя от знания порядкового номера этой вложенности + let calcId = getNewIdString(nestingCounter) + return ( + //Здесь можно в заранее созданную переменную оповещать нашли ли мы нужный id. И обработать ошибку если нет + array.forEach((element:any) => { + if (element.id === calcId) { + //Записываем найденный объект и ищем на следующем уровне + bufferObject = element + searchId(element.children) + } + + }) + ) + } + + } + searchId(array) + return bufferObject + + //Есть два варианта поиска: + //Рекурсивно пройтись по хранилищу тупо ожидая наткнуться на нужного ребёнка + //Проходиться по каждому слою вложенности, создавая id текущего слоя. Находить объект и повторять + //Навскидку второй вариант для ветвистых деревьев быстрее и позволит показать на каком уровне вложенности потанцевально может оборваться поиск... + //при (не дай боже) неверной записи фокусного id } export default () => { - - // const [stockroom, setStockroom] = React.useState>([ + //Id - строится на основании всех id родителя + свободное число от 0 до +бесконечности. + //Разделение айдишников в строке посредством пробела const [stockroom, setStockroom] = React.useState([ {id: "0", type: 7, children: [ { - id: "00", type: 7, children: [ - {id: "000", children: [], type: 4} + id: "0 0", type: 7, children: [ + // {id: "0 0 0", children: [], type: 4} ] }, { - id: "01", type: 7, children: [ + id: "0 1", type: 7, children: [ { - id: "010", children: [ - {id: "0100", children: [], type: 4}, - {id: "0101", children: [], type: 4} + id: "0 1 0", children: [ + {id: "0 1 0 0", children: [], type: 4}, + {id: "0 1 0 1", children: [], type: 4} ], type: 7 } ] }, - {id: "02", type: 4, children: []} + {id: "0 2", type: 4, children: []} ]} ]) - const [focus, setFocus] = React.useState("101") //Хранит путь объекта + const [focus, setFocus] = React.useState() //Хранит путь объекта (id) + // const [focus, setFocus] = React.useState("1 0 1") //Хранит путь объекта const setNewFocus = (value:string, multiFocus:boolean) => { //Фокусы ставятся или удаляются от клика по уже созданным элементам. @@ -160,103 +208,159 @@ export default () => { setFocus(value) } } - // Изменение типа очищает все поля - const createNewTree = (value:any, tree = stockroom) => { - return ( - tree.map((node: any) => { - if (node.id === focus) { - let obj = { - ...node, - ...value, + //Функция пересоздаёт дерево с проверкой каждого объекта. + // Если объект в фокусе - создаётся новый объект и в него высыпаются старые поля, затем новые поля + const createNewTreeFields = (value:any, tree = stockroom) => { + return ( + tree.map((node: any) => { + + if (node.id === focus) { + let obj = { + ...node, + ...value, + } + return (obj) + } else if (node.children.length !== 0) { + return { + ...node, + children: createNewTreeFields(value, node.children) + } + } else { + return node } - return (obj) - } else if (node.children.length !== 0) { - return { - ...node, - children: createNewTree(value, node.children) + }) + ) + } + //Создание дерева с обновлённым объектом + const createNewTreeObject = (value:any, tree = stockroom) => { + return ( + tree.map((node: any) => { + if (node.id === value.id) { + return value + } else if (node.children.length !== 0) { + return { + ...node, + children: createNewTreeObject(value, node.children) + } + } else { + return node } - } else { - return node - } - }) - )} + }) + ) + } + + // Изменение типа очищает все поля const typeHC = (type:any): void => { if (focus !== undefined) { - setStockroom(createNewTree({type:type})) + setStockroom(createNewTreeFields({type:type})) } } const colorHC = (color:any) => { if (focus !== undefined) { - setStockroom(createNewTree({color:color})) + setStockroom(createNewTreeFields({color:color})) } } const createObject = (obj:any, type:number = 4) => { if (focus !== undefined) { - //Созданный объект добавляется после объекта с фокусом //Если фокусный элемент - контейнер, добавление происходит внутрь него - // + //Если фокусный элемент - не контейнер, добавление происходит после объекта с фокусом const focusedObj = getObjectFromId(focus, stockroom) - const creacteChildrens = (arr = stockroom) => { - return arr.map((node: any) => { - if (node.children.length !== 0) { - //Объект с детьми должен быть добавлен + должен произойти вызов для поля children - return ( - { ...node, children: creacteChildrens(node.children) } - ) - } else { - //Объект без детей просто добавляется - return node - } - }) - } - //Находим родителя - const parentObj = getObjectFromId(focus.slice(0,-1), stockroom) - //Находим свободный ид - let newId:any = getFreeNumber(parentObj.children) - newId = focus.slice(0,-1) + newId - //Создаём новый объект - const newObj = { - id: newId, - type: type, - children: [] - } if (focusedObj.type === 7) { //Кладём внутрь фокусного объекта - console.log(focusedObj) + //Находим свободный ид и прикрепляем его к родительскому id + let newId:any = getFreeNumber(focusedObj.children) + newId = focusedObj.id + " " + newId + //Создаём новый объект + const newObj = { + id: newId, + type: type, + children: [] + } - focusedObj.children = [...focusedObj.children, newObj] + focusedObj.children.push(newObj) - console.log(focusedObj) - setStockroom(createNewTree(focusedObj)) + //Создаём дерево с обновлённым родителем + const newTree = createNewTreeObject(focusedObj) + setStockroom(newTree) } else { //Кладём рядом с фокусным объектом - //Создаём новый массив для поля children родителя и присваиваем его - let newCildrenArr = [] + //Находим родителя + //Отфигачиваем последний id + let parentId:any = focus.split(" ") + parentId.pop() + parentId = parentId.join(' ') + const parentObj = getObjectFromId(parentId, stockroom) + + //Находим свободный ид и прикрепляем его к родительскому id + let newId:any = getFreeNumber(parentObj.children) + newId = parentId + " " + newId + //Создаём новый объект + const newObj = { + id: newId, + type: type, + children: [] + } + + //Создаём новый массив для поля-children-родителя и присваиваем этот массив + let newChildrenArr = [] for (let i = 0; parentObj.children.length > i ; i++) { let node = parentObj.children[i] if (node.id === focus) { - newCildrenArr.push(node) - newCildrenArr.push(newObj) + newChildrenArr.push(node) + newChildrenArr.push(newObj) } else { - newCildrenArr.push(node) + newChildrenArr.push(node) } } - parentObj.children = newCildrenArr + parentObj.children = newChildrenArr //Создаём дерево с обновлённым родителем - const newTree = creacteChildrens() + const newTree = createNewTreeObject(parentObj) setStockroom(newTree) } } } + + const deleteObject = () => { + if (focus !== undefined) { + //Если просто запретить вкладывать объект при создании дерева - будет массив со значением undefined + //Поэтому скажем родителю, что его массив опустел + + const focusedObj = getObjectFromId(focus, stockroom) + + //Отфигачиваем последний id + let parentId:any = focus.split(" ") + parentId.pop() + parentId = parentId.join(' ') + + const parentObj = getObjectFromId(parentId, stockroom) + + //Создаём новый массив для поля-children-родителя, не включая в него фокусный объект + let newChildrenArr = [] + for (let i = 0; parentObj.children.length > i ; i++) { + let node = parentObj.children[i] + if (node.id !== focus) { + newChildrenArr.push(node) + } + } + parentObj.children = newChildrenArr + + + let newTree = createNewTreeObject(parentObj) + console.log(stockroom) + console.log(newTree) + setStockroom(newTree) + } + } + // const changeFocus = (id: number): void => { // //Не менять фокус если снова выбрано то же окно // if (focus !== id) { @@ -407,7 +511,7 @@ export default () => { changeText={stockroom} getIndexById={getIndexById} createObject={createObject} - deleteObject={stockroom} + deleteObject={deleteObject} /> + {/* {*/} {/* props.createObject({text: "контейнер", isFocus: true, type: 7, id: -1, parent: undefined})*/} diff --git a/src/create/workSpace.tsx b/src/create/workSpace.tsx index faf16e6e..04dc47ac 100644 --- a/src/create/workSpace.tsx +++ b/src/create/workSpace.tsx @@ -21,22 +21,23 @@ export default ({stockroom, setNewFocus, focus} : any) => { return( e.map((element:any, i:number) => { - if (element.children === undefined || element.children.length === 0) { + // if (element.children.length === 0) { + if (element.type === 7) { return( - - ) - } else { - return( -
{ - shiftKeyInfo(event, element.id) - }} +
{ + shiftKeyInfo(event, element.id) + }} > {isContains(element.children)}
) + } else { + return( + + ) } }) )