208 lines
8.8 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 React, { useState, useEffect, useContext, useCallback } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Box, Tabs, IconButton, Icon, Stack, Button } from "@mui/material"; //Интерфейсные компоненты
import { tabsClasses } from "@mui/material/Tabs"; //Классы закладок
import { ApplicationСtx } from "../../../context/application"; //Контекст взаимодействия с приложением
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../../context/messaging"; //Контекст сообщений
import { useConfSections } from "../hooks"; //Кастомные хуки
import { ActionMessage } from "./action_message"; //Сообщение с действиями
import { SectionTab } from "./section_tab"; //Закладка раздела
import { DialogSectionIU } from "./dialog_section_iu"; //Диалог добавления/исправления раздела
//---------
//Константы
//---------
//Стили
const STYLES = {
CONTAINER: { borderBottom: 1, borderColor: "divider", width: "100%", height: "100%" },
TABS_SECTIONS: { width: "100%", [`& .${tabsClasses.scrollButtons}`]: { "&.Mui-disabled": { opacity: 0.3 } } }
};
//-----------------------
//Вспомогательные функции
//-----------------------
//Поиск активного раздела после удаления текущего
const getNextSectionAfterDelete = (sections, deletedSection) => {
//Находим индекс удаляемого раздела
const delInd = sections.findIndex(s => s.NRN === deletedSection);
//Возвращаем рег. номер либо предыдущего раздела, либо следующего, либо ничего
return delInd === -1 ? null : sections[delInd - 1]?.NRN || sections[delInd + 1]?.NRN || null;
};
//-----------
//Тело модуля
//-----------
//Разделы настройки
const Sections = ({ conf, onSectionChange, onSectionCountChange }) => {
//Текущий раздел настройки
const [section, setSection] = useState(-1);
//Редактируемый раздел настройки
const [modSection, setModSection] = useState(null);
//Список разделов и просто описание настройки
const [confDesc, sections, refreshSections, sectionsLoading, sectionsInit] = useConfSections(conf);
//Подключение к контексту приложения
const { setAppBarTitle } = useContext(ApplicationСtx);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
//Выбор раздела
const selectSection = useCallback(
section => {
if (onSectionChange) onSectionChange(section);
setSection(section);
},
[onSectionChange]
);
//Добавление раздела
const insertSection = async ({ conf, code, name }) => {
const data = await executeStored({
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTN_INSERT",
args: { NPRN: conf, SCODE: code, SNAME: name },
loader: false
});
selectSection(data.NRN);
refreshSections();
};
//Исправление раздела
const updateSection = async ({ rn, code, name }) => {
await executeStored({
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTN_UPDATE",
args: { NRN: rn, SCODE: code, SNAME: name },
loader: false
});
refreshSections();
};
//Удаление раздела
const deleteSection = async section => {
await executeStored({
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTN_DELETE",
args: { NRN: section },
loader: false
});
selectSection(getNextSectionAfterDelete(sections, section));
refreshSections();
};
//При измении закладки текущего раздела
const handleSectionTabChange = (event, section) => selectSection(section);
//При добавлении раздела настройки
const handleSectionAdd = () => setModSection(true);
//При редактировании раздела настройки
const handleSectionEdit = section => setModSection(sections.find(s => s.NRN === section) || null);
//При удалении раздела настройки
const handleSectionDelete = section => showMsgWarn("Удалить раздел?", () => deleteSection(section));
//При закрытии формы добавления/исправления по "ОК"
const handleIUFormOk = async values => {
if (modSection === true) await insertSection({ conf, ...values });
else await updateSection({ rn: modSection.NRN, ...values });
setModSection(null);
};
//При закрытии формы добавления/исправления по "Отмена"
const handleIUFormCancel = () => setModSection(null);
//При изменении состава разделов
useEffect(() => {
//Если ещё не инициализировали выбранный раздел и есть чем
if (section === -1 && sections.length > 0) selectSection(sections[0].NRN);
}, [section, sections, selectSection]);
//При изменении количества разделов
useEffect(() => {
onSectionCountChange && onSectionCountChange(sections.length);
}, [sections.length, onSectionCountChange]);
//При изменении описания раздела
useEffect(() => {
if (confDesc?.SNAME) setAppBarTitle(confDesc.SNAME);
}, [confDesc, setAppBarTitle]);
//Вычисление подсвеченной закладки раздела
const hlSection = sections.find(s => s.NRN === section)?.NRN || false;
//Формирование представления
return (
<Stack direction={"row"} sx={STYLES.CONTAINER}>
{modSection && (
<DialogSectionIU
code={modSection?.SCODE}
name={modSection?.SNAME}
insert={modSection === true}
onOk={handleIUFormOk}
onCancel={handleIUFormCancel}
/>
)}
{sections.length > 0 ? (
<>
<Box display={"flex"} justifyContent={"center"} alignItems={"center"} sx={STYLES.PANELS_MAIN_COLOR} title={"Добавить раздел"}>
<IconButton onClick={handleSectionAdd}>
<Icon>add</Icon>
</IconButton>
</Box>
<Tabs value={hlSection} onChange={handleSectionTabChange} variant={"scrollable"} scrollButtons sx={STYLES.TABS_SECTIONS}>
{sections.map((s, i) => (
<SectionTab
key={i}
value={s.NRN}
section={section}
sectionDesc={s}
onSectionEdit={handleSectionEdit}
onSectionDelete={handleSectionDelete}
/>
))}
</Tabs>
</>
) : (
sectionsInit &&
!sectionsLoading && (
<ActionMessage icon={"info"} title={"В настройке нет разделов"} desc={"Добавьте первый..."}>
<Button startIcon={<Icon>add</Icon>} onClick={handleSectionAdd}>
Раздел
</Button>
</ActionMessage>
)
)}
</Stack>
);
};
//Контроль свойств - Разделы настройки
Sections.propTypes = {
conf: PropTypes.number,
onSectionChange: PropTypes.func,
onSectionCountChange: PropTypes.func
};
//----------------
//Интерфейс модуля
//----------------
export { Sections };