diff --git a/app/panels/prj_graph/index.js b/app/panels/prj_graph/index.js new file mode 100644 index 0000000..ca5d2c3 --- /dev/null +++ b/app/panels/prj_graph/index.js @@ -0,0 +1,16 @@ +/* + Парус 8 - Панели мониторинга - ПУП - Графики проектов + Панель мониторинга: Точка входа +*/ + +//--------------------- +//Подключение библиотек +//--------------------- + +import { PrjGraph } from "./prj_graph"; //Корневая панель графиков проекта + +//---------------- +//Интерфейс модуля +//---------------- + +export const RootClass = PrjGraph; diff --git a/app/panels/prj_graph/layouts.js b/app/panels/prj_graph/layouts.js new file mode 100644 index 0000000..f2605bf --- /dev/null +++ b/app/panels/prj_graph/layouts.js @@ -0,0 +1,96 @@ +/* + Парус 8 - Панели мониторинга - ПУП - Графики проектов + Дополнительная разметка и вёрстка клиентских элементов +*/ + +//--------------------- +//Подключение библиотек +//--------------------- + +import React from "react"; //Классы React +import { Icon, Stack, Link } from "@mui/material"; //Интерфейсные компоненты +import { formatDateRF } from "../../core/utils"; //Вспомогательные процедуры и функции + +//--------- +//Константы +//--------- + +//Шаблон имени ячейки месяца +const MONTH_COLUMN_REG_EXP = /[0-9]{4}_[0-9]{1,2}/; + +//----------- +//Тело модуля +//----------- + +//Формирование значения для плашки этапа +const formatStageItemValue = (state, text) => { + const [stateText, icon] = + state == 0 + ? ["Зарегистрирован", "app_registration"] + : state == 1 + ? ["Открыт", "lock_open"] + : state == 2 + ? ["Закрыт", "lock_outline"] + : state == 3 + ? ["Согласован", "thumb_up_alt"] + : state == 4 + ? ["Исполнение прекращено", "block"] + : ["Остановлен", "do_not_disturb_on"]; + return ( + + {icon} + {text} + + ); +}; + +//Генерация представления ячейки заголовка группы +export const groupCellRender = ({ group, pOnlineShowDocument }) => ({ + cellStyle: { padding: "2px" }, + data: ( + pOnlineShowDocument({ unitCode: "Projects", document: group.name })}> + {group.caption} + + ) +}); + +//Генерация представления ячейки c данными +export const dataCellRender = ({ row, columnDef, pOnlineShowDocument }) => { + if (MONTH_COLUMN_REG_EXP.test(columnDef.name)) { + const dF = new Date(row.DFROM); + const dT = new Date(row.DTO); + const [year, month] = columnDef.name.split("_"); + const mF = new Date(year, month - 1, 1); + const mT = new Date(year, month, 0); + let cellStyle = {}; + let cellProps = {}; + let data = null; + if ((dF <= mF && dT >= mT) || (dF >= mF && dF <= mT) || (dT >= mF && dT <= mT)) { + if (year == dF.getFullYear() && month == dF.getMonth() + 1) data = formatStageItemValue(row.NSTATE, row.SRESP); + cellStyle = { backgroundColor: row.NSTATE == 0 ? "lightyellow" : row.NSTATE == 1 ? "lightgreen" : "lightblue", cursor: "pointer" }; + cellProps = { + title: `${formatDateRF(dF)} - ${formatDateRF(dT)}`, + onClick: () => pOnlineShowDocument({ unitCode: "ProjectsStages", document: row.NRN }) + }; + } + return { + cellStyle: { padding: "2px", maxWidth: "30px", overflow: "visible", fontSize: "smaller", whiteSpace: "nowrap", ...cellStyle }, + cellProps, + data + }; + } + switch (columnDef.name) { + case "SJOB": + return { + cellProps: { title: row[columnDef.name] }, + cellStyle: { + padding: "2px", + maxWidth: "300px", + textOverflow: "ellipsis", + overflow: "hidden", + whiteSpace: "pre", + fontSize: "smaller" + } + }; + } +}; diff --git a/app/panels/prj_graph/prj_graph.js b/app/panels/prj_graph/prj_graph.js new file mode 100644 index 0000000..c4ba8ca --- /dev/null +++ b/app/panels/prj_graph/prj_graph.js @@ -0,0 +1,93 @@ +/* + Парус 8 - Панели мониторинга - ПУП - Графики проектов + Панель мониторинга: Корневая панель графиков проекта +*/ + +//--------------------- +//Подключение библиотек +//--------------------- + +import React, { useState, useContext, useCallback, useEffect } from "react"; //Классы React +import { Grid, Box } from "@mui/material"; //Интерфейсные элементы +import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных +import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения +import { ApplicationСtx } from "../../context/application"; //Контекст приложения +import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером +import { dataCellRender, groupCellRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов + +//----------- +//Тело модуля +//----------- + +//Графики проектов +const PrjGraph = () => { + //Собственное состояние - таблица данных + const [dataGrid, setdataGrid] = useState({ + dataLoaded: false, + columnsDef: [], + groups: [], + rows: [], + reload: true + }); + + //Подключение к контексту приложения + const { pOnlineShowDocument } = useContext(ApplicationСtx); + + //Подключение к контексту взаимодействия с сервером + const { executeStored } = useContext(BackEndСtx); + + //Загрузка данных таблицы с сервера + const loadData = useCallback(async () => { + if (dataGrid.reload) { + const data = await executeStored({ + stored: "PKG_P8PANELS_PROJECTS.GRAPH", + args: {}, + respArg: "COUT", + attributeValueProcessor: (name, val) => (["caption", "name", "parent"].includes(name) ? undefined : val) + }); + setdataGrid(pv => ({ + ...pv, + columnsDef: data.XCOLUMNS_DEF ? [...data.XCOLUMNS_DEF] : pv.columnsDef, + rows: [...(data.XROWS || [])], + groups: [...(data.XGROUPS || [])], + dataLoaded: true, + reload: false + })); + } + }, [dataGrid.reload, executeStored]); + + //При необходимости обновить данные таблицы + useEffect(() => { + loadData(); + }, [dataGrid.reload, loadData]); + + //Генерация содержимого + return ( +
+ + + + {dataGrid.dataLoaded ? ( + dataCellRender({ ...prms, pOnlineShowDocument })} + groupCellRender={prms => groupCellRender({ ...prms, pOnlineShowDocument })} + /> + ) : null} + + + +
+ ); +}; + +//---------------- +//Интерфейс модуля +//---------------- + +export { PrjGraph }; diff --git a/img/prj_graph.jpg b/img/prj_graph.jpg new file mode 100644 index 0000000..355b6c8 Binary files /dev/null and b/img/prj_graph.jpg differ