- Major Progress Commit
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -1,27 +1,12 @@
|
||||
import React, {useCallback, useEffect, useState} from 'react';
|
||||
import moment from "moment";
|
||||
import axios from 'axios';
|
||||
import {Card, Space, Table} from 'antd';
|
||||
import {Badge, Card, Space, Table, Tag} from 'antd';
|
||||
import {gql, useQuery} from "@apollo/client";
|
||||
import {DateTimeFormatterFunction} from "../../utils/DateFormatter";
|
||||
import {isEmpty} from "lodash";
|
||||
import {Bar, BarChart, CartesianGrid, Legend, Tooltip, YAxis} from "recharts";
|
||||
|
||||
|
||||
const transformDataForChart = (durations) => {
|
||||
const output = {};
|
||||
// output.amt = durations.total;
|
||||
// output.name = 'Total';
|
||||
durations.summations.forEach((summation) => {
|
||||
output[summation.status] = summation.value;
|
||||
});
|
||||
return [output];
|
||||
}
|
||||
const getColor = (key) => {
|
||||
// Generate a random color
|
||||
const randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
|
||||
return randomColor;
|
||||
};
|
||||
require('./job-lifecycle.styles.scss');
|
||||
|
||||
export function JobLifecycleComponent({job, ...rest}) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -124,34 +109,92 @@ export function JobLifecycleComponent({job, ...rest}) {
|
||||
{!loading ? (
|
||||
lifecycleData && lifecycleData.lifecycle && lifecycleData.durations ? (
|
||||
<Space direction='vertical' style={{width: '100%'}}>
|
||||
<Space direction='horizontal' style={{width: '100%'}} align='start'>
|
||||
<Card type='inner' title='Durations'>
|
||||
<BarChart
|
||||
width={500}
|
||||
height={500}
|
||||
data={transformDataForChart(lifecycleData.durations)}
|
||||
margin={{
|
||||
top: 20,
|
||||
right: 30,
|
||||
left: 20,
|
||||
bottom: 5,
|
||||
}}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3"/>
|
||||
<YAxis />
|
||||
<Tooltip/>
|
||||
<Legend/>
|
||||
{
|
||||
Object.keys(transformDataForChart(lifecycleData.durations)[0]).map((key) => {
|
||||
return (
|
||||
<Bar dataKey={key} stackId="a" fill={getColor(key)}/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</BarChart>
|
||||
<Card
|
||||
type='inner'
|
||||
title={(
|
||||
<Space direction='horizontal' size='small'>
|
||||
<Badge status='processing' count={lifecycleData.durations.totalStatuses} />
|
||||
Statuses
|
||||
</Space>
|
||||
|
||||
)}
|
||||
style={{width: '100%'}}
|
||||
>
|
||||
<div id="bar-container" style={{
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
height: '100px',
|
||||
textAlign: 'center',
|
||||
borderRadius: '5px',
|
||||
borderWidth: '5px',
|
||||
borderStyle: 'solid',
|
||||
borderColor: '#f0f2f5',
|
||||
margin: 0,
|
||||
padding: 0
|
||||
}}>
|
||||
{lifecycleData.durations.summations.map((key, index, array) => {
|
||||
const isFirst = index === 0;
|
||||
const isLast = index === array.length - 1;
|
||||
|
||||
return (
|
||||
<div key={key.status} style={{
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
borderTop: '1px solid #f0f2f5',
|
||||
borderBottom: '1px solid #f0f2f5',
|
||||
borderLeft: isFirst ? '1px solid #f0f2f5' : undefined,
|
||||
borderRight: isLast ? '1px solid #f0f2f5' : undefined,
|
||||
borderBottomLeftRadius: isFirst ? '5px' : undefined,
|
||||
borderTopLeftRadius: isFirst ? '5px' : undefined,
|
||||
borderBottomRightRadius: isLast ? '5px' : undefined,
|
||||
borderTopRightRadius: isLast ? '5px' : undefined,
|
||||
backgroundColor: key.color,
|
||||
width: `${key.percentage}%`
|
||||
}}
|
||||
aria-label={`${key.status} | ${key.roundedPercentage} | ${key.humanReadable}`}
|
||||
title={`${key.status} | ${key.roundedPercentage} | ${key.humanReadable}`}
|
||||
>
|
||||
{Math.round(key.percentage)}%
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<Card type='inner' title='Legend' style={{marginTop: '10px'}}>
|
||||
<div>
|
||||
{lifecycleData.durations.summations.map((key) => (
|
||||
<Tag color={key.color} style={{width: '13vh', padding: '4px', margin: '4px'}}>
|
||||
<div
|
||||
aria-label={`${key.status} | ${key.roundedPercentage} | ${key.humanReadable}`}
|
||||
title={`${key.status} | ${key.roundedPercentage} | ${key.humanReadable}`}
|
||||
style={{
|
||||
backgroundColor: '#f0f2f5',
|
||||
color: '#000',
|
||||
padding: '4px',
|
||||
textAlign: 'center'
|
||||
}}>
|
||||
{key.status} ({key.roundedPercentage})
|
||||
</div>
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</Space>
|
||||
<Card type='inner' title='Transitions'>
|
||||
<Card style={{marginTop: '10px'}}>
|
||||
<span style={{fontWeight: 'bold'}}>Accumulated Time:</span> {lifecycleData.durations.humanReadableTotal}
|
||||
</Card>
|
||||
</Card>
|
||||
<Card type='inner' title={(
|
||||
<>
|
||||
<Space direction="horizontal" size="small">
|
||||
<Badge status='processing' count={lifecycleData.lifecycle.length} />
|
||||
Transitions
|
||||
</Space>
|
||||
</>
|
||||
)}>
|
||||
|
||||
<Table columns={columns} dataSource={lifecycleData.lifecycle}/>
|
||||
</Card>
|
||||
</Space>
|
||||
|
||||
@@ -289,13 +289,6 @@ export function JobsDetailPage({
|
||||
form={form}
|
||||
/>
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane
|
||||
forceRender
|
||||
tab={<span><BarsOutlined />Lifecycle</span>}
|
||||
key="lifecycle"
|
||||
>
|
||||
<JobLifecycleComponent job={job} refetch={refetch} form={form}/>
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane
|
||||
forceRender
|
||||
tab={
|
||||
@@ -341,7 +334,15 @@ export function JobsDetailPage({
|
||||
>
|
||||
<JobsDetailLaborContainer job={job} jobId={job.id} />
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane
|
||||
<Tabs.TabPane
|
||||
forceRender
|
||||
tab={<span><BarsOutlined />Lifecycle</span>}
|
||||
key="lifecycle"
|
||||
>
|
||||
<JobLifecycleComponent job={job} refetch={refetch} form={form}/>
|
||||
</Tabs.TabPane>
|
||||
|
||||
<Tabs.TabPane
|
||||
forceRender
|
||||
tab={
|
||||
<span>
|
||||
|
||||
Reference in New Issue
Block a user