410 lines
17 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Парус 8 - Панели мониторинга - Редактор настройки регламентированного отчёта
Пользовательские хуки
*/
//---------------------
//Подключение библиотек
//---------------------
import { useState, useContext, useEffect, useCallback, useLayoutEffect } from "react"; //Классы React
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { NavigationCtx } from "../../context/navigation"; //Контекст навигации
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { STATUSES } from "./IUD/iud_form_dialog"; //Статусы диалогов
import { TEXTS } from "../../../app.text"; //Тексты для ошибок
//-----------
//Тело модуля
//-----------
//Хук для отработки изменений ширины и высоты рабочей области окна
const useWindowResize = () => {
//Состояние размера рабочей области
const [size, setSize] = useState([0, 0]);
//При изменении размера
useLayoutEffect(() => {
const updateSize = () => {
setSize([document.documentElement.clientWidth, document.documentElement.clientHeight]);
};
window.addEventListener("resize", updateSize);
updateSize();
return () => window.removeEventListener("resize", updateSize);
}, []);
//Вернём размеры
return size;
};
//Хук для настройки регламентированного отчета
const useConf = (currentTab, handleSectionChange, order) => {
//Собственное состояние - таблица данных
const dataGrid = {
rn: 0,
code: "",
name: "",
dataLoaded: false,
columnsDef: [],
groups: [],
rows: [],
fixedHeader: false,
fixedColumns: 0,
reload: false
};
//Собственное состояние
const [rrpConf, setRrpConf] = useState({
docLoaded: false,
sections: [],
orderChanged: false,
reload: true
});
//Состояние массива данных разделов
const [dataGrids] = useState([]);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
//Подключение к контексту навигации
const { getNavigationSearch } = useContext(NavigationCtx);
//При необходимости обновить
const handleReload = useCallback(async () => {
setRrpConf(pv => ({ ...pv, reload: true }));
}, []);
//Загрузка данных разделов регламентированного отчёта
const loadData = useCallback(
async () => {
if (rrpConf.reload) {
//Переменная номера раздела с фокусом
let tabFocus = currentTab ? currentTab : 0;
const data = await executeStored({
stored: "PKG_P8PANELS_RRPCONFED.RRPCONF_GET_SECTIONS",
args: {
NRN_RRPCONF: Number(getNavigationSearch().NRN),
NROW_ORDER: Number(order.rowOrder),
NCOL_ORDER: Number(order.columnOrder)
},
respArg: "COUT"
});
//Флаг первой загрузки данных
let firstLoad = dataGrids.length == 0 ? true : false;
//Копирование массива уже загруженных разделов
let cloneDGs = dataGrids.slice();
//Массив из нескольких разделов и из одного
const sections = data.SECTIONS ? (data.SECTIONS.length ? data.SECTIONS : [data.SECTIONS]) : [];
//Заполнение очередного раздела по шаблону
sections
.sort((a, b) => a.SCODE - b.SCODE)
.map(s => {
let dg = {};
Object.assign(dg, dataGrid, {
...s.XDATA.XDATA_GRID,
rn: s.NRN,
code: s.SCODE,
name: s.SNAME,
delete_allow: s.NDELETE_ALLOW,
dataLoaded: true,
columnsDef: [...(s.XDATA.XDATA_GRID.columnsDef || [])],
groups: [...(s.XDATA.XDATA_GRID.groups || [])],
rows: [...(s.XDATA.XDATA_GRID.rows || [])],
reload: false
});
//Если раздел имеет составы показателей
if (s.MARK_CNS.MARK_CN) {
//Обходим строки раздела
dg.rows.map(row => {
//Цикл по ключам строки
for (let key in row) {
//Если это ключ для группы составов показателей
if (key.match(/MARK_CNS_.*/)) {
//Считываем рег. номер показателя
let markRn = key.substring(9);
//Переносим из раздела
row[key] = Array.isArray(s.MARK_CNS.MARK_CN)
? [...s.MARK_CNS.MARK_CN].filter(el => el.NPRN === row[`NMARK_RN_${markRn}`])
: s.MARK_CNS.MARK_CN.NPRN === row[`NMARK_RN_${markRn}`]
? [s.MARK_CNS.MARK_CN]
: null;
}
}
});
}
//Ищем загружен ли уже раздел с таким же ид.
const dgItem = dataGrids.find(x => x.rn === dg.rn);
//Его индекс, если нет соответствия, то -1
let index = dataGrids.indexOf(dgItem);
//Если было соответствие
if (dgItem) {
//Если в нём не найдено изменений
if (JSON.stringify(dgItem, null, 4) === JSON.stringify(dg, null, 4)) {
//То из копированного массива его удаляем
cloneDGs.splice(cloneDGs.indexOf(cloneDGs.find(x => x.rn === dgItem.rn)), 1);
} else {
//Иначе обновляем раздел в массиве
dataGrids[index] = dg;
//Удаляем из копированного массива
cloneDGs.splice(cloneDGs.indexOf(cloneDGs.find(x => x.rn === dg.rn)), 1);
//Устанавливаем фокус на обновлённый раздел, если был добавлен
tabFocus = rrpConf.orderChanged ? 0 : index;
}
} else {
//Если раздел новый, то добавляем его в массив данных
dataGrids.push(dg);
//И устанавливаем на него фокус, если флаг первой загрузки = false
tabFocus = !firstLoad ? dataGrids.length - 1 : 0;
}
});
//Обходим разделы, что остались в копированном массиве (на удаление)
cloneDGs.map(s => {
let curIndex = dataGrids.indexOf(dataGrids.find(x => x.rn === s.rn));
//Устаревший раздел удаляем из массива данных
dataGrids.splice(curIndex, 1);
//Фокус на предшествующий раздел
if (curIndex > 0) tabFocus = curIndex - 1;
//Иначе фокус на следующий, если был удалён первый раздел
else tabFocus = curIndex;
});
setRrpConf(pv => ({
...pv,
docLoaded: true,
orderChanged: false,
reload: false,
sections: dataGrids
}));
handleSectionChange(tabFocus);
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[rrpConf.reload, rrpConf.docLoaded, dataGrid.reload, dataGrid.docLoaded, executeStored]
);
//При изменении сортировок
useEffect(() => {
setRrpConf(pv => ({ ...pv, orderChanged: true, reload: true }));
}, [order]);
//При необходимости обновить данные таблицы
useEffect(() => {
loadData();
}, [rrpConf.reload, dataGrid.reload, loadData]);
return [rrpConf, handleReload];
};
//Хук для вкладки
const useTab = () => {
//Состояние раздела
const [tabValue, setTabValue] = useState("");
//Переключение раздела
const handleSectionChange = useCallback(newValue => {
setTabValue(newValue);
}, []);
return [tabValue, handleSectionChange];
};
//Хук для функций открытия записей
const useRecOpen = handleReload => {
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
//Подключение к контексту сообщений
const { showMsgErr } = useContext(MessagingСtx);
//Отображение показателя раздела
const handleMarkOpen = useCallback(
async nRrpConfSctnMrk => {
const data = await executeStored({
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTNMRK_GET_CODES",
args: {
NRN: nRrpConfSctnMrk
},
tagValueProcessor: () => undefined
});
if (data) {
pOnlineShowDictionary({
unitCode: "RRPConfig",
showMethod: "main_mrk_settings",
inputParameters: [
{ name: "in_CODE", value: data.SRRPCONF },
{ name: "in_SCTN_CODE", value: data.SRRPCONFSCTN },
{ name: "in_MRK_CODE", value: data.SRRPCONFSCTNMRK }
],
callBack: res => {
res.success ? handleReload() : null;
}
});
} else showMsgErr(TEXTS.NO_DATA_FOUND);
},
[executeStored, handleReload, pOnlineShowDictionary, showMsgErr]
);
//Отображение показателя раздела
const handleMarkCnOpen = useCallback(
async (nRrpConfSctnMrk, nRrpConfSctnMrkCn) => {
pOnlineShowDictionary({
unitCode: "RRPConfigSectionMark",
showMethod: "link_cn",
inputParameters: [
{ name: "in_RN", value: nRrpConfSctnMrk },
{ name: "in_RRPCONFSCTNMRKCN", value: nRrpConfSctnMrkCn }
],
callBack: res => {
res.success ? handleReload() : null;
}
});
},
[handleReload, pOnlineShowDictionary]
);
//Отображение показателя раздела
const handleMarkCnInsert = useCallback(
async nRrpConfSctnMrk => {
pOnlineShowDictionary({
unitCode: "RRPConfigSectionMarkConstitution",
showMethod: "link_add",
inputParameters: [{ name: "in_PRN", value: nRrpConfSctnMrk }],
callBack: res => {
res.success ? handleReload() : null;
}
});
},
[handleReload, pOnlineShowDictionary]
);
return [handleMarkOpen, handleMarkCnOpen, handleMarkCnInsert];
};
//Хук для форм диалогового окна
const useFormDialog = () => {
//Состояние открытия диалогового окна
const [formOpen, setForm] = useState(false);
//Состояние диалогового окна
const [formData, setFormData] = useState({
reload: false,
rn: "",
prn: "",
sctnName: "",
sctnCode: "",
status: "",
code: "",
name: "",
colCode: "",
colRn: null,
rowCode: "",
rowRn: null
});
//Подключение к контексту навигации
const { getNavigationSearch } = useContext(NavigationCtx);
//Открытие диалогового окна
const openForm = () => {
setForm(true);
};
//Очистка диалогового окна
const clearFormData = () => {
setFormData({
reload: false,
rn: "",
prn: "",
sctnName: "",
sctnCode: "",
status: "",
code: "",
name: "",
colCode: "",
colRn: null,
rowCode: "",
rowRn: null
});
};
//Отработка нажатия на кнопку добавления секции
const handleSectionAdd = () => {
setFormData({ status: STATUSES.CREATE, prn: Number(getNavigationSearch().NRN) });
openForm();
};
//Отработка нажатия на кнопку исправления секции
const handleSectionEdit = (rn, code, name) => {
setFormData({ rn: rn, code: code, name: name, status: STATUSES.EDIT });
openForm();
};
//Отработка нажатия на кнопку удаления секции
const handleSectionDelete = (rn, code, name) => {
setFormData({ rn: rn, code: code, name: name, status: STATUSES.DELETE });
openForm();
};
//Отработка нажатия на кнопку добавления показателя раздела
const handleMarkAdd = (prn, rowRn = null, rowCode = "", colRn = null, colCode = "") => {
setFormData({
reload: rowRn && colRn ? true : false,
prn: prn,
rowRn: rowRn,
rowCode: rowCode,
colRn: colRn,
colCode: colCode,
status: STATUSES.RRPCONFSCTNMRK_CREATE
});
openForm();
};
//Отработка нажатия на кнопку исправления показателя раздела
const handleMarkEdit = rn => {
setFormData({ reload: true, rn: rn, status: STATUSES.RRPCONFSCTNMRK_EDIT });
openForm();
};
//Отработка нажатия на кнопку удаления показателя раздела
const handleMarkDelete = rn => {
setFormData({ rn: rn, status: STATUSES.RRPCONFSCTNMRK_DELETE });
openForm();
};
//При закрытии диалога
const handleDialogClose = () => {
setForm(false);
clearFormData();
};
return [
formOpen,
formData,
handleSectionAdd,
handleSectionEdit,
handleSectionDelete,
handleMarkAdd,
handleMarkEdit,
handleMarkDelete,
handleDialogClose
];
};
//Формирование разделов
const a11yProps = index => {
return {
id: `simple-tab-${index}`,
"aria-controls": `simple-tabpanel-${index}`
};
};
//----------------
//Интерфейс модуля
//----------------
export { useWindowResize, useConf, useTab, useRecOpen, useFormDialog, a11yProps };