/*
Парус 8 - Панели мониторинга - УДП - Доски задач
Компонент: Карточка события
*/
//---------------------
//Подключение библиотек
//---------------------
import React, { useState, useContext, useCallback } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Draggable } from "react-beautiful-dnd"; //Работа с drag&drop
import { Card, CardHeader, Typography, IconButton, Icon, Box, Menu, MenuItem, CardContent, Avatar, Stack } from "@mui/material"; //Интерфейсные компоненты
import { TaskDialog } from "../task_dialog"; //Форма события
import { ApplicationСtx } from "../../../context/application"; //Контекст приложения
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../../context/messaging"; //Контекст сообщений
import { EVENT_INDICATORS, indicatorColorRule, bgColorRule } from "../layouts"; //Дополнительная разметка и вёрстка клиентских элементов
//---------
//Константы
//---------
//Стили
const STYLES = {
CONTAINER: { margin: "5px 0px", textAlign: "center" },
MENU_ITEM_DELIMITER: { borderBottom: "1px solid lightgrey" },
CARD: (indicatorClr, bgClr) => {
const i = indicatorClr ? { borderLeft: `solid ${indicatorClr}` } : null;
const bc = bgClr ? { backgroundColor: bgClr } : null;
return { ...i, ...bc };
},
CARD_HEADER_TITLE: {
padding: "4px",
width: "292px",
display: "-webkit-box",
hyphens: "auto",
WebkitBoxOrient: "vertical",
WebkitLineClamp: 2,
overflow: "hidden"
},
CARD_HEADER_DESC: { padding: 0, cursor: "pointer" },
CARD_CONTENT: { padding: "4px !important" },
CARD_CONTENT_BOX: { display: "flex", alignItems: "center" },
ACCOUNT_STACK: { alignItems: "center", marginLeft: "auto" },
SECONDARY_TEXT: {
color: "text.secondary",
fontSize: 14
},
ICON_COLOR: linked => {
return { color: theme => (linked ? EVENT_INDICATORS.LINKED : theme.palette.grey[500]) };
}
};
//------------------------------------
//Вспомогательные функции и компоненты
//------------------------------------
//Действия карточки события
const DataCellCardActions = ({
taskRn,
menuItems,
cardActions,
onMethodsMenuButtonClick,
onMethodsMenuClose,
onReload,
eventPoints,
pointSettings,
onOpenNoteDialog
}) => {
return (
);
};
//Контроль свойств - Действия карточки события
DataCellCardActions.propTypes = {
taskRn: PropTypes.number.isRequired,
menuItems: PropTypes.array.isRequired,
cardActions: PropTypes.object.isRequired,
onMethodsMenuButtonClick: PropTypes.func.isRequired,
onMethodsMenuClose: PropTypes.func.isRequired,
onReload: PropTypes.func,
eventPoints: PropTypes.array,
pointSettings: PropTypes.object,
onOpenNoteDialog: PropTypes.func
};
//-----------
//Тело модуля
//-----------
//Карточка события
const TaskCard = ({ task, avatar, index, onReload, eventPoints, colorRule, pointSettings, onOpenNoteDialog }) => {
//Состояние диалога события
const [taskDialogOpen, setTaskDialogOpen] = useState(false);
//Состояние действий события
const [cardActions, setCardActions] = useState({ anchorMenuMethods: null, openMethods: false });
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
//Подключение к контексту приложения
const { pOnlineShowDocument } = useContext(ApplicationСtx);
//Удаление контрагента
const deleteTask = useCallback(
async (nEvent, handleReload) => {
await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_DELETE",
args: { NCLNEVENTS: nEvent }
});
//Если требуется перезагрузить данные
if (handleReload) {
handleReload();
}
},
[executeStored]
);
//Возврат в предыдущую точку события
const returnTask = useCallback(
async (nEvent, handleReload) => {
await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_RETURN",
args: { NCLNEVENTS: nEvent }
});
//Если требуется перезагрузить данные
if (handleReload) {
handleReload();
}
},
[executeStored]
);
//По нажатию на открытие меню действий
const handleMethodsMenuButtonClick = event => {
setCardActions(pv => ({ ...pv, anchorMenuMethods: event.currentTarget, openMethods: true }));
};
//При закрытии меню
const handleMethodsMenuClose = () => {
setCardActions(pv => ({ ...pv, anchorMenuMethods: null, openMethods: false }));
};
//По нажатия действия "Редактировать"
const handleTaskEdit = () => {
setTaskDialogOpen(true);
};
//По нажатия действия "Редактировать в разделе"
const handleTaskEditClient = useCallback(
async nEvent => {
const data = await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_SELECT",
args: {
NCLNEVENTS: nEvent
}
});
if (data.NIDENT) {
pOnlineShowDictionary({
unitCode: "ClientEvents",
inputParameters: [{ name: "in_Ident", value: data.NIDENT }]
});
}
},
[executeStored, pOnlineShowDictionary]
);
//По нажатию действия "Удалить"
const handleTaskDelete = (nEvent, handleReload) => {
showMsgWarn("Удалить событие?", () => deleteTask(nEvent, handleReload));
};
//По нажатию действия "Выполнить возврат"
const handleTaskReturn = (nEvent, handleReload) => {
showMsgWarn("Выполнить возврат события в предыдущую точку?", () => returnTask(nEvent, handleReload));
};
//По нажатию действия "Примечания"
const handleEventNotesOpen = useCallback(
async nEvent => {
pOnlineShowDictionary({
unitCode: "ClientEventsNotes",
showMethod: "main",
inputParameters: [{ name: "in_PRN", value: nEvent }]
});
},
[pOnlineShowDictionary]
);
//По нажатию действия "Присоединенные документы"
const handleFileLinksOpen = useCallback(
async nEvent => {
pOnlineShowDictionary({
unitCode: "FileLinks",
showMethod: "main_link",
inputParameters: [
{ name: "in_PRN", value: nEvent },
{ name: "in_UNITCODE", value: "ClientEvents" }
]
});
},
[pOnlineShowDictionary]
);
//По нажатию действия "Перейти"
const handleStateChange = useCallback(
async (nEvent, handleReload, evPoints, handleNote) => {
//Выполняем инициализацию параметров
const firstStep = await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE",
args: {
NSTEP: 1,
NEVENT: nEvent
}
});
if (firstStep) {
//Открываем раздел "Маршруты событий (точки перехода)" для выбора следующей точки
pOnlineShowDictionary({
unitCode: "EventRoutesPointsPasses",
showMethod: "main_passes",
inputParameters: [
{ name: "in_ENVTYPE_CODE", value: firstStep.SEVENT_TYPE },
{ name: "in_ENVSTAT_CODE", value: firstStep.SEVENT_STAT },
{ name: "in_POINT", value: firstStep.NPOINT }
],
callBack: async point => {
//Выполняем проверку необходимости выбора исполнителя
const secondStep = await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE",
args: {
NIDENT: firstStep.NIDENT,
NSTEP: 2,
NPASS: point.outParameters.out_RN
}
});
const pointSettings = evPoints.find(ep => ep.point === point.outParameters.out_NEXT_POINT);
if (secondStep) {
//Если требуется выбрать получателя
if (secondStep.NSELECT_EXEC === 1) {
//Открываем раздел "Маршруты событий (исполнители в точках)" для выбора исполнителя
pOnlineShowDictionary({
unitCode: "EventRoutesPointExecuters",
showMethod: "executers",
inputParameters: [
{ name: "in_IDENT", value: firstStep.NIDENT },
{ name: "in_EVENT", value: nEvent },
{ name: "in_EVENT_TYPE", value: firstStep.SEVENT_TYPE },
{ name: "in_EVENT_STAT", value: firstStep.SEVENT_STAT },
{ name: "in_INIT_PERSON", value: firstStep.SINIT_PERSON },
{ name: "in_INIT_AUTHNAME", value: firstStep.SINIT_AUTHNAME },
{ name: "in_CLIENT_CLIENT", value: firstStep.SCLIENT_CLIENT },
{ name: "in_CLIENT_PERSON", value: firstStep.SCLIENT_PERSON }
],
callBack: async send => {
//Общие аргументы
const mainArgs = {
NIDENT: firstStep.NIDENT,
NSTEP: 3,
NEVENT: nEvent,
SEVENT_STAT: point.outParameters.out_NEXT_POINT,
SSEND_CLIENT: send.outParameters.out_CLIENT_CODE,
SSEND_DIVISION: send.outParameters.out_DIVISION_CODE,
SSEND_POST: send.outParameters.out_POST_CODE,
SSEND_PERFORM: send.outParameters.out_POST_IN_DIV_CODE,
SSEND_PERSON: send.outParameters.out_PERSON_CODE,
SSEND_STAFFGRP: send.outParameters.out_STAFFGRP_CODE,
SSEND_USER_GROUP: send.outParameters.out_USER_GROUP_CODE,
SSEND_USER_NAME: send.outParameters.out_USER_NAME,
NSEND_PREDEFINED_EXEC: send.outParameters.out_PREDEFINED_EXEC,
NSEND_PREDEFINED_PROC: send.outParameters.out_PREDEFINED_PROC
};
//Выполняем переход к выбранной точке с исполнителем
pointSettings.addNoteOnChst
? handleNote(async n => {
//Если требуется примечание
await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE",
args: {
...mainArgs,
...{ SNOTE_HEADER: n.header, SNOTE: n.text }
}
});
//Если требуется перезагрузить данные
if (handleReload) {
handleReload();
}
})
: await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE",
args: mainArgs
});
//Если требуется перезагрузить данные
if (handleReload && !pointSettings.addNoteOnChst) {
handleReload();
}
}
});
} else {
//Общие аргументы
const mainArgs = {
NIDENT: firstStep.NIDENT,
NSTEP: 3,
NEVENT: nEvent,
SEVENT_STAT: point.outParameters.out_NEXT_POINT
};
//Выполняем переход к выбранной точке с предопределенным исполнителем
pointSettings.addNoteOnChst
? handleNote(async n => {
//Если требуется примечание
await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE",
args: {
...mainArgs,
...{ SNOTE_HEADER: n.header, SNOTE: n.text }
}
});
//Если требуется перезагрузить данные
if (handleReload) {
handleReload();
}
})
: await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_STATE_CHANGE",
args: mainArgs
});
//Если требуется перезагрузить данные
if (handleReload && !pointSettings.addNoteOnChst) {
handleReload();
}
}
}
}
});
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[executeStored, pOnlineShowDictionary]
);
//Изменение статуса события
const handleSend = useCallback(
async (nEvent, handleReload, note = null) => {
//Выполняем инициализацию параметров
const firstStep = await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_SEND",
args: {
NSTEP: 1,
NEVENT: nEvent
}
});
if (firstStep) {
//Открываем раздел "Маршруты событий (исполнители в точках)" для выбора исполнителя
pOnlineShowDictionary({
unitCode: "EventRoutesPointExecuters",
showMethod: "executers",
inputParameters: [
{ name: "in_IDENT", value: firstStep.NIDENT },
{ name: "in_EVENT", value: nEvent },
{ name: "in_PERSON_CODE", value: firstStep.SSEND_PERSON },
{ name: "in_USER_NAME", value: firstStep.SSEND_USER_NAME },
{ name: "in_EVENT_TYPE", value: firstStep.SEVENT_TYPE },
{ name: "in_EVENT_STAT", value: firstStep.SEVENT_STAT },
{ name: "in_INIT_PERSON", value: firstStep.SINIT_PERSON },
{ name: "in_INIT_AUTHNAME", value: firstStep.SINIT_AUTHNAME },
{ name: "in_CLIENT_CLIENT", value: firstStep.SCLIENT_CLIENT },
{ name: "in_CLIENT_PERSON", value: firstStep.SCLIENT_PERSON }
],
callBack: async send => {
//Выполняем проверку необходимости выбора исполнителя
await executeStored({
stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_SEND",
args: {
NIDENT: firstStep.NIDENT,
NSTEP: 2,
NEVENT: nEvent,
SSEND_CLIENT: send.outParameters.out_CLIENT_CODE,
SSEND_DIVISION: send.outParameters.out_DIVISION_CODE,
SSEND_POST: send.outParameters.out_POST_CODE,
SSEND_PERFORM: send.outParameters.out_POST_IN_DIV_CODE,
SSEND_PERSON: send.outParameters.out_PERSON_CODE,
SSEND_STAFFGRP: send.outParameters.out_STAFFGRP_CODE,
SSEND_USER_GROUP: send.outParameters.out_USER_GROUP_CODE,
SSEND_USER_NAME: send.outParameters.out_USER_NAME,
NSEND_PREDEFINED_EXEC: send.outParameters.out_PREDEFINED_EXEC,
NSEND_PREDEFINED_PROC: send.outParameters.out_PREDEFINED_PROC,
SNOTE_HEADER: note.text ? note.header : null,
SNOTE: note.text ? note.text : null
}
});
//Если требуется перезагрузить данные
if (handleReload) {
handleReload();
}
}
});
}
},
[executeStored, pOnlineShowDictionary]
);
const mItems = [
{ method: "EDIT", name: "Исправить", icon: "edit", visible: false, delimiter: false, needReload: false, func: handleTaskEdit },
{
method: "EDIT_CLIENT",
name: "Исправить в разделе",
icon: "edit_note",
visible: true,
delimiter: false,
needReload: false,
func: handleTaskEditClient
},
{ method: "DELETE", name: "Удалить", icon: "delete", visible: true, delimiter: true, needReload: true, func: handleTaskDelete },
{
method: "TASK_STATE_CHANGE",
name: "Перейти",
icon: "turn_right",
visible: true,
delimiter: false,
needReload: true,
func: handleStateChange
},
{
method: "TASK_RETURN",
name: "Выполнить возврат",
icon: "turn_left",
visible: true,
delimiter: false,
needReload: true,
func: handleTaskReturn
},
{ method: "TASK_SEND", name: "Направить", icon: "send", visible: true, delimiter: true, needReload: true, func: handleSend },
{ method: "NOTES", name: "Примечания", icon: "event_note", visible: true, delimiter: true, needReload: false, func: handleEventNotesOpen },
{
method: "FILE_LINKS",
name: "Присоединенные документы",
icon: "attach_file",
visible: true,
delimiter: false,
needReload: false,
func: handleFileLinksOpen
}
];
//Генерация содержимого
return (
{taskDialogOpen ? (
{
setTaskDialogOpen(false);
}}
/>
) : null}
{provided => (
{
mItems.find(a => (a.method === "EDIT" ? a.func(task.nrn, a.needReload ? onReload : null) : null));
}}
>
{task.sdescription}
}
sx={STYLES.CARD_HEADER_DESC}
action={
}
/>
pOnlineShowDocument({ unitCode: task.slinked_unit, document: task.nlinked_rn }) : null
}
sx={STYLES.ICON_COLOR(task.nlinked_rn)}
disabled={!task.nlinked_rn}
>
assignment
{task.name}
{task.sSender ? (
{task.sSender}
) : null}
)}
);
};
//Контроль свойств - Карточка события
TaskCard.propTypes = {
task: PropTypes.object.isRequired,
avatar: PropTypes.string,
index: PropTypes.number.isRequired,
onReload: PropTypes.func,
eventPoints: PropTypes.array,
colorRule: PropTypes.object,
pointSettings: PropTypes.object,
onOpenNoteDialog: PropTypes.func
};
//----------------
//Интерфейс модуля
//----------------
export { TaskCard };