ЦИТК-802 - Изменения блока выбора каталога
This commit is contained in:
parent
ab30b92d9a
commit
a0e9be4c4b
@ -13,10 +13,14 @@ import React from "react"; //Классы React
|
|||||||
//Тело модуля
|
//Тело модуля
|
||||||
//-----------
|
//-----------
|
||||||
|
|
||||||
//Клиентский отбор загруженных планов по поисковой фразе
|
//Клиентский отбор каталогов по поисковой фразе и наличию планов
|
||||||
export const useFilteredPlanCtlgs = (planCtlgs, filter) => {
|
export const useFilteredPlanCtlgs = (planCtlgs, filter) => {
|
||||||
const filteredPlanCtlgs = React.useMemo(() => {
|
const filteredPlanCtlgs = React.useMemo(() => {
|
||||||
return planCtlgs.filter(catalog => catalog.SNAME.toString().toLowerCase().includes(filter));
|
return planCtlgs.filter(
|
||||||
|
catalog =>
|
||||||
|
catalog.SNAME.toString().toLowerCase().includes(filter.ctlgName) &&
|
||||||
|
(filter.haveDocs ? catalog.NCOUNT_DOCS > 0 : catalog.NCOUNT_DOCS >= 0)
|
||||||
|
);
|
||||||
}, [planCtlgs, filter]);
|
}, [planCtlgs, filter]);
|
||||||
|
|
||||||
return filteredPlanCtlgs;
|
return filteredPlanCtlgs;
|
||||||
|
@ -9,7 +9,23 @@
|
|||||||
|
|
||||||
import React, { useContext, useState, useCallback, useEffect } from "react"; //Классы React
|
import React, { useContext, useState, useCallback, useEffect } from "react"; //Классы React
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||||
import { Drawer, Fab, Box, List, ListItemButton, ListItemText, Typography, Grid, TextField, Select, MenuItem, InputLabel } from "@mui/material"; //Интерфейсные элементы
|
import {
|
||||||
|
Drawer,
|
||||||
|
Fab,
|
||||||
|
Box,
|
||||||
|
List,
|
||||||
|
ListItemButton,
|
||||||
|
ListItemText,
|
||||||
|
Typography,
|
||||||
|
Grid,
|
||||||
|
TextField,
|
||||||
|
Select,
|
||||||
|
MenuItem,
|
||||||
|
InputLabel,
|
||||||
|
FormGroup,
|
||||||
|
FormControlLabel,
|
||||||
|
Checkbox
|
||||||
|
} from "@mui/material"; //Интерфейсные элементы
|
||||||
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
||||||
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
|
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
|
||||||
import { P8P_GANTT_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
import { P8P_GANTT_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
||||||
@ -21,6 +37,9 @@ import { useFilteredPlanCtlgs } from "./hooks"; //Вспомогательные
|
|||||||
//Константы
|
//Константы
|
||||||
//---------
|
//---------
|
||||||
|
|
||||||
|
//Склонения для документов
|
||||||
|
const DECLINATIONS = ["план", "плана", "планов"];
|
||||||
|
|
||||||
//Поля сортировки
|
//Поля сортировки
|
||||||
const SORT_REP_DATE = "DREP_DATE";
|
const SORT_REP_DATE = "DREP_DATE";
|
||||||
const SORT_REP_DATE_TO = "DREP_DATE_TO";
|
const SORT_REP_DATE_TO = "DREP_DATE_TO";
|
||||||
@ -34,13 +53,16 @@ const GANTT_WIDTH = "98vw";
|
|||||||
//Стили
|
//Стили
|
||||||
const STYLES = {
|
const STYLES = {
|
||||||
PLANS_FINDER: { marginTop: "10px", marginLeft: "10px", width: "93%" },
|
PLANS_FINDER: { marginTop: "10px", marginLeft: "10px", width: "93%" },
|
||||||
|
PLANS_CHECKBOX_HAVEDOCS: { alignContent: "space-around" },
|
||||||
|
PLANS_LIST_ITEM_ZERODOCS: { backgroundColor: "#ebecec" },
|
||||||
PLANS_LIST_ITEM_PRIMARY: { wordWrap: "break-word" },
|
PLANS_LIST_ITEM_PRIMARY: { wordWrap: "break-word" },
|
||||||
|
PLANS_LIST_ITEM_SECONDARY: { wordWrap: "break-word", fontSize: "0.6rem", textTransform: "uppercase" },
|
||||||
PLANS_BUTTON: { position: "absolute" },
|
PLANS_BUTTON: { position: "absolute" },
|
||||||
PLANS_DRAWER: {
|
PLANS_DRAWER: {
|
||||||
minWidth: "250px",
|
width: "350px",
|
||||||
display: "inline-block",
|
display: "inline-block",
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
[`& .MuiDrawer-paper`]: { minWidth: "250px", display: "inline-block", boxSizing: "border-box" }
|
[`& .MuiDrawer-paper`]: { width: "350px", 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" }
|
||||||
@ -59,6 +81,26 @@ const parseProdPlanSpXML = async xmlDoc => {
|
|||||||
return data.XDATA;
|
return data.XDATA;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Форматирование для отображения количества документов
|
||||||
|
const formatCountDocs = nCountDocs => {
|
||||||
|
//Получаем последнюю цифру в значении
|
||||||
|
let num = (nCountDocs % 100) % 10;
|
||||||
|
//Документов
|
||||||
|
if (nCountDocs > 10 && nCountDocs < 20) {
|
||||||
|
return `${nCountDocs} ${DECLINATIONS[2]}`;
|
||||||
|
}
|
||||||
|
//Документа
|
||||||
|
if (num > 1 && num < 5) {
|
||||||
|
return `${nCountDocs} ${DECLINATIONS[1]}`;
|
||||||
|
}
|
||||||
|
//Документ
|
||||||
|
if (num == 1) {
|
||||||
|
return `${nCountDocs} ${DECLINATIONS[0]}`;
|
||||||
|
}
|
||||||
|
//Документов
|
||||||
|
return `${nCountDocs} ${DECLINATIONS[2]}`;
|
||||||
|
};
|
||||||
|
|
||||||
//Список каталогов планов
|
//Список каталогов планов
|
||||||
const PlanCtlgsList = ({ planCtlgs = [], selectedPlanCtlg, filter, setFilter, onClick } = {}) => {
|
const PlanCtlgsList = ({ planCtlgs = [], selectedPlanCtlg, filter, setFilter, onClick } = {}) => {
|
||||||
//Генерация содержимого
|
//Генерация содержимого
|
||||||
@ -67,18 +109,48 @@ const PlanCtlgsList = ({ planCtlgs = [], selectedPlanCtlg, filter, setFilter, on
|
|||||||
<TextField
|
<TextField
|
||||||
sx={STYLES.PLANS_FINDER}
|
sx={STYLES.PLANS_FINDER}
|
||||||
name="planFilter"
|
name="planFilter"
|
||||||
label="План"
|
label="Каталог"
|
||||||
value={filter}
|
value={filter.ctlgName}
|
||||||
variant="standard"
|
variant="standard"
|
||||||
fullWidth
|
fullWidth
|
||||||
onChange={event => {
|
onChange={event => {
|
||||||
setFilter(event.target.value);
|
setFilter(pv => ({ ...pv, ctlgName: event.target.value }));
|
||||||
}}
|
}}
|
||||||
></TextField>
|
></TextField>
|
||||||
|
<FormGroup sx={STYLES.PLANS_CHECKBOX_HAVEDOCS}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={filter.haveDocs}
|
||||||
|
onChange={event => {
|
||||||
|
setFilter(pv => ({ ...pv, haveDocs: event.target.checked }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Только с планами"
|
||||||
|
labelPlacement="end"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
<List>
|
<List>
|
||||||
{planCtlgs.map(p => (
|
{planCtlgs.map(p => (
|
||||||
<ListItemButton key={p.NRN} selected={p.NRN === selectedPlanCtlg} onClick={() => (onClick ? onClick(p) : null)}>
|
<ListItemButton
|
||||||
<ListItemText primary={<Typography sx={STYLES.PLANS_LIST_ITEM_PRIMARY}>{p.SNAME}</Typography>} />
|
sx={p.NCOUNT_DOCS == 0 ? STYLES.PLANS_LIST_ITEM_ZERODOCS : null}
|
||||||
|
key={p.NRN}
|
||||||
|
selected={p.NRN === selectedPlanCtlg}
|
||||||
|
onClick={() => (onClick ? onClick(p) : null)}
|
||||||
|
>
|
||||||
|
<ListItemText
|
||||||
|
primary={<Typography sx={STYLES.PLANS_LIST_ITEM_PRIMARY}>{p.SNAME}</Typography>}
|
||||||
|
secondary={
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
...STYLES.PLANS_LIST_ITEM_SECONDARY
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{formatCountDocs(p.NCOUNT_DOCS)}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
@ -116,9 +188,10 @@ const MechRecCostProdPlans = () => {
|
|||||||
selectedPlanCtlgGanttDef: {},
|
selectedPlanCtlgGanttDef: {},
|
||||||
selectedPlanCtlgSpecs: []
|
selectedPlanCtlgSpecs: []
|
||||||
});
|
});
|
||||||
|
//Состояние для фильтра каталогов
|
||||||
|
const [filter, setFilter] = useState({ ctlgName: "", haveLinks: false });
|
||||||
|
|
||||||
const [filter, setFilter] = useState("");
|
//Массив отфильтрованных каталогов
|
||||||
|
|
||||||
const filteredPlanCtgls = useFilteredPlanCtlgs(state.planCtlgs, filter);
|
const filteredPlanCtgls = useFilteredPlanCtlgs(state.planCtlgs, filter);
|
||||||
|
|
||||||
//Подключение к контексту сообщений
|
//Подключение к контексту сообщений
|
||||||
|
@ -557,7 +557,32 @@ create or replace package body PKG_P8PANELS_MECHREC as
|
|||||||
PKG_XFAST.DOWN_NODE(SNAME => 'XDATA');
|
PKG_XFAST.DOWN_NODE(SNAME => 'XDATA');
|
||||||
/* Цикл по планам и отчетам производства изделий */
|
/* Цикл по планам и отчетам производства изделий */
|
||||||
for REC in (select T.RN as NRN,
|
for REC in (select T.RN as NRN,
|
||||||
T.NAME as SNAME
|
T.NAME as SNAME,
|
||||||
|
(select count(P.RN)
|
||||||
|
from FCPRODPLAN P,
|
||||||
|
FINSTATE FS
|
||||||
|
where P.CRN = T.RN
|
||||||
|
and P.CATEGORY = NFCPRODPLAN_CATEGORY
|
||||||
|
and P.STATUS = NFCPRODPLAN_STATUS
|
||||||
|
and FS.RN = P.TYPE
|
||||||
|
and FS.CODE = SFCPRODPLAN_TYPE
|
||||||
|
and exists
|
||||||
|
(select /*+ INDEX(UP I_USERPRIV_JUR_PERS_ROLEID) */
|
||||||
|
null
|
||||||
|
from USERPRIV UP
|
||||||
|
where UP.JUR_PERS = P.JUR_PERS
|
||||||
|
and UP.UNITCODE = 'CostProductPlans'
|
||||||
|
and UP.ROLEID in (select /*+ INDEX(UR I_USERROLES_AUTHID_FK) */
|
||||||
|
UR.ROLEID
|
||||||
|
from USERROLES UR
|
||||||
|
where UR.AUTHID = UTILIZER)
|
||||||
|
union all
|
||||||
|
select /*+ INDEX(UP I_USERPRIV_JUR_PERS_AUTHID) */
|
||||||
|
null
|
||||||
|
from USERPRIV UP
|
||||||
|
where UP.JUR_PERS = P.JUR_PERS
|
||||||
|
and UP.UNITCODE = 'CostProductPlans'
|
||||||
|
and UP.AUTHID = UTILIZER)) as NCOUNT_DOCS
|
||||||
from ACATALOG T,
|
from ACATALOG T,
|
||||||
UNITLIST UL
|
UNITLIST UL
|
||||||
where T.DOCNAME = 'CostProductPlans'
|
where T.DOCNAME = 'CostProductPlans'
|
||||||
@ -577,6 +602,7 @@ create or replace package body PKG_P8PANELS_MECHREC as
|
|||||||
/* Описываем план */
|
/* Описываем план */
|
||||||
PKG_XFAST.ATTR(SNAME => 'NRN', NVALUE => REC.NRN);
|
PKG_XFAST.ATTR(SNAME => 'NRN', NVALUE => REC.NRN);
|
||||||
PKG_XFAST.ATTR(SNAME => 'SNAME', SVALUE => REC.SNAME);
|
PKG_XFAST.ATTR(SNAME => 'SNAME', SVALUE => REC.SNAME);
|
||||||
|
PKG_XFAST.ATTR(SNAME => 'NCOUNT_DOCS', NVALUE => REC.NCOUNT_DOCS);
|
||||||
/* Закрываем план */
|
/* Закрываем план */
|
||||||
PKG_XFAST.UP();
|
PKG_XFAST.UP();
|
||||||
end loop;
|
end loop;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user