admin-dashboard-web/src/Pages/GroupTasks/Overview/GroupTasksViewModal.js

1053 lines
33 KiB
JavaScript

import {
Alert,
Button,
Col,
Form,
Image,
Input,
InputNumber,
Modal,
Popover,
Result,
Row,
Space,
Steps,
Tag,
notification,
} from "antd";
import { useContext, useMemo, useRef, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import {
Constants,
FormatDatetime,
WebSocketContext,
SentMessagesCommands,
GetDuration,
MyAvatar,
getUserId,
GroupTasksStepsLockedAndUserUpdateInputValueRememberId,
hasXYPermission,
} from "../../../utils";
import {
CheckOutlined,
FileImageOutlined,
InfoCircleOutlined,
LockOutlined,
RetweetOutlined,
UndoOutlined,
} from "@ant-design/icons";
import { StlViewer } from "react-stl-viewer";
import TextArea from "antd/es/input/TextArea";
import { useTranslation } from "react-i18next";
export default function GroupTasksViewModal({ isOpen }) {
const webSocketContext = useContext(WebSocketContext);
const navigate = useNavigate();
const [notificationApi, notificationContextHolder] =
notification.useNotification();
let { paramGroupTaskId } = useParams();
const { t } = useTranslation();
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 or no permissions
if (
!currentGroupTask ||
!hasXYPermission(
webSocketContext.User.Permissions,
Constants.PERMISSIONS.GROUP_TASKS.OVERVIEW.XYView,
currentGroupTask.Category
)
) {
return (
<Modal
open={isOpen}
width="70%"
maskClosable={true}
onCancel={handleCancel}
footer={
<Button onClick={handleCancel}>{t("common.button.close")}</Button>
}
>
<Result
status="500"
title={t("groupTasks.groupTasksViewModal.groupTaskNotFound")}
/>
</Modal>
);
}
const getAlertType = (status) => {
switch (status) {
case Constants.GROUP_TASKS_STATUS.FINISHED:
return "success";
case Constants.GROUP_TASKS_STATUS.FAILED:
return "error";
case Constants.GROUP_TASKS_STATUS.CANCELED:
case Constants.GROUP_TASKS_STATUS.PAUSED:
case Constants.GROUP_TASKS_STATUS.UNDO_ENDED:
return "warning";
case Constants.GROUP_TASKS_STATUS.INPUT_REQUIRED:
case Constants.GROUP_TASKS_STATUS.RUNNING:
default:
return "info";
}
};
const getAlertMessage = (status) => {
switch (status) {
case Constants.GROUP_TASKS_STATUS.FINISHED:
return t("groupTasks.groupTasksViewModal.alertMessage.successful");
case Constants.GROUP_TASKS_STATUS.RUNNING:
return t("groupTasks.groupTasksViewModal.alertMessage.taskIsRunning");
case Constants.GROUP_TASKS_STATUS.CANCELED:
return t("groupTasks.groupTasksViewModal.alertMessage.taskCanceled");
case Constants.GROUP_TASKS_STATUS.FAILED:
return t("groupTasks.groupTasksViewModal.alertMessage.taskFailed");
case Constants.GROUP_TASKS_STATUS.INPUT_REQUIRED:
return t(
"groupTasks.groupTasksViewModal.alertMessage.taskInputRequired"
);
case Constants.GROUP_TASKS_STATUS.PAUSED:
return t("groupTasks.groupTasksViewModal.alertMessage.paused");
case Constants.GROUP_TASKS_STATUS.UNDO_ENDED:
return t("groupTasks.groupTasksViewModal.alertMessage.undoEnded");
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:
case Constants.GROUP_TASKS_STATUS.PAUSED:
case Constants.GROUP_TASKS_STATUS.UNDO_ENDED:
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,
});
}
}
const specifiedTaskTextareas =
groupTasksViewModalRequiredInputsForm.getElementsByTagName("textarea");
if (specifiedTaskTextareas.length > 0) {
for (let i = 0; i < specifiedTaskTextareas.length; i++) {
if (specifiedTaskTextareas[i].value === "") {
canTaskContinued = false;
break;
}
taskInputs.push({
parameterName:
specifiedTaskTextareas[i].id.split(
"-"
)[6] /* Format: UUID-STEP-PARAMETER_NAME */,
value: specifiedTaskTextareas[i].value,
});
}
}
}
if (!canTaskContinued) {
notificationApi["error"]({
message: t(
"groupTasks.groupTasksViewModal.notification.inputsCannotBeEmpty.message"
),
description: t(
"groupTasks.groupTasksViewModal.notification.inputsCannotBeEmpty.description"
),
});
return;
}
webSocketContext.SendSocketMessage(
SentMessagesCommands.TaskContinueTaskStep,
{
groupTaskId: currentGroupTask.Id,
category: currentGroupTask.Category,
groupId: currentGroupTask.GroupId,
step: step,
taskStepId: taskStepId,
taskInputs: taskInputs,
}
);
};
const handleUserActionTaskStep = (action, taskStepId, step) => {
webSocketContext.SendSocketMessage(
SentMessagesCommands.HandleUserActionTaskStep,
{
action: action,
groupTaskId: currentGroupTask.Id,
category: currentGroupTask.Category,
groupId: currentGroupTask.GroupId,
step: step,
taskStepId: taskStepId,
}
);
};
const ActionHandler = ({ status, taskStepId, index, taskLocked }) => {
const currentStepTask = webSocketContext.CategoryGroups.find(
(category) => category.category === currentGroupTask.Category
).groups.find((group) => group.id === currentGroupTask.GroupId).tasks[
index
];
switch (status) {
case Constants.GROUP_TASKS_STATUS.FAILED:
return (
<Button
size="small"
danger
disabled={taskLocked}
onClick={() =>
handleTaskFailedTryAgainRunTaskStep(taskStepId, index + 1)
}
>
{t("common.button.tryAgain")}
</Button>
);
case Constants.GROUP_TASKS_STATUS.INPUT_REQUIRED:
return (
<Button
size="small"
disabled={taskLocked}
onClick={() => handleTaskContinueTaskStep(taskStepId, index + 1)}
>
{t("common.button.continue")}
</Button>
);
case Constants.GROUP_TASKS_STATUS.PAUSED:
return (
<Space>
{currentStepTask.repeatPossible && (
<Button
icon={<RetweetOutlined />}
size="small"
disabled={taskLocked}
onClick={() =>
handleUserActionTaskStep(2, taskStepId, index + 1)
}
>
{t("common.button.repeat")}
</Button>
)}
{currentStepTask.undoPossible && (
<Button
icon={<UndoOutlined />}
size="small"
disabled={taskLocked}
onClick={() =>
handleUserActionTaskStep(1, taskStepId, index + 1)
}
>
{t("common.button.undo")}
</Button>
)}
<Button
icon={<CheckOutlined />}
size="small"
type={
currentStepTask.repeatPossible && currentStepTask.undoPossible
? "primary"
: "default"
}
disabled={taskLocked}
onClick={() => handleUserActionTaskStep(0, taskStepId, index + 1)}
>
{t("common.button.resume")}
</Button>
</Space>
);
case Constants.GROUP_TASKS_STATUS.UNDO_ENDED:
return (
<Button
size="small"
disabled={taskLocked}
onClick={() => handleUserActionTaskStep(2, taskStepId, index + 1)}
>
{t("common.button.resume")}
</Button>
);
default:
return <></>;
}
};
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;
}
});
}
});
const getStepItem = (groupTask, index) => {
return {
key: index,
title:
groupTaskSteps[index] !== undefined &&
groupTaskSteps[index].Inputs !== "" &&
groupTaskSteps[index].Status !==
Constants.GROUP_TASKS_STATUS.INPUT_REQUIRED &&
groupTaskSteps[index].Status !==
Constants.GROUP_TASKS_STATUS.UNDO_ENDED ? (
<>
{groupTask.name}{" "}
<Popover
key={groupTaskSteps[index].Id + index}
trigger="click"
placement="bottomLeft"
title={
<h2
style={{
fontWeight: "bold",
color: Constants.COLORS.SECONDARY,
}}
>
{t(
"groupTasks.groupTasksViewModal.popover.specifiedTaskInputs"
)}
</h2>
}
content={
<>
{groupTask.parameters.length > 0 &&
groupTask.parameters.map((task) => {
return (
<span key={task.parameterName}>
<span style={{ fontWeight: "bold" }}>
{task.displayName}:{" "}
</span>
<span>
{
JSON.parse(groupTaskSteps[index].Inputs).find(
(input) =>
input.parameterName === task.parameterName
)?.value
}
</span>
<br />
</span>
);
})}
</>
}
>
<InfoCircleOutlined
style={{
fontSize: "18px",
color: Constants.COLORS.ICON_INFO,
marginBottom: "4px",
verticalAlign: "middle",
}}
/>
</Popover>{" "}
{groupTaskSteps[index]?.CreatorUserId !== undefined && (
<MyAvatar
tooltip
allUsers={webSocketContext.AllUsers}
userId={groupTaskSteps[index].CreatorUserId}
/>
)}
</>
) : (
<>
{groupTask.name}{" "}
{groupTaskSteps[index]?.CreatorUserId !== undefined && (
<MyAvatar
tooltip
allUsers={webSocketContext.AllUsers}
userId={groupTaskSteps[index].CreatorUserId}
/>
)}
</>
),
status:
groupTaskSteps[index] !== undefined
? getStepItemStatus(groupTaskSteps[index].Status)
: "wait",
description:
groupTaskSteps[index] !== undefined ? (
<>
<p style={{ color: "#000" }}>
<b>ID:</b> {groupTaskSteps[index].Id}
<br />
<b>{t("groupTasks.groupTasksViewModal.startedAt")}:</b>{" "}
{FormatDatetime(groupTaskSteps[index].StartedAt)}
<br />
<b>{t("groupTasks.groupTasksViewModal.endedAt")}:</b>{" "}
{groupTaskSteps[index].EndedAt !== "0001-01-01T00:00:00Z"
? FormatDatetime(groupTaskSteps[index].EndedAt)
: Constants.TEXT_EMPTY_PLACEHOLDER}
<br />
<b>{t("groupTasks.groupTasksViewModal.duration")}:</b>{" "}
{GetDuration(
groupTaskSteps[index].StartedAt,
groupTaskSteps[index].EndedAt
)}
</p>
<Alert
style={{ width: "100%" }}
message={
<div
style={{
display: "flex",
justifyContent: "space-between",
}}
>
<b>
{getAlertMessage(groupTaskSteps[index].Status)}{" "}
{groupTaskSteps[index].LockedByUserId !== "" && (
<>
<LockOutlined />{" "}
<MyAvatar
tooltip
allUsers={webSocketContext.AllUsers}
userId={groupTaskSteps[index].LockedByUserId}
avatarWidth={24}
/>
</>
)}
</b>
<ActionHandler
status={groupTaskSteps[index].Status}
index={index}
taskLocked={groupTaskSteps[index].LockedByUserId}
taskStepId={groupTaskSteps[index].Id}
/>
</div>
}
description={
groupTaskSteps[index].Status ===
Constants.GROUP_TASKS_STATUS.INPUT_REQUIRED ? (
<div id={`${currentGroupTask.Id}-scroll-${index}`}>
<InputRequiredHandler
webSocketContext={webSocketContext}
currentGroupTask={currentGroupTask}
groupTaskParameters={groupTask.parameters}
groupTaskStepInputs={
groupTaskSteps[index] !== undefined &&
groupTaskSteps[index].Inputs !== "" &&
groupTaskSteps[index].Inputs
}
notificationApi={notificationApi}
step={index + 1}
taskLockedByUserId={
groupTaskSteps[index].LockedByUserId
}
/>
</div>
) : (
groupTaskSteps[index].Log.length > 0 && (
<div
id={`${currentGroupTask.Id}-scroll-${index}`}
style={{ width: "100%" }}
>
<GroupTaskStepLogHandler
currentGroupTaskId={currentGroupTask.Id}
log={groupTaskSteps[index].Log}
files={groupTaskSteps[index].Files}
/>
</div>
)
)
}
type={getAlertType(groupTaskSteps[index].Status)}
showIcon
/>
</>
) : (
""
),
};
};
let stepItems = [];
groupTasks.forEach((groupTask, index) =>
stepItems.push(getStepItem(groupTask, index))
);
// occurs when tasks were taken from the group task config, but at a previous time the tasks existed
if (currentGroupTask.NumberOfSteps > groupTasks.length) {
for (let i = groupTasks.length; i < currentGroupTask.NumberOfSteps; i++) {
let stepParams = [];
if (groupTaskSteps[i].Inputs !== "") {
let params = JSON.parse(groupTaskSteps[i].Inputs);
for (let i2 = 0; i2 < params.length; i2++) {
params[i2].displayName = params[i2].parameterName;
}
stepParams = params;
}
stepItems.push(getStepItem({ name: "???", parameters: stepParams }, i));
}
}
return stepItems;
};
return (
<Modal
open={isOpen}
width="70%"
onCancel={handleCancel}
maskClosable={false}
footer={
<Button onClick={handleCancel}>{t("common.button.close")}</Button>
}
>
{notificationContextHolder}
{webSocketContext.GroupTasks.map((groupTask) => {
if (groupTask.Id === paramGroupTaskId) {
let currentGroupTask = groupTask;
return (
<div key={paramGroupTaskId}>
<h1
style={{
color: Constants.COLORS.PRIMARY,
fontWeight: "bold",
marginBottom: 0,
}}
>
{currentGroupTask.GroupName}{" "}
<Popover
trigger="click"
title={
<h2
style={{
fontWeight: "bold",
color: Constants.COLORS.SECONDARY,
}}
>
{t("groupTasks.groupTasksViewModal.popover.details")}
</h2>
}
content={
<>
<p>
<span style={{ fontWeight: "bold" }}>ID:</span>{" "}
{paramGroupTaskId} <br />
<span style={{ fontWeight: "bold" }}>
{t("groupTasks.groupTasksViewModal.category")}:
</span>{" "}
{currentGroupTask.Category}
<br />
<span style={{ fontWeight: "bold" }}>
{t("groupTasks.groupTasksViewModal.startedAt")}:
</span>{" "}
{FormatDatetime(currentGroupTask.StartedAt)}
<br />
<span style={{ fontWeight: "bold" }}>
{t("groupTasks.groupTasksViewModal.endedAt")}:
</span>{" "}
{FormatDatetime(currentGroupTask.EndedAt)}
<br />
<span style={{ fontWeight: "bold" }}>
{t("groupTasks.groupTasksViewModal.duration")}:
</span>{" "}
{GetDuration(
currentGroupTask.StartedAt,
currentGroupTask.EndedAt
)}
</p>
{currentGroupTask.GlobalInputs !== "[]" ? (
<>
<h2
style={{
fontWeight: "bold",
color: Constants.COLORS.SECONDARY,
}}
>
{t(
"groupTasks.groupTasksViewModal.popover.specifiedGlobalInputs"
)}
</h2>
<span>
{JSON.parse(currentGroupTask.GlobalInputs).map(
(globalInput) => {
return (
<span
key={
globalInput.parameterName +
globalInput.value
}
>
<span style={{ fontWeight: "bold" }}>
{
webSocketContext.CategoryGroups.find(
(categoryGroup) =>
categoryGroup.category ===
currentGroupTask.Category
)
.groups.find(
(group) =>
group.id ===
currentGroupTask.GroupId
)
.globalInputs.find(
(gI) =>
gI.parameterName ===
globalInput.parameterName
).displayName
}
:{" "}
</span>
<span>
{globalInput.value !== ""
? globalInput.value
: Constants.TEXT_EMPTY_PLACEHOLDER}
</span>
<br />
</span>
);
}
)}
</span>
</>
) : null}
</>
}
>
<InfoCircleOutlined
style={{
fontSize: "18px",
color: Constants.COLORS.ICON_INFO,
marginBottom: "4px",
verticalAlign: "middle",
}}
/>
</Popover>{" "}
<MyAvatar
tooltip
allUsers={webSocketContext.AllUsers}
userId={currentGroupTask.CreatorUserId}
/>
<br />
</h1>
<div style={{ marginBottom: 16 }}>
<span>{currentGroupTask.Description}</span>
</div>
<Steps direction="vertical" items={stepsItemHandler()} />
</div>
);
}
return "";
})}
</Modal>
);
}
function InputRequiredHandler({
webSocketContext,
currentGroupTask,
groupTaskParameters,
groupTaskStepInputs,
notificationApi,
step,
taskLockedByUserId,
}) {
const { t } = useTranslation();
const [inputFields, setInputFields] = useState({});
const globalInputs = JSON.parse(currentGroupTask.GlobalInputs);
const stepInputs = JSON.parse(groupTaskStepInputs);
const getDefaultValue = (groupTaskParameter) => {
if (stepInputs !== false) {
const stepInput = stepInputs.find(
(stepInput) =>
stepInput.parameterName === groupTaskParameter.parameterName
)?.value;
if (stepInput) {
return stepInput;
}
}
if (globalInputs === undefined || !groupTaskParameter.global) return null;
const globalInputValue = globalInputs.find(
(globalInput) =>
globalInput.parameterName === groupTaskParameter.parameterName
);
return globalInputValue !== undefined ? globalInputValue.value : "";
};
const getLabel = (displayName, groupTaskParameter) => {
return groupTaskParameter.global ? (
<>
{displayName}
<Tag style={{ marginLeft: 6 }} color="purple">
{t("groupTasks.tag.global")}
</Tag>
</>
) : (
displayName
);
};
let lastChange = useRef();
let typingTimer = useRef();
const sendTypingMessage = (
currentGroupTaskId,
groupTaskParameterName,
inputValue
) => {
webSocketContext.SendSocketMessage(SentMessagesCommands.TaskLocking, {
element: `${currentGroupTaskId}-${step}-${groupTaskParameterName}`,
lockedByUserId: getUserId(),
groupTaskId: currentGroupTaskId,
parameterName: groupTaskParameterName,
value: inputValue,
step: step,
rememberId: GroupTasksStepsLockedAndUserUpdateInputValueRememberId,
});
};
const onInputChange = (
inputValue,
currentGroupTaskId,
groupTaskParameterName
) => {
setInputFields((fields) => {
return ({ ...fields }[groupTaskParameterName] =
inputValue === null ? "" : inputValue);
});
if (taskLockedByUserId !== "") return;
if (Date.now() >= lastChange.current || lastChange.current === undefined) {
lastChange.current = Date.now() + 1000;
sendTypingMessage(currentGroupTaskId, groupTaskParameterName, inputValue);
} else {
clearTimeout(typingTimer.current);
}
typingTimer.current = setTimeout(
() =>
sendTypingMessage(
currentGroupTaskId,
groupTaskParameterName,
inputValue
),
1000
);
};
return (
<Form layout="vertical" id="groupTasksViewModalRequiredInputsForm">
{groupTaskParameters.map((groupTaskParameter) => {
switch (groupTaskParameter.type) {
case "text":
return (
<Form.Item
key={"fitem-" + groupTaskParameter.parameterName}
label={getLabel(
groupTaskParameter.displayName,
groupTaskParameter
)}
required
>
<Input
id={`${currentGroupTask.Id}-${step}-${groupTaskParameter.parameterName}`}
defaultValue={getDefaultValue(groupTaskParameter)}
disabled={taskLockedByUserId !== ""}
onChange={(e) =>
onInputChange(
e.target.value,
currentGroupTask.Id,
groupTaskParameter.parameterName
)
}
value={inputFields[groupTaskParameter.parameterName]}
/>
</Form.Item>
);
case "number":
return (
<Form.Item
key={"fitem-" + groupTaskParameter.parameterName}
label={getLabel(
groupTaskParameter.displayName,
groupTaskParameter
)}
required
>
<InputNumber
id={`${currentGroupTask.Id}-${step}-${groupTaskParameter.parameterName}`}
style={{ width: "100%" }}
defaultValue={getDefaultValue(groupTaskParameter)}
disabled={taskLockedByUserId !== ""}
max={Number.MAX_SAFE_INTEGER}
onChange={(e) =>
onInputChange(
e,
currentGroupTask.Id,
groupTaskParameter.parameterName
)
}
value={inputFields[groupTaskParameter.parameterName]}
/>
</Form.Item>
);
case "textarea":
return (
<Form.Item
key={"fitem-" + groupTaskParameter.parameterName}
label={getLabel(
groupTaskParameter.displayName,
groupTaskParameter
)}
required
>
<TextArea
id={`${currentGroupTask.Id}-${step}-${groupTaskParameter.parameterName}`}
defaultValue={getDefaultValue(groupTaskParameter)}
disabled={taskLockedByUserId !== ""}
onChange={(e) =>
onInputChange(
e.target.value,
currentGroupTask.Id,
groupTaskParameter.parameterName
)
}
value={inputFields[groupTaskParameter.parameterName]}
/>
</Form.Item>
);
default:
notificationApi["error"]({
message: t(
"groupTasks.groupTasksViewModal.notification.groupTaskParameterNotImplemented.message",
{ groupTaskParameterType: groupTaskParameter.type }
),
description: t(
"groupTasks.groupTasksViewModal.notification.groupTaskParameterNotImplemented.description",
{
groupTaskParameterDisplayName: groupTaskParameter.displayName,
}
),
});
return (
<p>
Type <b>{groupTaskParameter.type}</b> not implemented. Was
specified in: <b>{groupTaskParameter.displayName}</b>
</p>
);
}
})}
</Form>
);
}
const MyStlViewer = ({ url }) => {
const memoizedCode = useMemo(() => {
return (
<StlViewer
style={{ top: 0, left: 0, height: "100%" }}
orbitControls
modelProps={{
color: Constants.COLORS.SECONDARY,
scale: 1,
positionX: 200,
positionY: 200,
}}
shadows
floorProps={{ gridWidth: 400 }}
url={url}
onError={(err) => console.error(err)}
onFinishLoading={(ev) => console.log(ev)}
/>
);
}, [url]);
return memoizedCode;
};
function GroupTaskStepLogHandler({ currentGroupTaskId, log, files }) {
const getDownloadUrl = (file) => {
return `${Constants.STATIC_CONTENT_ADDRESS}grouptasks/${currentGroupTaskId}/${file.SystemFileName}`;
};
const getTag = (file) => {
return (
<a
key={"a" + file.SystemFileName}
href={getDownloadUrl(file)}
download="test"
target="_blank"
rel="noreferrer"
>
<Tag
icon={<FileImageOutlined />}
color="processing"
style={{ marginTop: 6 }}
>
{file.OriginalFileName}
</Tag>
</a>
);
};
const fileContent = (files) => {
const nonImageFiles = [];
const imageFiles = [];
for (const file of files) {
const fileExtension = file.SystemFileName.split(".")[1];
if (
fileExtension === "png" ||
fileExtension === "jpeg" ||
fileExtension === "jpg" ||
fileExtension === "webp"
) {
imageFiles.push(file);
} else {
nonImageFiles.push(file);
}
}
const elements = [];
for (const nonImageFile of nonImageFiles) {
const fileExtension = nonImageFile.SystemFileName.split(".")[1];
if (fileExtension === "stl") {
elements.push(
<div key={"tag" + nonImageFile.SystemFileName}>
<div style={{ height: 300, backgroundColor: "#fff" }}>
<MyStlViewer url={getDownloadUrl(nonImageFile)} />
</div>
{getTag(nonImageFile)}
</div>
);
} else {
elements.push(getTag(nonImageFile));
}
}
const imageFileElements = [];
for (const imageFile of imageFiles) {
imageFileElements.push(
<Col
key={imageFile.SystemFileName}
style={{ marginTop: 6 }}
className="gutter-row"
span={6}
>
<Image width={"100%"} src={getDownloadUrl(imageFile)} />
{getTag(imageFile)}
</Col>
);
}
if (imageFileElements.length > 0) {
elements.push(
<Row key={"imgrow"} gutter={16}>
{imageFileElements}
</Row>
);
}
return elements;
};
return (
<span style={{ whiteSpace: "pre-line" }}>
{log}
{files !== "" && files !== " " && fileContent(JSON.parse(files))}
</span>
);
}