import {
Alert,
Button,
Form,
Input,
InputNumber,
Modal,
Popover,
Result,
Steps,
Tag,
notification,
} from "antd";
import { useContext, useRef, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import {
Constants,
FormatDatetime,
WebSocketContext,
SentMessagesCommands,
GetDuration,
MyAvatar,
getUserId,
setNativeValue,
} from "../../utils";
import { InfoCircleOutlined, LockOutlined } from "@ant-design/icons";
export default function GroupTasksViewModal({ isOpen }) {
const webSocketContext = useContext(WebSocketContext);
const navigate = useNavigate();
const [notificationApi, notificationContextHolder] =
notification.useNotification();
let { paramGroupTaskId } = useParams();
const handleCancel = () => navigate(Constants.ROUTE_PATHS.GROUP_TASKS);
let currentGroupTask;
webSocketContext.GroupTasks.forEach((groupTask) => {
if (groupTask.Id === paramGroupTaskId) {
currentGroupTask = groupTask;
}
});
// invalid group task id in url specified
if (!currentGroupTask) {
return (
Close}
>
{" "}
);
}
const getAlertType = (status) => {
switch (status) {
case Constants.GROUP_TASKS_STATUS.FINISHED:
return "success";
case Constants.GROUP_TASKS_STATUS.RUNNING:
return "info";
case Constants.GROUP_TASKS_STATUS.CANCELED:
return "warning";
case Constants.GROUP_TASKS_STATUS.FAILED:
return "error";
case Constants.GROUP_TASKS_STATUS.INPUT_REQUIRED:
return "info";
default:
return "info";
}
};
const getAlertMessage = (status) => {
switch (status) {
case Constants.GROUP_TASKS_STATUS.FINISHED:
return "Success";
case Constants.GROUP_TASKS_STATUS.RUNNING:
return "Task is running";
case Constants.GROUP_TASKS_STATUS.CANCELED:
return "Task cancelled";
case Constants.GROUP_TASKS_STATUS.FAILED:
return "Task failed";
case Constants.GROUP_TASKS_STATUS.INPUT_REQUIRED:
return "Input required";
default:
return "Alert message not found";
}
};
const getStepItemStatus = (status) => {
switch (status) {
case Constants.GROUP_TASKS_STATUS.FINISHED:
return "finish";
case Constants.GROUP_TASKS_STATUS.RUNNING:
return "process";
case Constants.GROUP_TASKS_STATUS.CANCELED:
case Constants.GROUP_TASKS_STATUS.FAILED:
return "error";
case Constants.GROUP_TASKS_STATUS.INPUT_REQUIRED:
return "wait";
default:
return "wait";
}
};
const handleTaskFailedTryAgainRunTaskStep = (taskStepId, step) => {
webSocketContext.SendSocketMessage(
SentMessagesCommands.TaskFailedTryAgainRunTaskStep,
{
groupTaskId: currentGroupTask.Id,
category: currentGroupTask.Category,
groupId: currentGroupTask.GroupId,
step: step,
taskStepId: taskStepId,
}
);
};
const handleTaskContinueTaskStep = (taskStepId, step) => {
const groupTasksViewModalRequiredInputsForm = document.getElementById(
"groupTasksViewModalRequiredInputsForm"
);
let canTaskContinued = true;
let taskInputs = [];
if (groupTasksViewModalRequiredInputsForm !== null) {
const specifiedTaskInputs =
groupTasksViewModalRequiredInputsForm.getElementsByTagName("input");
if (specifiedTaskInputs.length > 0) {
for (let i = 0; i < specifiedTaskInputs.length; i++) {
if (specifiedTaskInputs[i].value === "") {
canTaskContinued = false;
break;
}
taskInputs.push({
parameterName:
specifiedTaskInputs[i].id.split(
"-"
)[6] /* Format: UUID-STEP-PARAMETER_NAME */,
value: specifiedTaskInputs[i].value,
});
}
}
}
if (!canTaskContinued) {
notificationApi["error"]({
message: `Inputs cannot be empty`,
description: `Please fill in all inputs`,
});
return;
}
webSocketContext.SendSocketMessage(
SentMessagesCommands.TaskContinueTaskStep,
{
groupTaskId: currentGroupTask.Id,
category: currentGroupTask.Category,
groupId: currentGroupTask.GroupId,
step: step,
taskStepId: taskStepId,
taskInputs: taskInputs,
}
);
};
const alertActionHandler = (status, taskStepId, index, taskLocked) => {
switch (status) {
case Constants.GROUP_TASKS_STATUS.FAILED:
return (
);
case Constants.GROUP_TASKS_STATUS.INPUT_REQUIRED:
return (
);
default:
return <>>;
}
};
const getGroupTaskStepLog = (log) => {
return log.length === 0 ? (
""
) : (
{log}
);
};
const stepsItemHandler = () => {
let groupTaskSteps = [];
let groupTasks = [];
webSocketContext.GroupTasksSteps.forEach((step) => {
if (step.GroupTasksId === paramGroupTaskId) {
groupTaskSteps.push(step);
}
});
groupTaskSteps.sort((a, b) => a.Step - b.Step);
webSocketContext.CategoryGroups.forEach((categoryGroup) => {
if (categoryGroup.category === currentGroupTask.Category) {
categoryGroup.groups.forEach((group) => {
if (currentGroupTask.GroupId === group.id) {
groupTasks = group.tasks;
}
});
}
});
let stepItems = [];
groupTasks.forEach((groupTask, index) => {
stepItems.push({
key: index,
title:
groupTaskSteps[index] !== undefined &&
groupTaskSteps[index].Inputs !== "" ? (
<>
{groupTask.name}{" "}
Specified Task Inputs
}
content={
<>
{groupTask.parameters.length > 0 &&
groupTask.parameters.map((task) => {
return (
{task.displayName}:{" "}
{
JSON.parse(groupTaskSteps[index].Inputs).find(
(step) =>
step.parameterName === task.parameterName
).value
}
);
})}
>
}
>
{" "}
{groupTaskSteps[index]?.CreatorUserId !== undefined && (
)}
>
) : (
<>
{groupTask.name}{" "}
{groupTaskSteps[index]?.CreatorUserId !== undefined && (
)}
>
),
status:
groupTaskSteps[index] !== undefined
? getStepItemStatus(groupTaskSteps[index].Status)
: "wait",
description:
groupTaskSteps[index] !== undefined ? (
<>
Id: {groupTaskSteps[index].Id}
Started at:{" "}
{FormatDatetime(groupTaskSteps[index].StartedAt)}
Ended at:{" "}
{groupTaskSteps[index].EndedAt !== "0001-01-01T00:00:00Z"
? FormatDatetime(groupTaskSteps[index].EndedAt)
: Constants.TEXT_EMPTY_PLACEHOLDER}
Duration:{" "}
{GetDuration(
groupTaskSteps[index].StartedAt,
groupTaskSteps[index].EndedAt
)}
{getAlertMessage(groupTaskSteps[index].Status)}{" "}
{groupTaskSteps[index].LockedByUserId !== "" && (
<>
{" "}
>
)}
}
description={
groupTaskSteps[index].Status ===
Constants.GROUP_TASKS_STATUS.INPUT_REQUIRED ? (
) : (
getGroupTaskStepLog(groupTaskSteps[index].Log)
)
}
type={getAlertType(groupTaskSteps[index].Status)}
showIcon
action={alertActionHandler(
groupTaskSteps[index].Status,
groupTaskSteps[index].Id,
index,
groupTaskSteps[index].LockedByUserId
)}
/>
>
) : (
""
),
});
});
return stepItems;
};
return (
Close}
>
{notificationContextHolder}
{webSocketContext.GroupTasks.map((groupTask) => {
if (groupTask.Id === paramGroupTaskId) {
let currentGroupTask = groupTask;
return (
{currentGroupTask.GroupName}{" "}
Details
}
content={
<>
ID:{" "}
{paramGroupTaskId}
Category:
{" "}
{currentGroupTask.Category}
Started at:
{" "}
{FormatDatetime(currentGroupTask.StartedAt)}
Endet at:
{" "}
{FormatDatetime(currentGroupTask.EndedAt)}
Duration:
{" "}
{GetDuration(
currentGroupTask.StartedAt,
currentGroupTask.EndedAt
)}
{currentGroupTask.GlobalInputs !== "[]" ? (
<>
Specified Global Inputs
{JSON.parse(currentGroupTask.GlobalInputs).map(
(globalInput) => {
return (
{globalInput.parameterName}:{" "}
{globalInput.value !== ""
? globalInput.value
: Constants.TEXT_EMPTY_PLACEHOLDER}
);
}
)}
>
) : null}
>
}
>
{" "}
{currentGroupTask.Description}
);
}
return "";
})}
);
}
function InputRequiredHandler({
webSocketContext,
currentGroupTask,
groupTaskParameters,
notificationApi,
step,
taskLockedByUserId,
}) {
const [inputFields, setInputFields] = useState({});
const globalInputs = JSON.parse(currentGroupTask.GlobalInputs);
const getDefaultValue = (groupTaskParameter) => {
if (globalInputs === undefined || !groupTaskParameter.global) return null;
return globalInputs.find(
(globalInput) =>
globalInput.parameterName === groupTaskParameter.parameterName
).value;
};
const getLabel = (displayName, groupTaskParameter) => {
return groupTaskParameter.global ? (
<>
{displayName}
Global
>
) : (
displayName
);
};
let lastChanges = useRef([]);
let typingTimer = useRef();
const onInputChange = (
inputValue,
currentGroupTaskId,
groupTaskParameterName
) => {
setInputFields((fields) => {
return ({ ...fields }[groupTaskParameterName] = inputValue);
});
if (taskLockedByUserId !== "") return;
lastChanges.current = lastChanges.current.filter(
(lc) =>
Date.now() - new Date(lc.changeTime) < Constants.GROUP_TASK_LOCKED_TIME
);
const lastChange = lastChanges.current.find((lC) => lC.step === step);
if (lastChange === undefined) {
lastChanges.current.push({
step: step,
changeTime: Date.now(),
});
webSocketContext.SendSocketMessage(SentMessagesCommands.TaskLocking, {
lockedByUserId: getUserId(),
groupTaskId: currentGroupTaskId,
step: step,
});
}
// sync input value with other web clients
clearTimeout(typingTimer.current);
typingTimer.current = setTimeout(() => {
webSocketContext.SendSocketMessage(
SentMessagesCommands.UpdateGroupTaskStepUserInputValue,
{
element: `${currentGroupTaskId}-${step}-${groupTaskParameterName}`,
value: inputValue,
}
);
}, 500);
};
return (
onInputChange(
e.target.value,
currentGroupTask.Id,
groupTaskParameter.parameterName
)
}
value={inputFields[groupTaskParameter.parameterName]}
/>
);
case "number":
return (
onInputChange(
e,
currentGroupTask.Id,
groupTaskParameter.parameterName
)
}
/>
);
default:
notificationApi["error"]({
message: `Type ${groupTaskParameter.type} not implemented`,
description: `Was specified in: ${groupTaskParameter.displayName}`,
});
return (
Type ${groupTaskParameter.type} not implemented. Was specified
in: ${groupTaskParameter.displayName}
);
}
})}
);
}