2022-07-04 12:59:17 +00:00
|
|
|
|
import React from 'react';
|
|
|
|
|
|
import { useField, Form, FormikProps, Formik } from 'formik';
|
|
|
|
|
|
import {
|
2022-07-13 13:57:32 +00:00
|
|
|
|
Select, Textarea, VStack, Checkbox, Button,
|
2022-07-04 12:59:17 +00:00
|
|
|
|
} from '@chakra-ui/react'
|
|
|
|
|
|
import 'suneditor/dist/css/suneditor.min.css'; // Import Sun Editor's CSS File
|
|
|
|
|
|
import Description from "./description";
|
|
|
|
|
|
import Settings from "./settings";
|
|
|
|
|
|
|
2022-07-13 13:57:32 +00:00
|
|
|
|
//Значения, собираемые для отправки на бэк
|
2022-07-04 12:59:17 +00:00
|
|
|
|
interface Values {
|
|
|
|
|
|
title: string;
|
2022-07-13 13:57:32 +00:00
|
|
|
|
type: string;
|
|
|
|
|
|
children: string;
|
|
|
|
|
|
description: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
//Поля объектов, используемых для отображения созданных пользователем инструментов
|
|
|
|
|
|
interface ElementsOfObject {
|
2022-07-04 12:59:17 +00:00
|
|
|
|
text: string;
|
2022-07-13 13:57:32 +00:00
|
|
|
|
id: number;
|
|
|
|
|
|
isFocus: boolean;
|
|
|
|
|
|
color?: string;
|
2022-07-04 12:59:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const types = [
|
|
|
|
|
|
{desc:"текст", value:"text"},
|
|
|
|
|
|
{desc:"селект", value:"select"},
|
|
|
|
|
|
{desc:"чекбокс", value:"checkbox"},
|
|
|
|
|
|
{desc:"файл", value:"file"},
|
|
|
|
|
|
{desc:"кнопка", value:"button"},
|
|
|
|
|
|
{desc:"ничего", value:"none"}
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
const TextField = (props: any) => {
|
|
|
|
|
|
|
|
|
|
|
|
const [field, meta, helpers] = useField(props);
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<>
|
|
|
|
|
|
<Textarea resize="none" width="80%" {...field} {...props} />
|
|
|
|
|
|
{meta.touched && meta.error ? (
|
|
|
|
|
|
<div className="error">{meta.error}</div>
|
|
|
|
|
|
) : null}
|
|
|
|
|
|
</>
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2022-07-13 13:57:32 +00:00
|
|
|
|
const getFreeNumber = (array:Array<ElementsOfObject>):number => {
|
|
|
|
|
|
// Для первого элемента в списке
|
|
|
|
|
|
if (array.length === 0) {
|
|
|
|
|
|
return(0)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
//Для всех последующих элементов
|
2022-07-04 12:59:17 +00:00
|
|
|
|
|
2022-07-13 13:57:32 +00:00
|
|
|
|
//Создаём массив, состоящий из id всех существующих модалок
|
|
|
|
|
|
let indexes:any = []
|
|
|
|
|
|
for (let i = 0; i < array.length; i++) {
|
|
|
|
|
|
indexes.push(array[i].id)
|
|
|
|
|
|
}
|
|
|
|
|
|
//Сортируем в порядке возрастания
|
|
|
|
|
|
indexes.sort(function compare(a:any, b:any):any {
|
|
|
|
|
|
if (a < b) { return -1;}
|
|
|
|
|
|
if (a > b) { return 1;}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
)
|
|
|
|
|
|
let max = indexes[indexes.length - 1]
|
|
|
|
|
|
|
|
|
|
|
|
//Создаём массив - маску от 0 до самого высокого значения id
|
|
|
|
|
|
let mask:any = []
|
|
|
|
|
|
for (let i = 0; i <= max; i++) {
|
|
|
|
|
|
mask.push(i)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Ищем разницу между существующими id окон и маской. Список пропущенных значений есть список доступных имён.
|
|
|
|
|
|
let difference = indexes
|
|
|
|
|
|
.filter((num:any):any => !mask.includes(num))
|
|
|
|
|
|
.concat(mask.filter((num:any):any => !indexes.includes(num)));
|
2022-07-04 12:59:17 +00:00
|
|
|
|
|
2022-07-13 13:57:32 +00:00
|
|
|
|
// difference - массив нехватающих в списке номеров.
|
|
|
|
|
|
// Если все окна у нас по порядку, без пропусков - нужно добавить новый номер
|
|
|
|
|
|
if (difference.length === 0) {
|
|
|
|
|
|
return(max + 1)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
//Иначе добавить нехватающий
|
|
|
|
|
|
return(difference[0])
|
|
|
|
|
|
}
|
2022-07-04 12:59:17 +00:00
|
|
|
|
}
|
2022-07-13 13:57:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
const getIndexById = (id:number, array:Array<ElementsOfObject>):number => {
|
|
|
|
|
|
let index
|
|
|
|
|
|
for (let i = 0; i <= array.length; i++) {
|
|
|
|
|
|
if (array[i] !== undefined) {
|
|
|
|
|
|
if (array[i].id === id) {
|
|
|
|
|
|
index = i
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (typeof index === "number") {
|
|
|
|
|
|
return index
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log("Я не нашёл нужный индекс, вывел 0")
|
|
|
|
|
|
return 0
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default () => {
|
|
|
|
|
|
|
2022-07-14 13:53:21 +00:00
|
|
|
|
|
2022-07-13 13:57:32 +00:00
|
|
|
|
const [type, setType] = React.useState<number>(4)
|
|
|
|
|
|
const [stockroom, setStockroom] = React.useState<Array<ElementsOfObject>>([])
|
|
|
|
|
|
const [focus, setFocus] = React.useState<number | undefined>() //Хранит id объекта
|
|
|
|
|
|
|
|
|
|
|
|
//При пересоздании массива для изменения фокуса объекта отменяются фокусы у всех элементов массива
|
|
|
|
|
|
|
|
|
|
|
|
const typeHC = (value:number): void => {
|
2022-07-04 12:59:17 +00:00
|
|
|
|
setType(value)
|
|
|
|
|
|
setStockroom([])
|
|
|
|
|
|
}
|
2022-07-13 13:57:32 +00:00
|
|
|
|
const changeFocus = (id: number): void => {
|
|
|
|
|
|
//Не менять фокус если снова выбрано то же окно
|
|
|
|
|
|
if (focus !== id) {
|
|
|
|
|
|
//Хранилище с отменённым фокусом у объектов (по задумке у одного элемента)
|
|
|
|
|
|
let newArr = stockroom.map((e:ElementsOfObject) => {
|
|
|
|
|
|
e.isFocus = false
|
|
|
|
|
|
return e
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
//Получаем индексы фокусированных объектов. Новый и, если есть, старый
|
|
|
|
|
|
let index = getIndexById(id, stockroom)
|
2022-07-04 12:59:17 +00:00
|
|
|
|
|
2022-07-13 13:57:32 +00:00
|
|
|
|
//Устанавливаем новый фокус и пересоздаём массив
|
|
|
|
|
|
setFocus(id)
|
|
|
|
|
|
|
|
|
|
|
|
newArr[index].isFocus = true
|
|
|
|
|
|
setStockroom([...newArr])
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
const changeBgColor = (color: string): void => {
|
|
|
|
|
|
if (focus !== undefined) {
|
|
|
|
|
|
let index = getIndexById(focus, stockroom)
|
|
|
|
|
|
|
|
|
|
|
|
let list = stockroom
|
|
|
|
|
|
list[index].color = color
|
|
|
|
|
|
setStockroom([...list])
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
const changeText = (text: string): void => {
|
|
|
|
|
|
if (focus !== undefined) {
|
|
|
|
|
|
let index = getIndexById(focus, stockroom)
|
|
|
|
|
|
let list = stockroom
|
|
|
|
|
|
list[index].text = text
|
|
|
|
|
|
setStockroom([...list])
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const createObject = (obj:ElementsOfObject) => {
|
|
|
|
|
|
|
|
|
|
|
|
//Получаем и присваиваем первый свободный айдишник (по возрастанию)
|
|
|
|
|
|
const free = getFreeNumber(stockroom)
|
|
|
|
|
|
obj.id = free
|
|
|
|
|
|
|
|
|
|
|
|
//Хранилище с отменённым фокусом у объектов (по задумке у одного элемента)
|
|
|
|
|
|
let newArr = stockroom.map((e:ElementsOfObject) => {
|
|
|
|
|
|
e.isFocus = false
|
|
|
|
|
|
return e
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
//Мы должны вставить новый объект следующим после того, на котором фокус. Это достигается позиционированием в массив
|
|
|
|
|
|
if (focus === undefined){ //фокуса нет - добавляем в конец массива
|
|
|
|
|
|
newArr.push(obj)
|
|
|
|
|
|
setStockroom([...newArr])
|
2022-07-14 13:53:21 +00:00
|
|
|
|
//Говорим стейту с фокусом, что фокус изменился
|
|
|
|
|
|
setFocus(newArr.length - 1)
|
2022-07-13 13:57:32 +00:00
|
|
|
|
} else { //фокус есть - добавляем после объекта с фокусом
|
|
|
|
|
|
let index = getIndexById(focus, stockroom)
|
2022-07-14 13:53:21 +00:00
|
|
|
|
newArr.splice(index + 1, 0, obj)
|
2022-07-13 13:57:32 +00:00
|
|
|
|
|
|
|
|
|
|
//Говорим стейту с фокусом, что фокус изменился
|
2022-07-14 13:53:21 +00:00
|
|
|
|
setFocus(index + 1)
|
|
|
|
|
|
setStockroom([...newArr])
|
2022-07-13 13:57:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
const deleteObject = (id: number): void => {
|
|
|
|
|
|
let index = getIndexById(id, stockroom)
|
|
|
|
|
|
//Проверка, что объект с таким id существует
|
|
|
|
|
|
if (stockroom[index] !== undefined) {
|
2022-07-14 13:53:21 +00:00
|
|
|
|
//Если удалён был фокусный объект - фокус теперь неизвестен
|
|
|
|
|
|
if (stockroom[index].isFocus) {
|
|
|
|
|
|
setFocus(undefined)
|
|
|
|
|
|
}
|
|
|
|
|
|
let newArr = stockroom
|
2022-07-13 13:57:32 +00:00
|
|
|
|
newArr.splice(index, 1)
|
|
|
|
|
|
setStockroom([...newArr])
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-07-04 12:59:17 +00:00
|
|
|
|
|
|
|
|
|
|
return(
|
|
|
|
|
|
<>
|
|
|
|
|
|
<Formik
|
|
|
|
|
|
initialValues={{
|
2022-07-13 13:57:32 +00:00
|
|
|
|
children: '',
|
2022-07-04 12:59:17 +00:00
|
|
|
|
title: '',
|
2022-07-13 13:57:32 +00:00
|
|
|
|
type: '',
|
|
|
|
|
|
description:'описание',
|
2022-07-04 12:59:17 +00:00
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
|
|
onSubmit={(values, actions) => {
|
|
|
|
|
|
console.log(JSON.stringify(values))
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{(props: FormikProps<Values>) => (
|
|
|
|
|
|
|
|
|
|
|
|
<Form>
|
|
|
|
|
|
<VStack>
|
|
|
|
|
|
<TextField placeholder="Заголовок" name="title" type="text" />
|
2022-07-13 13:57:32 +00:00
|
|
|
|
<Description name="description"/>
|
2022-07-04 12:59:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
type === 0 ? //Тип вопроса - текст?
|
|
|
|
|
|
<TextField name="text" placeholder="текст" type="text" />
|
|
|
|
|
|
:
|
2022-07-13 13:57:32 +00:00
|
|
|
|
type === 3 ? //Тип вопроса - файл?
|
|
|
|
|
|
<input type="file"/>
|
|
|
|
|
|
:
|
2022-07-04 12:59:17 +00:00
|
|
|
|
stockroom.length === 0 ? //В поле для юзерских данных есть что-то?
|
|
|
|
|
|
null //Ничего не внесено
|
|
|
|
|
|
:
|
|
|
|
|
|
type === 1 ? //Тип вопроса - селект?
|
2022-07-13 13:57:32 +00:00
|
|
|
|
<Select
|
|
|
|
|
|
>
|
2022-07-04 12:59:17 +00:00
|
|
|
|
{
|
|
|
|
|
|
stockroom.map((e: any, i: number) => {
|
|
|
|
|
|
return <option key={i}>{e.text}</option>
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
</Select>
|
|
|
|
|
|
:
|
|
|
|
|
|
type === 2 ? //Тип вопроса - чекбокс?
|
|
|
|
|
|
stockroom.map((e:any, i:number) => {
|
|
|
|
|
|
return <Checkbox key={i}>{e.text}</Checkbox>
|
|
|
|
|
|
})
|
|
|
|
|
|
:
|
|
|
|
|
|
type === 4 ? //Тип вопроса - кнопка?
|
|
|
|
|
|
stockroom.map((e:any, i:number) => {
|
2022-07-13 13:57:32 +00:00
|
|
|
|
return <Button
|
|
|
|
|
|
backgroundColor={e.color}
|
|
|
|
|
|
key={i}
|
|
|
|
|
|
onClick={(event: any) => {
|
|
|
|
|
|
changeFocus(e.id)
|
|
|
|
|
|
event.target.blur()
|
|
|
|
|
|
}}
|
|
|
|
|
|
>{e.text}</Button>
|
2022-07-04 12:59:17 +00:00
|
|
|
|
})
|
|
|
|
|
|
:
|
|
|
|
|
|
null //Тип вопроса - ничего
|
|
|
|
|
|
}
|
|
|
|
|
|
</VStack>
|
|
|
|
|
|
|
|
|
|
|
|
<Settings
|
|
|
|
|
|
types={types}
|
|
|
|
|
|
stockroom={stockroom}
|
|
|
|
|
|
typeHC={typeHC}
|
|
|
|
|
|
type={type}
|
2022-07-13 13:57:32 +00:00
|
|
|
|
focus={focus}
|
|
|
|
|
|
changeFocus={changeFocus}
|
|
|
|
|
|
changeBgColor={changeBgColor}
|
|
|
|
|
|
changeText={changeText}
|
|
|
|
|
|
getIndexById={getIndexById}
|
|
|
|
|
|
createObject={createObject}
|
|
|
|
|
|
deleteObject={deleteObject}
|
2022-07-04 12:59:17 +00:00
|
|
|
|
/>
|
|
|
|
|
|
</Form>
|
|
|
|
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
</Formik>
|
|
|
|
|
|
</>
|
|
|
|
|
|
)
|
2022-07-13 13:57:32 +00:00
|
|
|
|
}
|