import React, { useMemo, useEffect } from "react"; import { connect, ConnectedProps } from "react-redux"; import { useHistory } from "react-router-dom"; import { makeStyles } from "@material-ui/core/styles"; import Container from "@material-ui/core/Container"; import Grid from "@material-ui/core/Grid"; import Paper from "@material-ui/core/Paper"; import Typography from "@material-ui/core/Typography"; import Button from "@material-ui/core/Button"; import Alert from "@material-ui/lab/Alert"; import AlertTitle from "@material-ui/lab/AlertTitle"; import ArrowBackIcon from "@material-ui/icons/ArrowBack"; import { useParams } from "react-router-dom"; import QueueBreadCrumb from "../components/QueueBreadcrumb"; import { AppState } from "../store"; import { getTaskInfoAsync } from "../actions/tasksActions"; import { TaskDetailsRouteParams } from "../paths"; import { usePolling } from "../hooks"; import { listQueuesAsync } from "../actions/queuesActions"; import SyntaxHighlighter from "../components/SyntaxHighlighter"; import { durationFromSeconds, stringifyDuration, timeAgo, prettifyPayload } from "../utils"; function mapStateToProps(state: AppState) { return { loading: state.tasks.taskInfo.loading, error: state.tasks.taskInfo.error, taskInfo: state.tasks.taskInfo.data, pollInterval: state.settings.pollInterval, queues: state.queues.data.map((q) => q.name), // FIXME: This data may not be available }; } const connector = connect(mapStateToProps, { getTaskInfoAsync, listQueuesAsync, }); const useStyles = makeStyles((theme) => ({ container: { paddingTop: theme.spacing(2), }, alert: { borderTopLeftRadius: 0, borderTopRightRadius: 0, }, paper: { padding: theme.spacing(2), marginTop: theme.spacing(2), }, breadcrumbs: { marginBottom: theme.spacing(2), }, infoRow: { display: "flex", alignItems: "center", paddingTop: theme.spacing(1), }, infoKeyCell: { width: "140px", }, infoValueCell: { width: "auto", }, footer: { paddingTop: theme.spacing(3), paddingBottom: theme.spacing(3), }, })); type Props = ConnectedProps; function TaskDetailsView(props: Props) { const classes = useStyles(); const { qname, taskId } = useParams(); const { getTaskInfoAsync, pollInterval, listQueuesAsync, taskInfo } = props; const history = useHistory(); const fetchTaskInfo = useMemo(() => { return () => { getTaskInfoAsync(qname, taskId); }; }, [qname, taskId, getTaskInfoAsync]); usePolling(fetchTaskInfo, pollInterval); // Fetch queues data to populate props.queues useEffect(() => { listQueuesAsync(); }, [listQueuesAsync]); return ( {props.error ? ( Error {props.error} ) : ( Task Info
ID:{" "} {taskInfo?.id}
Type:{" "} {taskInfo?.type}
State:{" "} {taskInfo?.state}
Queue:{" "} {taskInfo?.queue}
Retry:{" "} {taskInfo?.retried}/{taskInfo?.max_retry}
Last Failure:{" "} {taskInfo?.last_failed_at ? ( {taskInfo?.error_message} ({taskInfo?.last_failed_at}) ) : ( - )}
Next Process Time:{" "} {taskInfo?.next_process_at ? ( {taskInfo?.next_process_at} ) : ( - )}
Timeout:{" "} {taskInfo?.timeout_seconds ? ( {taskInfo?.timeout_seconds} seconds ) : ( - )}
Deadline:{" "} {taskInfo?.deadline ? ( {taskInfo?.deadline} ) : ( - )}
Payload:{" "}
{taskInfo?.payload && ( {prettifyPayload(taskInfo.payload)} )}
{ /* Completed Task Only */ taskInfo?.state === "completed" && ( <>
Completed:{" "}
{timeAgo(taskInfo.completed_at)} ( {taskInfo.completed_at})
Result:{" "}
{prettifyPayload(taskInfo.result)}
TTL:{" "} {taskInfo.ttl_seconds > 0 ? `${stringifyDuration( durationFromSeconds(taskInfo.ttl_seconds) )} left` : "expired"}
) }
)}
); } export default connector(TaskDetailsView);