Панель - контроль прав доступа, удаление файлов данных, возможность переформирования файлов данных
Исправлена ошибка с "лишним" запросом к серверу на получение списка выборок данных
This commit is contained in:
parent
6e2a28e900
commit
f35d39fefa
@ -12,6 +12,7 @@ import PropTypes from "prop-types"; //Контроль свойств компо
|
||||
import { Box, Grid, Stack, Icon, Button, IconButton } from "@mui/material"; //Интерфейсные компоненты
|
||||
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
|
||||
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с серверомs
|
||||
import { P8PAppInlineError } from "../../components/p8p_app_message"; //Встраиваемое сообщение об ошибке
|
||||
import { DS_RN_DEFAULT, useEquipDataSelectionList } from "./eqs_tech_cond_forecast_hooks"; //Общие вспомогательные хуки
|
||||
import {
|
||||
EquipDataSelectionIU,
|
||||
@ -75,7 +76,9 @@ const AdminTab = ({ dataSelection = DS_RN_DEFAULT, dataSelectionClassMachine = n
|
||||
const [equipDataSelectionClassMachine, setDataSelectionClassMachine] = useState(dataSelectionClassMachine);
|
||||
|
||||
//Загрузка списка выборок данных
|
||||
const { equipDataSelectionList } = useEquipDataSelectionList(refresh.dataSelection);
|
||||
const { equipDataSelectionList, equipDataSelectionListIsLoading, equipDataSelectionListAccess } = useEquipDataSelectionList(
|
||||
refresh.dataSelection
|
||||
);
|
||||
|
||||
//Загрузка классов оборудования выбранной выборки данных
|
||||
const { equipDataSelectionClassMachineList } = useEquipDataSelectionClassMachineList(equipDataSelection, refresh.dataSelectionClassMachine);
|
||||
@ -164,16 +167,43 @@ const AdminTab = ({ dataSelection = DS_RN_DEFAULT, dataSelectionClassMachine = n
|
||||
setDataSelectionClassMachine(data.NRN);
|
||||
};
|
||||
|
||||
//Отработка результатов выполнения пользовательской процедуры формирования данных выборки
|
||||
const processMakeEquipDataSelectionClassMachineFilesResults = async (equipDSCM, dataSetIdent, dataSetConfigIdent, clear) => {
|
||||
await executeStored({
|
||||
stored: "UDO_PKG_EQUIPDS.CMFL_MAKE",
|
||||
args: {
|
||||
NEQUIPDSCM: equipDSCM,
|
||||
NDATASET_IDENT: dataSetIdent,
|
||||
NDATASET_CONFIG_IDENT: dataSetConfigIdent,
|
||||
NCLEAR: clear
|
||||
}
|
||||
});
|
||||
setRefresh(pv => ({ ...pv, dataSelectionClassMachineFilesList: pv.dataSelectionClassMachineFilesList + 1 }));
|
||||
};
|
||||
|
||||
//При нажатии "Сформировать" в списке файлов карточки класса оборудования
|
||||
const handleMakeEquipDataSelectionClassMachineFiles = (equipDSCM, procedure) => {
|
||||
const handleMakeEquipDataSelectionClassMachineFiles = (equipDSCM, procedure, clear) => {
|
||||
pOnlineUserProcedure({
|
||||
code: procedure,
|
||||
inputParameters: [{ name: "NEQUIPDSCM", value: equipDSCM }],
|
||||
callBack: res =>
|
||||
res.success ? setRefresh(pv => ({ ...pv, dataSelectionClassMachineFilesList: pv.dataSelectionClassMachineFilesList + 1 })) : null
|
||||
callBack: res => {
|
||||
if (res.success)
|
||||
processMakeEquipDataSelectionClassMachineFilesResults(
|
||||
equipDSCM,
|
||||
res.outParameters.NDATASET_IDENT,
|
||||
res.outParameters.NDATASET_CONFIG_IDENT,
|
||||
clear
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//При нажатии "Удалить" в списке файлов карточки класса оборудования
|
||||
const handleDeleteEquipDataSelectionClassMachineFiles = async equipDSCMFL => {
|
||||
await executeStored({ stored: "UDO_PKG_EQUIPDS.CMFL_DEL", args: { NRN: equipDSCMFL } });
|
||||
setRefresh(pv => ({ ...pv, dataSelectionClassMachineFilesList: pv.dataSelectionClassMachineFilesList + 1 }));
|
||||
};
|
||||
|
||||
//При нажатии "Загрузить на сервер" в списке файлов карточки класса оборудования
|
||||
const handleUploadEquipDataSelectionClassMachineFiles = async equipDSCM => {
|
||||
await executeStored({ stored: "UDO_PKG_EQUIPDS.CMFL_UPLOAD", args: { NEQUIPDSCM: equipDSCM } });
|
||||
@ -249,9 +279,19 @@ const AdminTab = ({ dataSelection = DS_RN_DEFAULT, dataSelectionClassMachine = n
|
||||
/>
|
||||
) : null}
|
||||
<Grid container>
|
||||
{equipDataSelectionListIsLoading ? null : !equipDataSelectionListAccess ? (
|
||||
<Grid item xs={12}>
|
||||
<P8PAppInlineError text="У вас нет прав доступа для обучения моделей. Обратитесь к администратору." />
|
||||
</Grid>
|
||||
) : (
|
||||
<>
|
||||
<Grid item xs={12}>
|
||||
<Stack direction="row" spacing={2} p={2} sx={STYLES.DATA_SELECTION_STACK}>
|
||||
<EquipDataSelectionList list={equipDataSelectionList} value={equipDataSelection} onChange={handleDataSelectionChange} />
|
||||
<EquipDataSelectionList
|
||||
list={equipDataSelectionList}
|
||||
value={equipDataSelection}
|
||||
onChange={handleDataSelectionChange}
|
||||
/>
|
||||
<Stack direction="row" spacing={0}>
|
||||
<IconButton onClick={handleAddEquipDataSelection}>
|
||||
<Icon>add</Icon>
|
||||
@ -288,6 +328,7 @@ const AdminTab = ({ dataSelection = DS_RN_DEFAULT, dataSelectionClassMachine = n
|
||||
modelsList={equipDataSelectionClassMachineModelsList}
|
||||
onCardDelete={handleDeleteEquipDataSelectionClassMachine}
|
||||
onClassMachineFilesMake={handleMakeEquipDataSelectionClassMachineFiles}
|
||||
onClassMachineFilesDelete={handleDeleteEquipDataSelectionClassMachineFiles}
|
||||
onClassMachineFilesUpload={handleUploadEquipDataSelectionClassMachineFiles}
|
||||
onClassMachineFilesSendMd={handleSendMdEquipDataSelectionClassMachineFiles}
|
||||
onClassMachineModelAdd={handleAddEquipDataSelectionClassMachineModel}
|
||||
@ -297,6 +338,8 @@ const AdminTab = ({ dataSelection = DS_RN_DEFAULT, dataSelectionClassMachine = n
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
|
@ -7,7 +7,7 @@
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React, { useState, useContext } from "react"; //Классы React
|
||||
import React, { useState, useContext, useRef } from "react"; //Классы React
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import {
|
||||
Box,
|
||||
@ -29,7 +29,12 @@ import {
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
IconButton,
|
||||
Icon
|
||||
Icon,
|
||||
Popper,
|
||||
ButtonGroup,
|
||||
ClickAwayListener,
|
||||
Paper,
|
||||
MenuList
|
||||
} from "@mui/material"; //Интерфейсные компоненты
|
||||
import { useTheme } from "@mui/material/styles"; //Темы оформления
|
||||
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
|
||||
@ -138,13 +143,23 @@ const formatFileStateValue = (theme, value, err) => {
|
||||
};
|
||||
|
||||
//Форматирование колонок таблицы файлов класса оборудования выборки данных
|
||||
const filesListDataCellRender = ({ row, columnDef, theme }) => {
|
||||
const filesListDataCellRender = ({ row, columnDef, theme, onDelete }) => {
|
||||
switch (columnDef.name) {
|
||||
case "NSTATUS":
|
||||
return {
|
||||
cellProps: { align: "left" },
|
||||
data: formatFileStateValue(theme, row.NSTATUS, row.SERR)
|
||||
};
|
||||
case "SACTIONS":
|
||||
return {
|
||||
data: (
|
||||
<Stack spacing={1} direction={"row"} alignItems={"center"}>
|
||||
<IconButton onClick={() => (onDelete ? onDelete(row.NRN) : null)}>
|
||||
<Icon>delete</Icon>
|
||||
</IconButton>
|
||||
</Stack>
|
||||
)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@ -183,6 +198,75 @@ const classMachineCardTableHeadCellRender = ({ columnDef }) => {
|
||||
}
|
||||
};
|
||||
|
||||
//Кнопка с всплывающим меню опций
|
||||
const PopUpButton = ({ onClick, options = [], zIndex = 10000 }) => {
|
||||
//Собственное состояние - выбранная опция
|
||||
const [selectedOption, setSelectedOption] = useState(0);
|
||||
|
||||
//Собственное состояние - флаг открытия списка опций
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
//Ссылка на группу кнопок для аттача всплывающего меню
|
||||
const anchorRef = useRef(null);
|
||||
|
||||
//Отработка нажатия на кнопку
|
||||
const handleClick = () => (onClick && options[selectedOption] ? onClick(options[selectedOption]) : null);
|
||||
|
||||
//Отработка открытия/закрытия меню опций
|
||||
const handleToggle = () => {
|
||||
setOpen(prevOpen => !prevOpen);
|
||||
};
|
||||
|
||||
//Принудительное закрытие меню опций (с проверкой открытости)
|
||||
const handleClose = event => {
|
||||
if (anchorRef.current && anchorRef.current.contains(event.target)) return;
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
//Отработка нажатия на элемент меню опций
|
||||
const handleMenuItemClick = index => {
|
||||
setSelectedOption(index);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
//Генерация содержимого
|
||||
return Array.isArray(options) && options.length > 0 ? (
|
||||
<>
|
||||
<ButtonGroup ref={anchorRef} variant="text">
|
||||
<Button onClick={handleClick}>{options[selectedOption]?.label || ""}</Button>
|
||||
<Button size="small" onClick={handleToggle}>
|
||||
<Icon>arrow_drop_down</Icon>
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
<Popper open={open} anchorEl={anchorRef.current} sx={{ zIndex }}>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<Paper>
|
||||
<MenuList autoFocusItem>
|
||||
{options.map((o, index) => (
|
||||
<MenuItem key={o.code} selected={index === selectedOption} onClick={() => handleMenuItemClick(index)}>
|
||||
{o.label}
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
</Paper>
|
||||
</ClickAwayListener>
|
||||
</Popper>
|
||||
</>
|
||||
) : null;
|
||||
};
|
||||
|
||||
//Контроль свойств - Кнопка с всплывающим меню опций
|
||||
PopUpButton.propTypes = {
|
||||
onClick: PropTypes.func,
|
||||
options: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
code: PropTypes.string.isRequired,
|
||||
label: PropTypes.string.isRequired
|
||||
})
|
||||
),
|
||||
zIndex: PropTypes.number
|
||||
};
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
@ -452,6 +536,7 @@ const EquipDataSelectionClassMachineCard = ({
|
||||
modelsList,
|
||||
onCardDelete,
|
||||
onClassMachineFilesMake,
|
||||
onClassMachineFilesDelete,
|
||||
onClassMachineFilesUpload,
|
||||
onClassMachineFilesSendMd,
|
||||
onClassMachineModelAdd,
|
||||
@ -465,7 +550,8 @@ const EquipDataSelectionClassMachineCard = ({
|
||||
const handleCardDeleteClick = () => (onCardDelete ? onCardDelete(card.NRN) : null);
|
||||
|
||||
//При нажатии на "Сформировать" для файлов данных
|
||||
const handleClassMachineFilesMakeClick = () => (onClassMachineFilesMake ? onClassMachineFilesMake(card.NRN, card.SUSERPROCS_DATA) : null);
|
||||
const handleClassMachineFilesMakeClick = option =>
|
||||
onClassMachineFilesMake ? onClassMachineFilesMake(card.NRN, card.SUSERPROCS_DATA, option.code === "CLEAR_AND_MAKE" ? 1 : 0) : null;
|
||||
|
||||
//При нажатии на "Загрузить на сервер" для файлов данных
|
||||
const handleClassMachineFilesUploadClick = () => (onClassMachineFilesUpload ? onClassMachineFilesUpload(card.NRN) : null);
|
||||
@ -473,6 +559,9 @@ const EquipDataSelectionClassMachineCard = ({
|
||||
//При нажатии на "Загрузить на сервер" для файлов данных
|
||||
const handleClassMachineFilesSendMdClick = () => (onClassMachineFilesSendMd ? onClassMachineFilesSendMd(card.NRN) : null);
|
||||
|
||||
//При нажатии на "Удалить" для файлов данных
|
||||
const handleClassMachineFilesDeleteClick = equipDSCMFL => (onClassMachineFilesDelete ? onClassMachineFilesDelete(equipDSCMFL) : null);
|
||||
|
||||
//При нажатии на "Добавить" для моделей
|
||||
const handleClassMachineModelAddClick = () => (onClassMachineModelAdd ? onClassMachineModelAdd() : null);
|
||||
|
||||
@ -502,7 +591,13 @@ const EquipDataSelectionClassMachineCard = ({
|
||||
Файлы данных
|
||||
</Typography>
|
||||
<Stack spacing={0} direction={"row"}>
|
||||
<Button onClick={handleClassMachineFilesMakeClick}>Сформировать</Button>
|
||||
<PopUpButton
|
||||
onClick={handleClassMachineFilesMakeClick}
|
||||
options={[
|
||||
{ code: "MAKE", label: "Сформировать" },
|
||||
{ code: "CLEAR_AND_MAKE", label: "Переформировать" }
|
||||
]}
|
||||
/>
|
||||
<Button onClick={handleClassMachineFilesUploadClick}>Загрузить на сервер</Button>
|
||||
<Button onClick={handleClassMachineFilesSendMdClick}>Передать фреймворку</Button>
|
||||
</Stack>
|
||||
@ -517,7 +612,7 @@ const EquipDataSelectionClassMachineCard = ({
|
||||
fixedHeader={true}
|
||||
reloading={false}
|
||||
headCellRender={classMachineCardTableHeadCellRender}
|
||||
dataCellRender={prms => filesListDataCellRender({ ...prms, theme })}
|
||||
dataCellRender={prms => filesListDataCellRender({ ...prms, theme, onDelete: handleClassMachineFilesDeleteClick })}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@ -565,6 +660,7 @@ EquipDataSelectionClassMachineCard.propTypes = {
|
||||
modelsList: PropTypes.object.isRequired,
|
||||
onCardDelete: PropTypes.func,
|
||||
onClassMachineFilesMake: PropTypes.func,
|
||||
onClassMachineFilesDelete: PropTypes.func,
|
||||
onClassMachineFilesUpload: PropTypes.func,
|
||||
onClassMachineFilesSendMd: PropTypes.func,
|
||||
onClassMachineModelAdd: PropTypes.func,
|
||||
|
@ -44,7 +44,7 @@ const useEquipDataSelectionList = refresh => {
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
|
||||
//Собственное состояние - данные
|
||||
const [data, setData] = useState([DS_DEFAULT]);
|
||||
const [data, setData] = useState({ list: [DS_DEFAULT], access: false });
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored } = useContext(BackEndСtx);
|
||||
@ -61,16 +61,16 @@ const useEquipDataSelectionList = refresh => {
|
||||
attributeValueProcessor: (name, val) => (["SNAME"].includes(name) ? undefined : val),
|
||||
loader: false
|
||||
});
|
||||
setData([DS_DEFAULT, ...(data?.XDS ? data.XDS : [])]);
|
||||
setData({ list: [DS_DEFAULT, ...(data?.XDS ? data.XDS : [])], access: data?.NACCESS == 1 ? true : false });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
loadData();
|
||||
if (refresh > 0) loadData();
|
||||
}, [refresh, executeStored]);
|
||||
|
||||
//Вернём данные
|
||||
return { equipDataSelectionList: data, equipDataSelectionListIsLoading: isLoading };
|
||||
return { equipDataSelectionList: data.list, equipDataSelectionListIsLoading: isLoading, equipDataSelectionListAccess: data.access };
|
||||
};
|
||||
|
||||
//----------------
|
||||
|
@ -15,6 +15,7 @@ import { ApplicationСtx } from "../../context/application"; //Контекст
|
||||
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с серверомs
|
||||
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
|
||||
import { BUTTONS, TEXTS } from "../../../app.text"; //Текстовые ресурсы и константы
|
||||
import { P8PAppInlineError } from "../../components/p8p_app_message"; //Встраиваемое сообщение об ошибке
|
||||
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
|
||||
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
||||
import { formatDateRF, xml2JSON } from "../../core/utils"; //Вспомогательные функции
|
||||
@ -641,7 +642,7 @@ const TechObjMakeDataSet = ({ eqobjKind, measureUnit, onOk, onCancel }) => {
|
||||
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
|
||||
|
||||
//Загрузка списка выборок данных
|
||||
const { equipDataSelectionList } = useEquipDataSelectionList(true);
|
||||
const { equipDataSelectionList, equipDataSelectionListIsLoading, equipDataSelectionListAccess } = useEquipDataSelectionList(true);
|
||||
|
||||
//Собственное состояние - значения формы
|
||||
const [values, setValues] = useState({
|
||||
@ -667,6 +668,8 @@ const TechObjMakeDataSet = ({ eqobjKind, measureUnit, onOk, onCancel }) => {
|
||||
<Dialog open={true} onClose={() => (onOk ? onCancel() : null)}>
|
||||
<DialogTitle>Регистрация выборки данных класса технического объекта</DialogTitle>
|
||||
<DialogContent sx={STYLES.TECH_OBJ_MAKE_DATASET_DIALOG_CONTENT}>
|
||||
{equipDataSelectionListIsLoading ? null : equipDataSelectionListAccess ? (
|
||||
<>
|
||||
<IUDFormTextField
|
||||
elementCode={"dataSet"}
|
||||
elementValue={values.dataSet}
|
||||
@ -752,9 +755,13 @@ const TechObjMakeDataSet = ({ eqobjKind, measureUnit, onOk, onCancel }) => {
|
||||
onChange={handleValueChanged}
|
||||
type={"number"}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<P8PAppInlineError text="У вас нет прав доступа для обучения моделей. Обратитесь к администратору." />
|
||||
)}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => (onOk ? onOk(values) : null)}>{BUTTONS.OK}</Button>
|
||||
{equipDataSelectionListAccess ? <Button onClick={() => (onOk ? onOk(values) : null)}>{BUTTONS.OK}</Button> : null}
|
||||
<Button onClick={() => (onOk ? onCancel() : null)}>{BUTTONS.CANCEL}</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
Loading…
x
Reference in New Issue
Block a user