The task processor is now wired up and ready to complete an assignment.
This commit is contained in:
parent
ea95b0747d
commit
61465130a6
@ -11,11 +11,14 @@ import LoadingPanel from "../../../../components/common/LoadingPanel";
|
||||
import AssigneePanel from "../../tasks/components/AssigneePanel";
|
||||
import TaskTypeAndNameDisplayPanel from "../../workflowTemplates/components/TaskTypeAndNameDisplayPanel";
|
||||
import Button, { ButtonType } from "../../../../components/common/Button";
|
||||
import TaskProcessor from "./components/TaskProcessor";
|
||||
import "../../../../Sass/_assignmentComplete.scss";
|
||||
|
||||
const AssignmentComplete: React.FC = () => {
|
||||
const { assignmentId } = useParams<{ assignmentId: string }>();
|
||||
const { t } = useTranslation(Namespaces.Common);
|
||||
const [isTaskValid, setIsTaskValid] = useState<boolean>(false);
|
||||
const [taskData, setTaskData] = useState<Record<string, unknown>>({});
|
||||
const [assignmentDetails, setAssignmentDetails] =
|
||||
useState<GetAssignmentForCompletion>();
|
||||
|
||||
@ -31,6 +34,9 @@ const AssignmentComplete: React.FC = () => {
|
||||
);
|
||||
if (assignmentDetails) {
|
||||
setAssignmentDetails(assignmentDetails);
|
||||
setTaskData({
|
||||
comments: assignmentDetails.assignment.comments ?? "",
|
||||
});
|
||||
}
|
||||
} catch (ex: any) {
|
||||
toast.error(ex.message);
|
||||
@ -63,16 +69,28 @@ const AssignmentComplete: React.FC = () => {
|
||||
<h2>{assignmentDetails.activity.name}</h2>
|
||||
</div>
|
||||
<div className="actions">
|
||||
<Button buttonType={ButtonType.primary}>Complete</Button>
|
||||
<Button
|
||||
buttonType={ButtonType.primary}
|
||||
disabled={!isTaskValid}
|
||||
onClick={() => {
|
||||
console.log("Task data to submit:", taskData);
|
||||
toast.info("Complete action not implemented yet");
|
||||
}}
|
||||
>
|
||||
Complete
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mainContent">
|
||||
<div className="workarea">
|
||||
<div className="workareaInner">
|
||||
<div>{taskDefinition.config.description}</div>
|
||||
|
||||
<div>Comments</div>
|
||||
<div>{assignmentDetails.assignment.comments}</div>
|
||||
<TaskProcessor
|
||||
assignmentDetails={assignmentDetails}
|
||||
taskDefinition={taskDefinition}
|
||||
taskData={taskData}
|
||||
onTaskDataChange={setTaskData}
|
||||
onValidationChange={setIsTaskValid}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { TaskDefinition } from "../../../workflowTemplates/services/WorkflowTemplateService";
|
||||
import { GetAssignmentForCompletion } from "../services/assignmentCompleteService";
|
||||
import BasicTask from "./tasksProcessor/BasicTask";
|
||||
|
||||
type TaskProcessorProps = {
|
||||
assignmentDetails: GetAssignmentForCompletion;
|
||||
taskDefinition: TaskDefinition;
|
||||
taskData: Record<string, unknown>;
|
||||
onTaskDataChange?: (data: Record<string, unknown>) => void;
|
||||
onValidationChange?: (isValid: boolean) => void;
|
||||
};
|
||||
|
||||
type TaskProcessorComponent = React.ComponentType<TaskProcessorProps>;
|
||||
|
||||
const taskProcessorRegistry: Record<string, TaskProcessorComponent> = {
|
||||
"e_suite.Workflow.Core.Tasks.BasicTask": BasicTask,
|
||||
};
|
||||
|
||||
const TaskProcessor: React.FC<TaskProcessorProps> = ({
|
||||
assignmentDetails,
|
||||
taskDefinition,
|
||||
taskData,
|
||||
onTaskDataChange,
|
||||
onValidationChange,
|
||||
}) => {
|
||||
const processorType = assignmentDetails.task.taskType;
|
||||
const Processor = taskProcessorRegistry[processorType];
|
||||
|
||||
useEffect(() => {
|
||||
if (!Processor) {
|
||||
onValidationChange?.(false);
|
||||
}
|
||||
}, [Processor, onValidationChange]);
|
||||
|
||||
if (!Processor) {
|
||||
return <div>Unsupported task type: {processorType}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Processor
|
||||
assignmentDetails={assignmentDetails}
|
||||
taskDefinition={taskDefinition}
|
||||
taskData={taskData}
|
||||
onTaskDataChange={onTaskDataChange}
|
||||
onValidationChange={onValidationChange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default TaskProcessor;
|
||||
@ -0,0 +1,114 @@
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import Joi from "joi";
|
||||
import { InputType } from "../../../../../../components/common/Input";
|
||||
import { renderInput } from "../../../../../../components/common/formHelpers";
|
||||
import {
|
||||
FormData,
|
||||
FormError,
|
||||
} from "../../../../../../components/common/useForm";
|
||||
import { TaskDefinition } from "../../../../workflowTemplates/services/WorkflowTemplateService";
|
||||
import { GetAssignmentForCompletion } from "../../services/assignmentCompleteService";
|
||||
|
||||
type BasicTaskProps = {
|
||||
assignmentDetails: GetAssignmentForCompletion;
|
||||
taskDefinition: TaskDefinition;
|
||||
taskData: Record<string, unknown>;
|
||||
onTaskDataChange?: (data: Record<string, unknown>) => void;
|
||||
onValidationChange?: (isValid: boolean) => void;
|
||||
};
|
||||
|
||||
const BasicTask: React.FC<BasicTaskProps> = ({
|
||||
assignmentDetails,
|
||||
taskDefinition,
|
||||
taskData,
|
||||
onTaskDataChange,
|
||||
onValidationChange,
|
||||
}) => {
|
||||
const [errors, setErrors] = useState<FormError>({});
|
||||
|
||||
const validateData = useCallback(
|
||||
(data: Record<string, unknown>) => {
|
||||
const result = Joi.object({
|
||||
comments: Joi.string().required().allow("").label("Comments"),
|
||||
}).validate(data, { abortEarly: false });
|
||||
|
||||
const nextErrors: FormError = {};
|
||||
|
||||
if (result.error) {
|
||||
for (const detail of result.error.details) {
|
||||
const key = String(detail.path[0] ?? "_general");
|
||||
nextErrors[key] = detail.message;
|
||||
}
|
||||
}
|
||||
|
||||
setErrors(nextErrors);
|
||||
|
||||
const hasValidationErrors = Object.keys(nextErrors).some(
|
||||
(key) => !key.startsWith("_"),
|
||||
);
|
||||
|
||||
onValidationChange?.(!hasValidationErrors);
|
||||
},
|
||||
[onValidationChange],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
validateData(taskData);
|
||||
}, [taskData, validateData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (taskData.comments === undefined) {
|
||||
onTaskDataChange?.({
|
||||
...taskData,
|
||||
comments: assignmentDetails.assignment.comments ?? "",
|
||||
});
|
||||
}
|
||||
}, [assignmentDetails.assignment.comments, onTaskDataChange, taskData]);
|
||||
|
||||
const commentsValue = String(taskData.comments ?? "");
|
||||
|
||||
const description =
|
||||
typeof taskDefinition.config === "object" &&
|
||||
taskDefinition.config !== null &&
|
||||
"description" in taskDefinition.config
|
||||
? String(
|
||||
(taskDefinition.config as Record<string, unknown>).description ?? "",
|
||||
)
|
||||
: "";
|
||||
|
||||
const handleCommentsChange = (
|
||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
||||
) => {
|
||||
if (e.target instanceof HTMLTextAreaElement) {
|
||||
onTaskDataChange?.({
|
||||
...taskData,
|
||||
comments: e.target.value,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="workareaInner">
|
||||
<div>{description}</div>
|
||||
|
||||
{renderInput(
|
||||
"comments",
|
||||
"Comments",
|
||||
{ comments: commentsValue } as FormData,
|
||||
errors,
|
||||
InputType.textarea,
|
||||
false,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
true,
|
||||
undefined,
|
||||
handleCommentsChange as (
|
||||
e: React.ChangeEvent<HTMLInputElement>,
|
||||
) => void,
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BasicTask;
|
||||
Loading…
Reference in New Issue
Block a user