diff --git a/src/Pages/GroupTasks/GroupTasksViewModal.js b/src/Pages/GroupTasks/GroupTasksViewModal.js
index 9b92f02..898b101 100644
--- a/src/Pages/GroupTasks/GroupTasksViewModal.js
+++ b/src/Pages/GroupTasks/GroupTasksViewModal.js
@@ -1,6 +1,5 @@
import {
Alert,
- Avatar,
Button,
Form,
Input,
@@ -10,10 +9,9 @@ import {
Result,
Steps,
Tag,
- Tooltip,
notification,
} from "antd";
-import { useContext } from "react";
+import { useContext, useRef, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import {
Constants,
@@ -23,12 +21,9 @@ import {
GetDuration,
MyAvatar,
getUserId,
+ setNativeValue,
} from "../../utils";
-import {
- AntDesignOutlined,
- InfoCircleOutlined,
- LockOutlined,
-} from "@ant-design/icons";
+import { InfoCircleOutlined, LockOutlined } from "@ant-design/icons";
export default function GroupTasksViewModal({ isOpen }) {
const webSocketContext = useContext(WebSocketContext);
@@ -102,7 +97,6 @@ export default function GroupTasksViewModal({ isOpen }) {
case Constants.GROUP_TASKS_STATUS.RUNNING:
return "process";
case Constants.GROUP_TASKS_STATUS.CANCELED:
- return "error";
case Constants.GROUP_TASKS_STATUS.FAILED:
return "error";
case Constants.GROUP_TASKS_STATUS.INPUT_REQUIRED:
@@ -145,7 +139,10 @@ export default function GroupTasksViewModal({ isOpen }) {
}
taskInputs.push({
- parameterName: specifiedTaskInputs[i].id,
+ parameterName:
+ specifiedTaskInputs[i].id.split(
+ "-"
+ )[6] /* Format: UUID-STEP-PARAMETER_NAME */,
value: specifiedTaskInputs[i].value,
});
}
@@ -528,6 +525,8 @@ function InputRequiredHandler({
step,
taskLockedByUserId,
}) {
+ const [inputFields, setInputFields] = useState({});
+
const globalInputs = JSON.parse(currentGroupTask.GlobalInputs);
const getDefaultValue = (groupTaskParameter) => {
@@ -552,18 +551,29 @@ function InputRequiredHandler({
);
};
- let lastChanges = [];
+ let lastChanges = useRef([]);
+ let typingTimer = useRef();
- const onInputChange = (currentGroupTaskId) => {
- lastChanges = lastChanges.filter(
+ 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.find((lC) => lC.step === step);
+ const lastChange = lastChanges.current.find((lC) => lC.step === step);
if (lastChange === undefined) {
- lastChanges.push({
+ lastChanges.current.push({
step: step,
changeTime: Date.now(),
});
@@ -574,6 +584,19 @@ function InputRequiredHandler({
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 (
@@ -592,15 +615,17 @@ function InputRequiredHandler({
>
+ onChange={(e) =>
onInputChange(
+ e.target.value,
currentGroupTask.Id,
groupTaskParameter.parameterName
)
}
+ value={inputFields[groupTaskParameter.parameterName]}
/>
);
@@ -616,12 +641,14 @@ function InputRequiredHandler({
>
+ max={Number.MAX_SAFE_INTEGER}
+ onChange={(e) =>
onInputChange(
+ e,
currentGroupTask.Id,
groupTaskParameter.parameterName
)
diff --git a/src/utils.js b/src/utils.js
index bbb18eb..a13ce51 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -1,6 +1,6 @@
import { UserOutlined } from "@ant-design/icons";
import { Avatar, Badge, Tooltip } from "antd";
-import { createContext, useEffect, useRef, useState } from "react";
+import { createContext, useContext, useEffect, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import { Buffer } from "buffer";
@@ -111,6 +111,7 @@ const ReceivedMessagesCommands = {
UpdateScannerLastUsed: 15,
TaskLocked: 16,
TaskUnlocked: 17,
+ UpdateGroupTaskStepUserInputValue: 18,
};
// commands sent to the backend server
@@ -120,6 +121,7 @@ export const SentMessagesCommands = {
TaskContinueTaskStep: 3,
ReloadGroupTasks: 4,
TaskLocking: 5,
+ UpdateGroupTaskStepUserInputValue: 6,
};
export function WebSocketProvider({
@@ -146,21 +148,19 @@ export function WebSocketProvider({
const navigate = useNavigate();
const StartGroupTasksOpenModalRememberIdRef = useRef(null);
- let socket = null;
+ //let socket = null;
const ws = useRef(null);
const connect = () => {
- socket = new WebSocket(Constants.WS_ADDRESS + "?auth=" + userSession);
+ ws.current = new WebSocket(Constants.WS_ADDRESS + "?auth=" + userSession);
- ws.current = socket;
-
- socket.onopen = () => {
+ ws.current.onopen = () => {
console.log("connected");
setConnectionBadgeStatus("success");
setIsReady(true);
};
- socket.onmessage = (event) => {
+ ws.current.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log("received message", data);
@@ -301,7 +301,6 @@ export function WebSocketProvider({
break;
case ReceivedMessagesCommands.UpdateScannerLastUsed:
- console.log("Received", body);
setScanners((arr) => {
const newArr = [...arr];
@@ -313,7 +312,6 @@ export function WebSocketProvider({
});
break;
case ReceivedMessagesCommands.TaskLocked:
- console.log("taskLocked", body);
setGroupTasksSteps((arr) => {
const newArr = [...arr];
@@ -343,13 +341,21 @@ export function WebSocketProvider({
return newArr;
});
break;
+ case ReceivedMessagesCommands.UpdateGroupTaskStepUserInputValue:
+ const foundInput = document.getElementById(body.element);
+
+ if (foundInput) {
+ setNativeValue(foundInput, body.value);
+ }
+ break;
+
default:
console.error("unknown command", cmd);
break;
}
};
- socket.onclose = (event) => {
+ ws.current.onclose = (event) => {
setIsReady(false);
setConnectionBadgeStatus("error");
console.log("closed", event);
@@ -374,7 +380,8 @@ export function WebSocketProvider({
useEffect(() => {
connect();
- return () => socket.close();
+ //return () => socket.close();
+ return () => ws.current.close();
}, []);
const SendSocketMessage = (cmd, body) => {
@@ -406,6 +413,33 @@ export function WebSocketProvider({
);
}
+/*
+function doEvent(obj, event) {
+ var event = new Event(event, { target: obj, bubbles: true });
+ event.simulated = true;
+
+ let tracker = obj._valueTracker;
+ if (tracker) {
+ tracker.setValue(lastValue);
+ }
+
+ return obj ? obj.dispatchEvent(event) : false;
+} */
+
+// https://stackoverflow.com/a/52486921
+function setNativeValue(element, value) {
+ let lastValue = element.value;
+ element.value = value;
+ let event = new Event("input", { target: element, bubbles: true });
+ // React 15
+ event.simulated = true;
+ // React 16
+ let tracker = element._valueTracker;
+ if (tracker) {
+ tracker.setValue(lastValue);
+ }
+ element.dispatchEvent(event);
+}
export function FormatDatetime(datetime) {
if (datetime === "0001-01-01T00:00:00Z") {