/* Парус 8 - Панели мониторинга Компонент: Диаграмма Ганта */ //--------------------- //Подключение библиотек //--------------------- import React, { useEffect, useState, useCallback, useRef } from "react"; //Классы React import PropTypes from "prop-types"; //Контроль свойств компонента import { Box, IconButton, Icon, Typography, Link } from "@mui/material"; //Интерфейсные компоненты import { P8PAppInlineError } from "./p8p_app_message"; //Встраиваемое сообщение об ошибке import { useP8PGantt } from "./p8p_gantt/p8p_gantt_hooks"; //Хук для диаграммы Ганта import { P8P_GANTT_ZOOM, P8P_GANTT_ZOOM_VIEW_MODES, P8P_GANTT_TASK_SHAPE, P8P_GANTT_TASK_ATTRIBUTE_SHAPE, P8P_GANTT_TASK_COLOR_SHAPE, TITLE_HEIGHT, ZOOM_HEIGHT } from "./p8p_gantt/p8p_gantt_constants"; //Константы диаграммы Ганта import { P8PGanttTaskEditor, taskLegendDesc } from "./p8p_gantt/p8p_gantt_task_editor"; //Редактор задачи import { P8P_TYPOGRAPHY_VARIANT } from "../theme/p8p_typography"; //Варианты шрифтов import { P8P_COMPONENT_HEIGHT } from "../theme/styles/common"; //Стили - общие import { P8P_BOX_GANTT } from "../theme/styles/box"; //Стили контейнеров import { P8P_TYPOGRAPHY_TITLE } from "../theme/styles/typography"; //Стили текста //----------- //Тело модуля //----------- //Диаграмма Ганта const P8PGantt = ({ containerStyle, title, titleStyle, onTitleClick, zoomBar, readOnly, readOnlyDates, readOnlyProgress, zoom, tasks, taskAttributes, taskColors, onTaskDatesChange, onTaskProgressChange, taskAttributeRenderer, taskDialogRenderer, taskDialogProps, noDataFoundText, numbTaskEditorCaption, nameTaskEditorCaption, startTaskEditorCaption, endTaskEditorCaption, progressTaskEditorCaption, legendTaskEditorCaption, okTaskEditorBtnCaption, cancelTaskEditorBtnCaption, zoomBarStyle, zoomBarHeight }) => { //Собственное состояние const [state, setState] = useState({ noData: true, gantt: null, zoom: P8P_GANTT_ZOOM.includes(zoom) ? zoom : 3, editTask: null }); //Ссылки на DOM const svgContainerRef = useRef(null); //Отображение диаграммы const showGantt = useCallback(() => { if (!state.gantt) { // eslint-disable-next-line no-undef const gantt = new Gantt("#__gantt__", tasks, { view_mode: P8P_GANTT_ZOOM_VIEW_MODES[state.zoom], date_format: "YYYY-MM-DD", language: "ru", readOnly, readOnlyDates, readOnlyProgress, on_date_change: (task, start, end, isMain) => (onTaskDatesChange ? onTaskDatesChange({ task, start, end, isMain }) : null), on_progress_change: (task, progress) => (onTaskProgressChange ? onTaskProgressChange({ task, progress }) : null), on_click: openTaskEditor }); setState(pv => ({ ...pv, gantt, noData: false })); } else { state.gantt.refresh(tasks); setState(pv => ({ ...pv, noData: false })); } }, [state.gantt, state.zoom, readOnly, readOnlyDates, readOnlyProgress, tasks, onTaskDatesChange, onTaskProgressChange]); //Обновление масштаба диаграммы const handleZoomChange = direction => setState(pv => ({ ...pv, zoom: pv.zoom + direction < 0 ? 0 : pv.zoom + direction >= P8P_GANTT_ZOOM.length ? P8P_GANTT_ZOOM.length - 1 : pv.zoom + direction })); //Открытие редактора задачи const openTaskEditor = task => setState(pv => ({ ...pv, editTask: { ...task } })); //При сохранении задачи в редакторе const handleTaskEditorSave = ({ task, start, end, progress }) => { setState(pv => ({ ...pv, editTask: null })); if (onTaskDatesChange && (task.start != start || task.end != end)) onTaskDatesChange({ task, start, end, isMain: true }); if (onTaskProgressChange && task.progress != progress) onTaskProgressChange({ task, progress }); }; //При закрытии редактора задачи без сохранения const handleTaskEditorCancel = () => setState(pv => ({ ...pv, editTask: null })); //При изменении масштаба useEffect(() => { if (state.gantt) state.gantt.change_view_mode(P8P_GANTT_ZOOM_VIEW_MODES[state.zoom]); }, [state.gantt, state.zoom]); //При изменении списка задач useEffect(() => { if (Array.isArray(tasks) && tasks.length > 0) showGantt(); else setState(pv => ({ ...pv, noData: true })); // eslint-disable-next-line react-hooks/exhaustive-deps }, [tasks]); //При подключении компонента к старице useEffect(() => { svgContainerRef.current.children[0].classList.add("scroll"); }, []); //Генерация содержимого return (