forked from CITKParus/P8-Panels
WEB APP: Панель "Производственная программа" - рефакторинг имён констант и компонентов, удаление лишних стилей и лишней вёрстки, расстановка комментов по регламенту, удалён isArray для типовых структурных элементов ("XGANTT_TASKS"), удалена лишняя консольная выдача
This commit is contained in:
parent
afa14d8c89
commit
92d3371b4d
@ -1,5 +1,19 @@
|
|||||||
import React from "react";
|
/*
|
||||||
|
Парус 8 - Панели мониторинга - ПУП - Производственная программа
|
||||||
|
Кастомные хуки
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------
|
||||||
|
//Подключение библиотек
|
||||||
|
//---------------------
|
||||||
|
|
||||||
|
import React from "react"; //Классы React
|
||||||
|
|
||||||
|
//-----------
|
||||||
|
//Тело модуля
|
||||||
|
//-----------
|
||||||
|
|
||||||
|
//Клиентский отбор загруженных планов по поисковой фразе
|
||||||
export const useFilteredPlans = (plans, filter) => {
|
export const useFilteredPlans = (plans, filter) => {
|
||||||
const filteredPlans = React.useMemo(() => {
|
const filteredPlans = React.useMemo(() => {
|
||||||
return plans.filter(project => project.SDOC_INFO.toLowerCase().includes(filter));
|
return plans.filter(project => project.SDOC_INFO.toLowerCase().includes(filter));
|
||||||
|
@ -31,32 +31,50 @@ const GANTT_WIDTH = "98vw";
|
|||||||
|
|
||||||
//Стили
|
//Стили
|
||||||
const STYLES = {
|
const STYLES = {
|
||||||
PROJECTS_FINDER: { marginTop: "10px", marginLeft: "10px", width: "93%" },
|
PLANS_FINDER: { marginTop: "10px", marginLeft: "10px", width: "93%" },
|
||||||
PROJECTS_LIST_ITEM_PRIMARY: { wordWrap: "break-word" },
|
PLANS_LIST_ITEM_PRIMARY: { wordWrap: "break-word" },
|
||||||
PROJECTS_LIST_ITEM_SECONDARY: { wordWrap: "break-word", fontSize: "0.5rem", textTransform: "uppercase" },
|
PLANS_BUTTON: { position: "absolute" },
|
||||||
PROJECTS_LIST_ITEM_SECONDARY_NOJOBS: { color: "red" },
|
PLANS_DRAWER: {
|
||||||
PROJECTS_LIST_ITEM_SECONDARY_NOEDIT: { color: "gray" },
|
|
||||||
PROJECTS_LIST_ITEM_SECONDARY_CHANGED: { color: "green" },
|
|
||||||
PROJECTS_BUTTON: { position: "absolute" },
|
|
||||||
PROJECTS_DRAWER: {
|
|
||||||
minWidth: "250px",
|
minWidth: "250px",
|
||||||
display: "inline-block",
|
display: "inline-block",
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
[`& .MuiDrawer-paper`]: { minWidth: "250px", display: "inline-block", boxSizing: "border-box" }
|
[`& .MuiDrawer-paper`]: { minWidth: "250px", display: "inline-block", boxSizing: "border-box" }
|
||||||
},
|
},
|
||||||
GANTT_CONTAINER: { height: GANTT_HEIGHT, width: GANTT_WIDTH },
|
GANTT_CONTAINER: { height: GANTT_HEIGHT, width: GANTT_WIDTH },
|
||||||
GANTT_TITLE: { paddingLeft: "100px", paddingRight: "120px" },
|
GANTT_TITLE: { paddingLeft: "100px", paddingRight: "120px" }
|
||||||
PERIODS_BUTTON: { position: "absolute", right: "20px" },
|
|
||||||
PERIODS_DRAWER: { width: "1000px", flexShrink: 0, [`& .MuiDrawer-paper`]: { width: "1000px", boxSizing: "border-box" } }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Список проектов
|
//------------------------------------
|
||||||
const ProjectsList = ({ plans = [], selectedPlan, filter, setFilter, onClick } = {}) => {
|
//Вспомогательные функции и компоненты
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
//Разбор XML с данными спецификации производственной программы
|
||||||
|
const parseProdPlanSpXML = xmlDoc => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const parser = new XMLParser({
|
||||||
|
ignoreDeclaration: true,
|
||||||
|
ignoreAttributes: false,
|
||||||
|
parseAttributeValue: true,
|
||||||
|
attributeNamePrefix: "",
|
||||||
|
attributeValueProcessor: (name, val) =>
|
||||||
|
name == "numb" ? undefined : ["start", "end"].includes(name) ? formatDateJSONDateOnly(val) : val
|
||||||
|
});
|
||||||
|
const data = parser.parse(xmlDoc);
|
||||||
|
resolve(data.XDATA);
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//Список планов
|
||||||
|
const PlansList = ({ plans = [], selectedPlan, filter, setFilter, onClick } = {}) => {
|
||||||
//Генерация содержимого
|
//Генерация содержимого
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
sx={STYLES.PROJECTS_FINDER}
|
sx={STYLES.PLANS_FINDER}
|
||||||
name="planFilter"
|
name="planFilter"
|
||||||
label="План"
|
label="План"
|
||||||
value={filter}
|
value={filter}
|
||||||
@ -69,21 +87,7 @@ const ProjectsList = ({ plans = [], selectedPlan, filter, setFilter, onClick } =
|
|||||||
<List>
|
<List>
|
||||||
{plans.map(p => (
|
{plans.map(p => (
|
||||||
<ListItemButton key={p.NRN} selected={p.NRN === selectedPlan} onClick={() => (onClick ? onClick(p) : null)}>
|
<ListItemButton key={p.NRN} selected={p.NRN === selectedPlan} onClick={() => (onClick ? onClick(p) : null)}>
|
||||||
<ListItemText
|
<ListItemText primary={<Typography sx={STYLES.PLANS_LIST_ITEM_PRIMARY}>{p.SDOC_INFO}</Typography>} />
|
||||||
primary={<Typography sx={STYLES.PROJECTS_LIST_ITEM_PRIMARY}>{p.SDOC_INFO}</Typography>}
|
|
||||||
secondary={
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
...STYLES.PROJECTS_LIST_ITEM_SECONDARY,
|
|
||||||
...(p.NJOBS == 0
|
|
||||||
? STYLES.PROJECTS_LIST_ITEM_SECONDARY_NOJOBS
|
|
||||||
: p.NCHANGED == 1
|
|
||||||
? STYLES.PROJECTS_LIST_ITEM_SECONDARY_CHANGED
|
|
||||||
: STYLES.PROJECTS_LIST_ITEM_SECONDARY_NOEDIT)
|
|
||||||
}}
|
|
||||||
></Typography>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
@ -91,8 +95,8 @@ const ProjectsList = ({ plans = [], selectedPlan, filter, setFilter, onClick } =
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
//Контроль свойств - Список проектов
|
//Контроль свойств - Список планов
|
||||||
ProjectsList.propTypes = {
|
PlansList.propTypes = {
|
||||||
plans: PropTypes.array,
|
plans: PropTypes.array,
|
||||||
selectedPlan: PropTypes.number,
|
selectedPlan: PropTypes.number,
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
@ -104,26 +108,6 @@ ProjectsList.propTypes = {
|
|||||||
//Тело модуля
|
//Тело модуля
|
||||||
//-----------
|
//-----------
|
||||||
|
|
||||||
//Разбор XML
|
|
||||||
const parseXML = (xmlDoc, attributeValueProcessor) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
try {
|
|
||||||
let opts = {
|
|
||||||
ignoreDeclaration: true,
|
|
||||||
ignoreAttributes: false,
|
|
||||||
parseAttributeValue: true,
|
|
||||||
attributeNamePrefix: ""
|
|
||||||
};
|
|
||||||
if (attributeValueProcessor) opts.attributeValueProcessor = attributeValueProcessor;
|
|
||||||
const parser = new XMLParser(opts);
|
|
||||||
const data = parser.parse(xmlDoc);
|
|
||||||
resolve(data.XDATA);
|
|
||||||
} catch (e) {
|
|
||||||
reject(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//Корневая панель производственной программы
|
//Корневая панель производственной программы
|
||||||
const MechRecCostProdPlans = () => {
|
const MechRecCostProdPlans = () => {
|
||||||
//Собственное состояние
|
//Собственное состояние
|
||||||
@ -160,14 +144,10 @@ const MechRecCostProdPlans = () => {
|
|||||||
const data = await executeStored({
|
const data = await executeStored({
|
||||||
stored: "PKG_P8PANELS_MECHREC.PRODPLAN_INIT",
|
stored: "PKG_P8PANELS_MECHREC.PRODPLAN_INIT",
|
||||||
args: {},
|
args: {},
|
||||||
respArg: "COUT"
|
respArg: "COUT",
|
||||||
|
isArray: name => name === "XFCPRODPLANS"
|
||||||
});
|
});
|
||||||
setState(pv => ({
|
setState(pv => ({ ...pv, init: true, plans: [...(data?.XFCPRODPLANS || [])], plansLoaded: true }));
|
||||||
...pv,
|
|
||||||
init: true,
|
|
||||||
plans: [...(data?.XFCPRODPLANS || [])],
|
|
||||||
plansLoaded: true
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [state.init, executeStored]);
|
}, [state.init, executeStored]);
|
||||||
@ -208,11 +188,7 @@ const MechRecCostProdPlans = () => {
|
|||||||
stored: "PKG_P8PANELS_MECHREC.FCPRODPLANSP_GET",
|
stored: "PKG_P8PANELS_MECHREC.FCPRODPLANSP_GET",
|
||||||
args: { NFCPRODPLAN: state.selectedPlan, NLEVEL: level }
|
args: { NFCPRODPLAN: state.selectedPlan, NLEVEL: level }
|
||||||
});
|
});
|
||||||
let doc = await parseXML(data.COUT, (name, val) =>
|
let doc = await parseProdPlanSpXML(data.COUT);
|
||||||
name == "numb" ? undefined : ["start", "end"].includes(name) ? formatDateJSONDateOnly(val) : val
|
|
||||||
);
|
|
||||||
console.log(doc.XGANTT_DEF);
|
|
||||||
console.log(doc.XGANTT_TASKS);
|
|
||||||
setState(pv => ({
|
setState(pv => ({
|
||||||
...pv,
|
...pv,
|
||||||
selectedPlanMaxLevel: data.NMAX_LEVEL,
|
selectedPlanMaxLevel: data.NMAX_LEVEL,
|
||||||
@ -256,19 +232,20 @@ const MechRecCostProdPlans = () => {
|
|||||||
loadPlanSpecs(selectedLevel);
|
loadPlanSpecs(selectedLevel);
|
||||||
setState(pv => ({ ...pv, selectedPlanLevel: selectedLevel }));
|
setState(pv => ({ ...pv, selectedPlanLevel: selectedLevel }));
|
||||||
};
|
};
|
||||||
|
|
||||||
//Генерация содержимого
|
//Генерация содержимого
|
||||||
return (
|
return (
|
||||||
<Box p={2}>
|
<Box p={2}>
|
||||||
<Fab variant="extended" sx={STYLES.PROJECTS_BUTTON} onClick={() => setState(pv => ({ ...pv, showPlanList: !pv.showPlanList }))}>
|
<Fab variant="extended" sx={STYLES.PLANS_BUTTON} onClick={() => setState(pv => ({ ...pv, showPlanList: !pv.showPlanList }))}>
|
||||||
Планы
|
Планы
|
||||||
</Fab>
|
</Fab>
|
||||||
<Drawer
|
<Drawer
|
||||||
anchor={"left"}
|
anchor={"left"}
|
||||||
open={state.showPlanList}
|
open={state.showPlanList}
|
||||||
onClose={() => setState(pv => ({ ...pv, showPlanList: false }))}
|
onClose={() => setState(pv => ({ ...pv, showPlanList: false }))}
|
||||||
sx={STYLES.PROJECTS_DRAWER}
|
sx={STYLES.PLANS_DRAWER}
|
||||||
>
|
>
|
||||||
<ProjectsList
|
<PlansList
|
||||||
plans={filteredPlans}
|
plans={filteredPlans}
|
||||||
selectedPlan={state.selectedPlan}
|
selectedPlan={state.selectedPlan}
|
||||||
filter={filter}
|
filter={filter}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user