345 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
Дополнительная разметка и вёрстка клиентских элементов
*/
//---------------------
//Подключение библиотек
//---------------------
import React, { useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import {
IconButton,
Icon,
Link,
Card,
CardContent,
CardHeader,
Menu,
MenuItem,
Table,
TableRow,
TableCell,
TableBody,
Box,
Typography
} from "@mui/material"; //Интерфейсные компоненты
//---------
//Константы
//---------
//Стили
export const STYLES = {
BOX_ROW: { display: "flex", justifyContent: "center", alignItems: "center" },
LINK_STYLE: { component: "button", cursor: "pointer", width: "-webkit-fill-available" },
DATA_CELL: columnDef => ({
padding: "5px 5px",
fontSize: "0.775rem",
letterSpacing: "0.005em",
textAlign: "center",
wordBreak: "break-all",
backgroundColor: columnDef.name === "SROW_NAME" ? "#b4b4b4" : "trasparent"
}),
DATA_CELL_CARD: {
padding: "0px 3px 3px 0px",
border: "1px solid lightgrey",
borderRadius: "5%"
},
DATA_CELL_CARD_HEADER: {
padding: "0px"
},
DATA_CELL_CARD_SUBHEADER: {
textAlign: "left",
paddingLeft: "10px",
fontSize: "1rem",
fontWeight: "450"
},
DATA_CELL_CARD_CONTENT: listLength => {
return {
fontSize: "0.75rem",
padding: "5px 0px",
minHeight: "105px",
maxHeight: "105px",
overflowY: "auto",
"&::-webkit-scrollbar": {
width: "8px"
},
"&::-webkit-scrollbar-track": {
borderRadius: "8px",
backgroundColor: "#EBEBEB"
},
"&::-webkit-scrollbar-thumb": {
borderRadius: "8px",
backgroundColor: "#b4b4b4"
},
"&::-webkit-scrollbar-thumb:hover": {
backgroundColor: "#808080"
},
"&:last-child": {
paddingBottom: "0px"
},
...(listLength === 0 ? { display: "flex", justifyContent: "center", alignItems: "center" } : null)
};
},
DATA_CELL_CARD_CONTEXT_FONT: {
fontSize: "0.75rem"
},
DATA_CELL_CARD_CONTEXT_MARK: {
padding: "0px 0px 0px 10px",
borderBottom: "1px solid #EBEBEB"
},
DATA_CELL_CN: {
textOverflow: "ellipsis",
overflow: "hidden",
whiteSpace: "pre",
padding: "0px 5px",
maxWidth: "100px",
border: "none"
},
GRID_PANEL_CARD: { maxWidth: 400, flexDirection: "column", display: "flex" },
MARK_INFO: {
fontSize: "0.8rem",
textAlign: "left",
textOverflow: "ellipsis",
overflow: "hidden",
whiteSpace: "pre",
maxWidth: "max-content",
width: "-webkit-fill-available"
},
BUTTON_CN_INSERT: {
padding: "0px 8px",
marginBottom: "2px",
"& .MuiIcon-root": {
fontWeight: "bold",
fontSize: "1rem"
}
},
HEAD_CELL: {
backgroundColor: "#b4b4b4",
textAlign: "center"
},
HEAD_CELL_STACK: {
justifyContent: "space-around"
}
};
//------------------------------------
//Вспомогательные функции и компоненты
//------------------------------------
//Действия карты показателя
const DataCellCardActions = ({ columnDef, menuItems, cellData, markRn }) => {
//Собственное состояние
const [cardActions, setCardActions] = useState({ anchorMenuMethods: null, openMethods: false });
//По нажатию на открытие меню действий
const handleMethodsMenuButtonClick = event => {
setCardActions(pv => ({ ...pv, anchorMenuMethods: event.currentTarget, openMethods: true }));
};
//При закрытии меню
const handleMethodsMenuClose = () => {
setCardActions(pv => ({ ...pv, anchorMenuMethods: null, openMethods: false }));
};
return (
<Box sx={STYLES.BOX_ROW}>
<IconButton id={`${columnDef.name}_menu_button`} aria-haspopup="true" onClick={handleMethodsMenuButtonClick}>
<Icon>more_vert</Icon>
</IconButton>
<Menu
id={`${columnDef.name}_menu`}
anchorEl={cardActions.anchorMenuMethods}
open={cardActions.openMethods}
onClose={handleMethodsMenuClose}
>
{menuItems.map(el => {
return (
<MenuItem
key={`${cellData}_${el.method}`}
onClick={() => {
el.func(markRn);
handleMethodsMenuClose();
}}
>
<Icon>{el.icon}</Icon>
{el.name}
</MenuItem>
);
})}
</Menu>
</Box>
);
};
//Контроль свойств - Действия карты показателя
DataCellCardActions.propTypes = {
columnDef: PropTypes.object.isRequired,
menuItems: PropTypes.array,
cellData: PropTypes.any,
markRn: PropTypes.number
};
//Таблица составов показателя
const MarkCnList = ({ markRn, list, handleMarkCnOpen }) => {
return (
<Table>
<TableBody>
{list.map((el, index) => {
return (
<TableRow key={index}>
<TableCell
sx={{ ...STYLES.DATA_CELL_CN, ...STYLES.DATA_CELL_CARD_CONTEXT_FONT }}
title={el.SDESC}
align="left"
size="small"
>
<Link sx={STYLES.LINK_STYLE} onClick={() => handleMarkCnOpen(markRn, el.NRN)}>
{el.SDESC}
</Link>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
);
};
//Контроль свойств - Таблица составов показателя
MarkCnList.propTypes = {
markRn: PropTypes.number.isRequired,
list: PropTypes.array.isRequired,
handleMarkCnOpen: PropTypes.func.isRequired
};
//Ячейка таблицы строки
const DataCellContent = ({ row, columnDef, menuItems, sectionRn, handleMarkAdd, handleMarkOpen, handleMarkCnOpen, handleMarkCnInsert }) => {
//Считываем информацию о показателе
let mark = {
sectionRn: sectionRn,
data: row[columnDef.name],
nRn: row["NMARK_RN_" + columnDef.name.substring(5)],
sCode: row["SMARK_CODE_" + columnDef.name.substring(5)],
sRowCode: row["SROW_CODE"],
nRowRn: row["NROW_RN"],
sColCode: columnDef.name.substring(5),
nColRn: row["NCOL_RN_" + columnDef.name.substring(5)],
rCnList: row["MARK_CNS_" + columnDef.name.substring(5)] ? [...row["MARK_CNS_" + columnDef.name.substring(5)]] : []
};
return (
<>
{mark.nRn ? (
<Card variant={"plain"} sx={STYLES.DATA_CELL_CARD}>
<CardHeader
sx={STYLES.DATA_CELL_CARD_HEADER}
subheader={
<Box>
<Link sx={STYLES.LINK_STYLE} onClick={() => (handleMarkOpen ? handleMarkOpen(mark.nRn) : null)}>
Состав
</Link>
{mark.rCnList.length !== 0 ? (
<IconButton sx={STYLES.BUTTON_CN_INSERT} aria-haspopup="true" onClick={() => handleMarkCnInsert(mark.nRn)}>
<Icon>add</Icon>
</IconButton>
) : null}
</Box>
}
subheaderTypographyProps={STYLES.DATA_CELL_CARD_SUBHEADER}
action={<DataCellCardActions columnDef={columnDef} menuItems={menuItems} cellData={mark.data} markRn={mark.nRn} />}
></CardHeader>
<CardContent sx={STYLES.DATA_CELL_CARD_CONTEXT_MARK}>
<Typography sx={STYLES.MARK_INFO} title={mark.sCode}>
{mark.sCode}
</Typography>
</CardContent>
<CardContent sx={STYLES.DATA_CELL_CARD_CONTENT(mark.rCnList.length)}>
{mark.rCnList.length !== 0 ? (
<MarkCnList markRn={mark.nRn} list={mark.rCnList} handleMarkCnOpen={handleMarkCnOpen} />
) : (
<Box>
<Typography sx={STYLES.DATA_CELL_CARD_CONTEXT_FONT}>Показатель не имеет состава</Typography>
<Link sx={STYLES.LINK_STYLE} onClick={() => (handleMarkCnInsert ? handleMarkCnInsert(mark.nRn) : null)}>
Добавить
</Link>
</Box>
)}
</CardContent>
</Card>
) : (
<Box>
<Typography sx={STYLES.DATA_CELL_CARD_CONTEXT_FONT}>Показатель отсутствует</Typography>
<Link
sx={STYLES.LINK_STYLE}
onClick={() =>
handleMarkOpen ? handleMarkAdd(mark.sectionRn, mark.nRowRn, mark.sRowCode, mark.nColRn, mark.sColCode) : null
}
>
Добавить
</Link>
</Box>
)}
</>
);
};
//Контроль свойств - Ячейка таблицы строки
DataCellContent.propTypes = {
row: PropTypes.object.isRequired,
columnDef: PropTypes.object.isRequired,
menuItems: PropTypes.array,
sectionRn: PropTypes.number.isRequired,
handleMarkAdd: PropTypes.func,
handleMarkOpen: PropTypes.func,
handleMarkCnOpen: PropTypes.func,
handleMarkCnInsert: PropTypes.func
};
//-----------
//Тело модуля
//-----------
//Генерация представления ячейки c данными показателя раздела регламентированного отчета
export const confSctnMrkCellRender = ({
row,
columnDef,
sectionRn,
handleMarkAdd,
handleMarkOpen,
handleMarkCnOpen,
handleMarkCnInsert,
menuItems
}) => {
//Иницализируем стили
let cellStyle = STYLES.DATA_CELL(columnDef);
//Считываем значение
let data = row[columnDef.name];
//Если это не наименование строки и есть значение
columnDef.name != "SROW_NAME" && data != undefined && columnDef.visible == true
? (data = (
<DataCellContent
row={row}
columnDef={columnDef}
menuItems={menuItems}
sectionRn={sectionRn}
handleMarkAdd={handleMarkAdd}
handleMarkOpen={handleMarkOpen}
handleMarkCnOpen={handleMarkCnOpen}
handleMarkCnInsert={handleMarkCnInsert}
/>
))
: null;
return { cellStyle: { ...cellStyle }, data: data };
};
//Генерация представления ячейки заголовка группы c данными показателя раздела регламентированного отчета
export const confSctnMrkHeadCellRender = ({ columnDef }) => {
return {
cellStyle: STYLES.HEAD_CELL,
stackStyle: STYLES.HEAD_CELL_STACK,
data: columnDef.caption
};
};