P8-Panels/app/panels/prj_fin/projects.js

209 lines
10 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, useContext } from "react"; //Классы React
import { Box, Grid, Paper, Fab, Icon } from "@mui/material"; //Интерфейсные компоненты
import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
import {
P8PDataGrid,
P8P_DATA_GRID_SIZE,
P8P_DATA_GRID_MORE_HEIGHT,
P8P_DATA_GRID_FILTERS_HEIGHT,
useP8PDataGrid
} from "../../components/p8p_data_grid"; //Таблица данных
import { P8PFullScreenDialog } from "../../components/p8p_fullscreen_dialog"; //Полноэкранный диалог
import { P8PChart, useP8PChart } from "../../components/p8p_chart"; //График
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { COMMON_PROJECTS_STYLES, PANEL_UNITS, headCellRender, dataCellRender, valueFormatter, rowExpandRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
import { Stages } from "./stages"; //Список этапов проекта
//---------
//Константы
//---------
//Высота графиков
const CHART_HEIGHT = "300px";
//Стили
const STYLES = {
TABLE_PROJECTS: (showCharts, morePages, filters) => ({
height: `calc(100vh - ${APP_BAR_HEIGHT} - ${showCharts ? CHART_HEIGHT : "0px"} - ${morePages ? P8P_DATA_GRID_MORE_HEIGHT : "0px"} - ${
filters ? P8P_DATA_GRID_FILTERS_HEIGHT : "0px"
} - 25px)`,
...APP_STYLES.SCROLL
}),
CHART: { maxHeight: CHART_HEIGHT, display: "flex", justifyContent: "center" },
CHART_PAPER: { height: "100%" },
CHART_FAB: { position: "absolute", top: 80, left: 16 }
};
//-----------
//Тело модуля
//-----------
//Список проектов
const Projects = () => {
//Собственное состояние - выбранный проект
const [selectedProject, setSelectedProject] = useState(null);
//Собственное состояние - фильтры этапов
const [stagesFilters, setStagesFilters] = useState([]);
//Подключение к контексту приложения
const { pOnlineShowDocument, pOnlineShowUnit, configSystemPageSize } = useContext(ApplicationСtx);
//Собственное состояние
const {
dataGrid: projectsDataGrid,
isDataLoaded: projectsLoaded,
handleFilterChanged,
handleOrderChanged,
handlePagesCountChanged
} = useP8PDataGrid({
stored: "PKG_P8PANELS_PROJECTS.LIST",
pageSize: configSystemPageSize,
executeStoredArgs: { attributeValueProcessor: (name, val) => (name == "SGOVCNTRID" ? undefined : val) }
});
//Состояния графиков
const [showCharts, setShowCharts] = useState(true);
const { chart: problemsChart, isDataLoaded: isProblemsLoaded } = useP8PChart({ stored: "PKG_P8PANELS_PROJECTS.CHART_PROBLEMS" });
const { chart: customersChart, isDataLoaded: isCustomersLoaded } = useP8PChart({ stored: "PKG_P8PANELS_PROJECTS.CHART_CUSTOMERS" });
const { chart: costNotesChart, isDataLoaded: isCostNotesLoaded } = useP8PChart({ stored: "PKG_P8PANELS_PROJECTS.CHART_FCCOSTNOTES" });
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
//Подключение к контексту сообщений
const { showMsgErr } = useContext(MessagingСtx);
//Отображение журнала платежей по этапу проекта
const showPayNotes = async ({ sender, direction }) => {
const data = await executeStored({
stored: "PKG_P8PANELS_PROJECTS.SELECT_FIN",
args: { NRN: sender.NRN, NDIRECTION: direction }
});
if (data.NIDENT) pOnlineShowUnit({ unitCode: "PayNotes", inputParameters: [{ name: "in_SelectList_Ident", value: data.NIDENT }] });
else showMsgErr(TEXTS.NO_DATA_FOUND);
};
//Отображение детализации точки графика затрат
const showCostNotesChartDetail = async ({ year, month }) => {
const data = await executeStored({
stored: "PKG_P8PANELS_PROJECTS.CHART_FCCOSTNOTES_SELECT_COST",
args: { NYEAR: year, NMONTH: month }
});
if (data.NIDENT) pOnlineShowUnit({ unitCode: "CostNotes", inputParameters: [{ name: "in_IDENT", value: data.NIDENT }] });
else showMsgErr(TEXTS.NO_DATA_FOUND);
};
//Отображение этапов проекта
const showStages = ({ sender, filters = [] } = {}) => {
setSelectedProject({ ...sender });
setStagesFilters([...filters]);
};
//При закрытии списка этапов проекта
const handleStagesClose = () => {
setSelectedProject(null);
setStagesFilters([]);
};
//Отработка нажатия на график
const handleChartClick = ({ item }) => {
if (item.SFILTER && item.SFILTER_VALUE) handleFilterChanged({ filters: [{ name: item.SFILTER, from: item.SFILTER_VALUE }] });
if (item.SUNITCODE == "CostNotes" && item.NYEAR && item.NMONTH) showCostNotesChartDetail({ year: item.NYEAR, month: item.NMONTH });
};
//Генерация содержимого
return (
<Box p={1}>
<Grid container spacing={1}>
{showCharts ? (
<>
<Grid item xs={4}>
<Paper elevation={3} sx={STYLES.CHART_PAPER}>
{isProblemsLoaded ? <P8PChart {...problemsChart} onClick={handleChartClick} style={STYLES.CHART} /> : null}
</Paper>
</Grid>
<Grid item xs={4}>
<Paper elevation={3} sx={STYLES.CHART_PAPER}>
{isCustomersLoaded ? <P8PChart {...customersChart} onClick={handleChartClick} style={STYLES.CHART} /> : null}
</Paper>
</Grid>
<Grid item xs={4}>
<Paper elevation={3} sx={STYLES.CHART_PAPER}>
{isCostNotesLoaded ? <P8PChart {...costNotesChart} onClick={handleChartClick} style={STYLES.CHART} /> : null}
</Paper>
</Grid>
</>
) : null}
<Grid item xs={12}>
{projectsLoaded ? (
<P8PDataGrid
{...P8P_DATA_GRID_CONFIG_PROPS}
containerComponentProps={{
sx: STYLES.TABLE_PROJECTS(showCharts, projectsDataGrid.morePages, (projectsDataGrid.filters || []).length > 0)
}}
columnsDef={projectsDataGrid.columnsDef}
rows={projectsDataGrid.rows}
size={P8P_DATA_GRID_SIZE.SMALL}
filtersInitial={projectsDataGrid.filters}
morePages={projectsDataGrid.morePages}
reloading={projectsDataGrid.reload}
fixedHeader={true}
expandable={true}
headCellRender={headCellRender}
dataCellRender={prms => dataCellRender({ ...prms, panelUnit: PANEL_UNITS.PROJECTS, showStages })}
rowExpandRender={prms =>
rowExpandRender({
...prms,
panelUnit: PANEL_UNITS.PROJECTS,
pOnlineShowDocument,
showPayNotes,
showStages
})
}
valueFormatter={prms => valueFormatter({ ...prms, panelUnit: PANEL_UNITS.PROJECTS })}
onOrderChanged={handleOrderChanged}
onFilterChanged={handleFilterChanged}
onPagesCountChanged={handlePagesCountChanged}
/>
) : null}
{selectedProject ? (
<P8PFullScreenDialog
title={`Этапы проекта "${selectedProject.SNAME_USL}"`}
onClose={handleStagesClose}
contentProps={{ sx: COMMON_PROJECTS_STYLES.FULL_SCREEN_DIALOG_CONTENT }}
>
<Stages project={selectedProject.NRN} projectName={selectedProject.SNAME_USL} filters={stagesFilters} />
</P8PFullScreenDialog>
) : null}
</Grid>
</Grid>
{isProblemsLoaded || isCustomersLoaded || isCostNotesLoaded ? (
<Fab size="small" color="secondary" sx={STYLES.CHART_FAB} onClick={() => setShowCharts(!showCharts)}>
<Icon>{showCharts ? "expand_less" : "expand_more"}</Icon>
</Fab>
) : null}
</Box>
);
};
//----------------
//Интерфейс модуля
//----------------
export { Projects };