File size: 3,050 Bytes
b9fe2b4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { TaskExecutorHeartbeatItem } from '@/interfaces/database/user-setting';
import { Divider, Flex } from 'antd';
import {
  Bar,
  BarChart,
  CartesianGrid,
  Legend,
  Rectangle,
  ResponsiveContainer,
  Tooltip,
  XAxis,
} from 'recharts';

import { formatDate, formatTime } from '@/utils/date';
import dayjs from 'dayjs';
import { get } from 'lodash';
import JsonView from 'react18-json-view';
import 'react18-json-view/src/style.css';

import styles from './index.less';

interface IProps {
  data: Record<string, TaskExecutorHeartbeatItem[]>;
}

const CustomTooltip = ({ active, payload, ...restProps }: any) => {
  if (active && payload && payload.length) {
    const taskExecutorHeartbeatItem: TaskExecutorHeartbeatItem = get(
      payload,
      '0.payload',
      {},
    );
    return (
      <div className="custom-tooltip">
        <div className="bg-slate-50 p-2 rounded-md border border-indigo-100">
          <div className="font-semibold text-lg">
            {formatDate(restProps.label)}
          </div>

          <JsonView
            src={taskExecutorHeartbeatItem}
            displaySize={30}
            className="w-full max-h-[300px] break-words overflow-auto"
          />
        </div>
      </div>
    );
  }

  return null;
};

const TaskBarChat = ({ data }: IProps) => {
  return Object.entries(data).map(([key, val]) => {
    const data = val.map((x) => ({
      ...x,
      now: dayjs(x.now).valueOf(),
    }));
    const firstItem = data[0];
    const lastItem = data[data.length - 1];

    const domain = [firstItem?.now, lastItem?.now];
    return (
      <Flex key={key} className={styles.taskBar} vertical>
        <div className="flex gap-8">
          <b className={styles.taskBarTitle}>ID: {key}</b>
          <b className={styles.taskBarTitle}>Lag: {lastItem?.lag}</b>
          <b className={styles.taskBarTitle}>Pending: {lastItem?.pending}</b>
        </div>
        <ResponsiveContainer>
          <BarChart data={data}>
            <XAxis
              dataKey="now"
              type="number"
              scale={'time'}
              domain={domain}
              tickFormatter={(x) => formatTime(x)}
              allowDataOverflow
              angle={60}
              padding={{ left: 20, right: 20 }}
              tickMargin={20}
            />
            <CartesianGrid strokeDasharray="3 3" />
            <Tooltip
              wrapperStyle={{ pointerEvents: 'auto' }}
              content={<CustomTooltip></CustomTooltip>}
              trigger="click"
            />
            <Legend wrapperStyle={{ bottom: -22 }} />
            <Bar
              dataKey="done"
              fill="#2fe235"
              activeBar={<Rectangle fill="pink" stroke="blue" />}
            />
            <Bar
              dataKey="failed"
              fill="#ef3b74"
              activeBar={<Rectangle fill="gold" stroke="purple" />}
            />
          </BarChart>
        </ResponsiveContainer>
        <Divider></Divider>
      </Flex>
    );
  });
};

export default TaskBarChat;