forked from CITKParus/P8-Panels
Compare commits
19 Commits
b3cfa176eb
...
ff4a67f375
Author | SHA1 | Date | |
---|---|---|---|
|
ff4a67f375 | ||
|
e70c6b8e84 | ||
d06f3a2db1 | |||
|
624b1bd7be | ||
|
bab08ba1d3 | ||
|
fcc254178f | ||
|
3eba0a52f0 | ||
|
72aa5bc89c | ||
|
dca71f5383 | ||
|
bdc032fa67 | ||
|
6d10f6258b | ||
|
852abd5482 | ||
|
27bd43afb5 | ||
|
83b0c75a3b | ||
|
ba8b7a5ce0 | ||
|
cca42f0b38 | ||
|
9469b01295 | ||
|
40242dedd4 | ||
|
aca423f16e |
38
README.md
38
README.md
@ -104,6 +104,9 @@
|
||||
git clone https://git.citpb.ru/CITKParus/P8-Panels.git
|
||||
```
|
||||
|
||||
> **Внимание:** если при клонировании репозитория возникает ошибка "Server certificate verification failed" - используйте ключ `http.sslVerify=false`:\
|
||||
> `git clone https://git.citpb.ru/CITKParus/P8-Panels.git -c http.sslVerify=false`
|
||||
|
||||
6. Проведите компиляцию хранимых объектов БД из каталога "db" клонированного репозитория (компиляцию проводить под пользователем-владельцем схемы серверной части Системы, с последующей перекомпиляцией зависимых инвалидных объектов), затем исполните скрипт "grants.sql", размещённый в этом же каталоге.
|
||||
|
||||
7. Перезапустите сервер приложений "ПАРУС 8 Онлайн"
|
||||
@ -1291,15 +1294,15 @@ const MyPanel = () => {
|
||||
|
||||
**Свойства**
|
||||
|
||||
`columnsDef` - обязательный, массив, описание колонок таблицы, содержит объекты вида `{caption: <ЗАГОЛОВОК_КОЛОНКИ>, dataType: <ТИП_ДАННЫХ - NUMB|STR|DATE>, filter: <ПРИЗНАК_ВОЗМОЖНОСТИ_ОТБОРА - true|false>, hint: <ОПИСАНИЕ_КОЛОНКИ_МОЖЕТ_СОДЕРЖАТЬ_HTML_РАЗМЕТКУ>, name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, order: <ПРИЗНАК_ВОЗМОЖНОСТИ_СОРТИРОВКИ - true|false>, values: <МАССИВ_ПРЕДОПРЕДЕЛЁННЫХ_ЗНАЧЕНИЙ>, visible: <ПРИЗНАК_ВИДИМОСТИ_КОЛОНКИ - true|false>,expandable: <ПРИЗНАК_РАЗВОРАЧИВАЕМОСТИ_ГРУППОВОГО_ЗАГОЛОВКА - true|false>, expanded: <ПРИЗНАК_РАЗВЕРНУТОСТИ_ГРУППОВОГО_ЗАГОЛОВКА - true|false>, parent: <НАИМЕНОВАНИЕ_РОДИТЕЛЬСКОЙ_КОЛОНКИ_В_ГРУППОВОМ_ЗАГОЛОВКЕ>, width: <ШИРИНА_КОЛОНКИ>}`\
|
||||
`columnsDef` - необязательный, массив, описание колонок таблицы, содержит объекты вида `{caption: <ЗАГОЛОВОК_КОЛОНКИ>, dataType: <ТИП_ДАННЫХ - NUMB|STR|DATE>, filter: <ПРИЗНАК_ВОЗМОЖНОСТИ_ОТБОРА - true|false>, hint: <ОПИСАНИЕ_КОЛОНКИ_МОЖЕТ_СОДЕРЖАТЬ_HTML_РАЗМЕТКУ>, name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, order: <ПРИЗНАК_ВОЗМОЖНОСТИ_СОРТИРОВКИ - true|false>, values: <МАССИВ_ПРЕДОПРЕДЕЛЁННЫХ_ЗНАЧЕНИЙ>, visible: <ПРИЗНАК_ВИДИМОСТИ_КОЛОНКИ - true|false>,expandable: <ПРИЗНАК_РАЗВОРАЧИВАЕМОСТИ_ГРУППОВОГО_ЗАГОЛОВКА - true|false>, expanded: <ПРИЗНАК_РАЗВЕРНУТОСТИ_ГРУППОВОГО_ЗАГОЛОВКА - true|false>, parent: <НАИМЕНОВАНИЕ_РОДИТЕЛЬСКОЙ_КОЛОНКИ_В_ГРУППОВОМ_ЗАГОЛОВКЕ>, width: <ШИРИНА_КОЛОНКИ>}`\
|
||||
`filtersInitial` - необязательныей, массив, начальное состояние фильтров таблицы, содержит объекты вида `{name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, from: <НАЧАЛО_ДИАПАЗОНА_ЗНАЧЕНИЙ_ФИЛЬТРА>, to: <ОКОНЧАНИЕ_ДИАПАЗОНА_ЗНАЧЕНИЙ_ФИЛЬТРА>}`\
|
||||
`groups` - необязательный, массив групп данных, содержит объекты вида `{name: <ИМЯ_ГРУППЫ>, caption: <ЗАГОЛОВОК_ГРУППЫ>, expandable: <ПРИЗНАК_РАЗВОРАЧИВАЕМОСТИ_ГРУППЫ - true|false>, expanded: <ПРИЗНАК_РАЗВЕРНУТОСТИ_ГРУППЫ - true|false>}`\
|
||||
`rows` - обязательный, массив, отображаемые таблицой строки данных, содержит объекты вида `{groupName: <ИМЯ_ГРУППЫ_СОДЕРЖАЩЕЙ_СТРОКУ>, <ИМЯ_КОЛОНКИ>: <ЗНАЧЕНИЕ>}`\
|
||||
`rows` - необязательный, массив, отображаемые таблицой строки данных, содержит объекты вида `{groupName: <ИМЯ_ГРУППЫ_СОДЕРЖАЩЕЙ_СТРОКУ>, <ИМЯ_КОЛОНКИ>: <ЗНАЧЕНИЕ>}`\
|
||||
`size` - необязательный, строка, размер отступов при вёрстке таблицы, `small|medium` (см. константу `P8P_DATA_GRID_SIZE` в исходном коде компонента)\
|
||||
`fixedHeader` - необязательный, логический, признак фиксации заголовка таблицы\
|
||||
`fixedColumns` - необязательный, число, количество фиксированных колонок слева
|
||||
`morePages` - обязательный, логический, признак отображения кнопки догрузки данных\
|
||||
`reloading` - обязательный, логический, признак выполнения обновления данных таблицы (служит для корректной выдачи сообщения об отсуствии данных и корректного отображения "разворачивающихся" строк)\
|
||||
`fixedHeader` - необязательный, логический, признак фиксации заголовка таблицы, по умолчанию - `false`\
|
||||
`fixedColumns` - необязательный, число, количество фиксированных колонок слева, по умолчанию - 0\
|
||||
`morePages` - необязательный, логический, признак отображения кнопки догрузки данных, по умолчанию - `false`\
|
||||
`reloading` - необязательный, логический, признак выполнения обновления данных таблицы (служит для корректной выдачи сообщения об отсуствии данных и корректного отображения "разворачивающихся" строк), по умолчанию - `false`\
|
||||
`expandable` - необязательный, логический, признак необходимости формирования "разворачивающихся" строк, по умолчанию - `false`\
|
||||
`orderAscMenuItemCaption` - обязательный, строка, текст для пункта меню сортировки колонки по возрастанию\
|
||||
`orderDescMenuItemCaption` - обязательный, строка, текст для пункта меню сортировки колонки по убыванию\
|
||||
@ -1635,16 +1638,12 @@ const DataGrid = ({ title }) => {
|
||||
//Собственное состояние - таблица данных
|
||||
const [dataGrid, setDataGrid] = useState({
|
||||
dataLoaded: false,
|
||||
columnsDef: [],
|
||||
filters: null,
|
||||
orders: null,
|
||||
groups: [],
|
||||
rows: [],
|
||||
reloading: true,
|
||||
pageNumber: 1,
|
||||
morePages: true,
|
||||
fixedHeader: false,
|
||||
fixedColumns: 0
|
||||
expandable: true,
|
||||
reloading: true
|
||||
});
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
@ -1670,13 +1669,13 @@ const DataGrid = ({ title }) => {
|
||||
setDataGrid(pv => ({
|
||||
...pv,
|
||||
...data.XDATA_GRID,
|
||||
columnsDef: data.XDATA_GRID.columnsDef ? [...data.XDATA_GRID.columnsDef] : pv.columnsDef,
|
||||
rows: pv.pageNumber == 1 ? [...(data.XDATA_GRID.rows || [])] : [...pv.rows, ...(data.XDATA_GRID.rows || [])],
|
||||
columnsDef: data.XDATA_GRID.columnsDef ? [...data.XDATA_GRID.columnsDef] : pv.columnsDef || [],
|
||||
rows: pv.pageNumber == 1 ? [...(data.XDATA_GRID.rows || [])] : [...(pv.rows || []), ...(data.XDATA_GRID.rows || [])],
|
||||
groups: data.XDATA_GRID.groups
|
||||
? pv.pageNumber == 1
|
||||
? [...data.XDATA_GRID.groups]
|
||||
: [...pv.groups, ...data.XDATA_GRID.groups.filter(g => !pv.groups.find(pg => pg.name == g.name))]
|
||||
: [...pv.groups],
|
||||
: [...(pv.groups || []), ...data.XDATA_GRID.groups.filter(g => !pv.groups.find(pg => pg.name == g.name))]
|
||||
: [...(pv.groups || [])],
|
||||
dataLoaded: true,
|
||||
reloading: false,
|
||||
morePages: (data.XDATA_GRID.rows || []).length >= DATA_GRID_PAGE_SIZE
|
||||
@ -1713,9 +1712,9 @@ const DataGrid = ({ title }) => {
|
||||
{dataGrid.dataLoaded ? (
|
||||
<P8PDataGrid
|
||||
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||
containerComponentProps={{ elevation: 6, style: STYLES.DATA_GRID_CONTAINER }}
|
||||
{...dataGrid}
|
||||
size={P8P_DATA_GRID_SIZE.LARGE}
|
||||
containerComponentProps={{ elevation: 6, style: STYLES.DATA_GRID_CONTAINER }}
|
||||
valueFormatter={valueFormatter}
|
||||
headCellRender={headCellRender}
|
||||
dataCellRender={dataCellRender}
|
||||
@ -1723,7 +1722,6 @@ const DataGrid = ({ title }) => {
|
||||
onOrderChanged={handleOrderChanged}
|
||||
onFilterChanged={handleFilterChanged}
|
||||
onPagesCountChanged={handlePagesCountChanged}
|
||||
expandable={true}
|
||||
rowExpandRender={({ row }) => (
|
||||
<Button onClick={() => handleAgnButtonClicked(row.SAGNABBR)}>Показать в разделе</Button>
|
||||
)}
|
||||
@ -1767,7 +1765,7 @@ const MyPanel = () => {
|
||||
`title` - необязательный, строка, заголовок графика, если не указано - заголовок не отображается\
|
||||
`legendPosition` - необязательный, строка, расположение легенды, может принимать значения `left|right|top|bottom`, если не указано - легенда не отображается\
|
||||
`options` - необязательный, объект, дополнительные параметры графика, формат и допустимый состав атрибутов определены в документации к библиотеке [ChartJS](https://www.chartjs.org/docs/latest/), будет объединён с параметрами графика уже зафиксированными в компоненте `P8PChart` (см. `useEffect` при подключении компонента к старице в его исходном коде, параметры графика, зафиксированные в компоненте, имеют более высокий приоритет по сравнению с данным свойством)
|
||||
`labels` - обязательный, массив строк, список меток для значений графика\
|
||||
`labels` - необязательный, массив строк, список меток для значений графика\
|
||||
`datasets` - необязательный, массив объектов, данные для отображения на диаграмме, каждый элемент массива - серия данных для отображения, содержит объекты вида `{label: <ЗАГОЛОВОК_СЕРИИ>, borderColor: <ЦВЕТ_ГРАНИЦЫ_СЕРИИ_НА_ГРАФИКЕ>, backgroundColor: <ЦВЕТ_ЗАЛИВКИ_СЕРИИ_НА_ГРАФИКЕ>, data: <МАССИВ_ЗНАЧЕНИЙ_СЕРИИ_ДАННЫХ>, items: <МАССИВ_ОБЪЕКТОВ_ПРОИЗВОЛЬНОЙ_СТРУКТУРЫ_ДЛЯ_ОПИСАНИЯ_СЕРИИ_ДАННЫХ>}`\
|
||||
`onClick` - необязательный, функция, будет вызвана при нажатии на элемент графика, сигнатура функции `f({datasetIndex, itemIndex, item})`, результат функции не интерпретируется. Функции будет передан объект, поле `datasetIndex` которого, будет содержать индекс серии данных, `itemIndex` - индекс элемента серии данных, а `item` - описание элмента данных серии, на котором было зафиксировано нажатие.\
|
||||
`style` - необязательный, объект, стили, которые будут применены к контейнеру `div` графика
|
||||
@ -1859,7 +1857,7 @@ const STYLES = {
|
||||
//Пример: Графики "P8PChart"
|
||||
const Chart = ({ title }) => {
|
||||
//Собственное состояние - график
|
||||
const [chart, setChart] = useState({ loaded: false, labels: [], datasets: [] });
|
||||
const [chart, setChart] = useState({ loaded: false });
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored } = useContext(BackEndСtx);
|
||||
|
@ -7,7 +7,7 @@
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React, { useEffect, useRef } from "react"; //Классы React
|
||||
import React, { useCallback, useEffect, useRef } from "react"; //Классы React
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import Chart from "chart.js/auto"; //Диаграммы и графики
|
||||
|
||||
@ -37,23 +37,26 @@ const P8P_CHART_DATASET_SHAPE = PropTypes.shape({
|
||||
//-----------
|
||||
|
||||
//График
|
||||
const P8PChart = ({ type, title, legendPosition, options, labels, datasets, onClick, style }) => {
|
||||
const P8PChart = ({ type, title, legendPosition, options = {}, labels = [], datasets = [], onClick, style }) => {
|
||||
//Ссылки на DOM
|
||||
const chartCanvasRef = useRef(null);
|
||||
const chartRef = useRef(null);
|
||||
|
||||
//Обработка нажатия на элемент графика
|
||||
const handleClick = e => {
|
||||
const bar = chartRef.current.getElementsAtEventForMode(e, "nearest", { intersect: true }, true)[0];
|
||||
if (onClick && bar)
|
||||
onClick({
|
||||
datasetIndex: bar.datasetIndex,
|
||||
itemIndex: bar.index,
|
||||
item: chartRef.current.data.datasets[bar.datasetIndex].items
|
||||
? chartRef.current.data.datasets[bar.datasetIndex].items[bar.index]
|
||||
: null
|
||||
});
|
||||
};
|
||||
const handleClick = useCallback(
|
||||
e => {
|
||||
const bar = chartRef.current.getElementsAtEventForMode(e, "nearest", { intersect: true }, true)[0];
|
||||
if (onClick && bar)
|
||||
onClick({
|
||||
datasetIndex: bar.datasetIndex,
|
||||
itemIndex: bar.index,
|
||||
item: chartRef.current.data.datasets[bar.datasetIndex].items
|
||||
? chartRef.current.data.datasets[bar.datasetIndex].items[bar.index]
|
||||
: null
|
||||
});
|
||||
},
|
||||
[onClick]
|
||||
);
|
||||
|
||||
//При подключении к старнице
|
||||
useEffect(() => {
|
||||
@ -89,9 +92,10 @@ const P8PChart = ({ type, title, legendPosition, options, labels, datasets, onCl
|
||||
if (chartRef.current) {
|
||||
chartRef.current.data.labels = [...labels];
|
||||
chartRef.current.data.datasets = [...datasets];
|
||||
chartRef.current.options.onClick = handleClick;
|
||||
chartRef.current.update();
|
||||
}
|
||||
}, [datasets, labels]);
|
||||
}, [datasets, labels, handleClick]);
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
@ -107,7 +111,7 @@ P8PChart.propTypes = {
|
||||
title: PropTypes.string,
|
||||
legendPosition: PropTypes.string,
|
||||
options: PropTypes.object,
|
||||
labels: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
labels: PropTypes.arrayOf(PropTypes.string),
|
||||
datasets: PropTypes.arrayOf(P8P_CHART_DATASET_SHAPE),
|
||||
onClick: PropTypes.func,
|
||||
style: PropTypes.object
|
||||
|
@ -36,15 +36,15 @@ const P8P_DATA_GRID_FILTERS_HEIGHT = P8P_TABLE_FILTERS_HEIGHT;
|
||||
|
||||
//Таблица данных
|
||||
const P8PDataGrid = ({
|
||||
columnsDef,
|
||||
columnsDef = [],
|
||||
filtersInitial,
|
||||
groups,
|
||||
rows,
|
||||
groups = [],
|
||||
rows = [],
|
||||
size,
|
||||
fixedHeader = false,
|
||||
fixedColumns = 0,
|
||||
morePages = false,
|
||||
reloading,
|
||||
reloading = false,
|
||||
expandable,
|
||||
orderAscMenuItemCaption,
|
||||
orderDescMenuItemCaption,
|
||||
@ -154,15 +154,15 @@ const P8PDataGrid = ({
|
||||
|
||||
//Контроль свойств - Таблица данных
|
||||
P8PDataGrid.propTypes = {
|
||||
columnsDef: PropTypes.array.isRequired,
|
||||
columnsDef: PropTypes.array,
|
||||
filtersInitial: PropTypes.arrayOf(P8P_DATA_GRID_FILTER_SHAPE),
|
||||
groups: PropTypes.array,
|
||||
rows: PropTypes.array.isRequired,
|
||||
rows: PropTypes.array,
|
||||
size: PropTypes.string,
|
||||
fixedHeader: PropTypes.bool,
|
||||
fixedColumns: PropTypes.number,
|
||||
morePages: PropTypes.bool,
|
||||
reloading: PropTypes.bool.isRequired,
|
||||
reloading: PropTypes.bool,
|
||||
expandable: PropTypes.bool,
|
||||
orderAscMenuItemCaption: PropTypes.string.isRequired,
|
||||
orderDescMenuItemCaption: PropTypes.string.isRequired,
|
||||
|
@ -135,7 +135,14 @@ const getPanelsLinks = ({ variant, panels, selectedPanel, group, defaultGroupTyt
|
||||
<Card sx={STYLES.GRID_PANEL_CARD}>
|
||||
{panel.preview ? (
|
||||
<CardMedia component="img" alt={panel.name} image={panel.preview} sx={STYLES.GRID_PANEL_CARD_MEDIA} />
|
||||
) : null}
|
||||
) : (
|
||||
<CardMedia
|
||||
component="img"
|
||||
alt={panel.name}
|
||||
image={"./img/default_preview.png"}
|
||||
sx={STYLES.GRID_PANEL_CARD_MEDIA}
|
||||
/>
|
||||
)}
|
||||
<CardContent>
|
||||
<Stack gap={1} direction="row" sx={STYLES.GRID_PANEL_CARD_CONTENT_TITLE}>
|
||||
{panel.icon ? <Icon sx={STYLES.GRID_PANEL_CARD_CONTENT_TITLE_ICON}>{panel.icon}</Icon> : null}
|
||||
|
@ -89,9 +89,7 @@ const P8P_TABLE_FILTERS_HEIGHT = "48px";
|
||||
|
||||
//Стили
|
||||
const STYLES = {
|
||||
TABLE: {
|
||||
with: "100%"
|
||||
},
|
||||
TABLE: {},
|
||||
TABLE_HEAD_STICKY: {
|
||||
position: "sticky",
|
||||
top: 0,
|
||||
@ -118,7 +116,9 @@ const STYLES = {
|
||||
},
|
||||
TABLE_CELL_EXPAND_CONTAINER: {
|
||||
paddingBottom: 0,
|
||||
paddingTop: 0
|
||||
paddingTop: 0,
|
||||
paddingLeft: 0,
|
||||
paddingRight: 0
|
||||
},
|
||||
TABLE_CELL_GROUP_HEADER: {
|
||||
backgroundColor: "lightgray"
|
||||
@ -486,16 +486,16 @@ P8PTableFiltersChips.propTypes = {
|
||||
|
||||
//Таблица
|
||||
const P8PTable = ({
|
||||
columnsDef,
|
||||
groups,
|
||||
rows,
|
||||
columnsDef = [],
|
||||
groups = [],
|
||||
rows = [],
|
||||
orders,
|
||||
filters,
|
||||
size,
|
||||
fixedHeader = false,
|
||||
fixedColumns = 0,
|
||||
morePages = false,
|
||||
reloading,
|
||||
reloading = false,
|
||||
expandable,
|
||||
orderAscMenuItemCaption,
|
||||
orderDescMenuItemCaption,
|
||||
@ -531,7 +531,9 @@ const P8PTable = ({
|
||||
const [expanded, setExpanded] = useState({});
|
||||
|
||||
//Собственное состояния - развёрнутые группы
|
||||
const [expandedGroups, setExpandedGroups] = useState({});
|
||||
const [expandedGroups, setExpandedGroups] = useState(
|
||||
Array.isArray(groups) && groups.length > 0 ? Object.assign({}, ...groups.map(g => ({ [g.name]: g.expanded }))) : {}
|
||||
);
|
||||
|
||||
//Собственное состояние - колонка с отображаемой подсказкой
|
||||
const [displayHintColumn, setDisplayHintColumn] = useState(null);
|
||||
@ -931,7 +933,7 @@ P8PTable.propTypes = {
|
||||
fixedHeader: PropTypes.bool,
|
||||
fixedColumns: PropTypes.number,
|
||||
morePages: PropTypes.bool,
|
||||
reloading: PropTypes.bool.isRequired,
|
||||
reloading: PropTypes.bool,
|
||||
expandable: PropTypes.bool,
|
||||
orderAscMenuItemCaption: PropTypes.string.isRequired,
|
||||
orderDescMenuItemCaption: PropTypes.string.isRequired,
|
||||
|
@ -107,7 +107,6 @@ const deepCopyObject = obj => JSON.parse(JSON.stringify(obj));
|
||||
//Конвертация объекта в Base64 XML
|
||||
const object2Base64XML = (obj, builderOptions) => {
|
||||
const builder = new XMLBuilder(builderOptions);
|
||||
//onOrderChanged({ orders: btoa(ordersBuilder.build(newOrders)) });
|
||||
return btoa(unescape(encodeURIComponent(builder.build(obj))));
|
||||
};
|
||||
|
||||
|
170
app/panels/prj_info/filter.js
Normal file
170
app/panels/prj_info/filter.js
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Фильтр
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React, { useState } from "react"; //Классы React
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import { Grid, Chip, Stack, Input, InputAdornment, IconButton, Icon } from "@mui/material"; //Интерфейсные элементы
|
||||
import { FILTER_INITIAL, FILTER_ITEMS, PRICE_STRUCT_STATUS, PROJECT_STATE, FilterDialog } from "./filter_dialog"; //Компонент "Диалог фильтра"
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
//---------
|
||||
|
||||
//Стили
|
||||
const STYLES = {
|
||||
CONTAINER: { paddingTop: "10px" },
|
||||
FILTER: { maxWidth: "99vw" },
|
||||
SEARCH_GRID_ITEM: { paddingRight: "15px" }
|
||||
};
|
||||
|
||||
//------------------------------------
|
||||
//Вспомогательные функции и компоненты
|
||||
//------------------------------------
|
||||
|
||||
//Элемент фильтра
|
||||
const FilterItem = ({ caption, value, defaultValue, onClick, onDelete }) => {
|
||||
//При нажатии на элемент
|
||||
const handleClick = () => (onClick ? onClick() : null);
|
||||
|
||||
//При нажатии на удаление элемента
|
||||
const handleDelete = () => (onDelete ? onDelete() : null);
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<Chip
|
||||
label={
|
||||
<Stack direction={"row"} alignItems={"center"}>
|
||||
<strong>{caption}</strong>: {value || defaultValue}
|
||||
</Stack>
|
||||
}
|
||||
variant="outlined"
|
||||
onClick={handleClick}
|
||||
onDelete={onDelete ? handleDelete : null}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
//Контроль свойств компонента - Элемент фильтра
|
||||
FilterItem.propTypes = {
|
||||
caption: PropTypes.string.isRequired,
|
||||
value: PropTypes.any,
|
||||
defaultValue: PropTypes.string.isRequired,
|
||||
onClick: PropTypes.func,
|
||||
onDelete: PropTypes.func
|
||||
};
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Фильтр
|
||||
const Filter = ({ values, onChange }) => {
|
||||
//Собственное состояние - отображение диалога ввода значений фильтра
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
//Собственное состояние - строка поиска
|
||||
const [search, setSearch] = useState(values.search);
|
||||
|
||||
//Передача сообщения об измении фильтра родителю
|
||||
const notifyChange = values => (onChange ? onChange(values) : null);
|
||||
|
||||
//При закрытии диалога с сохранением значений
|
||||
const handleFilterDialogOk = values => {
|
||||
setIsOpen(false);
|
||||
notifyChange(values);
|
||||
};
|
||||
|
||||
//При закрытии диалога без сохранения значений
|
||||
const handleFilterDialogCancel = () => setIsOpen(false);
|
||||
|
||||
//При нажатии на фильтр
|
||||
const handleClick = () => setIsOpen(true);
|
||||
|
||||
//При выполнении поиска
|
||||
const handleDoSearch = (clear = false) => {
|
||||
if (clear === true) setSearch("");
|
||||
notifyChange({ ...values, search: clear === true ? "" : search });
|
||||
};
|
||||
|
||||
//При изменении значения в строке поиска
|
||||
const handleSearchChange = e => setSearch(e.target.value);
|
||||
|
||||
//При нажатии клавиши в строке поиска
|
||||
const handleSearchKeyPress = e => ([13, 27].includes(e.keyCode) ? handleDoSearch(e.keyCode == 27) : null);
|
||||
|
||||
//Формирование функции обработки очистки элемента фильтар
|
||||
const buildFilterItemClearHandler = сode =>
|
||||
values[сode] != FILTER_INITIAL[сode] ? () => notifyChange({ ...values, [сode]: FILTER_INITIAL[сode] }) : null;
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<Grid container sx={STYLES.CONTAINER}>
|
||||
<Grid xs={10} item>
|
||||
{isOpen ? <FilterDialog valuesInitial={values} onOk={handleFilterDialogOk} onCancel={handleFilterDialogCancel} /> : null}
|
||||
<Stack direction="row" spacing={1} p={1} alignItems={"center"} sx={STYLES.FILTER} onClick={handleClick}>
|
||||
<FilterItem
|
||||
caption={"Тип заказа"}
|
||||
value={values.prjType}
|
||||
defaultValue={"Любой"}
|
||||
onDelete={buildFilterItemClearHandler("prjType")}
|
||||
/>
|
||||
<FilterItem
|
||||
caption={"Подразделение-ответственный"}
|
||||
defaultValue={"Любое"}
|
||||
value={values.insDep}
|
||||
onDelete={buildFilterItemClearHandler("insDep")}
|
||||
/>
|
||||
<FilterItem
|
||||
caption={"Статус структуры цены"}
|
||||
defaultValue={"Неподдерживаемое значение"}
|
||||
value={PRICE_STRUCT_STATUS.find(item => item.value == values.priceStructStatus)?.name}
|
||||
onDelete={buildFilterItemClearHandler("priceStructStatus")}
|
||||
/>
|
||||
<FilterItem
|
||||
caption={"Состояние проекта"}
|
||||
defaultValue={"Неподдерживаемое значение"}
|
||||
value={PROJECT_STATE.find(item => item.value == values.prjState)?.name}
|
||||
onDelete={buildFilterItemClearHandler("prjState")}
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid xs={2} item sx={STYLES.SEARCH_GRID_ITEM}>
|
||||
<Input
|
||||
fullWidth
|
||||
placeholder="Поиск..."
|
||||
value={search}
|
||||
endAdornment={
|
||||
<InputAdornment position="end">
|
||||
<IconButton onClick={() => handleDoSearch(true)}>
|
||||
<Icon>clear</Icon>
|
||||
</IconButton>
|
||||
<IconButton onClick={handleDoSearch}>
|
||||
<Icon>search</Icon>
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
}
|
||||
onKeyDown={handleSearchKeyPress}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
//Контроль свойств компонента - Фильтр
|
||||
Filter.propTypes = {
|
||||
values: FILTER_ITEMS.isRequired,
|
||||
onChange: PropTypes.func
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { FILTER_INITIAL, Filter };
|
147
app/panels/prj_info/filter_dialog.js
Normal file
147
app/panels/prj_info/filter_dialog.js
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Диалог фильтра
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React, { useState, useContext } from "react"; //Классы React
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import { Button, Dialog, DialogTitle, DialogContent, DialogActions } from "@mui/material"; //Интерфейсные элементы
|
||||
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
|
||||
import { BUTTONS } from "../../../app.text"; //Типовые тексты
|
||||
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
|
||||
import { FormField } from "./layouts"; //Общие компоненты панели
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
//---------
|
||||
|
||||
//Стили
|
||||
const STYLES = {
|
||||
DIALOG_CONTENT: { overflowY: "auto", ...APP_STYLES.SCROLL }
|
||||
};
|
||||
|
||||
//Структура фильтра
|
||||
const FILTER_ITEMS = PropTypes.shape({
|
||||
prjType: PropTypes.string,
|
||||
insDep: PropTypes.string,
|
||||
priceStructStatus: PropTypes.number.isRequired,
|
||||
prjState: PropTypes.number.isRequired,
|
||||
search: PropTypes.string
|
||||
});
|
||||
|
||||
//Начальное состояние фильтра
|
||||
const FILTER_INITIAL = { prjType: "", insDep: "", priceStructStatus: 0, prjState: 0, search: "" };
|
||||
|
||||
//Статусы структуры цены
|
||||
const PRICE_STRUCT_STATUS = [
|
||||
{ value: 0, name: "Все" },
|
||||
{ value: 1, name: "Есть статьи с расходом больше 90%" },
|
||||
{ value: 2, name: "Есть статьи с перерасходом" }
|
||||
];
|
||||
|
||||
//Состояния проекта
|
||||
const PROJECT_STATE = [
|
||||
{ value: 0, name: "Все" },
|
||||
{ value: 1, name: "Открытые" },
|
||||
{ value: 2, name: "Неоткрытые" }
|
||||
];
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Диалог фильтра
|
||||
const FilterDialog = ({ valuesInitial, onOk, onCancel }) => {
|
||||
//Собственное состояние элементов фильтра
|
||||
const [values, setValues] = useState({ ...valuesInitial });
|
||||
|
||||
//Подключение к контексту приложения
|
||||
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
|
||||
|
||||
//Изменение элемента формы фильтра
|
||||
const handleValueChanged = (name, value) => setValues(pv => ({ ...pv, [name]: value }));
|
||||
|
||||
//Сброс настроек фильтра
|
||||
const handleResetClick = () => setValues({ ...FILTER_INITIAL });
|
||||
|
||||
//Сохранение фильтра
|
||||
const handleOkClick = () => (onOk ? onOk(values) : null);
|
||||
|
||||
//Отмена фильтра
|
||||
const handleCancelClick = () => (onCancel ? onCancel() : null);
|
||||
|
||||
//Выбор значения элемента формы из словаря
|
||||
const selectFromDictionary = (unitCode, name, applyValue) => {
|
||||
pOnlineShowDictionary({
|
||||
unitCode,
|
||||
showMethod: "main",
|
||||
inputParameters: [{ name: "in_CODE", value: values[name] }],
|
||||
callBack: res => applyValue(res.success ? [{ name, value: res.outParameters.out_CODE }] : null)
|
||||
});
|
||||
};
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<Dialog open onClose={handleCancelClick} fullWidth maxWidth={"md"}>
|
||||
<DialogTitle>Фильтр отбора</DialogTitle>
|
||||
<DialogContent sx={STYLES.DIALOG_CONTENT}>
|
||||
<FormField
|
||||
elementCode={"prjType"}
|
||||
elementValue={values.prjType}
|
||||
labelText={"Тип заказа"}
|
||||
onChange={handleValueChanged}
|
||||
dictionary={applyValue => selectFromDictionary("ProjectTypes", "prjType", applyValue)}
|
||||
/>
|
||||
<FormField
|
||||
elementCode={"insDep"}
|
||||
elementValue={values.insDep}
|
||||
labelText={"Подразделение-ответственный"}
|
||||
onChange={handleValueChanged}
|
||||
dictionary={applyValue => selectFromDictionary("INS_DEPARTMENT", "insDep", applyValue)}
|
||||
/>
|
||||
<FormField
|
||||
elementCode={"priceStructStatus"}
|
||||
elementValue={values.priceStructStatus}
|
||||
labelText={"Статус структуры цены"}
|
||||
onChange={handleValueChanged}
|
||||
list={PRICE_STRUCT_STATUS}
|
||||
/>
|
||||
<FormField
|
||||
elementCode={"prjState"}
|
||||
elementValue={values.prjState}
|
||||
labelText={"Состояние проекта"}
|
||||
onChange={handleValueChanged}
|
||||
list={PROJECT_STATE}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions sx={STYLES.DIALOG_ACTIONS}>
|
||||
<Button variant="text" onClick={handleOkClick}>
|
||||
{BUTTONS.OK}
|
||||
</Button>
|
||||
<Button variant="text" onClick={handleResetClick}>
|
||||
{BUTTONS.CLEAR}
|
||||
</Button>
|
||||
<Button variant="text" onClick={handleCancelClick}>
|
||||
{BUTTONS.CANCEL}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
//Контроль свойств компонента - Диалог фильтра
|
||||
FilterDialog.propTypes = {
|
||||
valuesInitial: FILTER_ITEMS.isRequired,
|
||||
onOk: PropTypes.func,
|
||||
onCancel: PropTypes.func
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { FILTER_ITEMS, FILTER_INITIAL, PRICE_STRUCT_STATUS, PROJECT_STATE, FilterDialog };
|
16
app/panels/prj_info/index.js
Normal file
16
app/panels/prj_info/index.js
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Панель мониторинга: точка входа
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import { PrjInfo } from "./prj_info"; //Корневая панель информации о проектах
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export const RootClass = PrjInfo;
|
168
app/panels/prj_info/layouts.js
Normal file
168
app/panels/prj_info/layouts.js
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Общие дополнительная разметка и вёрстка клиентских элементов
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React, { useState, useEffect } from "react"; //Классы React
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import { Box, Icon, Input, InputAdornment, FormControl, Select, InputLabel, MenuItem, IconButton, Typography, Switch, Stack } from "@mui/material"; //Интерфейсные компоненты
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
//---------
|
||||
|
||||
//Стили
|
||||
const STYLES = {
|
||||
STATE: value => ({ color: value === 1 ? "green" : "black" }),
|
||||
COST_STATUS: color => ({ color, verticalAlign: "middle" }),
|
||||
COST_READY: value => ({ color: value <= 30 ? "red" : value >= 80 ? "green" : "#e2af00" }),
|
||||
TOGGLE_COLOR: checked => ({ color: checked ? "#006dd9" : "lightgrey" })
|
||||
};
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Поле ввода формы
|
||||
const FormField = ({ elementCode, elementValue, labelText, onChange, dictionary, list, type, ...other }) => {
|
||||
//Значение элемента
|
||||
const [value, setValue] = useState(elementValue);
|
||||
|
||||
//При получении нового значения из вне
|
||||
useEffect(() => {
|
||||
setValue(elementValue);
|
||||
}, [elementValue]);
|
||||
|
||||
//Выбор значения из словаря
|
||||
const handleDictionaryClick = () =>
|
||||
dictionary ? dictionary(res => (res ? res.map(i => handleChange({ target: { name: i.name, value: i.value } })) : null)) : null;
|
||||
|
||||
//Изменение значения элемента (по событию)
|
||||
const handleChange = e => {
|
||||
setValue(e.target.value);
|
||||
if (onChange) onChange(e.target.name, e.target.value);
|
||||
};
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<Box p={1}>
|
||||
<FormControl variant="standard" fullWidth {...other}>
|
||||
{list ? (
|
||||
<>
|
||||
<InputLabel id={`${elementCode}Lable`} shrink>
|
||||
{labelText}
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId={`${elementCode}Lable`}
|
||||
id={elementCode}
|
||||
name={elementCode}
|
||||
label={labelText}
|
||||
value={value || value == 0 ? value : ""}
|
||||
onChange={handleChange}
|
||||
displayEmpty
|
||||
>
|
||||
{list.map((item, i) => (
|
||||
<MenuItem key={i} value={item.value || item.value == 0 ? item.value : ""}>
|
||||
{item.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<InputLabel {...(type == "date" ? { shrink: true } : {})} htmlFor={elementCode}>
|
||||
{labelText}
|
||||
</InputLabel>
|
||||
<Input
|
||||
id={elementCode}
|
||||
name={elementCode}
|
||||
value={value || value == 0 ? value : ""}
|
||||
endAdornment={
|
||||
dictionary ? (
|
||||
<InputAdornment position="end">
|
||||
<IconButton aria-label={`${elementCode} select`} onClick={handleDictionaryClick} edge="end">
|
||||
<Icon>list</Icon>
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
) : null
|
||||
}
|
||||
{...(type ? { type } : {})}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</FormControl>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
//Контроль свойств - Поле ввода формы
|
||||
FormField.propTypes = {
|
||||
elementCode: PropTypes.string.isRequired,
|
||||
elementValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.instanceOf(Date)]),
|
||||
labelText: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func,
|
||||
dictionary: PropTypes.func,
|
||||
list: PropTypes.array,
|
||||
type: PropTypes.string
|
||||
};
|
||||
|
||||
//Переключатель
|
||||
const Toggle = ({ labels, checked, onChange }) => {
|
||||
//Обработка переключения
|
||||
const handleChange = event => (onChange ? onChange(event.target.checked) : null);
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<Stack direction={"row"} spacing={1} alignItems={"center"} justifyContent={"center"}>
|
||||
<Typography sx={STYLES.TOGGLE_COLOR(!checked)}>{labels[0]}</Typography>
|
||||
<Switch checked={checked} size="small" onChange={handleChange} />
|
||||
<Typography sx={STYLES.TOGGLE_COLOR(checked)}>{labels[1]}</Typography>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
//Контроль свойств компонента - Переключатель
|
||||
Toggle.propTypes = {
|
||||
labels: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
checked: PropTypes.bool.isRequired,
|
||||
onChange: PropTypes.func
|
||||
};
|
||||
|
||||
//Формирование значения для колонки "Статус структуры цены"
|
||||
const formatCostStatusValue = ({ value, onClick, type = 1 }) => {
|
||||
const [text, color] =
|
||||
value == 0
|
||||
? ["Без отклонений", "lightgreen"]
|
||||
: value == 1
|
||||
? [type == 1 ? "Есть статьи с расходом более 90%" : "Расход более 90%", "#ffdf71"]
|
||||
: value == 2
|
||||
? [type == 1 ? "Есть статьи с перерасходом" : "Перерасход", "#eb6b6b"]
|
||||
: ["Не определено", "lightgray"];
|
||||
return onClick ? (
|
||||
<IconButton onClick={onClick}>
|
||||
<Icon sx={STYLES.COST_STATUS(color)} title={`${text}\nНажмите для детальной информации`}>
|
||||
circle
|
||||
</Icon>
|
||||
</IconButton>
|
||||
) : (
|
||||
<Icon sx={STYLES.COST_STATUS(color)} title={text}>
|
||||
circle
|
||||
</Icon>
|
||||
);
|
||||
};
|
||||
|
||||
//Формирование значения для колонки "Готов (%, зтраты)"
|
||||
const formatCostReadyValue = value => {
|
||||
return <span style={STYLES.COST_READY(value)}>{value}</span>;
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { STYLES as COMMON_STYLES, FormField, Toggle, formatCostStatusValue, formatCostReadyValue };
|
27
app/panels/prj_info/prj_info.js
Normal file
27
app/panels/prj_info/prj_info.js
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Корневой компонент панели
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React from "react"; //Классы React
|
||||
import { Projects } from "./projects"; //Список проектов
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Корневой компонент панели "Информация о проектах"
|
||||
const PrjInfo = () => {
|
||||
//Генерация содержимого
|
||||
return <Projects />;
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { PrjInfo };
|
70
app/panels/prj_info/projects.js
Normal file
70
app/panels/prj_info/projects.js
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Список проектов
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React, { useState, useContext } from "react"; //Классы React
|
||||
import { P8PDataGrid } from "../../components/p8p_data_grid"; //Таблица данных
|
||||
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
||||
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
|
||||
import { useProjectsDataGrid } from "./projects_hooks"; //Хуки списка проектов
|
||||
import { FILTER_INITIAL, Filter } from "./filter"; //Компонент "Фильтр"
|
||||
import { PROJECTS_STYLES, projectDataCellRender, projectRowExpandRender } from "./projects_layouts"; //Дополнительная разметка и вёрстка клиентских элементов
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Список проектов
|
||||
const Projects = () => {
|
||||
//Собственное состояние
|
||||
const [projects, setProjects] = useState({ pageNumber: 1, orders: [], filter: { ...FILTER_INITIAL } });
|
||||
|
||||
//Состояние таблицы проектов
|
||||
const [projectsDataGrid] = useProjectsDataGrid({ ...projects.filter, pageNumber: projects.pageNumber, orders: projects.orders });
|
||||
|
||||
//Подключение к контексту приложения
|
||||
const { pOnlineShowDocument } = useContext(ApplicationСtx);
|
||||
|
||||
//Отображение записи проекта в штатном разделе
|
||||
const showProject = async rn => pOnlineShowDocument({ unitCode: "Projects", document: rn, modal: false });
|
||||
|
||||
//При изменении количества отображаемых страниц
|
||||
const handlePagesCountChanged = () => setProjects(pv => ({ ...pv, pageNumber: pv.pageNumber + 1 }));
|
||||
|
||||
//При изменении состояния сортировки
|
||||
const handleOrderChanged = ({ orders }) => setProjects(pv => ({ ...pv, orders: [...orders], pageNumber: 1 }));
|
||||
|
||||
//При изменении фильтра
|
||||
const handleFilterChanged = values => setProjects(pv => ({ ...pv, filter: { ...values }, pageNumber: 1 }));
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<>
|
||||
<Filter values={projects.filter} onChange={handleFilterChanged} />
|
||||
{projectsDataGrid.init ? (
|
||||
<P8PDataGrid
|
||||
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||
{...projectsDataGrid}
|
||||
containerComponentProps={{ sx: PROJECTS_STYLES.DATA_GRID_CONTAINER(projectsDataGrid.morePages), elevation: 0 }}
|
||||
expandable={true}
|
||||
fixedHeader={true}
|
||||
onPagesCountChanged={handlePagesCountChanged}
|
||||
onOrderChanged={handleOrderChanged}
|
||||
dataCellRender={prms => projectDataCellRender({ ...prms, showProject })}
|
||||
rowExpandRender={projectRowExpandRender}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { Projects };
|
82
app/panels/prj_info/projects_hooks.js
Normal file
82
app/panels/prj_info/projects_hooks.js
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Список проектов: пользовательские хуки для взаимодействия с сервером
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import { useState, useContext, useEffect } from "react"; //Классы React
|
||||
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
||||
import { object2Base64XML, formatDateRF } from "../../core/utils"; //Вспомогательные функции
|
||||
import config from "../../../app.config"; //Настройки приложения
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
//---------
|
||||
|
||||
//Размер страницы данных
|
||||
const DATA_GRID_PAGE_SIZE = config.SYSTEM.PAGE_SIZE;
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Получение данных проектов с сервера
|
||||
const useProjectsDataGrid = ({ prjType, insDep, priceStructStatus, prjState, search, pageNumber, orders }) => {
|
||||
//Собственное состояние - флаг загрузки
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
|
||||
//Собственное состояние - таблица данных
|
||||
const [data, setData] = useState({ init: false, morePages: true });
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
|
||||
|
||||
//При необходимости обновить данные таблицы
|
||||
useEffect(() => {
|
||||
//Загрузка данных таблицы с сервера
|
||||
const loadData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await executeStored({
|
||||
stored: "PKG_P8PANELS_PROJECTS.INFO_PROJECTS_DG",
|
||||
args: {
|
||||
SPRJ_TYPE: prjType,
|
||||
SINS_DEPARTMENT: insDep,
|
||||
NCOST_STATUS: priceStructStatus,
|
||||
NSTATE: prjState,
|
||||
SSEARCH: search,
|
||||
CORDERS: { VALUE: object2Base64XML(orders, { arrayNodeName: "orders" }), SDATA_TYPE: SERV_DATA_TYPE_CLOB },
|
||||
NPAGE_NUMBER: pageNumber,
|
||||
NPAGE_SIZE: DATA_GRID_PAGE_SIZE,
|
||||
NINCLUDE_DEF: pageNumber == 1 ? 1 : 0
|
||||
},
|
||||
respArg: "COUT",
|
||||
loader: true,
|
||||
attributeValueProcessor: (name, val) => (["DBEGPLAN", "DENDPLAN"].includes(name) ? formatDateRF(val) : val)
|
||||
});
|
||||
setData(pv => ({
|
||||
...pv,
|
||||
columnsDef: data.XDATA_GRID.columnsDef ? [...data.XDATA_GRID.columnsDef] : pv.columnsDef || [],
|
||||
rows: pageNumber == 1 ? [...(data.XDATA_GRID.rows || [])] : [...(pv.rows || []), ...(data.XDATA_GRID.rows || [])],
|
||||
morePages: DATA_GRID_PAGE_SIZE == 0 ? false : (data.XDATA_GRID.rows || []).length >= DATA_GRID_PAGE_SIZE,
|
||||
init: true
|
||||
}));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
loadData();
|
||||
}, [prjType, insDep, priceStructStatus, prjState, search, pageNumber, orders, executeStored, SERV_DATA_TYPE_CLOB]);
|
||||
|
||||
//Возвращаем интерфейс хука
|
||||
return [data, isLoading];
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { useProjectsDataGrid };
|
96
app/panels/prj_info/projects_layouts.js
Normal file
96
app/panels/prj_info/projects_layouts.js
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Список проектов: дополнительная разметка и вёрстка клиентских элементов
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React from "react"; //Классы React
|
||||
import { Icon, Stack, Paper, Link } from "@mui/material"; //Интерфейсные элементы
|
||||
import { P8P_DATA_GRID_MORE_HEIGHT } from "../../components/p8p_data_grid"; //Таблица данных
|
||||
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
|
||||
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
|
||||
import { COMMON_STYLES, formatCostStatusValue, formatCostReadyValue } from "./layouts"; //Общие стили и разметка панели
|
||||
import { Stages } from "./stages"; //Компонент "Этапы проекта"
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
//---------
|
||||
|
||||
//Высота фильтра (пиксели)
|
||||
const FILTER_HEIGHT = "60px";
|
||||
|
||||
//Стили
|
||||
const STYLES = {
|
||||
DATA_GRID_CONTAINER: morePages => ({
|
||||
height: `calc(100vh - ${APP_BAR_HEIGHT} - ${FILTER_HEIGHT} - ${morePages ? P8P_DATA_GRID_MORE_HEIGHT : "0px"} - 8px)`,
|
||||
...APP_STYLES.SCROLL
|
||||
})
|
||||
};
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Формирование значения для колонки "Состояние" проекта
|
||||
const formatPrjStateValue = value => {
|
||||
const [text, icon] =
|
||||
value == 0
|
||||
? ["Зарегистрирован", "app_registration"]
|
||||
: value == 1
|
||||
? ["Открыт", "lock_open"]
|
||||
: value == 2
|
||||
? ["Остановлен", "do_not_disturb_on"]
|
||||
: value == 3
|
||||
? ["Закрыт", "lock_outline"]
|
||||
: value == 4
|
||||
? ["Согласован", "thumb_up_alt"]
|
||||
: ["Исполнение прекращено", "block"];
|
||||
return (
|
||||
<Stack direction="row" gap={0.5} alignItems="center" justifyContent="center">
|
||||
<Icon title={text} sx={COMMON_STYLES.STATE(value)}>
|
||||
{icon}
|
||||
</Icon>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
//Форматирование ячеек таблицы "Проекты"
|
||||
const projectDataCellRender = ({ row, columnDef, showProject }) => {
|
||||
//Формирование представлений
|
||||
switch (columnDef.name) {
|
||||
case "NCOST_STATUS":
|
||||
return { cellProps: { align: "center" }, data: formatCostStatusValue({ value: row[columnDef.name] }) };
|
||||
case "NCOST_READY":
|
||||
return { cellProps: { align: "center" }, data: formatCostReadyValue(row[columnDef.name]) };
|
||||
case "NSTATE":
|
||||
return { cellProps: { align: "center" }, data: formatPrjStateValue(row[columnDef.name]) };
|
||||
case "SCODE":
|
||||
return {
|
||||
data: (
|
||||
<Link component="button" align="left" underline="hover" onClick={() => showProject(row["NRN"])}>
|
||||
{row[columnDef.name]}
|
||||
</Link>
|
||||
)
|
||||
};
|
||||
default:
|
||||
return { data: row[columnDef.name] };
|
||||
}
|
||||
};
|
||||
|
||||
//Генерация представления расширения строки таблицы "Проектов"
|
||||
const projectRowExpandRender = ({ row }) => {
|
||||
return (
|
||||
<Paper elevation={6}>
|
||||
<Stages projectRn={row.NRN} projectCode={row.SCODE} />
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { STYLES as PROJECTS_STYLES, projectDataCellRender, projectRowExpandRender };
|
173
app/panels/prj_info/stage_detail.js
Normal file
173
app/panels/prj_info/stage_detail.js
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Детальная информация об этапе проекта
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React, { useState, useContext } from "react"; //Классы React
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import { Grid, Box, Typography, Paper, Drawer, IconButton, Icon } from "@mui/material"; //Интерфейсные элементы
|
||||
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
|
||||
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
||||
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
|
||||
import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы
|
||||
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
|
||||
import { P8PChart } from "../../components/p8p_chart"; //График
|
||||
import { P8PAppInlineError } from "../../components/p8p_app_message"; //Встраиваемое сообщение об ошибке
|
||||
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
||||
import { useStageDetailInfoDataGrid, useStageDetailArtsDataGrid, useStageDetailArtsChart } from "./stage_detail_hooks"; //Хуки детализации этапов проекта
|
||||
import { Toggle } from "./layouts"; //Общая разметка и компоненты панели
|
||||
import {
|
||||
STAGE_DETAIL_STYLES,
|
||||
stageDetailInfoHeadCellRender,
|
||||
stageDetailInfoDataCellRender,
|
||||
stageDetailArtsHeadCellRender,
|
||||
stageDetailArtsDataCellRender
|
||||
} from "./stage_detail_layouts"; //Дополнительная разметка и вёрстка клиентских элементов
|
||||
|
||||
//------------------------------------
|
||||
//Вспомогательные функции и компоненты
|
||||
//------------------------------------
|
||||
|
||||
//Данные этапа
|
||||
const StageDetailData = ({ stageRn }) => {
|
||||
//Собственное состояние
|
||||
const [state, setState] = useState({ artsDisplayType: 0, artsChartType: 0 });
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored } = useContext(BackEndСtx);
|
||||
|
||||
//Подключение к контексту приложения
|
||||
const { pOnlineShowUnit } = useContext(ApplicationСtx);
|
||||
|
||||
//Подключение к контексту сообщений
|
||||
const { showMsgErr } = useContext(MessagingСtx);
|
||||
|
||||
//Отображение журнала затрат (фактического, по рег. номеру ЛС и статьи затрат)
|
||||
const showCostNotesFact = async ({ faceAccRn, artclRn }) => {
|
||||
const data = await executeStored({
|
||||
stored: "PKG_P8PANELS_PROJECTS.INFO_FCCOSTNOTES_FACT_SELECT",
|
||||
args: { NFACEACC: faceAccRn, NFPDARTCL: artclRn }
|
||||
});
|
||||
if (data.NIDENT) pOnlineShowUnit({ unitCode: "CostNotes", inputParameters: [{ name: "in_IDENT", value: data.NIDENT }] });
|
||||
else showMsgErr(TEXTS.NO_DATA_FOUND);
|
||||
};
|
||||
|
||||
//Состояние таблицы с информацией об этапе
|
||||
const [stageDeatilInfoDataGrid] = useStageDetailInfoDataGrid({ stageRn });
|
||||
|
||||
//Состояние таблицы с данными структуры цены
|
||||
const [stageDeatilArtsDataGrid] = useStageDetailArtsDataGrid({ stageRn });
|
||||
|
||||
//Состояние графика с данными структуры цены
|
||||
const [stageDeatilArtsChart] = useStageDetailArtsChart({ stageRn, display: state.artsDisplayType == 1, type: state.artsChartType });
|
||||
|
||||
//При изменении способа отображения структуры цены
|
||||
const handleArtsDisplayTypeChange = checked => setState(pv => ({ ...pv, artsDisplayType: checked ? 1 : 0 }));
|
||||
|
||||
//При изменении типа данных графика структуры цены
|
||||
const handleArtsChartTypeChange = checked => setState(pv => ({ ...pv, artsChartType: checked ? 1 : 0 }));
|
||||
|
||||
//Отработка нажатия на график
|
||||
const handleChartClick = ({ item }) =>
|
||||
state.artsChartType === 1 && item.NFACEACC && item.NFPDARTCL
|
||||
? showCostNotesFact({ faceAccRn: item.NFACEACC, artclRn: item.NFPDARTCL })
|
||||
: null;
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<Grid container spacing={2} sx={STAGE_DETAIL_STYLES.DATA_AREA_CONTAINER}>
|
||||
<Grid item xs={5}>
|
||||
<Typography variant={"h6"} sx={STAGE_DETAIL_STYLES.DATA_AREA_HEADER}>
|
||||
Сведения
|
||||
</Typography>
|
||||
{stageDeatilInfoDataGrid.init ? (
|
||||
<P8PDataGrid
|
||||
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||
containerComponentProps={{ sx: STAGE_DETAIL_STYLES.DATA_AREA, elevation: 6 }}
|
||||
{...stageDeatilInfoDataGrid}
|
||||
size={P8P_DATA_GRID_SIZE.SMALL}
|
||||
fixedHeader={true}
|
||||
headCellRender={stageDetailInfoHeadCellRender}
|
||||
dataCellRender={stageDetailInfoDataCellRender}
|
||||
/>
|
||||
) : null}
|
||||
</Grid>
|
||||
<Grid item xs={7}>
|
||||
<Box sx={STAGE_DETAIL_STYLES.DATA_AREA_HEADER_CONTAINER}>
|
||||
<Typography variant={"h6"} sx={STAGE_DETAIL_STYLES.DATA_AREA_HEADER}>
|
||||
Структура цены
|
||||
</Typography>
|
||||
<Toggle labels={["Таблица", "График"]} checked={state.artsDisplayType === 1} onChange={handleArtsDisplayTypeChange} />
|
||||
</Box>
|
||||
{state.artsDisplayType === 0 ? (
|
||||
stageDeatilArtsDataGrid.init ? (
|
||||
<P8PDataGrid
|
||||
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||
containerComponentProps={{ sx: STAGE_DETAIL_STYLES.DATA_AREA, elevation: 6 }}
|
||||
{...stageDeatilArtsDataGrid}
|
||||
size={P8P_DATA_GRID_SIZE.SMALL}
|
||||
fixedHeader={true}
|
||||
headCellRender={stageDetailArtsHeadCellRender}
|
||||
dataCellRender={prms => stageDetailArtsDataCellRender({ ...prms, showCostNotesFact })}
|
||||
/>
|
||||
) : null
|
||||
) : (
|
||||
<Paper elevation={6} sx={STAGE_DETAIL_STYLES.DATA_AREA}>
|
||||
<Box sx={STAGE_DETAIL_STYLES.CHART_CONTAINER}>
|
||||
<Toggle labels={["План", "Факт"]} checked={state.artsChartType === 1} onChange={handleArtsChartTypeChange} />
|
||||
{stageDeatilArtsDataGrid?.rows?.length > 0 ? (
|
||||
stageDeatilArtsChart.init ? (
|
||||
<P8PChart style={STAGE_DETAIL_STYLES.CHART} {...stageDeatilArtsChart} onClick={handleChartClick} />
|
||||
) : null
|
||||
) : (
|
||||
<P8PAppInlineError text={TEXTS.NO_DATA_FOUND} />
|
||||
)}
|
||||
</Box>
|
||||
</Paper>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
//Контроль свойств компонента - Данные этапа
|
||||
StageDetailData.propTypes = {
|
||||
stageRn: PropTypes.number
|
||||
};
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Детальная информация об этапе проекта
|
||||
const StageDetail = ({ stageRn, stageName, isOpen, onClose }) => {
|
||||
return (
|
||||
<Drawer anchor={"right"} open={isOpen} onClose={onClose} sx={STAGE_DETAIL_STYLES.STAGE_DETAIL_DRAWER}>
|
||||
<Box sx={STAGE_DETAIL_STYLES.STAGE_DETAIL_HEADER}>
|
||||
<IconButton sx={STAGE_DETAIL_STYLES.STAGE_DETAIL_CLOSE_BUTTON} size={"small"} onClick={onClose}>
|
||||
<Icon>close</Icon>
|
||||
</IconButton>
|
||||
<Typography variant={"h6"} color={"white"} pl={2}>{`Этап: ${stageName}`}</Typography>
|
||||
</Box>
|
||||
<StageDetailData stageRn={stageRn} />
|
||||
</Drawer>
|
||||
);
|
||||
};
|
||||
|
||||
//Контроль свойств компонента - Детальная информация об этапе проекта
|
||||
StageDetail.propTypes = {
|
||||
stageRn: PropTypes.number,
|
||||
stageName: PropTypes.string,
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { StageDetail };
|
126
app/panels/prj_info/stage_detail_hooks.js
Normal file
126
app/panels/prj_info/stage_detail_hooks.js
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Детальная информация об этапе проекта: пользовательские хуки для взаимодействия с сервером
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import { useState, useContext, useEffect } from "react"; //Классы React
|
||||
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Детали этапа проекта - информация об этапе
|
||||
const useStageDetailInfoDataGrid = ({ stageRn }) => {
|
||||
//Собственное состояние - флаг загрузки
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
|
||||
//Собственное состояние - таблица данных
|
||||
const [data, setData] = useState({ init: false });
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored } = useContext(BackEndСtx);
|
||||
|
||||
//При необходимости обновить данные таблицы
|
||||
useEffect(() => {
|
||||
//Загрузка данных таблицы с сервера
|
||||
const loadData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await executeStored({
|
||||
stored: "PKG_P8PANELS_PROJECTS.INFO_STAGE_DTL_DG",
|
||||
args: { NPROJECTSTAGE: stageRn },
|
||||
respArg: "COUT",
|
||||
loader: true
|
||||
});
|
||||
setData(pv => ({ ...pv, ...data.XDATA_GRID, init: true }));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
if (stageRn) loadData();
|
||||
}, [stageRn, executeStored]);
|
||||
|
||||
//Возвращаем интерфейс хука
|
||||
return [data, isLoading];
|
||||
};
|
||||
|
||||
//Детали этапа проекта - структура цены - таблица данных
|
||||
const useStageDetailArtsDataGrid = ({ stageRn }) => {
|
||||
//Собственное состояние - флаг загрузки
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
|
||||
//Собственное состояние - таблица данных
|
||||
const [data, setData] = useState({ init: false });
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
|
||||
|
||||
//При необходимости обновить данные таблицы
|
||||
useEffect(() => {
|
||||
//Загрузка данных таблицы с сервера
|
||||
const loadData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const artsData = await executeStored({
|
||||
stored: "PKG_P8PANELS_PROJECTS.INFO_STAGE_ARTS_DG",
|
||||
args: { NPROJECTSTAGE: stageRn },
|
||||
respArg: "COUT",
|
||||
loader: true
|
||||
});
|
||||
setData(pv => ({ ...pv, ...artsData.XDATA_GRID, init: true }));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
if (stageRn) loadData();
|
||||
}, [stageRn, executeStored, SERV_DATA_TYPE_CLOB]);
|
||||
|
||||
//Возвращаем интерфейс хука
|
||||
return [data, isLoading];
|
||||
};
|
||||
|
||||
//Детали этапа проекта - структура цены - график
|
||||
const useStageDetailArtsChart = ({ stageRn, display, type }) => {
|
||||
//Собственное состояние - флаг загрузки
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
|
||||
//Собственное состояние - график
|
||||
const [data, setData] = useState({ init: false, currentType: null });
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored } = useContext(BackEndСtx);
|
||||
|
||||
//При необходимости обновить данные таблицы
|
||||
useEffect(() => {
|
||||
//Загрузка данных таблицы с сервера
|
||||
const loadData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await executeStored({
|
||||
stored: "PKG_P8PANELS_PROJECTS.INFO_STAGE_ARTS_CHART",
|
||||
args: { NPROJECTSTAGE: stageRn, NTYPE: type },
|
||||
respArg: "COUT",
|
||||
loader: true
|
||||
});
|
||||
setData(pv => ({ ...pv, ...data.XCHART, currentType: type, init: true }));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
if (stageRn && display && data.currentType != type) loadData();
|
||||
}, [stageRn, display, type, data.currentType, executeStored]);
|
||||
|
||||
//Возвращаем интерфейс хука
|
||||
return [data, isLoading];
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { useStageDetailInfoDataGrid, useStageDetailArtsDataGrid, useStageDetailArtsChart };
|
148
app/panels/prj_info/stage_detail_layouts.js
Normal file
148
app/panels/prj_info/stage_detail_layouts.js
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Детальная информация об этапе проекта: дополнительная разметка и вёрстка клиентских элементов
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React from "react"; //Классы React
|
||||
import { Link } from "@mui/material"; //Интерфейсные элементы
|
||||
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
|
||||
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
|
||||
import { formatNumberRFCurrency } from "../../core/utils"; //Вспомогательные функции
|
||||
import { formatCostStatusValue } from "./layouts"; //Общие стили и разметка панели
|
||||
import { formatStageStatusValue } from "./stages_layouts"; //Cтили и разметка списка этапов проекта
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
//---------
|
||||
|
||||
//Высота заголовка информационного блока
|
||||
const DATA_AREA_HEADER_HEIGHT = "52px";
|
||||
|
||||
//Стили
|
||||
const STYLES = {
|
||||
STAGE_DETAIL_DRAWER: { flexShrink: 0, [`& .MuiDrawer-paper`]: { width: "70%", boxSizing: "border-box", ...APP_STYLES.SCROLL } },
|
||||
STAGE_DETAIL_HEADER: {
|
||||
height: APP_BAR_HEIGHT,
|
||||
paddingLeft: "24px",
|
||||
backgroundColor: "#1976d2",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start"
|
||||
},
|
||||
STAGE_DETAIL_CLOSE_BUTTON: { color: "white", marginBottom: "3px" },
|
||||
DATA_AREA_CONTAINER: { paddingLeft: "10px", paddingRight: "10px" },
|
||||
DATA_AREA: { height: `calc(100vh - ${APP_BAR_HEIGHT} - ${DATA_AREA_HEADER_HEIGHT} - 10px)`, overflowY: "auto", ...APP_STYLES.SCROLL },
|
||||
DATA_AREA_HEADER_CONTAINER: { display: "flex", justifyContent: "space-between" },
|
||||
DATA_AREA_HEADER: { paddingTop: "10px", paddingBottom: "10px" },
|
||||
DATA_GRID_HEADER: { fontSize: "10pt", padding: "6px 10px" },
|
||||
DATA_GRID_CELL: value => ({ fontSize: "9pt", padding: "6px 10px", ...(value ? { color: value > 0 ? "green" : "red" } : {}) }),
|
||||
CHART_CONTAINER: { paddingTop: "20px" },
|
||||
CHART: { maxHeight: "60vh", display: "flex", justifyContent: "center" }
|
||||
};
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Форматирование заголовков колонок таблицы "Сведения"
|
||||
const stageDetailInfoHeadCellRender = ({ columnDef }) => {
|
||||
//Инициализируем общий стиль ячеек
|
||||
let cellStyle = STYLES.DATA_GRID_HEADER;
|
||||
//Формирование представлений
|
||||
switch (columnDef.name) {
|
||||
case "SATTR":
|
||||
return { cellStyle, stackProps: { justifyContent: "left" } };
|
||||
case "SVALUE":
|
||||
return { cellStyle, stackProps: { justifyContent: "right" } };
|
||||
default:
|
||||
return { cellStyle: cellStyle };
|
||||
}
|
||||
};
|
||||
|
||||
//Форматирование ячеек строк таблицы "Сведения"
|
||||
const stageDetailInfoDataCellRender = ({ row, columnDef }) => {
|
||||
//Инициализируем общий стиль ячеек
|
||||
let cellStyle = STYLES.DATA_GRID_CELL();
|
||||
//Формирование представлений
|
||||
switch (columnDef.name) {
|
||||
case "SATTR":
|
||||
return { cellStyle: { ...cellStyle, color: "#1976d2" }, cellProps: { align: "left" } };
|
||||
case "SVALUE": {
|
||||
const res = { cellStyle, cellProps: { align: "right" } };
|
||||
if (["NCOST_SUM", "NSTAGE_COST_SUM"].includes(row["SCODE"]))
|
||||
res.data = row["SVALUE"] || row["SVALUE"] === 0 ? formatNumberRFCurrency(row["SVALUE"]) : "-";
|
||||
if (row["SCODE"] == "NSTATE")
|
||||
res.data = formatStageStatusValue({ value: parseInt(row["SVALUE"]), addText: true, justifyContent: "right" });
|
||||
return res;
|
||||
}
|
||||
default:
|
||||
return { cellStyle };
|
||||
}
|
||||
};
|
||||
|
||||
//Форматирование заголовков колонок таблицы "Структура затрат"
|
||||
const stageDetailArtsHeadCellRender = ({ columnDef }) => {
|
||||
//Инициализируем общий стиль ячеек
|
||||
let cellStyle = STYLES.DATA_GRID_HEADER;
|
||||
//Формирование представлений
|
||||
switch (columnDef.name) {
|
||||
case "NSTATE":
|
||||
return { cellStyle: { ...cellStyle, justifyContent: "center" }, stackStyle: { justifyContent: "center" } };
|
||||
default:
|
||||
return { cellStyle: cellStyle };
|
||||
}
|
||||
};
|
||||
|
||||
//Форматирование ячеек строк таблицы "Структура затрат"
|
||||
const stageDetailArtsDataCellRender = ({ row, columnDef, showCostNotesFact }) => {
|
||||
//Инициализируем общий стиль ячеек
|
||||
let cellStyle = STYLES.DATA_GRID_CELL;
|
||||
//Формирование представлений
|
||||
switch (columnDef.name) {
|
||||
case "NCOST_STATUS":
|
||||
return {
|
||||
cellProps: { align: "center" },
|
||||
data: formatCostStatusValue({ value: row[columnDef.name], type: 0 })
|
||||
};
|
||||
case "NPLAN_SUM":
|
||||
case "NPLAN_FACT_SUM":
|
||||
return {
|
||||
cellStyle: cellStyle(columnDef.name == "NPLAN_FACT_SUM" ? row[columnDef.name] : null),
|
||||
data: row[columnDef.name] || row[columnDef.name] === 0 ? formatNumberRFCurrency(row[columnDef.name]) : "-"
|
||||
};
|
||||
case "NFACT_SUM":
|
||||
return {
|
||||
cellStyle: cellStyle(),
|
||||
data:
|
||||
row[columnDef.name] || row[columnDef.name] === 0 ? (
|
||||
row[columnDef.name] > 0 ? (
|
||||
<Link component="button" onClick={() => showCostNotesFact({ faceAccRn: row["NFACEACC"], artclRn: row["NFPDARTCL"] })}>
|
||||
{formatNumberRFCurrency(row[columnDef.name])}
|
||||
</Link>
|
||||
) : (
|
||||
formatNumberRFCurrency(row[columnDef.name])
|
||||
)
|
||||
) : (
|
||||
"-"
|
||||
)
|
||||
};
|
||||
default:
|
||||
return { cellStyle: cellStyle(), data: row[columnDef.name] };
|
||||
}
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export {
|
||||
STYLES as STAGE_DETAIL_STYLES,
|
||||
stageDetailInfoHeadCellRender,
|
||||
stageDetailInfoDataCellRender,
|
||||
stageDetailArtsHeadCellRender,
|
||||
stageDetailArtsDataCellRender
|
||||
};
|
95
app/panels/prj_info/stages.js
Normal file
95
app/panels/prj_info/stages.js
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Список этапов проекта
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React, { useState, useContext } from "react"; //Классы React
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import { Typography } from "@mui/material"; //Интерфейсные элементы
|
||||
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
|
||||
import { P8PDataGrid } from "../../components/p8p_data_grid"; //Таблица данных
|
||||
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
||||
import { useStagesDataGrid } from "./stages_hooks"; //Хуки списка этапов проекта
|
||||
import { STAGES_STYLES, projectStageDataCellRender } from "./stages_layouts"; //Дополнительная разметка и вёрстка клиентских элементов
|
||||
import { StageDetail } from "./stage_detail"; //Компонент "Информация об этапе проекта"
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Список этапов проекта
|
||||
const Stages = ({ projectRn, projectCode }) => {
|
||||
//Собственное состояние
|
||||
const [stages, setStages] = useState({ pageNumber: 1, orders: [] });
|
||||
|
||||
//Состояние таблицы этапов
|
||||
const [stagesDataGrid] = useStagesDataGrid({ ...stages, projectRn });
|
||||
|
||||
//Состояние информации о этапе
|
||||
const [stageInfo, setStageInfo] = useState({ showInfo: false, stage: null, sFaceAcc: null });
|
||||
|
||||
//Подключение к контексту приложения
|
||||
const { pOnlineShowUnit } = useContext(ApplicationСtx);
|
||||
|
||||
//Отображение записи этапа проекта в штатном разделе
|
||||
const showProjectStage = (prn, rn) => {
|
||||
pOnlineShowUnit({
|
||||
unitCode: "Projects",
|
||||
inputParameters: [
|
||||
{ name: "in_RN", value: prn },
|
||||
{ name: "in_STAGE_RN", value: rn }
|
||||
],
|
||||
modal: false
|
||||
});
|
||||
};
|
||||
|
||||
//Отображение деталей этапа
|
||||
const showStageDetails = stage => setStageInfo(pv => ({ ...pv, showInfo: true, stage: stage["NRN"], sFaceAcc: stage["SFACEACC"] }));
|
||||
|
||||
//При изменении количества отображаемых страниц
|
||||
const handlePagesCountChanged = () => setStages(pv => ({ ...pv, pageNumber: pv.pageNumber + 1 }));
|
||||
|
||||
//При изменении состояния сортировки
|
||||
const handleOrderChanged = ({ orders }) => setStages(pv => ({ ...pv, orders: [...orders], pageNumber: 1 }));
|
||||
|
||||
//Генерация содержимого
|
||||
return stagesDataGrid.init ? (
|
||||
<>
|
||||
<div style={STAGES_STYLES.CONTAINER}>
|
||||
<Typography variant={"subtitle2"} sx={STAGES_STYLES.TITLE}>
|
||||
{`Этапы проекта "${projectCode}"`}
|
||||
</Typography>
|
||||
<P8PDataGrid
|
||||
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||
{...stagesDataGrid}
|
||||
containerComponentProps={{ sx: STAGES_STYLES.DATA_GRID_CONTAINER, elevation: 0 }}
|
||||
onPagesCountChanged={handlePagesCountChanged}
|
||||
onOrderChanged={handleOrderChanged}
|
||||
dataCellRender={prms => projectStageDataCellRender({ ...prms, showProjectStage, showStageDetails })}
|
||||
/>
|
||||
</div>
|
||||
<StageDetail
|
||||
stageRn={stageInfo.stage}
|
||||
stageName={stageInfo.sFaceAcc}
|
||||
isOpen={stageInfo.showInfo}
|
||||
onClose={() => setStageInfo(pv => ({ ...pv, showInfo: false, stage: null, sFaceAcc: null }))}
|
||||
/>
|
||||
</>
|
||||
) : null;
|
||||
};
|
||||
|
||||
//Контроль свойств компонента - Список этапов проекта
|
||||
Stages.propTypes = {
|
||||
projectRn: PropTypes.number.isRequired,
|
||||
projectCode: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { Stages };
|
78
app/panels/prj_info/stages_hooks.js
Normal file
78
app/panels/prj_info/stages_hooks.js
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Список этапов проекта: пользовательские хуки для взаимодействия с сервером
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import { useState, useContext, useEffect } from "react"; //Классы React
|
||||
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
||||
import { object2Base64XML, formatDateRF } from "../../core/utils"; //Вспомогательные функции
|
||||
import config from "../../../app.config"; //Настройки приложения
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
//---------
|
||||
|
||||
//Размер страницы данных
|
||||
const DATA_GRID_PAGE_SIZE = config.SYSTEM.PAGE_SIZE;
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Этапы проекта
|
||||
const useStagesDataGrid = ({ projectRn, pageNumber, orders }) => {
|
||||
//Собственное состояние - флаг загрузки
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
|
||||
//Собственное состояние - таблица данных
|
||||
const [data, setData] = useState({ init: false, morePages: true });
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
|
||||
|
||||
//При необходимости обновить данные таблицы
|
||||
useEffect(() => {
|
||||
//Загрузка данных таблицы с сервера
|
||||
const loadData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await executeStored({
|
||||
stored: "PKG_P8PANELS_PROJECTS.INFO_STAGES_DG",
|
||||
args: {
|
||||
NPROJECT: projectRn,
|
||||
CORDERS: { VALUE: object2Base64XML(orders, { arrayNodeName: "orders" }), SDATA_TYPE: SERV_DATA_TYPE_CLOB },
|
||||
NPAGE_NUMBER: pageNumber,
|
||||
NPAGE_SIZE: DATA_GRID_PAGE_SIZE,
|
||||
NINCLUDE_DEF: pageNumber == 1 ? 1 : 0
|
||||
},
|
||||
respArg: "COUT",
|
||||
loader: true,
|
||||
attributeValueProcessor: (name, val) => (["DBEGPLAN", "DENDPLAN"].includes(name) ? formatDateRF(val) : val)
|
||||
});
|
||||
setData(pv => ({
|
||||
...pv,
|
||||
columnsDef: data.XDATA_GRID.columnsDef ? [...data.XDATA_GRID.columnsDef] : pv.columnsDef || [],
|
||||
rows: pageNumber == 1 ? [...(data.XDATA_GRID.rows || [])] : [...(pv.rows || []), ...(data.XDATA_GRID.rows || [])],
|
||||
morePages: DATA_GRID_PAGE_SIZE == 0 ? false : (data.XDATA_GRID.rows || []).length >= DATA_GRID_PAGE_SIZE,
|
||||
init: true
|
||||
}));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
if (projectRn) loadData();
|
||||
}, [projectRn, orders, pageNumber, executeStored, SERV_DATA_TYPE_CLOB]);
|
||||
|
||||
//Возвращаем интерфейс хука
|
||||
return [data, isLoading];
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { useStagesDataGrid };
|
86
app/panels/prj_info/stages_layouts.js
Normal file
86
app/panels/prj_info/stages_layouts.js
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ПУП - Информация о проектах
|
||||
Список этапов проекта: дополнительная разметка и вёрстка клиентских элементов
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React from "react"; //Классы React
|
||||
import { Icon, Stack, Link } from "@mui/material"; //Интерфейсные элементы
|
||||
import { formatNumberRFCurrency } from "../../core/utils"; //Спомогательные функции
|
||||
import { COMMON_STYLES, formatCostStatusValue, formatCostReadyValue } from "./layouts"; //Общие стили и разметка панели
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
//---------
|
||||
|
||||
//Стили
|
||||
const STYLES = {
|
||||
CONTAINER: { textAlign: "center", paddingTop: "10px", backgroundColor: "lightcyan" },
|
||||
TITLE: { fontSize: "13pt", paddingBottom: "10px" },
|
||||
DATA_GRID_CONTAINER: { backgroundColor: "lightcyan" }
|
||||
};
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Формирование значения для колонки "Состояние" этапа
|
||||
const formatStageStatusValue = ({ value, addText = false, justifyContent = "center" }) => {
|
||||
const [text, icon] =
|
||||
value == 0
|
||||
? ["Зарегистрирован", "app_registration"]
|
||||
: value == 1
|
||||
? ["Открыт", "lock_open"]
|
||||
: value == 2
|
||||
? ["Закрыт", "lock_outline"]
|
||||
: value == 3
|
||||
? ["Согласован", "thumb_up_alt"]
|
||||
: value == 4
|
||||
? ["Исполнение прекращено", "block"]
|
||||
: ["Остановлен", "do_not_disturb_on"];
|
||||
return (
|
||||
<Stack direction="row" gap={0.5} alignItems={"center"} justifyContent={justifyContent || "center"}>
|
||||
<Icon title={text} sx={COMMON_STYLES.STATE(value)}>
|
||||
{icon}
|
||||
</Icon>
|
||||
{addText == true ? text : null}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
//Форматирование ячеек таблицы "Этапы проекта"
|
||||
const projectStageDataCellRender = ({ row, columnDef, showProjectStage, showStageDetails }) => {
|
||||
//Формирование представлений
|
||||
switch (columnDef.name) {
|
||||
case "NCOST_STATUS":
|
||||
return {
|
||||
cellProps: { align: "center" },
|
||||
data: formatCostStatusValue({ value: row[columnDef.name], onClick: () => showStageDetails(row) })
|
||||
};
|
||||
case "NCOST_READY":
|
||||
return { cellProps: { align: "center" }, data: formatCostReadyValue(row[columnDef.name]) };
|
||||
case "NSTATE":
|
||||
return { cellProps: { align: "center" }, data: formatStageStatusValue({ value: row[columnDef.name] }) };
|
||||
case "SFACEACC":
|
||||
return {
|
||||
data: (
|
||||
<Link component="button" align="left" underline="hover" onClick={() => showProjectStage(row["NPRN"], row["NRN"])}>
|
||||
{row[columnDef.name]}
|
||||
</Link>
|
||||
)
|
||||
};
|
||||
case "NCOST_SUM":
|
||||
return { data: formatNumberRFCurrency(row[columnDef.name]) };
|
||||
default:
|
||||
return { data: row[columnDef.name] };
|
||||
}
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { STYLES as STAGES_STYLES, projectStageDataCellRender, formatStageStatusValue };
|
@ -33,7 +33,7 @@ const STYLES = {
|
||||
//Пример: Графики "P8PChart"
|
||||
const Chart = ({ title }) => {
|
||||
//Собственное состояние - график
|
||||
const [chart, setChart] = useState({ loaded: false, labels: [], datasets: [] });
|
||||
const [chart, setChart] = useState({ loaded: false });
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored } = useContext(BackEndСtx);
|
||||
|
@ -89,16 +89,12 @@ const DataGrid = ({ title }) => {
|
||||
//Собственное состояние - таблица данных
|
||||
const [dataGrid, setDataGrid] = useState({
|
||||
dataLoaded: false,
|
||||
columnsDef: [],
|
||||
filters: null,
|
||||
orders: null,
|
||||
groups: [],
|
||||
rows: [],
|
||||
reloading: true,
|
||||
pageNumber: 1,
|
||||
morePages: true,
|
||||
fixedHeader: false,
|
||||
fixedColumns: 0
|
||||
expandable: true,
|
||||
reloading: true
|
||||
});
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
@ -124,13 +120,13 @@ const DataGrid = ({ title }) => {
|
||||
setDataGrid(pv => ({
|
||||
...pv,
|
||||
...data.XDATA_GRID,
|
||||
columnsDef: data.XDATA_GRID.columnsDef ? [...data.XDATA_GRID.columnsDef] : pv.columnsDef,
|
||||
rows: pv.pageNumber == 1 ? [...(data.XDATA_GRID.rows || [])] : [...pv.rows, ...(data.XDATA_GRID.rows || [])],
|
||||
columnsDef: data.XDATA_GRID.columnsDef ? [...data.XDATA_GRID.columnsDef] : pv.columnsDef || [],
|
||||
rows: pv.pageNumber == 1 ? [...(data.XDATA_GRID.rows || [])] : [...(pv.rows || []), ...(data.XDATA_GRID.rows || [])],
|
||||
groups: data.XDATA_GRID.groups
|
||||
? pv.pageNumber == 1
|
||||
? [...data.XDATA_GRID.groups]
|
||||
: [...pv.groups, ...data.XDATA_GRID.groups.filter(g => !pv.groups.find(pg => pg.name == g.name))]
|
||||
: [...pv.groups],
|
||||
: [...(pv.groups || []), ...data.XDATA_GRID.groups.filter(g => !pv.groups.find(pg => pg.name == g.name))]
|
||||
: [...(pv.groups || [])],
|
||||
dataLoaded: true,
|
||||
reloading: false,
|
||||
morePages: (data.XDATA_GRID.rows || []).length >= DATA_GRID_PAGE_SIZE
|
||||
@ -167,9 +163,9 @@ const DataGrid = ({ title }) => {
|
||||
{dataGrid.dataLoaded ? (
|
||||
<P8PDataGrid
|
||||
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||
containerComponentProps={{ elevation: 6, sx: STYLES.DATA_GRID_CONTAINER }}
|
||||
{...dataGrid}
|
||||
size={P8P_DATA_GRID_SIZE.LARGE}
|
||||
containerComponentProps={{ elevation: 6, sx: STYLES.DATA_GRID_CONTAINER }}
|
||||
valueFormatter={valueFormatter}
|
||||
headCellRender={headCellRender}
|
||||
dataCellRender={dataCellRender}
|
||||
@ -177,7 +173,6 @@ const DataGrid = ({ title }) => {
|
||||
onOrderChanged={handleOrderChanged}
|
||||
onFilterChanged={handleFilterChanged}
|
||||
onPagesCountChanged={handlePagesCountChanged}
|
||||
expandable={true}
|
||||
rowExpandRender={({ row }) => (
|
||||
<Button onClick={() => handleAgnButtonClicked(row.SAGNABBR)}>Показать в разделе</Button>
|
||||
)}
|
||||
|
@ -19,8 +19,8 @@ create table P8PNL_JB_JOBS
|
||||
EDITABLE number(1) default 0 not null, -- Признак возможности редактирования (0 - нет, 1 - да)
|
||||
CHANGED number(1) default 0 not null, -- Признак наличия изменений, требующих сохранения (0 - нет, 1 - да)
|
||||
constraint C_P8PNL_JB_JOBS_RN_PK primary key (RN),
|
||||
constraint C_P8PNL_JB_JOBS_PRN_FK foreign key (PRN) references P8PNL_JB_PRJCTS (RN),
|
||||
constraint C_P8PNL_JB_JOBS_HRN_FK foreign key (HRN) references P8PNL_JB_JOBS (RN),
|
||||
constraint C_P8PNL_JB_JOBS_PRN_FK foreign key (PRN) references P8PNL_JB_PRJCTS (RN) on delete cascade,
|
||||
constraint C_P8PNL_JB_JOBS_HRN_FK foreign key (HRN) references P8PNL_JB_JOBS (RN) on delete cascade,
|
||||
constraint C_P8PNL_JB_JOBS_STAGE_VAL check (STAGE in (0, 1)),
|
||||
constraint C_P8PNL_JB_JOBS_EDTBL_VAL check (EDITABLE in (0, 1)),
|
||||
constraint C_P8PNL_JB_JOBS_CHNGD_VAL check (CHANGED in (0, 1)),
|
||||
|
@ -9,7 +9,7 @@ create table P8PNL_JB_JOBSPREV
|
||||
PRN number(17) not null, -- Рег. номер родителя
|
||||
JB_JOBS number(17) not null, -- Рег. номер предшествующей работы/этапа
|
||||
constraint C_P8PNL_JB_JOBSPREV_RN_PK primary key (RN),
|
||||
constraint C_P8PNL_JB_JOBSPREV_PRN_FK foreign key (PRN) references P8PNL_JB_JOBS (RN),
|
||||
constraint C_P8PNL_JB_JOBSPREV_JB_JOBS_FK foreign key (JB_JOBS) references P8PNL_JB_JOBS (RN),
|
||||
constraint C_P8PNL_JB_JOBSPREV_PRN_FK foreign key (PRN) references P8PNL_JB_JOBS (RN) on delete cascade,
|
||||
constraint C_P8PNL_JB_JOBSPREV_JB_JOBS_FK foreign key (JB_JOBS) references P8PNL_JB_JOBS (RN) on delete cascade,
|
||||
constraint C_P8PNL_JB_JOBSPREV_UN unique (IDENT, PRN, JB_JOBS)
|
||||
);
|
||||
|
@ -15,7 +15,7 @@ create table P8PNL_JB_PERIODS
|
||||
LAB_PLAN_JOBS number(17,3) default 0 not null, -- Трудоёмкость (план, по графику)
|
||||
constraint C_P8PNL_JB_PERIODS_RN_PK primary key (RN),
|
||||
constraint C_P8PNL_JB_PERIODS_DATE_VAL check (DATE_FROM <= DATE_TO),
|
||||
constraint C_P8PNL_JB_PERIODS_INS_DEP_FK foreign key (INS_DEPARTMENT) references INS_DEPARTMENT (RN),
|
||||
constraint C_P8PNL_JB_PERIODS_FCMNPWR_FK foreign key (FCMANPOWER) references FCMANPOWER (RN),
|
||||
constraint C_P8PNL_JB_PERIODS_INS_DEP_FK foreign key (INS_DEPARTMENT) references INS_DEPARTMENT (RN) on delete cascade,
|
||||
constraint C_P8PNL_JB_PERIODS_FCMNPWR_FK foreign key (FCMANPOWER) references FCMANPOWER (RN) on delete cascade,
|
||||
constraint C_P8PNL_JB_PERIODS_UN unique (IDENT, DATE_FROM, INS_DEPARTMENT, FCMANPOWER)
|
||||
);
|
||||
|
@ -11,7 +11,7 @@ create table P8PNL_JB_PRJCTS
|
||||
EDITABLE number(1) default 0 not null, -- Признак возможности редактирования (0 - нет, 1 - да)
|
||||
CHANGED number(1) default 0 not null, -- Признак наличия изменений, требующих сохранения (0 - нет, 1 - да)
|
||||
constraint C_P8PNL_JB_PRJCTS_RN_PK primary key (RN),
|
||||
constraint C_P8PNL_JB_PRJCTS_PROJECT_FK foreign key (PROJECT) references PROJECT (RN),
|
||||
constraint C_P8PNL_JB_PRJCTS_PROJECT_FK foreign key (PROJECT) references PROJECT (RN) on delete cascade,
|
||||
constraint C_P8PNL_JB_PRJCTS_JOBS_VAL check (JOBS in (0, 1)),
|
||||
constraint C_P8PNL_JB_PRJCTS_EDTBL_VAL check (EDITABLE in (0, 1)),
|
||||
constraint C_P8PNL_JB_PRJCTS_CHNGD_VAL check (CHANGED in (0, 1)),
|
||||
|
@ -27,6 +27,13 @@ create or replace package PKG_P8PANELS_BASE as
|
||||
NDOCUMENT in number -- Рег. номер документа
|
||||
) return number; -- Флаг доступности (см. константы NACCESS_*)
|
||||
|
||||
/* Подготовка пользовательской строки поиска для вставки в запрос */
|
||||
procedure UTL_SEARCH_PREPARE
|
||||
(
|
||||
SSEARCH in varchar2, -- Пользовательская строка поиска
|
||||
SSEARCH_PREPARED out varchar2 -- Подготовленная строка поиска
|
||||
);
|
||||
|
||||
/* Базовое исполнение действий */
|
||||
procedure PROCESS
|
||||
(
|
||||
@ -191,6 +198,36 @@ create or replace package body PKG_P8PANELS_BASE as
|
||||
return NACCESS_NO;
|
||||
end UTL_DOC_ACCESS_CHECK;
|
||||
|
||||
/* Подготовка пользовательской строки поиска для вставки в запрос */
|
||||
procedure UTL_SEARCH_PREPARE
|
||||
(
|
||||
SSEARCH in varchar2, -- Пользовательская строка поиска
|
||||
SSEARCH_PREPARED out varchar2 -- Подготовленная строка поиска
|
||||
)
|
||||
is
|
||||
/* Локальные константы */
|
||||
SANY_SYS constant char(1) := '%'; -- Маска "любое количество любых символов" Oracle
|
||||
SONE_SYS constant char(1) := '_'; -- Маска "любой один символ" Oracle
|
||||
SENT_WRD_DELIM constant varchar2(1) := ' '; -- Разделитель слов в предложении
|
||||
SANY_PRS constant varchar2(240) := PKG_OPTIONS.STARSYMB; -- Маска "любое количество любых символов" Парус
|
||||
SONE_PRS constant varchar2(240) := PKG_OPTIONS.QUESTSYMB; -- Маска "любой один символ" Парус
|
||||
begin
|
||||
/* Если пользовательская строка пустая - то это всё что угодно */
|
||||
if (SSEARCH is null)
|
||||
then
|
||||
SSEARCH_PREPARED := SANY_SYS;
|
||||
else
|
||||
/* Подменим пользовательские маски на системные и соберем подготовленную строку поиска */
|
||||
SSEARCH_PREPARED := '%' || replace(replace(replace(SSEARCH
|
||||
,SANY_PRS
|
||||
,SANY_SYS)
|
||||
,SONE_PRS
|
||||
,SONE_SYS)
|
||||
,SENT_WRD_DELIM
|
||||
,SANY_SYS) || '%';
|
||||
end if;
|
||||
end UTL_SEARCH_PREPARE;
|
||||
|
||||
/* Формирование сообщения об отсутствии значения */
|
||||
function MSG_NO_DATA_MAKE
|
||||
(
|
||||
|
File diff suppressed because it is too large
Load Diff
7624
dist/p8-panels.js
vendored
7624
dist/p8-panels.js
vendored
File diff suppressed because one or more lines are too long
BIN
img/prj_info.jpg
Normal file
BIN
img/prj_info.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 134 KiB |
@ -8,6 +8,7 @@
|
||||
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowPrjPanelFin" caption="Экономика проектов" panelName="PrjFin"/>
|
||||
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowPrjPanelJob" caption="Работы проектов" panelName="PrjJobs"/>
|
||||
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowPrjPanelGraph" caption="Графики проектов" panelName="PrjGraph"/>
|
||||
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowPrjPanelInfo" caption="Информация о проектах" panelName="PrjInfo"/>
|
||||
<MenuItem parent="{BA073333-DFBC-4BA3-8EA7-172F3F6B4FEE}" name="ShowPrjPanelHelp" caption="Инструкции ПУП" panelName="PrjHelp"/>
|
||||
</App>
|
||||
<App name="EquipSrv">
|
||||
@ -59,6 +60,16 @@
|
||||
icon="insights"
|
||||
showInPanelsList="true"
|
||||
preview="./img/prj_graph.jpg"/>
|
||||
<Panel
|
||||
name="PrjInfo"
|
||||
group="Планирование и учёт в проектах"
|
||||
caption="Информация о проектах"
|
||||
desc="Информация о проектах"
|
||||
url="prj_info"
|
||||
path="prj_info"
|
||||
icon="featured_play_list"
|
||||
showInPanelsList="true"
|
||||
preview="./img/prj_info.jpg"/>
|
||||
<Panel
|
||||
name="PrjHelp"
|
||||
group="Планирование и учёт в проектах"
|
||||
@ -109,7 +120,7 @@
|
||||
icon="psychology"
|
||||
showInPanelsList="true"
|
||||
preview="./img/mech_rec_cost_jobs_manage.jpg"/>
|
||||
<Panel
|
||||
<Panel
|
||||
name="MechRecCostJobsManageMP"
|
||||
group="Планирование и учёт в дискретном производстве"
|
||||
caption="Выдача сменного задания на участок"
|
||||
|
469
package-lock.json
generated
469
package-lock.json
generated
@ -25,6 +25,7 @@
|
||||
"file-loader": "^6.2.0",
|
||||
"query-string": "^8.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.15.0",
|
||||
"webpack": "^5.88.2",
|
||||
@ -1113,9 +1114,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
|
||||
},
|
||||
"node_modules/@types/hoist-non-react-statics": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz",
|
||||
"integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==",
|
||||
"dependencies": {
|
||||
"@types/react": "*",
|
||||
"hoist-non-react-statics": "^3.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
@ -1123,11 +1133,11 @@
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.14.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz",
|
||||
"integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==",
|
||||
"version": "22.13.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz",
|
||||
"integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
"undici-types": "~6.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
@ -1149,6 +1159,17 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-redux": {
|
||||
"version": "7.1.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz",
|
||||
"integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==",
|
||||
"dependencies": {
|
||||
"@types/hoist-non-react-statics": "^3.3.0",
|
||||
"@types/react": "*",
|
||||
"hoist-non-react-statics": "^3.3.0",
|
||||
"redux": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-transition-group": {
|
||||
"version": "4.4.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz",
|
||||
@ -1163,133 +1184,133 @@
|
||||
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/ast": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
|
||||
"integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
|
||||
"integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/helper-numbers": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6"
|
||||
"@webassemblyjs/helper-numbers": "1.13.2",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/floating-point-hex-parser": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
|
||||
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw=="
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
|
||||
"integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-api-error": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
|
||||
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q=="
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
|
||||
"integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-buffer": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
|
||||
"integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw=="
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
|
||||
"integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-numbers": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
|
||||
"integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
|
||||
"integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/floating-point-hex-parser": "1.11.6",
|
||||
"@webassemblyjs/helper-api-error": "1.11.6",
|
||||
"@webassemblyjs/floating-point-hex-parser": "1.13.2",
|
||||
"@webassemblyjs/helper-api-error": "1.13.2",
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
|
||||
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA=="
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
|
||||
"integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-wasm-section": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
|
||||
"integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
|
||||
"integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/helper-buffer": "1.12.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/wasm-gen": "1.12.1"
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@webassemblyjs/helper-buffer": "1.14.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
||||
"@webassemblyjs/wasm-gen": "1.14.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/ieee754": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
|
||||
"integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
|
||||
"integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
|
||||
"dependencies": {
|
||||
"@xtuc/ieee754": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/leb128": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
|
||||
"integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
|
||||
"integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
|
||||
"dependencies": {
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/utf8": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
|
||||
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA=="
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
|
||||
"integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-edit": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
|
||||
"integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
|
||||
"integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/helper-buffer": "1.12.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-section": "1.12.1",
|
||||
"@webassemblyjs/wasm-gen": "1.12.1",
|
||||
"@webassemblyjs/wasm-opt": "1.12.1",
|
||||
"@webassemblyjs/wasm-parser": "1.12.1",
|
||||
"@webassemblyjs/wast-printer": "1.12.1"
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@webassemblyjs/helper-buffer": "1.14.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
||||
"@webassemblyjs/helper-wasm-section": "1.14.1",
|
||||
"@webassemblyjs/wasm-gen": "1.14.1",
|
||||
"@webassemblyjs/wasm-opt": "1.14.1",
|
||||
"@webassemblyjs/wasm-parser": "1.14.1",
|
||||
"@webassemblyjs/wast-printer": "1.14.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-gen": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
|
||||
"integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
|
||||
"integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/ieee754": "1.11.6",
|
||||
"@webassemblyjs/leb128": "1.11.6",
|
||||
"@webassemblyjs/utf8": "1.11.6"
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
||||
"@webassemblyjs/ieee754": "1.13.2",
|
||||
"@webassemblyjs/leb128": "1.13.2",
|
||||
"@webassemblyjs/utf8": "1.13.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-opt": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
|
||||
"integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
|
||||
"integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/helper-buffer": "1.12.1",
|
||||
"@webassemblyjs/wasm-gen": "1.12.1",
|
||||
"@webassemblyjs/wasm-parser": "1.12.1"
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@webassemblyjs/helper-buffer": "1.14.1",
|
||||
"@webassemblyjs/wasm-gen": "1.14.1",
|
||||
"@webassemblyjs/wasm-parser": "1.14.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-parser": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
|
||||
"integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
|
||||
"integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/helper-api-error": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/ieee754": "1.11.6",
|
||||
"@webassemblyjs/leb128": "1.11.6",
|
||||
"@webassemblyjs/utf8": "1.11.6"
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@webassemblyjs/helper-api-error": "1.13.2",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
||||
"@webassemblyjs/ieee754": "1.13.2",
|
||||
"@webassemblyjs/leb128": "1.13.2",
|
||||
"@webassemblyjs/utf8": "1.13.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wast-printer": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
|
||||
"integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
|
||||
"integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
@ -1345,9 +1366,9 @@
|
||||
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.12.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
|
||||
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@ -1355,14 +1376,6 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-import-attributes": {
|
||||
"version": "1.9.5",
|
||||
"resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
|
||||
"integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
|
||||
"peerDependencies": {
|
||||
"acorn": "^8"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-jsx": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
||||
@ -1644,9 +1657,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.23.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz",
|
||||
"integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==",
|
||||
"version": "4.24.4",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
|
||||
"integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -1662,10 +1675,10 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001640",
|
||||
"electron-to-chromium": "^1.4.820",
|
||||
"node-releases": "^2.0.14",
|
||||
"update-browserslist-db": "^1.1.0"
|
||||
"caniuse-lite": "^1.0.30001688",
|
||||
"electron-to-chromium": "^1.5.73",
|
||||
"node-releases": "^2.0.19",
|
||||
"update-browserslist-db": "^1.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"browserslist": "cli.js"
|
||||
@ -1706,9 +1719,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001643",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz",
|
||||
"integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==",
|
||||
"version": "1.0.30001700",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz",
|
||||
"integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -1839,9 +1852,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
@ -1851,6 +1864,14 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/css-box-model": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
|
||||
"integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
|
||||
"dependencies": {
|
||||
"tiny-invariant": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
@ -1991,9 +2012,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.1.tgz",
|
||||
"integrity": "sha512-FKbOCOQ5QRB3VlIbl1LZQefWIYwszlBloaXcY2rbfpu9ioJnNh3TK03YtIDKDo3WKBi8u+YV4+Fn2CkEozgf4w=="
|
||||
"version": "1.5.104",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.104.tgz",
|
||||
"integrity": "sha512-Us9M2L4cO/zMBqVkJtnj353nQhMju9slHm62NprKTmdF3HH8wYOtNvDFq/JB2+ZRoGLzdvYDiATlMHs98XBM1g=="
|
||||
},
|
||||
"node_modules/emojis-list": {
|
||||
"version": "3.0.0",
|
||||
@ -2190,9 +2211,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
||||
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
||||
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@ -2518,21 +2539,17 @@
|
||||
"integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw=="
|
||||
},
|
||||
"node_modules/fast-xml-parser": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.0.tgz",
|
||||
"integrity": "sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg==",
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz",
|
||||
"integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/NaturalIntelligence"
|
||||
},
|
||||
{
|
||||
"type": "paypal",
|
||||
"url": "https://paypal.me/naturalintelligence"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"strnum": "^1.0.5"
|
||||
"strnum": "^1.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"fxparser": "src/cli/cli.js"
|
||||
@ -3632,6 +3649,11 @@
|
||||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/memoize-one": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||
},
|
||||
"node_modules/merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
@ -3683,9 +3705,9 @@
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.18",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
|
||||
"integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="
|
||||
"version": "2.0.19",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
|
||||
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
@ -3903,9 +3925,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
|
||||
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew=="
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
||||
},
|
||||
"node_modules/pkg-dir": {
|
||||
"version": "7.0.0",
|
||||
@ -4071,6 +4093,11 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/raf-schd": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
|
||||
"integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ=="
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@ -4090,6 +4117,25 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-beautiful-dnd": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz",
|
||||
"integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==",
|
||||
"deprecated": "react-beautiful-dnd is now deprecated. Context and options: https://github.com/atlassian/react-beautiful-dnd/issues/2672",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.9.2",
|
||||
"css-box-model": "^1.2.0",
|
||||
"memoize-one": "^5.1.1",
|
||||
"raf-schd": "^4.0.2",
|
||||
"react-redux": "^7.2.0",
|
||||
"redux": "^4.0.4",
|
||||
"use-memo-one": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.5 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
@ -4107,6 +4153,35 @@
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "7.2.9",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz",
|
||||
"integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.15.4",
|
||||
"@types/react-redux": "^7.1.20",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-is": "^17.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.3 || ^17 || ^18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
},
|
||||
"react-native": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-redux/node_modules/react-is": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "6.25.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz",
|
||||
@ -4163,6 +4238,14 @@
|
||||
"node": ">= 10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/redux": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
|
||||
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.9.2"
|
||||
}
|
||||
},
|
||||
"node_modules/reflect.getprototypeof": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
|
||||
@ -4363,9 +4446,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/schema-utils": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
|
||||
"integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
|
||||
"integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"ajv": "^8.9.0",
|
||||
@ -4373,7 +4456,7 @@
|
||||
"ajv-keywords": "^5.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12.13.0"
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@ -4643,9 +4726,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/strnum": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
|
||||
"integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.1.tgz",
|
||||
"integrity": "sha512-O7aCHfYCamLCctjAiaucmE+fHf2DYHkus2OKCn4Wv03sykfFtgeECn505X6K4mPl8CRNd/qurC9guq+ynoN4pw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/NaturalIntelligence"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/stylis": {
|
||||
"version": "4.2.0",
|
||||
@ -4683,9 +4772,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.31.3",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz",
|
||||
"integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==",
|
||||
"version": "5.39.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz",
|
||||
"integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==",
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.8.2",
|
||||
@ -4700,15 +4789,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser-webpack-plugin": {
|
||||
"version": "5.3.10",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
|
||||
"integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
|
||||
"version": "5.3.11",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz",
|
||||
"integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "^0.3.20",
|
||||
"@jridgewell/trace-mapping": "^0.3.25",
|
||||
"jest-worker": "^27.4.5",
|
||||
"schema-utils": "^3.1.1",
|
||||
"serialize-javascript": "^6.0.1",
|
||||
"terser": "^5.26.0"
|
||||
"schema-utils": "^4.3.0",
|
||||
"serialize-javascript": "^6.0.2",
|
||||
"terser": "^5.31.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
@ -4732,28 +4821,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/terser-webpack-plugin/node_modules/schema-utils": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.8",
|
||||
"ajv": "^6.12.5",
|
||||
"ajv-keywords": "^3.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="
|
||||
},
|
||||
"node_modules/tiny-invariant": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
|
||||
"integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="
|
||||
},
|
||||
"node_modules/to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
@ -4868,14 +4945,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
||||
"version": "6.20.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="
|
||||
},
|
||||
"node_modules/update-browserslist-db": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
|
||||
"integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz",
|
||||
"integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -4891,8 +4968,8 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"escalade": "^3.1.2",
|
||||
"picocolors": "^1.0.1"
|
||||
"escalade": "^3.2.0",
|
||||
"picocolors": "^1.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"update-browserslist-db": "cli.js"
|
||||
@ -4909,6 +4986,14 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/use-memo-one": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz",
|
||||
"integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz",
|
||||
@ -4922,20 +5007,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.93.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz",
|
||||
"integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==",
|
||||
"version": "5.98.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz",
|
||||
"integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==",
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.3",
|
||||
"@types/estree": "^1.0.5",
|
||||
"@webassemblyjs/ast": "^1.12.1",
|
||||
"@webassemblyjs/wasm-edit": "^1.12.1",
|
||||
"@webassemblyjs/wasm-parser": "^1.12.1",
|
||||
"acorn": "^8.7.1",
|
||||
"acorn-import-attributes": "^1.9.5",
|
||||
"browserslist": "^4.21.10",
|
||||
"@types/eslint-scope": "^3.7.7",
|
||||
"@types/estree": "^1.0.6",
|
||||
"@webassemblyjs/ast": "^1.14.1",
|
||||
"@webassemblyjs/wasm-edit": "^1.14.1",
|
||||
"@webassemblyjs/wasm-parser": "^1.14.1",
|
||||
"acorn": "^8.14.0",
|
||||
"browserslist": "^4.24.0",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "^5.17.0",
|
||||
"enhanced-resolve": "^5.17.1",
|
||||
"es-module-lexer": "^1.2.1",
|
||||
"eslint-scope": "5.1.1",
|
||||
"events": "^3.2.0",
|
||||
@ -4945,9 +5029,9 @@
|
||||
"loader-runner": "^4.2.0",
|
||||
"mime-types": "^2.1.27",
|
||||
"neo-async": "^2.6.2",
|
||||
"schema-utils": "^3.2.0",
|
||||
"schema-utils": "^4.3.0",
|
||||
"tapable": "^2.1.1",
|
||||
"terser-webpack-plugin": "^5.3.10",
|
||||
"terser-webpack-plugin": "^5.3.11",
|
||||
"watchpack": "^2.4.1",
|
||||
"webpack-sources": "^3.2.3"
|
||||
},
|
||||
@ -5060,23 +5144,6 @@
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/schema-utils": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.8",
|
||||
"ajv": "^6.12.5",
|
||||
"ajv-keywords": "^3.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
@ -35,6 +35,7 @@
|
||||
"file-loader": "^6.2.0",
|
||||
"query-string": "^8.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.15.0",
|
||||
"webpack": "^5.88.2",
|
||||
|
Loading…
x
Reference in New Issue
Block a user