File size: 3,050 Bytes
f36a767
d684338
 
 
 
 
f36a767
 
d684338
 
f36a767
d684338
 
f36a767
 
 
9efd53f
 
 
d684338
 
 
f36a767
d684338
 
f36a767
d684338
f36a767
 
 
 
 
d684338
9efd53f
 
 
 
 
 
 
 
 
 
 
f36a767
d684338
 
 
 
 
 
 
 
f36a767
 
 
 
 
 
 
 
983d047
f36a767
 
 
 
983d047
 
f36a767
 
9efd53f
f36a767
 
 
 
 
 
 
 
 
 
 
 
9efd53f
 
 
 
 
f36a767
 
 
9efd53f
f36a767
 
 
 
9efd53f
f36a767
 
 
 
 
 
 
 
d684338
 
 
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;