WEB APP: Панель "Работы проектов" - отображение параметров инициализации панели и диалог переформирования

This commit is contained in:
Mikhail Chechnev 2024-04-18 12:48:07 +03:00
parent f31030cbc5
commit 761237c110

View File

@ -9,13 +9,34 @@
import React, { useContext, useState, useCallback, useEffect } from "react"; //Классы React import React, { useContext, useState, useCallback, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента import PropTypes from "prop-types"; //Контроль свойств компонента
import { Drawer, Fab, Box, Grid, List, ListItemButton, ListItemText, ListItemIcon, Icon, Typography } from "@mui/material"; //Интерфейсные элементы import {
Drawer,
Fab,
Box,
Grid,
List,
ListItemButton,
ListItemText,
ListItemIcon,
Icon,
Typography,
Divider,
ListItem,
Button,
Dialog,
DialogContent,
DialogActions,
TextField,
DialogTitle
} from "@mui/material"; //Интерфейсные элементы
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { ApplicationСtx } from "../../context/application"; //Контекст приложения import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { formatDateJSONDateOnly } from "../../core/utils"; //Вспомогательные функции import { formatDateJSONDateOnly } from "../../core/utils"; //Вспомогательные функции
import { P8P_GANTT_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения import { P8P_GANTT_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { P8PGantt } from "../../components/p8p_gantt"; //Диаграмма Ганта import { P8PGantt } from "../../components/p8p_gantt"; //Диаграмма Ганта
import { formatDateRF } from "../../core/utils"; //Вспомогательные функции
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы и константы
import { ResMon } from "./res_mon"; //Монитор ресурсов import { ResMon } from "./res_mon"; //Монитор ресурсов
import { taskAttributeRenderer } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов import { taskAttributeRenderer } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
@ -31,7 +52,6 @@ const GANTT_WIDTH = "98vw";
//Стили //Стили
const STYLES = { const STYLES = {
PROJECTS_LIST_SAVE_BUTTON: { backgroundColor: "orange" },
PROJECTS_LIST_ITEM_NOJOBS: { backgroundColor: "#ff000045" }, PROJECTS_LIST_ITEM_NOJOBS: { backgroundColor: "#ff000045" },
PROJECTS_LIST_ITEM_PRIMARY: { wordWrap: "break-word" }, PROJECTS_LIST_ITEM_PRIMARY: { wordWrap: "break-word" },
PROJECTS_LIST_ITEM_SECONDARY: { wordWrap: "break-word", fontSize: "0.5rem", textTransform: "uppercase" }, PROJECTS_LIST_ITEM_SECONDARY: { wordWrap: "break-word", fontSize: "0.5rem", textTransform: "uppercase" },
@ -46,10 +66,77 @@ const STYLES = {
PERIODS_DRAWER: { width: "1200px", flexShrink: 0, [`& .MuiDrawer-paper`]: { width: "1200px", boxSizing: "border-box" } } PERIODS_DRAWER: { width: "1200px", flexShrink: 0, [`& .MuiDrawer-paper`]: { width: "1200px", boxSizing: "border-box" } }
}; };
//Единицы измерения длительности
const DURATION_MEAS = {
0: "День",
1: "Неделя",
2: "Декада",
3: "Месяц",
4: "Квартал",
5: "Год"
};
//------------------------------------ //------------------------------------
//Вспомогательные функции и компоненты //Вспомогательные функции и компоненты
//------------------------------------ //------------------------------------
//Диалог параметров инициализации панели
const InitDialog = ({ dateBegin, dateFact, onOk, onCancel }) => {
//Собственное состояние - значения с-по
const [values, setValues] = useState({ dateBegin: formatDateJSONDateOnly(dateBegin), dateFact: formatDateJSONDateOnly(dateFact) });
//Отработка воода значения в фильтр
const handleValueTextFieldChanged = e => setValues(prev => ({ ...prev, [e.target.name]: e.target.value }));
//Генерация содержимого
return (
<Dialog
open={true}
aria-labelledby="init-dialog-title"
aria-describedby="init-dialog-description"
onClose={() => (onCancel ? onCancel() : null)}
>
<DialogTitle>Параметры инициализации</DialogTitle>
<DialogContent>
<TextField
style={{ padding: "10px" }}
name="dateBegin"
type="date"
value={values.dateBegin}
onChange={handleValueTextFieldChanged}
label="Начало (будет использован первый день месяца)"
variant="standard"
fullWidth
/>
<TextField
style={{ padding: "10px" }}
name="dateFact"
type="date"
value={values.dateFact}
onChange={handleValueTextFieldChanged}
label="Факт на (будет использован последний день месяца)"
variant="standard"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={() => (onOk ? onOk({ dateBegin: new Date(values.dateBegin), dateFact: new Date(values.dateFact) }) : null)}>
{BUTTONS.OK}
</Button>
<Button onClick={() => (onCancel ? onCancel() : null)}>{BUTTONS.CANCEL}</Button>
</DialogActions>
</Dialog>
);
};
//Контроль свойств - Диалог параметров инициализации панели
InitDialog.propTypes = {
dateBegin: PropTypes.instanceOf(Date).isRequired,
dateFact: PropTypes.instanceOf(Date).isRequired,
onOk: PropTypes.func,
onCancel: PropTypes.func
};
//Список проектов //Список проектов
const ProjectsList = ({ projects = [], selectedProject, onClick } = {}) => { const ProjectsList = ({ projects = [], selectedProject, onClick } = {}) => {
//Подключение к контексту сообщений //Подключение к контексту сообщений
@ -132,7 +219,8 @@ const PrjJobs = () => {
selectedProject: null, selectedProject: null,
selectedProjectDocRn: null, selectedProjectDocRn: null,
selectedProjectGanttDef: {}, selectedProjectGanttDef: {},
selectedProjectTasks: [] selectedProjectTasks: [],
showInitDialog: false
}); });
//Подключение к контексту приложения //Подключение к контексту приложения
@ -216,8 +304,8 @@ const PrjJobs = () => {
const data = await executeStored({ const data = await executeStored({
stored: "PKG_P8PANELS_PROJECTS.JB_INIT", stored: "PKG_P8PANELS_PROJECTS.JB_INIT",
args: { args: {
DBEGIN: state.dateBegin ? new Date(state.dateBegin) : null, DBEGIN: state.dateBegin ? state.dateBegin : null,
DFACT: state.dateFact ? new Date(state.dateFact) : null, DFACT: state.dateFact ? state.dateFact : null,
NDURATION_MEAS: state.durationMeas, NDURATION_MEAS: state.durationMeas,
SLAB_MEAS: state.labMeas, SLAB_MEAS: state.labMeas,
NIDENT: state.ident NIDENT: state.ident
@ -226,8 +314,9 @@ const PrjJobs = () => {
setState(pv => ({ setState(pv => ({
...pv, ...pv,
init: true, init: true,
dateBegin: data.DBEGIN, reInit: false,
dateFact: data.DFACT, dateBegin: new Date(data.DBEGIN),
dateFact: new Date(data.DFACT),
durationMeas: data.NDURATION_MEAS, durationMeas: data.NDURATION_MEAS,
labMeas: data.SLAB_MEAS, labMeas: data.SLAB_MEAS,
resourceStatus: data.NRESOURCE_STATUS, resourceStatus: data.NRESOURCE_STATUS,
@ -246,11 +335,10 @@ const PrjJobs = () => {
if (state.selectedProject) loadProjectJobs(false); if (state.selectedProject) loadProjectJobs(false);
}, [state.selectedProject, loadProjectJobs]); }, [state.selectedProject, loadProjectJobs]);
//При подключении компонента к странице //При изменении флага инициализации
useEffect(() => { useEffect(() => {
initJobs(); initJobs();
// eslint-disable-next-line react-hooks/exhaustive-deps }, [state.init, initJobs]);
}, []);
//Выбор проекта //Выбор проекта
const selectPoject = (project, projectDocRn) => { const selectPoject = (project, projectDocRn) => {
@ -292,6 +380,16 @@ const PrjJobs = () => {
if (isMain) modifyJob(task.rn, new Date(start), new Date(end), new Date(state.dateBegin), new Date(state.dateFact), state.durationMeas); if (isMain) modifyJob(task.rn, new Date(start), new Date(end), new Date(state.dateBegin), new Date(state.dateFact), state.durationMeas);
}; };
//Отработка нажатия на отображения диалога параметров инициализации панели
const handleShowInitDialogClick = () => setState(pv => ({ ...pv, showInitDialog: true }));
//Отработка нажатия на "ОК" в диалоге параметров инициализации панели
const handleOKInitDialogClick = values =>
setState(pv => ({ ...pv, dateBegin: values.dateBegin, dateFact: values.dateFact, showInitDialog: false, init: false }));
//Отработка нажатия на "Отмена" в диалоге параметров инициализации панели
const handleCancelInitDialogClick = () => setState(pv => ({ ...pv, showInitDialog: false }));
//Обработка нажатия на сохранение данных в проект //Обработка нажатия на сохранение данных в проект
const handleSaveToProjectsClick = () => saveProjects(); const handleSaveToProjectsClick = () => saveProjects();
@ -304,6 +402,14 @@ const PrjJobs = () => {
//Генерация содержимого //Генерация содержимого
return ( return (
<Box p={2}> <Box p={2}>
{state.showInitDialog ? (
<InitDialog
dateBegin={state.dateBegin}
dateFact={state.dateFact}
onOk={handleOKInitDialogClick}
onCancel={handleCancelInitDialogClick}
/>
) : null}
<Fab variant="extended" sx={STYLES.PROJECTS_BUTTON} onClick={() => setState(pv => ({ ...pv, showProjectsList: !pv.showProjectsList }))}> <Fab variant="extended" sx={STYLES.PROJECTS_BUTTON} onClick={() => setState(pv => ({ ...pv, showProjectsList: !pv.showProjectsList }))}>
Проекты Проекты
{state.needSave ? ( {state.needSave ? (
@ -321,15 +427,50 @@ const PrjJobs = () => {
> >
{state.projectsLoaded ? ( {state.projectsLoaded ? (
<> <>
<List>
<ListItem>
<ListItemText
secondary={
<>
<b>Начало: </b>
{formatDateRF(state.dateBegin)}
<br />
<b>Факт на: </b>
{formatDateRF(state.dateFact)}
<br />
<b>Длительность: </b>
{DURATION_MEAS[state.durationMeas]}
<br />
<b>Трудоёмкость: </b>
{state.labMeas}
</>
}
/>
</ListItem>
<ListItem>
<Button fullWidth variant="contained" startIcon={<Icon>refresh</Icon>} onClick={handleShowInitDialogClick}>
Переформировать...
</Button>
</ListItem>
</List>
<Divider />
{state.needSave ? ( {state.needSave ? (
<List> <>
<ListItemButton sx={STYLES.PROJECTS_LIST_SAVE_BUTTON} onClick={handleSaveToProjectsClick}> <List>
<ListItemIcon> <ListItem>
<Icon>save</Icon> <Button
</ListItemIcon> fullWidth
<ListItemText primary="Сохранить" secondary="Перенсти изменения в проекты" /> color="warning"
</ListItemButton> variant="contained"
</List> startIcon={<Icon>save</Icon>}
onClick={handleSaveToProjectsClick}
>
Сохранить
</Button>
</ListItem>
</List>
<Divider />
</>
) : null} ) : null}
<ProjectsList projects={state.projects} selectedProject={state.selectedProject} onClick={handleProjectClick} /> <ProjectsList projects={state.projects} selectedProject={state.selectedProject} onClick={handleProjectClick} />
</> </>