515 lines
17 KiB
JavaScript
515 lines
17 KiB
JavaScript
import {
|
|
ArrowLeftOutlined,
|
|
ArrowRightOutlined,
|
|
ReloadOutlined,
|
|
} from "@ant-design/icons";
|
|
import { Card, Checkbox, Popover, Space, Spin, Tooltip } from "antd";
|
|
import { useContext, useEffect, useState } from "react";
|
|
import {
|
|
Constants,
|
|
FormatDatetime,
|
|
WebSocketContext,
|
|
getUserSessionFromLocalStorage,
|
|
handleUnauthorizedStatus,
|
|
} from "../../utils";
|
|
import { Link } from "react-router-dom";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
export default function LogCard({ type }) {
|
|
const webSocketContext = useContext(WebSocketContext);
|
|
const { t, i18n } = useTranslation();
|
|
const [checkboxInfoChecked, setCheckboxInfoChecked] = useState(true);
|
|
const [checkboxErrorChecked, setCheckboxErrorChecked] = useState(true);
|
|
|
|
const getDate = () => {
|
|
const today = new Date();
|
|
|
|
return `${today.getDate()}-${today.getMonth() + 1}-${today.getFullYear()}`;
|
|
};
|
|
|
|
const [logData, setLogData] = useState({ Logs: [], Dates: [] });
|
|
const [selectedDate, setSelectedDate] = useState(getDate());
|
|
const [loadingSpinner, setLoadingSpinner] = useState(true);
|
|
|
|
useEffect(() => {
|
|
loadLogs(selectedDate);
|
|
}, [selectedDate]);
|
|
|
|
const getColorCode = (index) => {
|
|
const colorCodes = ["#3498db", "#9b59b6", "#1abc9c"];
|
|
const colorIndex = index % colorCodes.length;
|
|
return colorCodes[colorIndex];
|
|
};
|
|
|
|
const ColoredSpanItem = ({ dataLogs, splittedMessage, children }) => {
|
|
const logDataIndex = dataLogs.LogData.findIndex(
|
|
(data) => data.Type === splittedMessage.replace(new RegExp("%", "g"), "")
|
|
);
|
|
|
|
if (logDataIndex !== -1) {
|
|
return (
|
|
<span style={{ color: getColorCode(logDataIndex) }}>
|
|
{children === undefined ? (
|
|
dataLogs.LogData[logDataIndex].Value
|
|
) : (
|
|
<>{children}</>
|
|
)}{" "}
|
|
</span>
|
|
);
|
|
}
|
|
return <></>;
|
|
};
|
|
|
|
const getGroupTaskStepName = (groupTaskStep) => {
|
|
const foundName = webSocketContext.CategoryGroups.find(
|
|
(categoryGroup) =>
|
|
categoryGroup.category ===
|
|
webSocketContext.GroupTasks.find(
|
|
(groupTask) => groupTask.Id === groupTaskStep.GroupTasksId
|
|
)?.Category
|
|
)?.groups.find(
|
|
(groups) =>
|
|
groups.id ===
|
|
webSocketContext.GroupTasks.find(
|
|
(groupTask) => groupTask.Id === groupTaskStep.GroupTasksId
|
|
).GroupId
|
|
).tasks[groupTaskStep.Step - 1];
|
|
|
|
return foundName !== undefined ? foundName.name : groupTaskStep.Id;
|
|
};
|
|
|
|
const loadLogs = (date) => {
|
|
setLoadingSpinner(true);
|
|
|
|
fetch(
|
|
`${Constants.API_ADDRESS}/log?type=${
|
|
type === "grouptasks" ? "g" : "s"
|
|
}&date=${date}&lang=${i18n.language}`,
|
|
{
|
|
method: "GET",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"X-Authorization": getUserSessionFromLocalStorage(),
|
|
},
|
|
}
|
|
)
|
|
.then((res) => {
|
|
handleUnauthorizedStatus(res.status);
|
|
return res.json();
|
|
})
|
|
.then((data) => {
|
|
setLoadingSpinner(false);
|
|
|
|
if (data.Logs === null) {
|
|
data.Logs = [];
|
|
} else {
|
|
for (let i = 0; i < data.Logs.length; i++) {
|
|
let items = [];
|
|
|
|
if (data.Logs[i].Message === "") {
|
|
items.push(
|
|
<span style={{ color: "#e74c3c" }}>
|
|
Message not found.{" "}
|
|
{data.Logs[i].LogData.length > 0 && (
|
|
<>
|
|
Given Args:{" "}
|
|
{data.Logs[i].LogData.map((data) => (
|
|
<span>
|
|
{data.Type}:{data.Value}
|
|
</span>
|
|
))}
|
|
</>
|
|
)}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
let splittedMessage = data.Logs[i].Message.split(" ");
|
|
|
|
for (let s = 0; s < splittedMessage.length; s++) {
|
|
if (splittedMessage[s].includes("%")) {
|
|
if (splittedMessage[s] === "%userId%") {
|
|
const foundData = data.Logs[i].LogData.find(
|
|
(data) => data.Type === "userId"
|
|
);
|
|
|
|
if (foundData !== undefined) {
|
|
const foundUser = webSocketContext.AllUsers.find(
|
|
(user) => user.Id === foundData.Value
|
|
);
|
|
|
|
items.push(
|
|
<span key={s} style={{ color: Constants.COLORS.PRIMARY }}>
|
|
{foundUser !== undefined
|
|
? foundUser.Username
|
|
: foundData.Value}{" "}
|
|
</span>
|
|
);
|
|
} else {
|
|
items.push(
|
|
<ColoredSpanItem
|
|
key={s}
|
|
dataLogs={data.Logs[i]}
|
|
splittedMessage={splittedMessage[s]}
|
|
/>
|
|
);
|
|
}
|
|
} else if (splittedMessage[s] === "%groupTaskId%") {
|
|
const foundData = data.Logs[i].LogData.find(
|
|
(data) => data.Type === "groupTaskId"
|
|
);
|
|
|
|
if (foundData !== undefined) {
|
|
const foundGroupTask = webSocketContext.GroupTasks.find(
|
|
(groupTask) => groupTask.Id === foundData.Value
|
|
);
|
|
|
|
items.push(
|
|
<ColoredSpanItem
|
|
key={s}
|
|
dataLogs={data.Logs[i]}
|
|
splittedMessage={splittedMessage[s]}
|
|
children={
|
|
<Popover
|
|
content={
|
|
<div>
|
|
<span style={{ fontWeight: "bold" }}>ID: </span>
|
|
<Link
|
|
to={`${Constants.ROUTE_PATHS.GROUP_TASKS_VIEW}${foundData.Value}`}
|
|
>
|
|
{foundData.Value}
|
|
</Link>
|
|
</div>
|
|
}
|
|
title={t("logCard.popover.groupTaskId.title")}
|
|
trigger="click"
|
|
>
|
|
<span style={{ cursor: "pointer" }}>
|
|
{foundGroupTask !== undefined
|
|
? foundGroupTask.GroupName
|
|
: foundData.Value}
|
|
</span>
|
|
</Popover>
|
|
}
|
|
/>
|
|
);
|
|
} else {
|
|
items.push(
|
|
<ColoredSpanItem
|
|
key={s}
|
|
dataLogs={data.Logs[i]}
|
|
splittedMessage={splittedMessage[s]}
|
|
/>
|
|
);
|
|
}
|
|
} else if (splittedMessage[s] === "%taskStepId%") {
|
|
const foundData = data.Logs[i].LogData.find(
|
|
(data) => data.Type === "taskStepId"
|
|
);
|
|
|
|
if (foundData !== undefined) {
|
|
const foundGroupTaskStep =
|
|
webSocketContext.GroupTasksSteps.find(
|
|
(step) => step.Id === foundData.Value
|
|
);
|
|
|
|
items.push(
|
|
<ColoredSpanItem
|
|
key={s}
|
|
dataLogs={data.Logs[i]}
|
|
splittedMessage={splittedMessage[s]}
|
|
children={
|
|
<Popover
|
|
content={
|
|
<div>
|
|
<span style={{ fontWeight: "bold" }}>ID: </span>
|
|
<span>
|
|
{foundGroupTaskStep !== undefined
|
|
? foundGroupTaskStep.Id
|
|
: foundData.Value}
|
|
</span>
|
|
</div>
|
|
}
|
|
title={t("logCard.popover.groupTaskStep.title")}
|
|
trigger="click"
|
|
>
|
|
{" "}
|
|
<span style={{ cursor: "pointer" }}>
|
|
{foundGroupTaskStep !== undefined
|
|
? getGroupTaskStepName(foundGroupTaskStep)
|
|
: foundData.Value}
|
|
</span>
|
|
</Popover>
|
|
}
|
|
/>
|
|
);
|
|
} else {
|
|
items.push(
|
|
<ColoredSpanItem
|
|
key={s}
|
|
dataLogs={data.Logs[i]}
|
|
splittedMessage={splittedMessage[s]}
|
|
/>
|
|
);
|
|
}
|
|
} else if (splittedMessage[s] === "%roleId%") {
|
|
const foundData = data.Logs[i].LogData.find(
|
|
(data) => data.Type === "roleId"
|
|
);
|
|
|
|
if (foundData !== undefined) {
|
|
const foundRole = webSocketContext.AllRoles.find(
|
|
(role) => role.Id === foundData.Value
|
|
);
|
|
|
|
items.push(
|
|
<ColoredSpanItem
|
|
key={s}
|
|
dataLogs={data.Logs[i]}
|
|
splittedMessage={splittedMessage[s]}
|
|
children={
|
|
<Popover
|
|
content={
|
|
<div>
|
|
<span style={{ fontWeight: "bold" }}>ID: </span>
|
|
<span>{foundData.Value}</span>
|
|
</div>
|
|
}
|
|
title={t("logCard.popover.role.title")}
|
|
trigger="click"
|
|
>
|
|
{" "}
|
|
<span style={{ cursor: "pointer" }}>
|
|
{foundRole !== undefined
|
|
? foundRole.DisplayName
|
|
: foundData.Value}
|
|
</span>
|
|
</Popover>
|
|
}
|
|
/>
|
|
);
|
|
} else {
|
|
items.push(
|
|
<ColoredSpanItem
|
|
key={s}
|
|
dataLogs={data.Logs[i]}
|
|
splittedMessage={splittedMessage[s]}
|
|
/>
|
|
);
|
|
}
|
|
} else if (splittedMessage[s] === "%groupId%") {
|
|
const foundDataCategory = data.Logs[i].LogData.find(
|
|
(data) => data.Type === "category"
|
|
);
|
|
|
|
const foundDataGroupId = data.Logs[i].LogData.find(
|
|
(data) => data.Type === "groupId"
|
|
);
|
|
|
|
if (
|
|
foundDataCategory !== undefined &&
|
|
foundDataGroupId !== undefined
|
|
) {
|
|
const foundGroup = webSocketContext.CategoryGroups.find(
|
|
(categoryGroup) =>
|
|
categoryGroup.category === foundDataCategory.Value
|
|
).groups.find(
|
|
(group) => group.id === foundDataGroupId.Value
|
|
);
|
|
|
|
items.push(
|
|
<ColoredSpanItem
|
|
key={s}
|
|
dataLogs={data.Logs[i]}
|
|
splittedMessage={splittedMessage[s]}
|
|
children={
|
|
<Popover
|
|
content={
|
|
<div>
|
|
<span style={{ fontWeight: "bold" }}>ID: </span>
|
|
<span>{foundDataGroupId.Value}</span>
|
|
</div>
|
|
}
|
|
title={t("logCard.popover.groupId.title")}
|
|
trigger="click"
|
|
>
|
|
{" "}
|
|
<span style={{ cursor: "pointer" }}>
|
|
{foundGroup !== undefined
|
|
? foundGroup.name
|
|
: foundDataGroupId.Value}
|
|
</span>
|
|
</Popover>
|
|
}
|
|
/>
|
|
);
|
|
} else {
|
|
items.push(
|
|
<ColoredSpanItem
|
|
key={s}
|
|
dataLogs={data.Logs[i]}
|
|
splittedMessage={splittedMessage[s]}
|
|
/>
|
|
);
|
|
}
|
|
} else {
|
|
items.push(
|
|
<ColoredSpanItem
|
|
key={s}
|
|
dataLogs={data.Logs[i]}
|
|
splittedMessage={splittedMessage[s]}
|
|
/>
|
|
);
|
|
}
|
|
} else {
|
|
items.push(<span key={s}>{splittedMessage[s]} </span>);
|
|
}
|
|
}
|
|
|
|
data.Logs[i].Message = items;
|
|
}
|
|
}
|
|
|
|
setLogData(data);
|
|
})
|
|
.catch((errStatus) => console.log("error", errStatus));
|
|
};
|
|
|
|
const inBrackets = (content, contentColor) => {
|
|
return (
|
|
<>
|
|
<span style={{ color: "#95a5a6" }}>[</span>
|
|
<span style={{ color: contentColor }}>{content}</span>
|
|
<span style={{ color: "#95a5a6" }}>] </span>
|
|
</>
|
|
);
|
|
};
|
|
|
|
const getMessageType = (logType) => {
|
|
if (logType === Constants.SYSTEM_LOG_TYPE.INFO) {
|
|
return inBrackets("INFO", "#27ae60");
|
|
}
|
|
if (logType === Constants.SYSTEM_LOG_TYPE.DEBUG) {
|
|
return inBrackets("DEB", "#e67e22");
|
|
}
|
|
if (logType === Constants.SYSTEM_LOG_TYPE.ERROR) {
|
|
return inBrackets("ERR", "#e74c3c");
|
|
}
|
|
return "";
|
|
};
|
|
|
|
return (
|
|
<Card
|
|
title={selectedDate}
|
|
extra={
|
|
<Space>
|
|
<Checkbox
|
|
checked={checkboxInfoChecked}
|
|
onChange={(e) => setCheckboxInfoChecked(e.target.checked)}
|
|
>
|
|
{t("logCard.card.checkbox.info")}
|
|
</Checkbox>
|
|
<Checkbox
|
|
checked={checkboxErrorChecked}
|
|
onChange={(e) => setCheckboxErrorChecked(e.target.checked)}
|
|
>
|
|
{t("logCard.card.checkbox.error")}
|
|
</Checkbox>
|
|
|
|
{logData.Dates.findIndex((date) => date === selectedDate) > 0 ? (
|
|
<Tooltip title={t("logCard.tooltip.previous")}>
|
|
<ArrowLeftOutlined
|
|
onClick={() =>
|
|
setSelectedDate(
|
|
logData.Dates[
|
|
logData.Dates.findIndex((date) => date === selectedDate) -
|
|
1
|
|
]
|
|
)
|
|
}
|
|
/>
|
|
</Tooltip>
|
|
) : (
|
|
<ArrowLeftOutlined
|
|
style={{
|
|
color: "rgba(0, 0, 0, 0.25)",
|
|
cursor: "not-allowed",
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
{logData.Dates.findIndex((date) => date === selectedDate) + 1 <
|
|
logData.Dates.length ? (
|
|
<Tooltip title={t("logCard.tooltip.next")}>
|
|
<ArrowRightOutlined
|
|
onClick={() =>
|
|
setSelectedDate(
|
|
logData.Dates[
|
|
logData.Dates.findIndex((date) => date === selectedDate) +
|
|
1
|
|
]
|
|
)
|
|
}
|
|
/>
|
|
</Tooltip>
|
|
) : (
|
|
<ArrowRightOutlined
|
|
style={{
|
|
color: "rgba(0, 0, 0, 0.25)",
|
|
cursor: "not-allowed",
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
<Tooltip title={t("logCard.tooltip.reload")}>
|
|
<ReloadOutlined onClick={() => loadLogs(selectedDate)} />
|
|
</Tooltip>
|
|
</Space>
|
|
}
|
|
style={{
|
|
height: "90vh",
|
|
overflow: "hidden",
|
|
overflowWrap: "break-word",
|
|
width: "100%",
|
|
}}
|
|
>
|
|
{!loadingSpinner ? (
|
|
<div style={{ height: "80vh", overflowY: "scroll", paddingRight: 6 }}>
|
|
{logData.Logs.filter((log) => {
|
|
return (
|
|
(log.Type === 0 && checkboxInfoChecked) ||
|
|
(log.Type === 1 && checkboxErrorChecked)
|
|
);
|
|
}).map((log, i) => {
|
|
if (
|
|
(log.Type === 0 && !checkboxInfoChecked) ||
|
|
(log.Type === 1 && !checkboxErrorChecked)
|
|
) {
|
|
return "";
|
|
}
|
|
|
|
return (
|
|
<div key={i}>
|
|
{inBrackets(FormatDatetime(log.Time), "#7f8c8d")}{" "}
|
|
{getMessageType(log.Type)}
|
|
{log.Message}
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
) : (
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
height: "80vh",
|
|
}}
|
|
>
|
|
<Spin size="large"></Spin>
|
|
</div>
|
|
)}
|
|
</Card>
|
|
);
|
|
}
|