Skip to content

Commit

Permalink
[CE-337] Implement overview page in react theme
Browse files Browse the repository at this point in the history
Implement overview for cluster & host in operator dashboard.

Change-Id: Ic6f2409e97c15b11c851b22fbdd75ed72bdfeb0f
Signed-off-by: Haitao Yue <hightall@me.com>
  • Loading branch information
hightall committed Apr 18, 2018
1 parent 93ab0e1 commit cccd958
Show file tree
Hide file tree
Showing 12 changed files with 834 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/themes/react/static/dashboard/src/common/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export const getRouterData = app => {
component: dynamicWrapper(app, ['user'], () => import('../layouts/BasicLayout')),
},
'/overview': {
component: dynamicWrapper(app, [], () => import('../routes/Overview')),
component: dynamicWrapper(app, ['overview'], () => import('../routes/Overview')),
},
'/host': {
component: dynamicWrapper(app, [], () => import('../routes/Host')),
Expand Down
258 changes: 258 additions & 0 deletions src/themes/react/static/dashboard/src/components/Charts/Pie/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
/*
SPDX-License-Identifier: Apache-2.0
*/
import React, { Component } from 'react';
import { Chart, Tooltip, Geom, Coord } from 'bizcharts';
import { DataView } from '@antv/data-set';
import { Divider } from 'antd';
import classNames from 'classnames';
import ReactFitText from 'react-fittext';
import Debounce from 'lodash-decorators/debounce';
import Bind from 'lodash-decorators/bind';
import autoHeight from '../autoHeight';

import styles from './index.less';

/* eslint react/no-danger:0 */
@autoHeight()
export default class Pie extends Component {
state = {
legendData: [],
legendBlock: false,
};

componentDidMount() {
this.getLengendData();
this.resize();
window.addEventListener('resize', this.resize);
}

componentWillReceiveProps(nextProps) {
if (this.props.data !== nextProps.data) {
// because of charts data create when rendered
// so there is a trick for get rendered time
this.setState(
{
legendData: [...this.state.legendData],
},
() => {
this.getLengendData();
}
);
}
}

componentWillUnmount() {
window.removeEventListener('resize', this.resize);
this.resize.cancel();
}

getG2Instance = chart => {
this.chart = chart;
};

// for custom lengend view
getLengendData = () => {
if (!this.chart) return;
const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
const items = geom.get('dataArray') || []; // 获取图形对应的

const legendData = items.map(item => {
/* eslint no-underscore-dangle:0 */
const origin = item[0]._origin;
origin.color = item[0].color;
origin.checked = true;
return origin;
});

this.setState({
legendData,
});
};

// for window resize auto responsive legend
@Bind()
@Debounce(300)
resize() {
const { hasLegend } = this.props;
if (!hasLegend || !this.root) {
window.removeEventListener('resize', this.resize);
return;
}
if (this.root.parentNode.clientWidth <= 380) {
if (!this.state.legendBlock) {
this.setState({
legendBlock: true,
});
}
} else if (this.state.legendBlock) {
this.setState({
legendBlock: false,
});
}
}

handleRoot = n => {
this.root = n;
};

handleLegendClick = (item, i) => {
const newItem = item;
newItem.checked = !newItem.checked;

const { legendData } = this.state;
legendData[i] = newItem;

const filteredLegendData = legendData.filter(l => l.checked).map(l => l.x);

if (this.chart) {
this.chart.filter('x', val => filteredLegendData.indexOf(val) > -1);
}

this.setState({
legendData,
});
};

render() {
const {
valueFormat,
subTitle,
total,
hasLegend = false,
className,
style,
height,
forceFit = true,
percent = 0,
color,
inner = 0.75,
animate = true,
colors,
lineWidth = 1,
} = this.props;

const { legendData, legendBlock } = this.state;
const pieClassName = classNames(styles.pie, className, {
[styles.hasLegend]: !!hasLegend,
[styles.legendBlock]: legendBlock,
});

const defaultColors = colors;
let data = this.props.data || [];
let selected = this.props.selected || true;
let tooltip = this.props.tooltip || true;
let formatColor;

const scale = {
x: {
type: 'cat',
range: [0, 1],
},
y: {
min: 0,
},
};

if (percent) {
selected = false;
tooltip = false;
formatColor = value => {
if (value === '占比') {
return color || 'rgba(24, 144, 255, 0.85)';
} else {
return '#F0F2F5';
}
};

data = [
{
x: '占比',
y: parseFloat(percent),
},
{
x: '反比',
y: 100 - parseFloat(percent),
},
];
}

const tooltipFormat = [
'x*percent',
(x, p) => ({
name: x,
value: `${(p * 100).toFixed(2)}%`,
}),
];

const padding = [12, 0, 12, 0];

const dv = new DataView();
dv.source(data).transform({
type: 'percent',
field: 'y',
dimension: 'x',
as: 'percent',
});

return (
<div ref={this.handleRoot} className={pieClassName} style={style}>
<ReactFitText maxFontSize={25}>
<div className={styles.chart}>
<Chart
scale={scale}
height={height}
forceFit={forceFit}
data={dv}
padding={padding}
animate={animate}
onGetG2Instance={this.getG2Instance}
>
{!!tooltip && <Tooltip showTitle={false} />}
<Coord type="theta" innerRadius={inner} />
<Geom
style={{ lineWidth, stroke: '#fff' }}
tooltip={tooltip && tooltipFormat}
type="intervalStack"
position="percent"
color={['x', percent ? formatColor : defaultColors]}
selected={selected}
/>
</Chart>

{(subTitle || total) && (
<div className={styles.total}>
{subTitle && <h4 className="pie-sub-title">{subTitle}</h4>}
{/* eslint-disable-next-line */}
{total && (
<div className="pie-stat">{typeof total === 'function' ? total() : total}</div>
)}
</div>
)}
</div>
</ReactFitText>

{hasLegend && (
<ul className={styles.legend}>
{legendData.map((item, i) => (
<li key={item.x} onClick={() => this.handleLegendClick(item, i)}>
<span
className={styles.dot}
style={{
backgroundColor: !item.checked ? '#aaa' : item.color,
}}
/>
<span className={styles.legendTitle}>{item.x}</span>
<Divider type="vertical" />
<span className={styles.percent}>
{`${(isNaN(item.percent) ? 0 : item.percent * 100).toFixed(2)}%`}
</span>
<span className={styles.value}>{valueFormat ? valueFormat(item.y) : item.y}</span>
</li>
))}
</ul>
)}
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
@import '~antd/lib/style/themes/default.less';

.pie {
position: relative;
.chart {
position: relative;
}
&.hasLegend .chart {
width: ~'calc(100% - 240px)';
}
.legend {
position: absolute;
right: 0;
min-width: 200px;
top: 50%;
transform: translateY(-50%);
margin: 0 20px;
list-style: none;
padding: 0;
li {
cursor: pointer;
margin-bottom: 16px;
height: 22px;
line-height: 22px;
&:last-child {
margin-bottom: 0;
}
}
}
.dot {
border-radius: 8px;
display: inline-block;
margin-right: 8px;
position: relative;
top: -1px;
height: 8px;
width: 8px;
}
.line {
background-color: @border-color-split;
display: inline-block;
margin-right: 8px;
width: 1px;
height: 16px;
}
.legendTitle {
color: @text-color;
}
.percent {
color: @text-color-secondary;
}
.value {
position: absolute;
right: 0;
}
.title {
margin-bottom: 8px;
}
.total {
position: absolute;
left: 50%;
top: 50%;
text-align: center;
height: 62px;
transform: translate(-50%, -50%);
& > h4 {
color: @text-color-secondary;
font-size: 14px;
line-height: 22px;
height: 22px;
margin-bottom: 8px;
font-weight: normal;
}
& > p {
color: @heading-color;
display: block;
font-size: 1.2em;
height: 32px;
line-height: 32px;
white-space: nowrap;
}
}
}

.legendBlock {
&.hasLegend .chart {
width: 100%;
margin: 0 0 32px 0;
}
.legend {
position: relative;
transform: none;
}
}

0 comments on commit cccd958

Please sign in to comment.