forked from CITKParus/P8-Panels
ЦИТК-902 - вызов панели "Производственная программа" из контекстного меню
This commit is contained in:
parent
17b4c55d53
commit
79eea7f38f
@ -40,7 +40,9 @@ import {
|
||||
} from "@mui/material"; //Интерфейсные элементы
|
||||
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
||||
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
|
||||
import { NavigationCtx } from "../../context/navigation"; //Контекст навигации
|
||||
import { P8P_GANTT_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
||||
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
|
||||
import { P8PGantt, taskLegendDesc } from "../../components/p8p_gantt"; //Диаграмма Ганта
|
||||
import { xml2JSON, formatDateJSONDateOnly, formatDateRF, hasValue } from "../../core/utils"; //Вспомогательные функции
|
||||
import { useFilteredPlanCtlgs } from "./hooks"; //Вспомогательные хуки
|
||||
@ -58,12 +60,6 @@ const DECLINATIONS = ["план", "плана", "планов"];
|
||||
const SORT_REP_DATE = "DREP_DATE";
|
||||
const SORT_REP_DATE_TO = "DREP_DATE_TO";
|
||||
|
||||
//Высота диаграммы Ганта
|
||||
const GANTT_HEIGHT = "75vh";
|
||||
|
||||
//Ширина диаграммы Ганта
|
||||
const GANTT_WIDTH = "98vw";
|
||||
|
||||
//Стили
|
||||
const STYLES = {
|
||||
PLANS_FINDER: { marginTop: "10px", marginLeft: "10px", width: "93%" },
|
||||
@ -71,20 +67,23 @@ const STYLES = {
|
||||
PLANS_LIST_ITEM_ZERODOCS: { backgroundColor: "#ebecec" },
|
||||
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", top: `calc(${APP_BAR_HEIGHT} + 16px)`, left: "16px" },
|
||||
PLANS_DRAWER: {
|
||||
width: "350px",
|
||||
display: "inline-block",
|
||||
flexShrink: 0,
|
||||
[`& .MuiDrawer-paper`]: { width: "350px", display: "inline-block", boxSizing: "border-box" }
|
||||
},
|
||||
GANTT_CONTAINER: { height: GANTT_HEIGHT, width: GANTT_WIDTH },
|
||||
GANTT_TITLE: { paddingLeft: "100px", paddingRight: "120px" },
|
||||
GANTT_CONTAINER: { height: `calc(100vh - ${APP_BAR_HEIGHT})`, width: "100vw", paddingTop: "24px" },
|
||||
GANTT_TITLE: { paddingLeft: "250px", paddingRight: "250px" },
|
||||
SECOND_TABLE: { paddingTop: "30px" },
|
||||
TASK_DIALOG_CARD_CONTAINER: { padding: "0px" },
|
||||
TASK_DIALOG_LIST_ITEM_ICON: { justifyContent: "center" },
|
||||
TASK_DIALOG_ICON: { fontSize: "2rem" },
|
||||
TASK_DIALOG_ACTION_CONTAINER: { border: 1, borderColor: "text.primary", borderRadius: "5px", width: "100%" }
|
||||
TASK_DIALOG_ACTION_CONTAINER: { border: 1, borderColor: "text.primary", borderRadius: "5px", width: "100%" },
|
||||
FILTERS: { display: "table", float: "right" },
|
||||
FILTERS_DATE: { display: "table-cell", verticalAlign: "middle" },
|
||||
FILTERS_LEVEL: { display: "table-cell", verticalAlign: "middle", paddingLeft: "15px" }
|
||||
};
|
||||
|
||||
//------------------------------------
|
||||
@ -148,7 +147,7 @@ const PlanCtlgsList = ({ planCtlgs = [], selectedPlanCtlg, filter, setFilter, on
|
||||
>
|
||||
<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>}
|
||||
secondary={<Typography sx={STYLES.PLANS_LIST_ITEM_SECONDARY}>{formatCountDocs(p.NCOUNT_DOCS)}</Typography>}
|
||||
/>
|
||||
</ListItemButton>
|
||||
))}
|
||||
@ -210,7 +209,9 @@ const taskDialogRenderer = ({ task, taskColors, close, handleTaskDetailOpen }) =
|
||||
{task["detail_list"]}
|
||||
</Button>
|
||||
) : (
|
||||
<Typography color="textSecondary">{`Анализ отклонений недоступен: ${task["detail_list"]}`}</Typography>
|
||||
<Typography color="textSecondary">{`Анализ отклонений недоступен${
|
||||
task["detail_list"] ? `: ${task["detail_list"]}` : ""
|
||||
}`}</Typography>
|
||||
)}
|
||||
</Box>
|
||||
</CardActions>
|
||||
@ -239,7 +240,8 @@ const MechRecCostProdPlans = () => {
|
||||
selectedPlanCtlgGanttDef: {},
|
||||
selectedPlanCtlgSpecs: [],
|
||||
selectedTaskDetail: null,
|
||||
selectedTaskDetailType: null
|
||||
selectedTaskDetailType: null,
|
||||
planSpec: null
|
||||
});
|
||||
//Состояние для фильтра каталогов
|
||||
const [filter, setFilter] = useState({ ctlgName: "", haveDocs: false });
|
||||
@ -253,7 +255,10 @@ const MechRecCostProdPlans = () => {
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored } = useContext(BackEndСtx);
|
||||
|
||||
// Инициализация каталогов планов
|
||||
//Подключение к контексту навигации
|
||||
const { getNavigationSearch } = useContext(NavigationCtx);
|
||||
|
||||
//Инициализация каталогов планов
|
||||
const initPlanCtlgs = useCallback(async () => {
|
||||
if (!state.init) {
|
||||
const data = await executeStored({
|
||||
@ -307,7 +312,7 @@ const MechRecCostProdPlans = () => {
|
||||
async (level = null, sort = null) => {
|
||||
const data = await executeStored({
|
||||
stored: "PKG_P8PANELS_MECHREC.FCPRODPLANSP_GET",
|
||||
args: { NCRN: state.selectedPlanCtlg, NLEVEL: level, SSORT_FIELD: sort }
|
||||
args: { NCRN: state.selectedPlanCtlg, NLEVEL: level, SSORT_FIELD: sort, NFCPRODPLANSP: state.planSpec }
|
||||
});
|
||||
let doc = await parseProdPlanSpXML(data.COUT);
|
||||
setState(pv => ({
|
||||
@ -324,7 +329,7 @@ const MechRecCostProdPlans = () => {
|
||||
}));
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[executeStored, state.ident, state.selectedPlanCtlg]
|
||||
[executeStored, state.ident, state.selectedPlanCtlg, state.planSpec]
|
||||
);
|
||||
|
||||
//Обработка нажатия на элемент в списке каталогов планов
|
||||
@ -335,14 +340,16 @@ const MechRecCostProdPlans = () => {
|
||||
|
||||
//При подключении компонента к странице
|
||||
useEffect(() => {
|
||||
initPlanCtlgs();
|
||||
const actionPrms = getNavigationSearch();
|
||||
if (actionPrms.NSPRN) setState(pv => ({ ...pv, planSpec: parseInt(actionPrms.NSPRN), init: true }));
|
||||
else initPlanCtlgs();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
//При смене выбранного каталога плана
|
||||
//При смене выбранного каталога плана или при явном указании позиции спецификации плана
|
||||
useEffect(() => {
|
||||
if (state.selectedPlanCtlg) loadPlanCtglSpecs(null, SORT_REP_DATE_TO);
|
||||
}, [state.selectedPlanCtlg, loadPlanCtglSpecs]);
|
||||
if (state.selectedPlanCtlg || state.planSpec) loadPlanCtglSpecs(null, SORT_REP_DATE_TO);
|
||||
}, [state.selectedPlanCtlg, state.planSpec, loadPlanCtglSpecs]);
|
||||
|
||||
//Выбор уровня
|
||||
const handleChangeSelectLevel = selectedLevel => {
|
||||
@ -368,35 +375,48 @@ const MechRecCostProdPlans = () => {
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<Box p={2}>
|
||||
<Fab variant="extended" sx={STYLES.PLANS_BUTTON} onClick={() => setState(pv => ({ ...pv, showPlanList: !pv.showPlanList }))}>
|
||||
Каталоги планов
|
||||
</Fab>
|
||||
<Drawer
|
||||
anchor={"left"}
|
||||
open={state.showPlanList}
|
||||
onClose={() => setState(pv => ({ ...pv, showPlanList: false }))}
|
||||
sx={STYLES.PLANS_DRAWER}
|
||||
>
|
||||
<PlanCtlgsList
|
||||
planCtlgs={filteredPlanCtgls}
|
||||
selectedPlanCtlg={state.selectedPlanCtlg}
|
||||
filter={filter}
|
||||
setFilter={setFilter}
|
||||
onClick={handleProjectClick}
|
||||
/>
|
||||
</Drawer>
|
||||
<Box>
|
||||
{!state.planSpec ? (
|
||||
<>
|
||||
<Fab variant="extended" sx={STYLES.PLANS_BUTTON} onClick={() => setState(pv => ({ ...pv, showPlanList: !pv.showPlanList }))}>
|
||||
Каталоги планов
|
||||
</Fab>
|
||||
<Drawer
|
||||
anchor={"left"}
|
||||
open={state.showPlanList}
|
||||
onClose={() => setState(pv => ({ ...pv, showPlanList: false }))}
|
||||
sx={STYLES.PLANS_DRAWER}
|
||||
>
|
||||
<PlanCtlgsList
|
||||
planCtlgs={filteredPlanCtgls}
|
||||
selectedPlanCtlg={state.selectedPlanCtlg}
|
||||
filter={filter}
|
||||
setFilter={setFilter}
|
||||
onClick={handleProjectClick}
|
||||
/>
|
||||
</Drawer>
|
||||
</>
|
||||
) : null}
|
||||
{state.init == true ? (
|
||||
<Grid container spacing={1}>
|
||||
<Grid container>
|
||||
<Grid item xs={12}>
|
||||
{state.selectedPlanCtlgSpecsLoaded ? (
|
||||
state.selectedPlanCtlgSpecs.length === 0 ? (
|
||||
<InlineMsgInfo okBtn={false} text={"В каталоге планов отсутствуют записи спецификации"} />
|
||||
<Box pt={3}>
|
||||
<InlineMsgInfo
|
||||
okBtn={false}
|
||||
text={
|
||||
state.planSpec
|
||||
? "Не найдено данных для выбранной позиции плана"
|
||||
: "В каталоге планов отсутствуют записи спецификации"
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={STYLES.GANTT_CONTAINER} p={1}>
|
||||
<Box>
|
||||
{state.selectedPlanCtlgMaxLevel ? (
|
||||
<Box sx={{ display: "table", float: "right" }}>
|
||||
<Box sx={{ display: "table-cell", verticalAlign: "middle" }}>
|
||||
<Box sx={STYLES.FILTERS} p={1}>
|
||||
<Box sx={STYLES.FILTERS_DATE}>
|
||||
<InputLabel id="select-label-sort">Сортировка</InputLabel>
|
||||
<Select
|
||||
labelId="select-label-sort"
|
||||
@ -416,7 +436,7 @@ const MechRecCostProdPlans = () => {
|
||||
</MenuItem>
|
||||
</Select>
|
||||
</Box>
|
||||
<Box sx={{ display: "table-cell", verticalAlign: "middle", paddingLeft: "15px" }}>
|
||||
<Box sx={STYLES.FILTERS_LEVEL}>
|
||||
<InputLabel id="select-label-level">До уровня</InputLabel>
|
||||
<Select
|
||||
labelId="select-label-level"
|
||||
@ -440,7 +460,7 @@ const MechRecCostProdPlans = () => {
|
||||
<P8PGantt
|
||||
{...P8P_GANTT_CONFIG_PROPS}
|
||||
{...state.selectedPlanCtlgGanttDef}
|
||||
height={GANTT_HEIGHT}
|
||||
containerStyle={STYLES.GANTT_CONTAINER}
|
||||
titleStyle={STYLES.GANTT_TITLE}
|
||||
tasks={state.selectedPlanCtlgSpecs}
|
||||
taskDialogRenderer={prms => taskDialogRenderer({ ...prms, handleTaskDetailOpen })}
|
||||
@ -448,7 +468,16 @@ const MechRecCostProdPlans = () => {
|
||||
</Box>
|
||||
)
|
||||
) : !state.selectedPlanCtlg ? (
|
||||
<InlineMsgInfo okBtn={false} text={"Укажите каталог планов для отображения их спецификаций"} />
|
||||
<Box pt={3}>
|
||||
<InlineMsgInfo
|
||||
okBtn={false}
|
||||
text={
|
||||
state.planSpec
|
||||
? "Загружаю график для выбранной позиции плана..."
|
||||
: "Укажите каталог планов для отображения их спецификаций"
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
) : null}
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
@ -81,6 +81,7 @@ create or replace package PKG_P8PANELS_MECHREC as
|
||||
procedure FCPRODPLANSP_GET
|
||||
(
|
||||
NCRN in number, -- Рег. номер каталога
|
||||
NFCPRODPLANSP in number, -- Рег. номер позиции спецификации
|
||||
NLEVEL in number := null, -- Уровень отбора
|
||||
SSORT_FIELD in varchar2 := 'DREP_DATE_TO', -- Поле сортировки
|
||||
COUT out clob, -- Список задач
|
||||
@ -2164,6 +2165,7 @@ create or replace package body PKG_P8PANELS_MECHREC as
|
||||
procedure FCPRODPLANSP_GET
|
||||
(
|
||||
NCRN in number, -- Рег. номер каталога
|
||||
NFCPRODPLANSP in number, -- Рег. номер позиции спецификации
|
||||
NLEVEL in number := null, -- Уровень отбора
|
||||
SSORT_FIELD in varchar2 := 'DREP_DATE_TO', -- Поле сортировки
|
||||
COUT out clob, -- Список задач
|
||||
@ -2210,7 +2212,8 @@ create or replace package body PKG_P8PANELS_MECHREC as
|
||||
/* Считывание максимального уровня иерархии плана по каталогу */
|
||||
function PRODPLAN_MAX_LEVEL_GET
|
||||
(
|
||||
NCRN in number -- Рег. номер каталога планов
|
||||
NCRN in number, -- Рег. номер каталога планов
|
||||
NFCPRODPLANSP in number -- Рег. номер позиции спецификации
|
||||
) return number -- Максимальный уровень иерархии
|
||||
is
|
||||
NRESULT PKG_STD.TNUMBER := 1; -- Максимальный уровень иерархии
|
||||
@ -2224,7 +2227,10 @@ create or replace package body PKG_P8PANELS_MECHREC as
|
||||
from FCPRODPLAN P,
|
||||
FCPRODPLANSP T,
|
||||
FINSTATE FS
|
||||
where P.CRN = NCRN
|
||||
where ((NCRN is null) or ((NCRN is not null) and (P.CRN = NCRN)))
|
||||
and ((NFCPRODPLANSP is null) or
|
||||
((NFCPRODPLANSP is not null) and
|
||||
(P.RN = (select PRN from FCPRODPLANSP where RN = NFCPRODPLANSP))))
|
||||
and P.CATEGORY = NFCPRODPLAN_CATEGORY
|
||||
and P.STATUS = NFCPRODPLAN_STATUS
|
||||
and FS.RN = P.TYPE
|
||||
@ -2248,7 +2254,8 @@ create or replace package body PKG_P8PANELS_MECHREC as
|
||||
and T.PRN = P.RN
|
||||
and T.MAIN_QUANT > 0) TMP
|
||||
connect by prior TMP.RN = TMP.UP_LEVEL
|
||||
start with TMP.UP_LEVEL is null
|
||||
start with (((NCRN is not null) and (TMP.UP_LEVEL is null)) or
|
||||
((NCRN is null) and (TMP.RN = NFCPRODPLANSP)))
|
||||
group by level
|
||||
order by level)
|
||||
loop
|
||||
@ -2603,12 +2610,36 @@ create or replace package body PKG_P8PANELS_MECHREC as
|
||||
end GET_TASK_COLORS;
|
||||
begin
|
||||
/* Определяем заголовок плана */
|
||||
FIND_ACATALOG_RN(NFLAG_SMART => 0,
|
||||
NCOMPANY => NCOMPANY,
|
||||
NVERSION => null,
|
||||
SUNITCODE => 'CostProductPlans',
|
||||
NRN => NCRN,
|
||||
SNAME => SPLAN_TITLE);
|
||||
if (NCRN is not null) then
|
||||
FIND_ACATALOG_RN(NFLAG_SMART => 0,
|
||||
NCOMPANY => NCOMPANY,
|
||||
NVERSION => null,
|
||||
SUNITCODE => 'CostProductPlans',
|
||||
NRN => NCRN,
|
||||
SNAME => SPLAN_TITLE);
|
||||
else
|
||||
if (NFCPRODPLANSP is not null) then
|
||||
begin
|
||||
select MR.CODE || ' - ' || MR.NAME || ', ' || T.REL_FACT || ' ' || DM.MEAS_MNEMO || ', ' ||
|
||||
COALESCE(TO_CHAR(T.REP_DATE_TO, 'dd.mm.yyyy'), '<ДАТА ВЫПУСКА НЕ УКАЗА>')
|
||||
into SPLAN_TITLE
|
||||
from FCPRODPLANSP T,
|
||||
FCMATRESOURCE MR,
|
||||
DICNOMNS DN,
|
||||
DICMUNTS DM
|
||||
where T.RN = NFCPRODPLANSP
|
||||
and T.MATRES = MR.RN
|
||||
and MR.NOMENCLATURE = DN.RN
|
||||
and DN.UMEAS_MAIN = DM.RN;
|
||||
exception
|
||||
when NO_DATA_FOUND then
|
||||
PKG_MSG.RECORD_NOT_FOUND(NFLAG_SMART => 0, NDOCUMENT => NFCPRODPLANSP, SUNIT_TABLE => 'FCPRODPLANSP');
|
||||
end;
|
||||
else
|
||||
P_EXCEPTION(0,
|
||||
'Не указан каталог размещения или позиция спецификации плана.');
|
||||
end if;
|
||||
end if;
|
||||
/* Инициализируем диаграмму Ганта */
|
||||
RG := PKG_P8PANELS_VISUAL.TGANTT_MAKE(STITLE => SPLAN_TITLE,
|
||||
NZOOM => PKG_P8PANELS_VISUAL.NGANTT_ZOOM_DAY,
|
||||
@ -2619,7 +2650,7 @@ create or replace package body PKG_P8PANELS_MECHREC as
|
||||
/* Инициализируем описания цветов */
|
||||
TASK_COLORS_INIT(RG => RG);
|
||||
/* Определяем максимальный уровень иерархии */
|
||||
NMAX_LEVEL := PRODPLAN_MAX_LEVEL_GET(NCRN => NCRN);
|
||||
NMAX_LEVEL := PRODPLAN_MAX_LEVEL_GET(NCRN => NCRN, NFCPRODPLANSP => NFCPRODPLANSP);
|
||||
/* Определяем уровень фильтра */
|
||||
NLEVEL_FILTER := COALESCE(NLEVEL, NMAX_LEVEL);
|
||||
/* Обходим данные */
|
||||
@ -2662,7 +2693,10 @@ create or replace package body PKG_P8PANELS_MECHREC as
|
||||
FCMATRESOURCE FM,
|
||||
DICNOMNS D,
|
||||
DICMUNTS DM
|
||||
where P.CRN = NCRN
|
||||
where ((NCRN is null) or ((NCRN is not null) and (P.CRN = NCRN)))
|
||||
and ((NFCPRODPLANSP is null) or
|
||||
((NFCPRODPLANSP is not null) and
|
||||
(P.RN = (select PRN from FCPRODPLANSP where RN = NFCPRODPLANSP))))
|
||||
and P.CATEGORY = NFCPRODPLAN_CATEGORY
|
||||
and P.STATUS = NFCPRODPLAN_STATUS
|
||||
and FS.RN = P.TYPE
|
||||
@ -2692,7 +2726,8 @@ create or replace package body PKG_P8PANELS_MECHREC as
|
||||
and D.UMEAS_MAIN = DM.RN) TMP
|
||||
where level <= NLEVEL_FILTER
|
||||
connect by prior TMP.NRN = TMP.NUP_LEVEL
|
||||
start with TMP.NUP_LEVEL is null
|
||||
start with (((NCRN is not null) and (TMP.NUP_LEVEL is null)) or
|
||||
((NCRN is null) and (TMP.NRN = NFCPRODPLANSP)))
|
||||
order siblings by TMP.DORDER_DATE asc)
|
||||
loop
|
||||
/* Формируем описание задачи в Ганте */
|
||||
|
Loading…
x
Reference in New Issue
Block a user