Skip to content

Commit 32a8c09

Browse files
authored
HDDS-11160. Improve Insights page UI (#7327)
1 parent 782ad62 commit 32a8c09

28 files changed

Lines changed: 2587 additions & 441 deletions

hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/api/db.json

Lines changed: 261 additions & 382 deletions
Large diffs are not rendered by default.

hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { Switch as AntDSwitch, Layout } from 'antd';
2222
import NavBar from './components/navBar/navBar';
2323
import NavBarV2 from '@/v2/components/navBar/navBar';
2424
import Breadcrumbs from './components/breadcrumbs/breadcrumbs';
25+
import BreadcrumbsV2 from '@/v2/components/breadcrumbs/breadcrumbs';
2526
import { HashRouter as Router, Switch, Route, Redirect } from 'react-router-dom';
2627
import { routes } from '@/routes';
2728
import { routesV2 } from '@/v2/routes-v2';
@@ -70,7 +71,7 @@ class App extends React.Component<Record<string, object>, IAppState> {
7071
<Layout className={layoutClass}>
7172
<Header>
7273
<div style={{ margin: '16px 0', display: 'flex', justifyContent: 'space-between' }}>
73-
<Breadcrumbs />
74+
{(enableNewUI) ? <BreadcrumbsV2 /> : <Breadcrumbs />}
7475
<AntDSwitch
7576
disabled={true}
7677
checkedChildren={<div style={{ paddingLeft: '2px' }}>New UI</div>}

hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/constants/breadcrumbs.constants.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@ export const breadcrumbNameMap: IBreadcrumbNameMap = {
3131
'/Insights': 'Insights',
3232
'/DiskUsage': 'Disk Usage',
3333
'/Heatmap': 'Heatmap',
34-
'/Om': 'Om',
34+
'/Om': 'Om'
3535
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import React from 'react';
20+
import { Breadcrumb } from 'antd';
21+
import { HomeOutlined } from '@ant-design/icons';
22+
import { Link, useLocation } from 'react-router-dom';
23+
24+
import { breadcrumbNameMap } from '@/v2/constants/breadcrumbs.constants';
25+
26+
const Breadcrumbs: React.FC<{}> = () => {
27+
const location = useLocation();
28+
//Split and filter to remove empty strings
29+
const pathSnippets = location.pathname.split('/').filter(i => i);
30+
31+
const extraBreadcrumbItems = pathSnippets.map((_: string, index: number) => {
32+
const url = `/${pathSnippets.slice(0, index + 1).join('/')}`;
33+
return (
34+
<Breadcrumb.Item key={url}>
35+
<Link to={url}>
36+
{breadcrumbNameMap[url]}
37+
</Link>
38+
</Breadcrumb.Item>
39+
)
40+
});
41+
42+
const breadcrumbItems = [(
43+
<Breadcrumb.Item key='home'>
44+
<Link to='/'><HomeOutlined /></Link>
45+
</Breadcrumb.Item>
46+
)].concat(extraBreadcrumbItems);
47+
48+
return (
49+
<Breadcrumb>
50+
{breadcrumbItems}
51+
</Breadcrumb>
52+
);
53+
}
54+
55+
export default Breadcrumbs;

hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/overviewCard/overviewSummaryCard.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type OverviewTableCardProps = {
3939
data?: string | React.ReactElement;
4040
linkToUrl?: string;
4141
showHeader?: boolean;
42+
state?: Record<string, any>;
4243
}
4344

4445
// ------------- Styles -------------- //
@@ -63,15 +64,18 @@ const OverviewSummaryCard: React.FC<OverviewTableCardProps> = ({
6364
columns = [],
6465
tableData = [],
6566
linkToUrl = '',
66-
showHeader = false
67+
showHeader = false,
68+
state
6769
}) => {
68-
6970
const titleElement = (linkToUrl)
7071
? (
7172
<div className='card-title-div'>
7273
{title}
7374
<Link
74-
to={linkToUrl}
75+
to={{
76+
pathname: linkToUrl,
77+
state: state
78+
}}
7579
style={{
7680
fontWeight: 400
7781
}}>View Insights</Link>

hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/duPieChart/duPieChart.tsx renamed to hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/plots/duPieChart.tsx

File renamed without changes.
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import React from 'react';
20+
import filesize from 'filesize';
21+
import { EChartsOption } from 'echarts';
22+
23+
import EChart from '@/v2/components/eChart/eChart';
24+
import { ContainerCountResponse, ContainerPlotData } from '@/v2/types/insights.types';
25+
26+
type ContainerSizeDistributionProps = {
27+
containerCountResponse: ContainerCountResponse[];
28+
containerSizeError: string | undefined;
29+
}
30+
31+
const size = filesize.partial({ standard: 'iec', round: 0 });
32+
33+
const ContainerSizeDistribution: React.FC<ContainerSizeDistributionProps> = ({
34+
containerCountResponse,
35+
containerSizeError
36+
}) => {
37+
38+
const [containerPlotData, setContainerPlotData] = React.useState<ContainerPlotData>({
39+
containerCountValues: [],
40+
containerCountMap: new Map<number, number>()
41+
});
42+
43+
function updatePlotData() {
44+
const containerCountMap: Map<number, number> = containerCountResponse.reduce(
45+
(map: Map<number, number>, current) => {
46+
const containerSize = current.containerSize;
47+
const oldCount = map.get(containerSize) ?? 0;
48+
map.set(containerSize, oldCount + current.count);
49+
return map;
50+
},
51+
new Map<number, number>()
52+
);
53+
54+
const containerCountValues = Array.from(containerCountMap.keys()).map(value => {
55+
const upperbound = size(value);
56+
const upperboundPwr = Math.log2(value);
57+
58+
const lowerbound = upperboundPwr > 10 ? size(2 ** (upperboundPwr - 1)) : size(0);
59+
return `${lowerbound} - ${upperbound}`;
60+
});
61+
62+
setContainerPlotData({
63+
containerCountValues: containerCountValues,
64+
containerCountMap: containerCountMap
65+
});
66+
}
67+
68+
React.useEffect(() => {
69+
updatePlotData();
70+
}, []);
71+
72+
const { containerCountMap, containerCountValues } = containerPlotData;
73+
74+
const containerPlotOptions: EChartsOption = {
75+
tooltip: {
76+
trigger: 'item',
77+
formatter: ({ data }) => {
78+
return `Size Range: <strong>${data.name}</strong><br>Count: <strong>${data.value}</strong>`
79+
}
80+
},
81+
legend: {
82+
orient: 'vertical',
83+
left: 'right'
84+
},
85+
series: {
86+
type: 'pie',
87+
radius: '50%',
88+
data: Array.from(containerCountMap?.values() ?? []).map((value, idx) => {
89+
return {
90+
value: value,
91+
name: containerCountValues[idx] ?? ''
92+
}
93+
}),
94+
},
95+
graphic: (containerSizeError) ? {
96+
type: 'group',
97+
left: 'center',
98+
top: 'middle',
99+
z: 100,
100+
children: [
101+
{
102+
type: 'rect',
103+
left: 'center',
104+
top: 'middle',
105+
z: 100,
106+
shape: {
107+
width: 500,
108+
height: 500
109+
},
110+
style: {
111+
fill: 'rgba(256, 256, 256, 0.5)'
112+
}
113+
},
114+
{
115+
type: 'rect',
116+
left: 'center',
117+
top: 'middle',
118+
z: 100,
119+
shape: {
120+
width: 500,
121+
height: 40
122+
},
123+
style: {
124+
fill: '#FC909B'
125+
}
126+
},
127+
{
128+
type: 'text',
129+
left: 'center',
130+
top: 'middle',
131+
z: 100,
132+
style: {
133+
text: `No data available. ${containerSizeError}`,
134+
font: '20px sans-serif'
135+
}
136+
}
137+
]
138+
} : undefined
139+
}
140+
141+
return (<>
142+
<EChart option={containerPlotOptions} style={{
143+
width: '30vw',
144+
height: '65vh'
145+
}} />
146+
</>)
147+
}
148+
149+
export default ContainerSizeDistribution;

0 commit comments

Comments
 (0)