forked from CITKParus/P8-Panels
ЦИТК-831, ЦИТК-833 - ТОиР "Выполнение работ" - фиксированные строки, колонки, сохранение фильтра
This commit is contained in:
commit
59d85451ec
@ -8,7 +8,7 @@
|
||||
//---------------------
|
||||
|
||||
import React, { useState, useContext, useCallback, useEffect } from "react"; //Классы React
|
||||
import { Grid, Paper, Box } from "@mui/material"; //Интерфейсные компоненты
|
||||
import { Box } from "@mui/material"; //Интерфейсные компоненты
|
||||
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
|
||||
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
||||
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
||||
@ -18,6 +18,33 @@ import { headCellRender, dataCellRender, groupCellRender, DIGITS_REG_EXP, MONTH_
|
||||
import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы
|
||||
import { Filter } from "./filter"; //Компонент фильтра
|
||||
import { FilterDialog } from "./filter_dialog"; //Компонент диалогового окна фильтра отбора
|
||||
import { useWindowResize } from "./hooks"; //Пользовательские хуки
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
//---------
|
||||
|
||||
//Высота меню Парус (пиксели)
|
||||
const pxOuterMenuH = 53;
|
||||
//Высота заголовка панели (пиксели)
|
||||
const pxPanelHeaderH = 64;
|
||||
//Минимальная ширина таблицы (пиксели)
|
||||
const minGridW = 800;
|
||||
//Минимальная высота таблицы (пиксели)
|
||||
const minGridH = 200;
|
||||
|
||||
//Стили
|
||||
const STYLES = {
|
||||
BOX_ROW: { display: "flex", justifyContent: "center", alignItems: "center" },
|
||||
GRID_PADDING: { paddingTop: 1, paddingBottom: 1 },
|
||||
GRID_SIZES: (width, height) => ({
|
||||
padding: "0px",
|
||||
minWidth: minGridW,
|
||||
maxWidth: width * 0.975 > minGridW ? width * 0.975 : minGridW,
|
||||
minHeight: minGridH,
|
||||
maxHeight: (height - pxOuterMenuH - pxPanelHeaderH) * 0.975 > minGridH ? (height - pxOuterMenuH - pxPanelHeaderH) * 0.975 : minGridH
|
||||
})
|
||||
};
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
@ -31,6 +58,8 @@ const EqsPrfrm = () => {
|
||||
columnsDef: [],
|
||||
groups: [],
|
||||
rows: [],
|
||||
fixedHeader: false,
|
||||
fixedColumns: 0,
|
||||
reload: false
|
||||
});
|
||||
|
||||
@ -39,6 +68,7 @@ const EqsPrfrm = () => {
|
||||
isOpen: false,
|
||||
isDefault: false,
|
||||
isSetByUser: false,
|
||||
needSave: false,
|
||||
values: {
|
||||
belong: "",
|
||||
prodObj: "",
|
||||
@ -128,6 +158,8 @@ const EqsPrfrm = () => {
|
||||
...pv,
|
||||
columnsDef: data.XCOLUMNS_DEF ? [...data.XCOLUMNS_DEF] : pv.columnsDef,
|
||||
rows: [...(data.XROWS || [])],
|
||||
fixedHeader: data.XDATA_GRID.fixedHeader,
|
||||
fixedColumns: data.XDATA_GRID.fixedColumns,
|
||||
groups: [...(data.XGROUPS || [])],
|
||||
dataLoaded: true,
|
||||
reload: false
|
||||
@ -135,7 +167,7 @@ const EqsPrfrm = () => {
|
||||
}
|
||||
}, [dataGrid.reload, filter, executeStored]);
|
||||
|
||||
//Загрузка значений фильра по умолчанию
|
||||
//Загрузка значений фильтра по умолчанию
|
||||
const loadDefaultFilter = useCallback(async () => {
|
||||
const data = await executeStored({
|
||||
stored: "PKG_P8PANELS_EQUIPSRV.GET_DEFAULT_FP",
|
||||
@ -148,6 +180,17 @@ const EqsPrfrm = () => {
|
||||
}));
|
||||
}, [executeStored]);
|
||||
|
||||
//Загрузка значений фильтра из локального хранилища браузера
|
||||
const loadLocalFilter = useCallback(async () => {
|
||||
let vs = filter.values;
|
||||
Object.keys(vs).map(function (k) {
|
||||
vs[k] =
|
||||
k == "fromMonth" || k == "fromYear" || k == "toMonth" || k == "toYear" ? Number(localStorage.getItem(k)) : localStorage.getItem(k);
|
||||
});
|
||||
setFilter(pv => ({ ...pv, isDefault: true, values: { ...vs } }));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
//Отбор документа (ТОиР или Ремонтных ведомостей) по ячейке даты
|
||||
const showEquipSrv = async ({ date, workType, info }) => {
|
||||
const [techName, servKind] = info.split("_");
|
||||
@ -180,7 +223,7 @@ const EqsPrfrm = () => {
|
||||
const setFilterOpen = isOpen => setFilter(pv => ({ ...pv, isOpen }));
|
||||
|
||||
//Установить значение фильтра
|
||||
const setFilterValues = values => setFilter(pv => ({ ...pv, isSetByUser: true, values: { ...values } }));
|
||||
const setFilterValues = values => setFilter(pv => ({ ...pv, isSetByUser: true, needSave: true, values: { ...values } }));
|
||||
|
||||
//Отработка события скрытия/раскрытия ячейки даты
|
||||
const handleClick = (e, ref) => {
|
||||
@ -223,16 +266,26 @@ const EqsPrfrm = () => {
|
||||
//eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [refIsDeprecated]);
|
||||
|
||||
//При закрытии панели
|
||||
useEffect(() => {
|
||||
filter.needSave
|
||||
? window.addEventListener("beforeunload", function () {
|
||||
Object.keys(filter.values).map(function (k) {
|
||||
localStorage.setItem(k, filter.values[k]);
|
||||
});
|
||||
})
|
||||
: null;
|
||||
}, [filter.needSave, filter.values]);
|
||||
|
||||
//При загрузке фильтра по умолчанию
|
||||
useEffect(() => {
|
||||
if (filter.isDefault) setFilterOpen(true);
|
||||
}, [filter.isDefault]);
|
||||
|
||||
//При подключении к страницк
|
||||
//При подключении к странице
|
||||
useEffect(() => {
|
||||
loadDefaultFilter();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
localStorage.getItem("belong") ? loadLocalFilter() : loadDefaultFilter();
|
||||
}, [loadDefaultFilter, loadLocalFilter]);
|
||||
|
||||
//При открытии диалога фильтра
|
||||
const handleFilterClick = () => setFilterOpen(true);
|
||||
@ -246,32 +299,37 @@ const EqsPrfrm = () => {
|
||||
//При закрытии диалога фильтра
|
||||
const handleFilterCancel = () => setFilterOpen(false);
|
||||
|
||||
//Состояние ширины и высоты рабочей области окна
|
||||
const [width, height] = useWindowResize();
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<div>
|
||||
{filter.isOpen ? <FilterDialog initial={filter.values} onOk={handleFilterOk} onCancel={handleFilterCancel} /> : null}
|
||||
<Filter filter={filter.values} onClick={handleFilterClick} />
|
||||
{dataGrid.dataLoaded ? (
|
||||
<Paper variant="outlined">
|
||||
<Grid container spacing={1}>
|
||||
<Grid item xs={12}>
|
||||
<Box p={1}>
|
||||
<P8PDataGrid
|
||||
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||
columnsDef={dataGrid.columnsDef}
|
||||
groups={dataGrid.groups}
|
||||
rows={dataGrid.rows}
|
||||
size={P8P_DATA_GRID_SIZE.LARGE}
|
||||
reloading={dataGrid.reload}
|
||||
headCellRender={prms => headCellRender({ ...prms }, handleClick)}
|
||||
dataCellRender={prms => dataCellRender({ ...prms }, showEquipSrv)}
|
||||
groupCellRender={prms => groupCellRender({ ...prms })}
|
||||
showCellRightBorder={true}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Paper>
|
||||
<Box sx={{ ...STYLES.GRID_PADDING, ...STYLES.BOX_ROW }}>
|
||||
<P8PDataGrid
|
||||
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||
containerComponentProps={{
|
||||
elevation: 6,
|
||||
style: {
|
||||
...STYLES.GRID_SIZES(width, height)
|
||||
}
|
||||
}}
|
||||
columnsDef={dataGrid.columnsDef}
|
||||
groups={dataGrid.groups}
|
||||
rows={dataGrid.rows}
|
||||
fixedHeader={dataGrid.fixedHeader}
|
||||
fixedColumns={dataGrid.fixedColumns}
|
||||
size={P8P_DATA_GRID_SIZE.LARGE}
|
||||
reloading={dataGrid.reload}
|
||||
headCellRender={prms => headCellRender({ ...prms }, handleClick)}
|
||||
dataCellRender={prms => dataCellRender({ ...prms }, width * 0.2, showEquipSrv)}
|
||||
groupCellRender={prms => groupCellRender({ ...prms })}
|
||||
showCellRightBorder={true}
|
||||
/>
|
||||
</Box>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
36
app/panels/eqs_prfrm/hooks.js
Normal file
36
app/panels/eqs_prfrm/hooks.js
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ТОиР - Выполнение работ
|
||||
Пользовательские хуки
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import { useState, useLayoutEffect } from "react"; //Классы React
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Хук для отработки изменений ширины и высоты рабочей области окна
|
||||
const useWindowResize = () => {
|
||||
//Состояние размера рабочей области
|
||||
const [size, setSize] = useState([0, 0]);
|
||||
//При изменении размера
|
||||
useLayoutEffect(() => {
|
||||
function updateSize() {
|
||||
setSize([document.documentElement.clientWidth, document.documentElement.clientHeight]);
|
||||
}
|
||||
window.addEventListener("resize", updateSize);
|
||||
updateSize();
|
||||
return () => window.removeEventListener("resize", updateSize);
|
||||
}, []);
|
||||
return size;
|
||||
};
|
||||
|
||||
//--------------
|
||||
//Интерфейс хука
|
||||
//--------------
|
||||
|
||||
export { useWindowResize };
|
@ -20,7 +20,7 @@ export const MONTH_NAME_REG_EXP = /_\d{4}_\d{1,2}/;
|
||||
export const DAY_NAME_REG_EXP = /_\d{4}_\d{1,2}_\d{1,2}/;
|
||||
|
||||
//Стили
|
||||
export const STYLES = {
|
||||
const STYLES = {
|
||||
HIDE_CELL_STYLE: { display: "none" },
|
||||
HCR_MAIN_STYLE: { border: "1px solid rgba(0, 0, 0)", textAlign: "center" },
|
||||
HCR_DATE_STYLE: { padding: "5px", minWidth: "25px", maxWidth: "25px" },
|
||||
@ -31,7 +31,12 @@ export const STYLES = {
|
||||
DCR_FACT_NOT_RELATED_CELL_STYLE: { cursor: "pointer", backgroundColor: "crimson", border: "1px solid rgba(0, 0, 0) !important" },
|
||||
DCR_DOUBLE_CELL: { padding: "unset" },
|
||||
DCR_DOUBLE_CELL_GRID_ITEM: backgroundColor => ({ cursor: "pointer", backgroundColor }),
|
||||
HIDDEN_PARAGRAPH: { display: "none" }
|
||||
HIDDEN_PARAGRAPH: { display: "none" },
|
||||
STICKY_WIDTH_UNSET: { minWidth: "unset", maxWidth: "unset" },
|
||||
FIRST_STICKY_CELL: { left: "0px" },
|
||||
OBJINFO_WIDTH: width => ({ minWidth: width, maxWidth: width }),
|
||||
OBJINFO_WRKNAME_WIDTH: width => ({ minWidth: width * 0.6, maxWidth: width * 0.6 }),
|
||||
WRKTYPE_WIDTH: width => ({ left: width * 0.6, minWidth: width - width * 0.4, maxWidth: width - width * 0.4 })
|
||||
};
|
||||
|
||||
//-----------
|
||||
@ -71,7 +76,11 @@ export const headCellRender = ({ columnDef }, hClick) => {
|
||||
//Объединение нужных колонок и строк
|
||||
if (columnDef.name == "SINFO" || columnDef.name == "SWRKTYPE") {
|
||||
cellProps = { colSpan: 2 };
|
||||
if (columnDef.name == "SINFO") cellProps = { ...cellProps, rowSpan: 2 };
|
||||
cellStyle = { ...cellStyle, ...STYLES.STICKY_WIDTH_UNSET };
|
||||
if (columnDef.name == "SINFO") {
|
||||
cellProps = { ...cellProps, rowSpan: 2 };
|
||||
cellStyle = { ...cellStyle, ...STYLES.FIRST_STICKY_CELL };
|
||||
}
|
||||
}
|
||||
//Изменения в заголовках с датами
|
||||
if (columnDef.visible && DAY_NAME_REG_EXP.test(columnDef.name)) {
|
||||
@ -82,7 +91,7 @@ export const headCellRender = ({ columnDef }, hClick) => {
|
||||
};
|
||||
|
||||
//Генерация представления ячейки
|
||||
export const dataCellRender = ({ row, columnDef }, showEquipSrv) => {
|
||||
export const dataCellRender = ({ row, columnDef }, width, showEquipSrv) => {
|
||||
let curParent = "";
|
||||
let cellDate;
|
||||
let cellStyle = STYLES.DCR_MAIN_STYLE;
|
||||
@ -93,10 +102,10 @@ export const dataCellRender = ({ row, columnDef }, showEquipSrv) => {
|
||||
//Ячейка "Информация по объекту ремонта"
|
||||
if (columnDef.name == "SOBJINFO") {
|
||||
cellProps = { colSpan: 2 };
|
||||
cellStyle = { ...cellStyle, ...STYLES.DCR_OBJECT_INFO_STYLE };
|
||||
cellStyle = { ...cellStyle, ...STYLES.DCR_OBJECT_INFO_STYLE, ...STYLES.OBJINFO_WIDTH(width) };
|
||||
}
|
||||
//Ячейка "Тип работ"
|
||||
if (columnDef.name == "SWRKTYPE") cellStyle = STYLES.HIDE_CELL_STYLE;
|
||||
if (columnDef.name == "SWRKTYPE") cellStyle = { ...STYLES.HIDE_CELL_STYLE };
|
||||
//Ячейки колонок месяцев
|
||||
if (columnDef.parent == "" && columnDef.expandable == true && columnDef.expanded == false) {
|
||||
curParent = columnDef.name;
|
||||
@ -118,13 +127,17 @@ export const dataCellRender = ({ row, columnDef }, showEquipSrv) => {
|
||||
}
|
||||
//Строка плана по объекту ремонта
|
||||
if (columnDef.name == "SOBJINFO" && row["SWRKTYPE"] == "План") {
|
||||
cellStyle = { ...cellStyle };
|
||||
cellStyle = { ...cellStyle, ...STYLES.FIRST_STICKY_CELL, ...STYLES.OBJINFO_WRKNAME_WIDTH(width) };
|
||||
cellProps = { rowSpan: 2 };
|
||||
}
|
||||
//Строка факта по объекту ремонта
|
||||
if (columnDef.name == "SOBJINFO" && row["SWRKTYPE"] == "Факт") {
|
||||
cellStyle = { display: "none" };
|
||||
}
|
||||
//Ячейка план/факт
|
||||
if (columnDef.name == "SWRKTYPE") {
|
||||
cellStyle = { ...cellStyle, ...STYLES.WRKTYPE_WIDTH(width) };
|
||||
}
|
||||
//Закрашивание ячеек
|
||||
switch (row[columnDef.name]) {
|
||||
case "blue":
|
||||
|
@ -399,21 +399,24 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
|
||||
/* Определим дату конца периода */
|
||||
NTODATE := LAST_DAY(TO_DATE('01.' || LPAD(TO_CHAR(NTOMONTH), 2, '0') || '.' || TO_CHAR(NTOYEAR), 'dd.mm.yyyy'));
|
||||
/* Инициализируем таблицу данных */
|
||||
RDG := PKG_P8PANELS_VISUAL.TDATA_GRID_MAKE();
|
||||
RDG := PKG_P8PANELS_VISUAL.TDATA_GRID_MAKE(BFIXED_HEADER => true, NFIXED_COLUMNS => 2);
|
||||
/* Формируем структуру заголовка */
|
||||
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
|
||||
SNAME => 'SOBJINFO',
|
||||
SCAPTION => 'Информация по объекту ремонта',
|
||||
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
|
||||
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
|
||||
NWIDTH => 80);
|
||||
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
|
||||
SNAME => 'SINFO',
|
||||
SCAPTION => 'Объект ремонта',
|
||||
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
|
||||
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
|
||||
NWIDTH => 80);
|
||||
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
|
||||
SNAME => 'SWRKTYPE',
|
||||
SCAPTION => 'Тип работ',
|
||||
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
|
||||
SPARENT => 'SINFO');
|
||||
SPARENT => 'SINFO',
|
||||
NWIDTH => 80);
|
||||
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
|
||||
SNAME => 'NRN',
|
||||
SCAPTION => 'Рег. номер',
|
||||
|
Loading…
x
Reference in New Issue
Block a user