ЦИТК-839 - Рефакторинг кода панели "Выполнение работ" для ТОиР

This commit is contained in:
Mikhail Chechnev 2024-06-24 18:38:33 +03:00 committed by GitHub
commit a96738013c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 496 additions and 442 deletions

View File

@ -8,26 +8,7 @@
//--------------------- //---------------------
import React, { useState, useContext, useCallback, useEffect } from "react"; //Классы React import React, { useState, useContext, useCallback, useEffect } from "react"; //Классы React
import { import { Grid, Paper, Box, Link } from "@mui/material"; //Интерфейсные компоненты
Grid,
Paper,
Box,
Link,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
InputLabel,
FormControl,
OutlinedInput,
InputAdornment,
IconButton,
Icon,
Select,
MenuItem,
FormHelperText
} from "@mui/material";
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
@ -35,6 +16,7 @@ import { ApplicationСtx } from "../../context/application"; //Контекст
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { headCellRender, dataCellRender, groupCellRender, DIGITS_REG_EXP, MONTH_NAME_REG_EXP, DAY_NAME_REG_EXP } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов import { headCellRender, dataCellRender, groupCellRender, DIGITS_REG_EXP, MONTH_NAME_REG_EXP, DAY_NAME_REG_EXP } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы
import { FilterDialog } from "./filter_dialog"; //Компонент диалогового окна фильтра отбора
//----------- //-----------
//Тело модуля //Тело модуля
@ -51,10 +33,7 @@ const EqsPrfrm = () => {
reload: false reload: false
}); });
// Состояние информации о трудоёмкости //Состояние фильтра
const [info, setInfo] = useState({ cntP: 0, sumP: 0, cntF: 0, sumF: 0 });
// Состояние фильтра
const [filter, setFilter] = useState({ const [filter, setFilter] = useState({
belong: "", belong: "",
prodObj: "", prodObj: "",
@ -65,22 +44,24 @@ const EqsPrfrm = () => {
toMonth: 1, toMonth: 1,
toYear: 1990 toYear: 1990
}); });
// Состояние открытия фильтра
const [filterOpen, setFilterOpen] = useState(true);
// Состояние данных по умолчанию для фильтра
const [defaultLoaded, setDefaultLoaded] = useState(false);
// Состояние хранения копии фильтра
const [filterCopy, setFilterCopy] = useState({ ...filter });
// Состояние ограничения редактирования фильтра
const [filterLock, setFilterLock] = useState(false);
// Состояние ячейки заголовка даты (по раскрытию/скрытию) //Состояние хранения копии фильтра
const [filterCopy, setFilterCopy] = useState({ ...filter });
//Состояние открытия фильтра
const [filterOpen, setFilterOpen] = useState(true);
//Состояние данных по умолчанию для фильтра
const [defaultLoaded, setDefaultLoaded] = useState(false);
//Состояние ячейки заголовка даты (по раскрытию/скрытию)
const [activeRef, setActiveRef] = useState(); const [activeRef, setActiveRef] = useState();
// Состояние актуальности ссылки на ячейку
//Состояние актуальности ссылки на ячейку
const [refIsDeprecated, setRidFlag] = useState(true); const [refIsDeprecated, setRidFlag] = useState(true);
//Подключение к контексту приложения //Подключение к контексту приложения
const { pOnlineShowDictionary, pOnlineShowUnit } = useContext(ApplicationСtx); const { pOnlineShowUnit } = useContext(ApplicationСtx);
//Подключение к контексту взаимодействия с сервером //Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx); const { executeStored } = useContext(BackEndСtx);
@ -146,7 +127,6 @@ const EqsPrfrm = () => {
} }
}); });
} }
setInfo({ cntP: cP, sumP: sP, cntF: cF, sumF: sF });
setDataGrid(pv => ({ setDataGrid(pv => ({
...pv, ...pv,
columnsDef: data.XCOLUMNS_DEF ? [...data.XCOLUMNS_DEF] : pv.columnsDef, columnsDef: data.XCOLUMNS_DEF ? [...data.XCOLUMNS_DEF] : pv.columnsDef,
@ -164,23 +144,17 @@ const EqsPrfrm = () => {
stored: "PKG_P8PANELS_EQUIPSRV.GET_DEFAULT_FP", stored: "PKG_P8PANELS_EQUIPSRV.GET_DEFAULT_FP",
respArg: "COUT" respArg: "COUT"
}); });
setFilter(pv => ({ ...pv, belong: data.JURPERS, fromMonth: 1, fromYear: data.YEAR, toMonth: 12, toYear: data.YEAR })); setFilter(pv => ({ ...pv, belong: data.JURPERS, fromMonth: 1, fromYear: data.YEAR, toMonth: 12, toYear: data.YEAR }));
setDefaultLoaded(true); setDefaultLoaded(true);
}, [executeStored]); }, [executeStored]);
// Отбор документа (ТОиР или Ремонтных ведомостей) по ячейке даты //Отбор документа (ТОиР или Ремонтных ведомостей) по ячейке даты
const showEquipSrv = async ({ date, workType, info }) => { const showEquipSrv = async ({ date, workType, info }) => {
const [techName, servKind] = info.split("_"); const [techName, servKind] = info.split("_");
let type; let type;
if (workType == "План") type = 0; if (workType == "План") type = 0;
else type = 1; else type = 1;
let [year, month, day] = date.substring(1).split("_"); let [year, month, day] = date.substring(1).split("_");
//if (day == undefined) day = null;
const data = await executeStored({ const data = await executeStored({
stored: "PKG_P8PANELS_EQUIPSRV.SELECT_EQUIPSRV", stored: "PKG_P8PANELS_EQUIPSRV.SELECT_EQUIPSRV",
args: { args: {
@ -202,47 +176,26 @@ const EqsPrfrm = () => {
} else showMsgErr(TEXTS.NO_DATA_FOUND); } else showMsgErr(TEXTS.NO_DATA_FOUND);
}; };
// Открыть фильтр //Открыть фильтр
const openFilter = () => { const openFilter = () => {
setFilterOpen(true); setFilterOpen(true);
}; };
// Закрыть фильтр //Отработка события скрытия/раскрытия ячейки даты
const closeFilter = e => {
if (filterLock && e != undefined) setFilter(filterCopy);
setFilterOpen(false);
};
// Очистить фильтр
const clearFilter = () => {
setFilter({
belong: "",
prodObj: "",
techServ: "",
respDep: "",
fromMonth: "",
fromYear: "",
toMonth: "",
toYear: ""
});
};
// Отработка события скрытия/раскрытия ячейки даты
const handleClick = (e, ref) => { const handleClick = (e, ref) => {
const curCell = ref.current; const curCell = ref.current;
if (e.target.type == "button" || e.target.offsetParent.type == "button") { if (e.target.type == "button" || e.target.offsetParent.type == "button") {
setActiveRef(curCell); setActiveRef(curCell);
setRidFlag(false); setRidFlag(false);
} }
}; };
// При необходимости обновить данные таблицы //При необходимости обновить данные таблицы
useEffect(() => { useEffect(() => {
loadData(); loadData();
}, [loadData, dataGrid.reload]); }, [loadData, dataGrid.reload]);
// При открытом фильтре //При открытом фильтре
useEffect(() => { useEffect(() => {
if (filterOpen) { if (filterOpen) {
{ {
@ -250,10 +203,10 @@ const EqsPrfrm = () => {
if (!defaultLoaded) loadDefaultFilter(); if (!defaultLoaded) loadDefaultFilter();
} }
} }
// eslint-disable-next-line react-hooks/exhaustive-deps //eslint-disable-next-line react-hooks/exhaustive-deps
}, [filterOpen]); }, [filterOpen]);
// При нажатии скрытии/раскрытии ячейки даты, фокус на неё //При нажатии скрытии/раскрытии ячейки даты, фокус на неё
useEffect(() => { useEffect(() => {
if (!refIsDeprecated) { if (!refIsDeprecated) {
if (activeRef) { if (activeRef) {
@ -262,313 +215,20 @@ const EqsPrfrm = () => {
setRidFlag(true); setRidFlag(true);
} }
} }
// eslint-disable-next-line react-hooks/exhaustive-deps //eslint-disable-next-line react-hooks/exhaustive-deps
}, [refIsDeprecated]); }, [refIsDeprecated]);
let yearArray = [];
const monthArray = ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"];
let today = new Date();
// Получение списка лет
const getYearArray = () => {
for (let i = 1990; i <= today.getFullYear(); i++) {
yearArray.push(i);
}
};
//Генерация содержимого //Генерация содержимого
return ( return (
<div> <div>
{getYearArray()} <FilterDialog
<Dialog open={filterOpen} onClose={closeFilter}> filter={filter}
<DialogTitle>Фильтр отбора</DialogTitle> filterCopy={filterCopy}
<IconButton filterOpen={filterOpen}
aria-label="close" setFilter={setFilter}
onClick={closeFilter} setFilterOpen={setFilterOpen}
sx={{ setDataGrid={setDataGrid}
position: "absolute",
right: 8,
top: 8,
color: theme => theme.palette.grey[500]
}}
>
<Icon>close</Icon>
</IconButton>
<DialogContent>
<Paper>
<Box component="section" sx={{ p: 1 }}>
<FormControl readOnly fullWidth variant="outlined">
<InputLabel htmlFor="belong-outlined">Принадлежность</InputLabel>
<OutlinedInput
error={filter.belong ? false : true}
id="belong-outlined"
value={filter.belong}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="belong select"
onClick={() => {
pOnlineShowDictionary({
unitCode: "JuridicalPersons",
callBack: res =>
res.success === true
? setFilter(pv => ({ ...pv, belong: res.outParameters.out_CODE }))
: null
});
}}
edge="end"
>
<Icon>list</Icon>
</IconButton>
</InputAdornment>
}
aria-describedby="belong-outlined-helper-text"
label="Принадлежность"
/> />
{filter.belong ? null : (
<FormHelperText id="belong-outlined-helper-text" sx={{ color: "red" }}>
*Обязательное поле
</FormHelperText>
)}
</FormControl>
</Box>
<Box component="section" sx={{ p: 1 }}>
<FormControl readOnly fullWidth>
<InputLabel htmlFor="prodObj-outlined">Производственный объект</InputLabel>
<OutlinedInput
error={filter.prodObj ? false : true}
id="prodObj-outlined"
value={filter.prodObj}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="prodObj select"
onClick={() => {
pOnlineShowDictionary({
unitCode: "EquipConfiguration",
callBack: res =>
res.success === true
? setFilter(pv => ({ ...pv, prodObj: res.outParameters.out_CODE }))
: null
});
}}
edge="end"
>
<Icon>list</Icon>
</IconButton>
</InputAdornment>
}
aria-describedby="prodObj-outlined-helper-text"
label="Производственный объект"
/>
{filter.prodObj ? null : (
<FormHelperText id="prodObj-outlined-helper-text" sx={{ color: "red" }}>
*Обязательное поле
</FormHelperText>
)}
</FormControl>
</Box>
<Box component="section" sx={{ p: 1 }}>
<FormControl readOnly fullWidth>
<InputLabel htmlFor="techServ-outlined">Техническая служба</InputLabel>
<OutlinedInput
id="techServ-outlined"
value={filter.techServ}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="techServ select"
onClick={() => {
pOnlineShowDictionary({
unitCode: "INS_DEPARTMENT",
callBack: res =>
res.success === true
? setFilter(pv => ({ ...pv, techServ: res.outParameters.out_CODE }))
: null
});
}}
edge="end"
>
<Icon>list</Icon>
</IconButton>
</InputAdornment>
}
label="Техническая служба"
/>
</FormControl>
</Box>
<Box component="section" sx={{ p: 1 }}>
<FormControl readOnly fullWidth>
<InputLabel htmlFor="respDep-outlined">Ответственное подразделение</InputLabel>
<OutlinedInput
id="respDep-outlined"
value={filter.respDep}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="respDep select"
onClick={() => {
pOnlineShowDictionary({
unitCode: "INS_DEPARTMENT",
callBack: res =>
res.success === true
? setFilter(pv => ({ ...pv, respDep: res.outParameters.out_CODE }))
: null
});
}}
edge="end"
>
<Icon>list</Icon>
</IconButton>
</InputAdornment>
}
label="Ответственное подразделение"
/>
</FormControl>
</Box>
<Box component="section" sx={{ p: 1 }}>
<Grid container spacing={2}>
<Grid textAlign={"center"} item xs={4}>
Начало периода:
</Grid>
<Grid item xs={4}>
<FormControl fullWidth>
<InputLabel id="from-month-select-label">Месяц</InputLabel>
<Select
error={filter.fromMonth ? false : true}
labelId="from-month-select-label"
id="from-month-select"
value={filter.fromMonth}
aria-describedby="from-month-select-helper-text"
label="Месяц"
onChange={e => setFilter(pv => ({ ...pv, fromMonth: e.target.value }))}
>
{monthArray.map((item, i) => (
<MenuItem key={i + 1} value={i + 1}>
{item}
</MenuItem>
))}
</Select>
{filter.fromMonth ? null : (
<FormHelperText id="from-month-select-helper-text" sx={{ color: "red" }}>
*Обязательное поле
</FormHelperText>
)}
</FormControl>
</Grid>
<Grid item xs={4}>
<FormControl fullWidth>
<InputLabel id="from-year-select-label">Год</InputLabel>
<Select
error={filter.fromYear ? false : true}
labelId="from-year-select-label"
id="from-year-select"
value={filter.fromYear}
aria-describedby="from-year-select-helper-text"
label="Год"
onChange={e => setFilter(pv => ({ ...pv, fromYear: e.target.value }))}
>
{yearArray.map((item, i) => (
<MenuItem key={i} value={item}>
{item}
</MenuItem>
))}
</Select>
{filter.fromYear ? null : (
<FormHelperText id="from-year-select-helper-text" sx={{ color: "red" }}>
*Обязательное поле
</FormHelperText>
)}
</FormControl>
</Grid>
</Grid>
</Box>
<Box component="section" sx={{ p: 1 }}>
<Grid container spacing={2}>
<Grid textAlign={"center"} item xs={4}>
Конец периода:
</Grid>
<Grid item xs={4}>
<FormControl fullWidth>
<InputLabel id="to-month-select-label">Месяц</InputLabel>
<Select
error={filter.toMonth ? false : true}
labelId="to-month-select-label"
id="to-month-select"
value={filter.toMonth}
aria-describedby="to-month-select-helper-text"
label="Месяц"
onChange={e => setFilter(pv => ({ ...pv, toMonth: e.target.value }))}
>
{monthArray.map((item, i) => (
<MenuItem key={i + 1} value={i + 1}>
{item}
</MenuItem>
))}
</Select>
{filter.toMonth ? null : (
<FormHelperText id="to-month-select-helper-text" sx={{ color: "red" }}>
*Обязательное поле
</FormHelperText>
)}
</FormControl>
</Grid>
<Grid item xs={4}>
<FormControl fullWidth>
<InputLabel id="to-year-select-label">Год</InputLabel>
<Select
error={filter.toYear ? false : true}
labelId="to-year-select-label"
id="to-year-select"
value={filter.toYear}
aria-describedby="to-year-select-helper-text"
label="Год"
onChange={e => setFilter(pv => ({ ...pv, toYear: e.target.value }))}
>
{yearArray.map((item, i) => (
<MenuItem key={i} value={item}>
{item}
</MenuItem>
))}
</Select>
{filter.toYear ? null : (
<FormHelperText id="to-year-select-helper-text" sx={{ color: "red" }}>
*Обязательное поле
</FormHelperText>
)}
</FormControl>
</Grid>
</Grid>
</Box>
</Paper>
</DialogContent>
<DialogActions>
<Button
variant="contained"
disabled={
filter.belong && filter.prodObj && filter.fromMonth && filter.fromYear && filter.toMonth && filter.toYear ? false : true
}
onClick={() => {
setFilterLock(true);
setDataGrid({ reload: true });
closeFilter();
}}
>
Сформировать
</Button>
<Button variant="contained" onClick={clearFilter}>
Очистить
</Button>
<Button
variant="contained"
onClick={() => {
setFilter(filterCopy);
}}
>
Отмена
</Button>
</DialogActions>
</Dialog>
<Link component="button" variant="body2" textAlign={"left"} onClick={openFilter}> <Link component="button" variant="body2" textAlign={"left"} onClick={openFilter}>
Фильтр отбора: {filter.belong ? `Принадлежность: ${filter.belong}` : ""}{" "} Фильтр отбора: {filter.belong ? `Принадлежность: ${filter.belong}` : ""}{" "}
{filter.prodObj ? `Производственный объект: ${filter.prodObj}` : ""} {filter.techServ ? `Техническая служба: ${filter.techServ}` : ""}{" "} {filter.prodObj ? `Производственный объект: ${filter.prodObj}` : ""} {filter.techServ ? `Техническая служба: ${filter.techServ}` : ""}{" "}
@ -592,9 +252,7 @@ const EqsPrfrm = () => {
rows={dataGrid.rows} rows={dataGrid.rows}
size={P8P_DATA_GRID_SIZE.LARGE} size={P8P_DATA_GRID_SIZE.LARGE}
reloading={dataGrid.reload} reloading={dataGrid.reload}
headCellRender={prms => headCellRender={prms => headCellRender({ ...prms }, handleClick)}
headCellRender({ ...prms }, handleClick, filter.techServ, info.cntP, info.sumP, info.cntF, info.sumF)
}
dataCellRender={prms => dataCellRender({ ...prms }, showEquipSrv)} dataCellRender={prms => dataCellRender({ ...prms }, showEquipSrv)}
groupCellRender={prms => groupCellRender({ ...prms })} groupCellRender={prms => groupCellRender({ ...prms })}
showCellRightBorder={true} showCellRightBorder={true}

View File

@ -0,0 +1,257 @@
/*
Парус 8 - Панели мониторинга - ТОиР - Выполнение работ
Панель мониторинга: Диалоговое окно фильтра отбора
*/
//---------------------
//Подключение библиотек
//---------------------
import React, { useState, useContext, useEffect, useCallback } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Dialog, DialogTitle, IconButton, Icon, DialogContent, DialogActions, Button, Paper, Box, Grid } from "@mui/material"; //Интерфейсные компоненты
import { FilterInputField } from "./filter_input_field"; //Компонент поля ввода
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { STYLES } from "./layouts"; //Стили
//---------
//Константы
//---------
//Массив месяцев
export const MONTH_ARRAY = ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"];
//---------------
//Тело компонента
//---------------
//Диалоговое окно фильтра отбора
const FilterDialog = props => {
//Свойства
const { filter, filterCopy, filterOpen, setFilter, setFilterOpen, setDataGrid } = props;
//Состояние ограничения редактирования фильтра
const [filterLock, setFilterLock] = useState(false);
//Состояние массива лет
const [years, setYears] = useState({ array: [1990], filled: false });
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
//Закрыть фильтр
const closeFilter = e => {
if (filterLock && e != undefined) setFilter(filterCopy);
setFilterOpen(false);
};
//Очистить фильтр
const clearFilter = () => {
setFilter({
belong: "",
prodObj: "",
techServ: "",
respDep: "",
fromMonth: "",
fromYear: "",
toMonth: "",
toYear: ""
});
};
//Заполнение состояния массива лет
const getYearArray = useCallback(async () => {
const today = new Date();
for (let i = years.array[0] + 1; i <= today.getFullYear(); i++) {
setYears(pv => ({ ...pv, array: [...pv.array, i] }));
}
setYears(pv => ({ ...pv, filled: true }));
//eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
//Только при первичном рендере
useEffect(() => {
if (filterOpen && !years.filled) getYearArray();
}, [filterOpen, getYearArray, years.filled]);
//Генерация содержимого
return (
<div>
<Dialog open={filterOpen} onClose={closeFilter}>
<DialogTitle>Фильтр отбора</DialogTitle>
<IconButton
aria-label="close"
onClick={closeFilter}
sx={{
position: "absolute",
right: 8,
top: 8,
color: theme => theme.palette.grey[500]
}}
>
<Icon>close</Icon>
</IconButton>
<DialogContent>
<Paper>
<Box component="section" sx={{ p: 1 }}>
<FilterInputField
elementCode="belong"
elementValue={filter.belong}
labelText="Принадлежность"
changeFunc={() => {
pOnlineShowDictionary({
unitCode: "JuridicalPersons",
callBack: res =>
res.success === true ? setFilter(pv => ({ ...pv, belong: res.outParameters.out_CODE })) : null
});
}}
required={true}
/>
</Box>
<Box component="section" sx={{ p: 1 }}>
<FilterInputField
elementCode="prodObj"
elementValue={filter.prodObj}
labelText="Производственный объект"
changeFunc={() => {
pOnlineShowDictionary({
unitCode: "EquipConfiguration",
callBack: res =>
res.success === true ? setFilter(pv => ({ ...pv, prodObj: res.outParameters.out_CODE })) : null
});
}}
required={true}
/>
</Box>
<Box component="section" sx={{ p: 1 }}>
<FilterInputField
elementCode="techServ"
elementValue={filter.techServ}
labelText="Техническая служба"
changeFunc={() => {
pOnlineShowDictionary({
unitCode: "INS_DEPARTMENT",
callBack: res =>
res.success === true ? setFilter(pv => ({ ...pv, techServ: res.outParameters.out_CODE })) : null
});
}}
/>
</Box>
<Box component="section" sx={{ p: 1 }}>
<FilterInputField
elementCode="respDep"
elementValue={filter.respDep}
labelText="Ответственное подразделение"
changeFunc={() => {
pOnlineShowDictionary({
unitCode: "INS_DEPARTMENT",
callBack: res =>
res.success === true ? setFilter(pv => ({ ...pv, respDep: res.outParameters.out_CODE })) : null
});
}}
/>
</Box>
<Box component="section" sx={{ p: 1 }}>
<Grid container spacing={2}>
<Grid textAlign={"center"} item xs={4}>
Начало периода:
</Grid>
<Grid item xs={4}>
<FilterInputField
elementCode="from-month"
elementValue={filter.fromMonth}
labelText="Месяц"
changeFunc={e => setFilter(pv => ({ ...pv, fromMonth: e.target.value }))}
required={true}
isDateField={true}
/>
</Grid>
<Grid item xs={4}>
<FilterInputField
elementCode="from-year"
elementValue={filter.fromYear}
labelText="Год"
changeFunc={e => setFilter(pv => ({ ...pv, fromYear: e.target.value }))}
required={true}
isDateField={true}
yearArray={years.array}
/>
</Grid>
</Grid>
</Box>
<Box component="section" sx={{ p: 1 }}>
<Grid container spacing={2}>
<Grid textAlign={"center"} item xs={4}>
Конец периода:
</Grid>
<Grid item xs={4}>
<FilterInputField
elementCode="to-month"
elementValue={filter.toMonth}
labelText="Месяц"
changeFunc={e => setFilter(pv => ({ ...pv, toMonth: e.target.value }))}
required={true}
isDateField={true}
/>
</Grid>
<Grid item xs={4}>
<FilterInputField
elementCode="to-year"
elementValue={filter.toYear}
labelText="Год"
changeFunc={e => setFilter(pv => ({ ...pv, toYear: e.target.value }))}
required={true}
isDateField={true}
yearArray={years.array}
/>
</Grid>
</Grid>
</Box>
</Paper>
</DialogContent>
<DialogActions sx={{ ...STYLES.FILTER_DIALOG_ACTIONS }}>
<Button
variant="text"
disabled={
filter.belong && filter.prodObj && filter.fromMonth && filter.fromYear && filter.toMonth && filter.toYear ? false : true
}
onClick={() => {
setFilterLock(true);
setDataGrid({ reload: true });
closeFilter();
}}
>
Сформировать
</Button>
<Button variant="text" onClick={clearFilter}>
Очистить
</Button>
<Button
variant="text"
onClick={() => {
setFilter(filterCopy);
}}
>
Отмена
</Button>
</DialogActions>
</Dialog>
</div>
);
};
//Контроль свойств компонента - Диалоговое окно фильтра отбора
FilterDialog.propTypes = {
filter: PropTypes.object.isRequired,
filterCopy: PropTypes.object.isRequired,
filterOpen: PropTypes.bool.isRequired,
setFilter: PropTypes.func.isRequired,
setFilterOpen: PropTypes.func.isRequired,
setDataGrid: PropTypes.func.isRequired
};
//--------------------
//Интерфейс компонента
//--------------------
export { FilterDialog };

View File

@ -0,0 +1,121 @@
/*
Парус 8 - Панели мониторинга - ТОиР - Выполнение работ
Панель мониторинга: Компонент поля ввода
*/
//---------------------
//Подключение библиотек
//---------------------
import React, { useEffect, useState, useCallback } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { FormControl, InputLabel, Input, InputAdornment, IconButton, Icon, FormHelperText, Select, MenuItem } from "@mui/material"; //Интерфейсные компоненты
import { MONTH_ARRAY } from "./filter_dialog"; //Название месяцев
//---------------
//Тело компонента
//---------------
//Поле ввода
const FilterInputField = props => {
//Свойства
const { elementCode, elementValue, labelText, changeFunc, required, isDateField, yearArray } = props;
//Состояние идентификатора элемента
const [elementId, setElementId] = useState("");
//Формирование идентификатора элемента
const generateId = useCallback(async () => {
setElementId(!isDateField ? `${elementCode}-input` : `${elementCode}-select`);
}, [elementCode, isDateField]);
//При рендере поля ввода
useEffect(() => {
generateId();
}, [generateId]);
//Генерация поля с выбором из словаря Парус
const renderInput = () => {
return (
<Input
error={!elementValue && required ? true : false}
id={elementId}
value={elementValue}
endAdornment={
<InputAdornment position="end">
<IconButton aria-label={`${elementCode} select`} onClick={changeFunc} edge="end">
<Icon>list</Icon>
</IconButton>
</InputAdornment>
}
aria-describedby={`${elementId}-helper-text`}
label={labelText}
/>
);
};
//Генерация поля с выпадающим списком
const renderSelect = () => {
return (
<Select
error={elementValue ? false : true}
id={elementId}
value={elementValue}
aria-describedby={`${elementId}-helper-text`}
label={labelText}
onChange={changeFunc}
>
{labelText === "Месяц"
? MONTH_ARRAY.map((item, i) => (
<MenuItem key={i + 1} value={i + 1}>
{item}
</MenuItem>
))
: null}
{labelText === "Год"
? yearArray.map(item => (
<MenuItem key={item} value={item}>
{item}
</MenuItem>
))
: null}
</Select>
);
};
//Генерация содержимого
return (
<FormControl readOnly={isDateField ? false : true} fullWidth variant="standard">
<InputLabel htmlFor={elementId}>{labelText}</InputLabel>
{isDateField ? renderSelect() : renderInput()}
{required && !elementValue ? (
<FormHelperText id={`${elementId}-helper-text`} sx={{ color: "red" }}>
*Обязательное поле
</FormHelperText>
) : null}
</FormControl>
);
};
//Контроль свойств - Поле ввода
FilterInputField.propTypes = {
elementCode: PropTypes.string.isRequired,
elementValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
labelText: PropTypes.string.isRequired,
changeFunc: PropTypes.func.isRequired,
required: PropTypes.bool,
isDateField: PropTypes.bool,
yearArray: PropTypes.arrayOf(PropTypes.number)
};
//Значения по умолчанию - Поле ввода
FilterInputField.defaultProps = {
required: false,
isDateField: false
};
//--------------------
//Интерфейс компонента
//--------------------
export { FilterInputField };

View File

@ -1,5 +1,5 @@
/* /*
Парус 8 - Парус 8 - Панели мониторинга - ТОиР - Выполнение работ
Дополнительная разметка и вёрстка клиентских элементов Дополнительная разметка и вёрстка клиентских элементов
*/ */
@ -8,7 +8,7 @@
//--------------------- //---------------------
import React, { createRef } from "react"; //Классы React import React, { createRef } from "react"; //Классы React
import { Grid, Stack } from "@mui/material"; import { Grid, Stack } from "@mui/material"; //Интерфейсные компоненты
//--------- //---------
//Константы //Константы
@ -19,28 +19,39 @@ export const DIGITS_REG_EXP = /\d+,?\d*/g;
export const MONTH_NAME_REG_EXP = /_\d{4}_\d{1,2}/; export const MONTH_NAME_REG_EXP = /_\d{4}_\d{1,2}/;
export const DAY_NAME_REG_EXP = /_\d{4}_\d{1,2}_\d{1,2}/; export const DAY_NAME_REG_EXP = /_\d{4}_\d{1,2}_\d{1,2}/;
let curParent = ""; //Стили
let x = 0; export const STYLES = {
HIDE_CELL_STYLE: { display: "none" },
HCR_MAIN_STYLE: { border: "1px solid rgba(0, 0, 0)", textAlign: "center" },
HCR_DATE_STYLE: { padding: "5px", minWidth: "25px", maxWidth: "25px" },
DCR_MAIN_STYLE: { padding: "2px", border: "1px solid rgba(0, 0, 0) !important", textAlign: "center" },
DCR_OBJECT_INFO_STYLE: { textAlign: "right", fontWeight: "bold" },
DCR_PLAN_CELL_STYLE: { cursor: "pointer", backgroundColor: "lightblue", border: "1px solid rgba(0, 0, 0) !important" },
DCR_FACT_RELATED_CELL_STYLE: { cursor: "pointer", backgroundColor: "green", border: "1px solid rgba(0, 0, 0) !important" },
DCR_FACT_NOT_RELATED_CELL_STYLE: { cursor: "pointer", backgroundColor: "crimson", border: "1px solid rgba(0, 0, 0) !important" },
FILTER_DIALOG_ACTIONS: { justifyContent: "center" }
};
//----------- //-----------
//Тело модуля //Тело модуля
//----------- //-----------
const formatDate = date => { //Формирование даты полной и даты без дней из наименования ячейки
const [year, month, day] = date.substring(1).split("_"); const formatDate = dateCellName => {
let nd; const [year, month, day] = dateCellName.substring(1).split("_");
if (day == null) nd = `${month < 10 ? "0" + month : month}.${year}`; let date;
else nd = `${day < 10 ? "0" + day : day}.${month < 10 ? "0" + month : month}.${year}`; if (day == null) date = `${month < 10 ? "0" + month : month}.${year}`;
return nd; else date = `${day < 10 ? "0" + day : day}.${month < 10 ? "0" + month : month}.${year}`;
return date;
}; };
// eslint-disable-next-line no-unused-vars //Генерация представления заголовка колонки
export const headCellRender = ({ columnDef }, hClick, podr, cntP, sumP, cntF, sumF) => { export const headCellRender = ({ columnDef }, hClick) => {
let cellStyle = { border: "1px solid rgba(0, 0, 0)", textAlign: "center" }; let cellStyle = STYLES.HCR_MAIN_STYLE;
let cellProps = {}; let cellProps = {};
let stackStyle = {}; let stackStyle = {};
let data = columnDef.caption; let data = columnDef.caption;
//Для разворачивающихся колонок
if (columnDef.expandable) { if (columnDef.expandable) {
const ref = createRef(); const ref = createRef();
cellStyle = { ...cellStyle, padding: "5px" }; cellStyle = { ...cellStyle, padding: "5px" };
@ -51,49 +62,51 @@ export const headCellRender = ({ columnDef }, hClick, podr, cntP, sumP, cntF, su
hClick(e, ref); hClick(e, ref);
} }
}; };
stackStyle = { flexDirection: "column" }; stackStyle = { flexDirection: "column" };
} }
if (columnDef.name == "SOBJINFO") cellStyle = { display: "none" }; //Скрываем ненужные колонки
if (columnDef.name == "SOBJINFO" || columnDef.name == "SWRKTYPE") cellStyle = STYLES.HIDE_CELL_STYLE;
//Объединение нужных колонок и строк
if (columnDef.name == "SINFO" || columnDef.name == "SWRKTYPE") { if (columnDef.name == "SINFO" || columnDef.name == "SWRKTYPE") {
cellProps = { colSpan: 2 }; cellProps = { colSpan: 2 };
if (columnDef.name == "SINFO") cellProps = { ...cellProps, rowSpan: 2 }; if (columnDef.name == "SINFO") cellProps = { ...cellProps, rowSpan: 2 };
} }
//Изменения в заголовках с датами
if (columnDef.name == "SWRKTYPE") cellStyle = { display: "none" };
if (columnDef.visible && DAY_NAME_REG_EXP.test(columnDef.name)) { if (columnDef.visible && DAY_NAME_REG_EXP.test(columnDef.name)) {
cellStyle = { ...cellStyle, padding: "5px", minWidth: "25px", maxWidth: "25px" }; cellStyle = { ...cellStyle, ...STYLES.HCR_DATE_STYLE };
stackStyle = { justifyContent: "center" }; stackStyle = { justifyContent: "center" };
} }
return { cellStyle, cellProps, stackStyle, data }; return { cellStyle, cellProps, stackStyle, data };
}; };
//Генерация представления ячейки
export const dataCellRender = ({ row, columnDef }, showEquipSrv) => { export const dataCellRender = ({ row, columnDef }, showEquipSrv) => {
let cellStyle = { let curParent = "";
padding: "2px", let cellDate;
border: "1px solid rgba(0, 0, 0) !important", let cellStyle = STYLES.DCR_MAIN_STYLE;
textAlign: "center"
};
let cellProps = {}; let cellProps = {};
let data = " "; let data = " ";
//Если строка с трудоёмкостью по объекту ремонта
if (row["SWRKTYPE"] == undefined) { if (row["SWRKTYPE"] == undefined) {
//Ячейка "Информация по объекту ремонта"
if (columnDef.name == "SOBJINFO") { if (columnDef.name == "SOBJINFO") {
cellProps = { colSpan: 2 }; cellProps = { colSpan: 2 };
cellStyle = { ...cellStyle, textAlign: "right", fontWeight: "bold" }; cellStyle = { ...cellStyle, ...STYLES.DCR_OBJECT_INFO_STYLE };
} }
if (columnDef.name == "SWRKTYPE") cellStyle = { display: "none" }; //Ячейка "Тип работ"
if (columnDef.name == "SWRKTYPE") cellStyle = STYLES.HIDE_CELL_STYLE;
//Ячейки колонок месяцев
if (columnDef.parent == "" && columnDef.expandable == true && columnDef.expanded == false) { if (columnDef.parent == "" && columnDef.expandable == true && columnDef.expanded == false) {
curParent = columnDef.name; curParent = columnDef.name;
return { cellStyle: { ...cellStyle, height: "25px" }, data }; return { cellStyle: { ...cellStyle, height: "25px" }, data };
} else if (columnDef.name != "SWRKTYPE" && columnDef.parent != "" && columnDef.expandable == false && columnDef.expanded == true) { }
//Поиск развёрнутых месяцев
else if (columnDef.name != "SWRKTYPE" && columnDef.parent != "" && columnDef.expandable == false && columnDef.expanded == true) {
if (columnDef.name.endsWith("_1")) { if (columnDef.name.endsWith("_1")) {
curParent = columnDef.parent; curParent = columnDef.parent;
const [year, month] = curParent.substring(1).split("_"); const [year, month] = curParent.substring(1).split("_");
x = new Date(year, month, 0).getDate(); cellDate = new Date(year, month, 0).getDate();
cellProps = { colSpan: x }; cellProps = { colSpan: cellDate };
data = row[curParent]; data = row[curParent];
return { cellStyle, cellProps, data }; return { cellStyle, cellProps, data };
} else { } else {
@ -101,17 +114,19 @@ export const dataCellRender = ({ row, columnDef }, showEquipSrv) => {
} }
} }
} }
//Строка плана по объекту ремонта
if (columnDef.name == "SOBJINFO" && row["SWRKTYPE"] == "План") { if (columnDef.name == "SOBJINFO" && row["SWRKTYPE"] == "План") {
cellStyle = { ...cellStyle }; cellStyle = { ...cellStyle };
cellProps = { rowSpan: 2 }; cellProps = { rowSpan: 2 };
} }
//Строка факта по объекту ремонта
if (columnDef.name == "SOBJINFO" && row["SWRKTYPE"] == "Факт") { if (columnDef.name == "SOBJINFO" && row["SWRKTYPE"] == "Факт") {
cellStyle = { display: "none" }; cellStyle = { display: "none" };
} }
//Закрашивание ячеек
switch (row[columnDef.name]) { switch (row[columnDef.name]) {
case "blue": case "blue":
cellStyle = { ...cellStyle, cursor: "pointer", backgroundColor: "lightblue", border: "1px solid rgba(0, 0, 0) !important" }; cellStyle = { ...cellStyle, ...STYLES.DCR_PLAN_CELL_STYLE };
cellProps = { cellProps = {
title: formatDate(columnDef.name), title: formatDate(columnDef.name),
onClick: () => { onClick: () => {
@ -120,7 +135,7 @@ export const dataCellRender = ({ row, columnDef }, showEquipSrv) => {
}; };
return { cellStyle, cellProps, data }; return { cellStyle, cellProps, data };
case "green": case "green":
cellStyle = { ...cellStyle, cursor: "pointer", backgroundColor: "green", border: "1px solid rgba(0, 0, 0) !important" }; cellStyle = { ...cellStyle, ...STYLES.DCR_FACT_RELATED_CELL_STYLE };
cellProps = { cellProps = {
title: formatDate(columnDef.name), title: formatDate(columnDef.name),
onClick: () => { onClick: () => {
@ -129,7 +144,7 @@ export const dataCellRender = ({ row, columnDef }, showEquipSrv) => {
}; };
return { cellStyle, cellProps, data }; return { cellStyle, cellProps, data };
case "red": case "red":
cellStyle = { ...cellStyle, cursor: "pointer", backgroundColor: "crimson", border: "1px solid rgba(0, 0, 0) !important" }; cellStyle = { ...cellStyle, ...STYLES.DCR_FACT_NOT_RELATED_CELL_STYLE };
cellProps = { cellProps = {
title: formatDate(columnDef.name), title: formatDate(columnDef.name),
onClick: () => { onClick: () => {
@ -137,6 +152,7 @@ export const dataCellRender = ({ row, columnDef }, showEquipSrv) => {
} }
}; };
return { cellStyle, cellProps, data }; return { cellStyle, cellProps, data };
//Случай двойного закрашивания месяца
case "green red": case "green red":
case "red green": case "red green":
cellStyle = { ...cellStyle, padding: "unset" }; cellStyle = { ...cellStyle, padding: "unset" };
@ -167,7 +183,9 @@ export const dataCellRender = ({ row, columnDef }, showEquipSrv) => {
return { cellStyle, cellProps }; return { cellStyle, cellProps };
}; };
//Генерация представления заголовка группы
export const groupCellRender = () => { export const groupCellRender = () => {
let cellStyle = { display: "none" }; //Скрываем все группы
let cellStyle = STYLES.HIDE_CELL_STYLE;
return { cellStyle }; return { cellStyle };
}; };

View File

@ -226,9 +226,9 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
SPRJ_GROUP_NAME PKG_STD.TSTRING; -- Наименование группы для проекта SPRJ_GROUP_NAME PKG_STD.TSTRING; -- Наименование группы для проекта
BEXPANDED boolean; -- Флаг раскрытости уровня BEXPANDED boolean; -- Флаг раскрытости уровня
RDG PKG_P8PANELS_VISUAL.TDATA_GRID; -- Описание таблицы RDG PKG_P8PANELS_VISUAL.TDATA_GRID; -- Описание таблицы
RDG_ROW0 PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы0 RDG_ROW_INFO PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы с информацией по объекту ремонта
RDG_ROW PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы RDG_ROW_PLAN PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы с планом по объекту ремонта
RDG_ROW2 PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы2 RDG_ROW_FACT PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы с фактом по объекту ремонта
NCURYEAR PKG_STD.TNUMBER; -- Текущий год NCURYEAR PKG_STD.TNUMBER; -- Текущий год
NCURMONTH PKG_STD.TNUMBER; -- Текущий месяц NCURMONTH PKG_STD.TNUMBER; -- Текущий месяц
NTOTALDAYS PKG_STD.TNUMBER; -- Дней в текущем месяце NTOTALDAYS PKG_STD.TNUMBER; -- Дней в текущем месяце
@ -270,7 +270,7 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
TT.DDATEPRD_BEG DDATEPLANBEG, TT.DDATEPRD_BEG DDATEPLANBEG,
TT.DDATEPRD_END DDATEPLANEND, TT.DDATEPRD_END DDATEPLANEND,
EQJ.DATEFACT_BEG DDATEFACTBEG, EQJ.DATEFACT_BEG DDATEFACTBEG,
COALESCE(EQJ.DATEFACT_END, EQJ.DATEFACT_BEG) DDATEFACTEND, -- COALESCE(EQJ.DATEFACT_END, EQJ.DATEFACT_BEG) DDATEFACTEND,
EK.CODE STECSRVKINDCODE, EK.CODE STECSRVKINDCODE,
EK.NAME STECSRVKINDNAME, EK.NAME STECSRVKINDNAME,
COALESCE(EW.NSUM, (TT.DDATEPRD_END - TT.DDATEPRD_BEG) * 24) NSUMWORKPLAN, COALESCE(EW.NSUM, (TT.DDATEPRD_END - TT.DDATEPRD_BEG) * 24) NSUMWORKPLAN,
@ -554,7 +554,7 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
/* Если новый объект ремонта */ /* Если новый объект ремонта */
if ((SCURTECHOBJ != QQ.STECHOBJNAME) or (SCURTECHOBJ is null)) then if ((SCURTECHOBJ != QQ.STECHOBJNAME) or (SCURTECHOBJ is null)) then
/* Если строка с трудоёмкостью по объекту ремонта сформирована */ /* Если строка с трудоёмкостью по объекту ремонта сформирована */
if (RDG_ROW0.RCOLS is not null) then if (RDG_ROW_INFO.RCOLS is not null) then
/* Цикл по годам периода */ /* Цикл по годам периода */
for Y in NFROMYEAR .. NTOYEAR for Y in NFROMYEAR .. NTOYEAR
loop loop
@ -562,7 +562,7 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
if (NFROMYEAR = NTOYEAR) then if (NFROMYEAR = NTOYEAR) then
NMS := NFROMMONTH; NMS := NFROMMONTH;
NME := NTOMONTH; NME := NTOMONTH;
/* Иначе вычисляем кол-во месяцев в каждом году периода отчёта*/ /* Иначе вычисляем кол-во месяцев в каждом году периода отчёта */
else else
if (Y = NFROMYEAR) then if (Y = NFROMYEAR) then
NMS := NFROMMONTH; NMS := NFROMMONTH;
@ -579,7 +579,7 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
for M in NMS .. NME for M in NMS .. NME
loop loop
SPERIODNAME := '_' || TO_CHAR(Y) || '_' || TO_CHAR(M); SPERIODNAME := '_' || TO_CHAR(Y) || '_' || TO_CHAR(M);
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW0, PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW_INFO,
SNAME => SPERIODNAME, SNAME => SPERIODNAME,
SVALUE => 'план: ' || HOURS_STR(NHOURS => TRUNC(PKG_CONTVALLOC1S.GETN(RCONTAINER => YM, SVALUE => 'план: ' || HOURS_STR(NHOURS => TRUNC(PKG_CONTVALLOC1S.GETN(RCONTAINER => YM,
SROWID => SPERIODNAME || '_P'), SROWID => SPERIODNAME || '_P'),
@ -594,7 +594,7 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
end loop; end loop;
end loop; end loop;
/* Добавление строки с трудоёмкостью */ /* Добавление строки с трудоёмкостью */
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW0); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW_INFO);
end if; end if;
/* Добавление группы с объектом ремонта */ /* Добавление группы с объектом ремонта */
SCURTECHOBJ := QQ.STECHOBJNAME; SCURTECHOBJ := QQ.STECHOBJNAME;
@ -603,29 +603,29 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
SNAME => SPRJ_GROUP_NAME, SNAME => SPRJ_GROUP_NAME,
SCAPTION => QQ.STECHOBJNAME, SCAPTION => QQ.STECHOBJNAME,
BEXPANDABLE => false); BEXPANDABLE => false);
RDG_ROW0 := PKG_P8PANELS_VISUAL.TROW_MAKE(SGROUP => SPRJ_GROUP_NAME); RDG_ROW_INFO := PKG_P8PANELS_VISUAL.TROW_MAKE(SGROUP => SPRJ_GROUP_NAME);
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW0, SNAME => 'SOBJINFO', SVALUE => SCURTECHOBJ); PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW_INFO, SNAME => 'SOBJINFO', SVALUE => SCURTECHOBJ);
end if; end if;
/* Формируем имя группы для вида ремонта */ /* Формируем имя группы для вида ремонта */
SCURTSKCODE := SCURTECHOBJ || '_' || QQ.STECSRVKINDCODE; SCURTSKCODE := SCURTECHOBJ || '_' || QQ.STECSRVKINDCODE;
/* Если по данной группе еще нет строк плана и факта */ /* Если по данной группе еще нет строк плана и факта */
if (PKG_CONTVALLOC1S.EXISTS_(RCONTAINER => GF, SROWID => SCURTSKCODE) = false) then if (PKG_CONTVALLOC1S.EXISTS_(RCONTAINER => GF, SROWID => SCURTSKCODE) = false) then
/* Добавляем строку плана */ /* Добавляем строку плана */
if (RDG_ROW.RCOLS is not null) then if (RDG_ROW_PLAN.RCOLS is not null) then
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW_PLAN);
end if; end if;
/* Добавляем строку факта */ /* Добавляем строку факта */
if (RDG_ROW2.RCOLS is not null) then if (RDG_ROW_FACT.RCOLS is not null) then
CR := PKG_CONTVALLOC1S.FIRST_(RCONTAINER => MCLR); CR := PKG_CONTVALLOC1S.FIRST_(RCONTAINER => MCLR);
/* Цикл по коллекции для закрашивания месяцев */ /* Цикл по коллекции для закрашивания месяцев */
for Z in 1 .. PKG_CONTVALLOC1S.COUNT_(RCONTAINER => MCLR) for Z in 1 .. PKG_CONTVALLOC1S.COUNT_(RCONTAINER => MCLR)
loop loop
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW2, PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW_FACT,
SNAME => CR, SNAME => CR,
SVALUE => PKG_CONTVALLOC1S.GETS(RCONTAINER => MCLR, SROWID => CR)); SVALUE => PKG_CONTVALLOC1S.GETS(RCONTAINER => MCLR, SROWID => CR));
CR := PKG_CONTVALLOC1S.NEXT_(RCONTAINER => MCLR, SROWID => CR); CR := PKG_CONTVALLOC1S.NEXT_(RCONTAINER => MCLR, SROWID => CR);
end loop; end loop;
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW2); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW_FACT);
end if; end if;
PKG_CONTVALLOC1S.PURGE(RCONTAINER => MCLR); PKG_CONTVALLOC1S.PURGE(RCONTAINER => MCLR);
/* Добвим группу для вида ремонта */ /* Добвим группу для вида ремонта */
@ -635,12 +635,12 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
SCAPTION => QQ.STECSRVKINDCODE, SCAPTION => QQ.STECSRVKINDCODE,
BEXPANDABLE => false); BEXPANDABLE => false);
/* Строка плана */ /* Строка плана */
RDG_ROW := PKG_P8PANELS_VISUAL.TROW_MAKE(SGROUP => SPRJ_GROUP_NAME); RDG_ROW_PLAN := PKG_P8PANELS_VISUAL.TROW_MAKE(SGROUP => SPRJ_GROUP_NAME);
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SOBJINFO', SVALUE => QQ.STECSRVKINDCODE); PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW_PLAN, SNAME => 'SOBJINFO', SVALUE => QQ.STECSRVKINDCODE);
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SWRKTYPE', SVALUE => 'План'); PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW_PLAN, SNAME => 'SWRKTYPE', SVALUE => 'План');
/* Строка факта */ /* Строка факта */
RDG_ROW2 := PKG_P8PANELS_VISUAL.TROW_MAKE(SGROUP => SPRJ_GROUP_NAME); RDG_ROW_FACT := PKG_P8PANELS_VISUAL.TROW_MAKE(SGROUP => SPRJ_GROUP_NAME);
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW2, SNAME => 'SWRKTYPE', SVALUE => 'Факт'); PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW_FACT, SNAME => 'SWRKTYPE', SVALUE => 'Факт');
/* Добавляем в заполненные группы */ /* Добавляем в заполненные группы */
PKG_CONTVALLOC1S.PUTS(RCONTAINER => GF, SROWID => SPRJ_GROUP_NAME, SVALUE => ''); PKG_CONTVALLOC1S.PUTS(RCONTAINER => GF, SROWID => SPRJ_GROUP_NAME, SVALUE => '');
end if; end if;
@ -665,7 +665,7 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
/* Закрашивание месяца плана синим */ /* Закрашивание месяца плана синим */
if (PKG_CONTVALLOC1S.EXISTS_(RCONTAINER => COLS, SROWID => SPRJ_GROUP_NAME || ' ' || SPERIODNAME || ' PLAN') = if (PKG_CONTVALLOC1S.EXISTS_(RCONTAINER => COLS, SROWID => SPRJ_GROUP_NAME || ' ' || SPERIODNAME || ' PLAN') =
false) then false) then
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => SPERIODNAME, SVALUE => 'blue'); PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW_PLAN, SNAME => SPERIODNAME, SVALUE => 'blue');
PKG_CONTVALLOC1S.PUTS(RCONTAINER => COLS, PKG_CONTVALLOC1S.PUTS(RCONTAINER => COLS,
SROWID => SPRJ_GROUP_NAME || ' ' || SPERIODNAME || ' PLAN', SROWID => SPRJ_GROUP_NAME || ' ' || SPERIODNAME || ' PLAN',
SVALUE => ''); SVALUE => '');
@ -675,7 +675,7 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
/* Закрашивание дня плана синим */ /* Закрашивание дня плана синим */
if (PKG_CONTVALLOC1S.EXISTS_(RCONTAINER => COLS, SROWID => SPRJ_GROUP_NAME || ' ' || SPERIODNAME || ' PLAN') = if (PKG_CONTVALLOC1S.EXISTS_(RCONTAINER => COLS, SROWID => SPRJ_GROUP_NAME || ' ' || SPERIODNAME || ' PLAN') =
false) then false) then
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => SPERIODNAME, SVALUE => 'blue'); PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW_PLAN, SNAME => SPERIODNAME, SVALUE => 'blue');
PKG_CONTVALLOC1S.PUTS(RCONTAINER => COLS, PKG_CONTVALLOC1S.PUTS(RCONTAINER => COLS,
SROWID => SPRJ_GROUP_NAME || ' ' || SPERIODNAME || ' PLAN', SROWID => SPRJ_GROUP_NAME || ' ' || SPERIODNAME || ' PLAN',
SVALUE => ''); SVALUE => '');
@ -749,7 +749,7 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
end if; end if;
end loop; end loop;
end if; end if;
if ((RDG_ROW0.RCOLS is not null) and (NROWS = 0)) then if ((RDG_ROW_INFO.RCOLS is not null) and (NROWS = 0)) then
/* Цикл по годам периода */ /* Цикл по годам периода */
for Y in NFROMYEAR .. NTOYEAR for Y in NFROMYEAR .. NTOYEAR
loop loop
@ -772,7 +772,7 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
for M in NMS .. NME for M in NMS .. NME
loop loop
SPERIODNAME := '_' || TO_CHAR(Y) || '_' || TO_CHAR(M); SPERIODNAME := '_' || TO_CHAR(Y) || '_' || TO_CHAR(M);
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW0, PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW_INFO,
SNAME => SPERIODNAME, SNAME => SPERIODNAME,
SVALUE => 'план: ' || HOURS_STR(NHOURS => TRUNC(PKG_CONTVALLOC1S.GETN(RCONTAINER => YM, SVALUE => 'план: ' || HOURS_STR(NHOURS => TRUNC(PKG_CONTVALLOC1S.GETN(RCONTAINER => YM,
SROWID => SPERIODNAME || '_P'), SROWID => SPERIODNAME || '_P'),
@ -782,23 +782,23 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as
1))); 1)));
end loop; end loop;
end loop; end loop;
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW0); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW_INFO);
end if; end if;
/* План для последней записи */ /* План для последней записи */
if ((RDG_ROW.RCOLS is not null) and (NROWS = 0)) then if ((RDG_ROW_PLAN.RCOLS is not null) and (NROWS = 0)) then
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW_PLAN);
end if; end if;
/* Факт для последней записи */ /* Факт для последней записи */
if ((RDG_ROW2.RCOLS is not null) and (NROWS = 0)) then if ((RDG_ROW_FACT.RCOLS is not null) and (NROWS = 0)) then
CR := PKG_CONTVALLOC1S.FIRST_(RCONTAINER => MCLR); CR := PKG_CONTVALLOC1S.FIRST_(RCONTAINER => MCLR);
for Z in 1 .. PKG_CONTVALLOC1S.COUNT_(RCONTAINER => MCLR) for Z in 1 .. PKG_CONTVALLOC1S.COUNT_(RCONTAINER => MCLR)
loop loop
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW2, PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW_FACT,
SNAME => CR, SNAME => CR,
SVALUE => PKG_CONTVALLOC1S.GETS(RCONTAINER => MCLR, SROWID => CR)); SVALUE => PKG_CONTVALLOC1S.GETS(RCONTAINER => MCLR, SROWID => CR));
CR := PKG_CONTVALLOC1S.NEXT_(RCONTAINER => MCLR, SROWID => CR); CR := PKG_CONTVALLOC1S.NEXT_(RCONTAINER => MCLR, SROWID => CR);
end loop; end loop;
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW2); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW_FACT);
end if; end if;
end loop; end loop;
/* Сериализуем описание */ /* Сериализуем описание */