Commit 0be9af58 authored by Viacheslav Pavlov's avatar Viacheslav Pavlov Committed by Matija Obreza
Browse files

Institute PDCI chart



- fixed "the same key" warning
Signed-off-by: Matija Obreza's avatarMatija Obreza <matija.obreza@croptrust.org>
parent 498b070b
......@@ -264,5 +264,8 @@
"0": "Other (please elaborate in Notes field)",
"1": "Research for food and agriculture"
}
},
"institute": {
"Institute PDCI score": "Average PDCI score for {{count, number}} accessions is {{avg, number}}, with minimum score of {{min, number}} and maximum score of {{max, number}}."
}
}
import * as React from 'react';
export const Bar = ({value, color, height, width, x, y}) => (
<svg>
<rect fill={ color } height={ `${height}px` } width={ `${width}%` } x={ `${x}%` } y={ `${y}px` } />
<text y={ y + height + 15 } x={ `${x + width / 2}%` } > { value } </text>
</svg>
);
import * as React from 'react';
import withStyles from '@material-ui/core/styles/withStyles';
const style = (theme) => ({
root: {
width: 'calc(100% - 16px)',
height: '220px',
padding: '0 8px',
},
});
class BarGrid extends React.Component<any> {
public render() {
const {classes, children, height = 200, strokeColor = 'gray'} = this.props;
return (
<svg className={ classes.root }>
<line x1="0" y1="1px" x2="0" y2={ `${height + 1}px` } strokeWidth="2px" stroke={ strokeColor }/> {/* Top-left -> bottom */ }
<line x1="0" y1="1px" x2="100%" y2="1px" strokeWidth="2px" stroke={ strokeColor }/> {/* Top-left -> right */ }
<line x1="100%" y1={ `${height + 1}px` } x2="100%" y2="1px" strokeWidth="2px" stroke={ strokeColor }/>
<line x1="100%" y1={ `${height + 1}px` } x2="0" y2={ `${height + 1}px` } strokeWidth="2px" stroke={ strokeColor }/>
<line x1="0" y1="0" x2="100%" y2="0" strokeWidth="1px" stroke={ strokeColor }/>
<line x1="0" y1="25%" x2="100%" y2="25%" strokeWidth="1px" stroke={ strokeColor }/>
<line x1="0" y1="50%" x2="100%" y2="50%" strokeWidth="1px" stroke={ strokeColor }/>
<line x1="0" y1="75%" x2="100%" y2="75%" strokeWidth="1px" stroke={ strokeColor }/>
{ children }
</svg>
);
}
}
export default withStyles(style)(BarGrid);
import * as React from 'react';
import withStyles from '@material-ui/core/styles/withStyles';
import {Bar} from './Bar';
import BarGrid from './BarGrid';
const chartHeight = 200;
const measureMargin = chartHeight / 4;
const defaultChartColor = '#88ba42';
const spacingQuota = 7;
const style = (theme) => ({
root: {
display: 'flex' as 'flex',
},
/*tslint:disable*/
measureSection: {
'& > div': {
marginBottom: `calc(${measureMargin}px - 1em)`,
}
},
/*tslint:enable*/
});
class BarChart extends React.Component<any> {
public state = {
measures: [],
scale: 0,
};
private getMeasures = () => {
const {data} = this.props;
const max = Math.max(...data.map((item) => item.value));
const topMeasure = Math.round((max / 0.75) / Math.pow(10, `${max}`.length - 1)) * Math.pow(10, `${max}`.length - 1);
return {measures: [topMeasure, topMeasure * 0.75, topMeasure * 0.5, topMeasure * 0.25], scale: chartHeight / topMeasure};
}
private renderBar = (item, index, dataLength) => {
const {scale} = this.state;
const barHeight = Math.round(item.value * scale);
const width = 90 / dataLength;
return (
<Bar
key={ `bar_${index}` }
value={ item.key }
color={ defaultChartColor }
height={ barHeight }
width={ width }
x={ (width + spacingQuota / dataLength) * index + 1.5 }
y={ chartHeight - barHeight }
/>
);
}
public componentWillMount() {
if (this.props.data) {
this.setState(this.getMeasures());
}
}
public componentWillReceiveProps(nextProps) {
if (this.state.measures.length === 0 && this.props.data) {
this.setState(this.getMeasures());
}
}
public render() {
this.getMeasures();
const {data, classes} = this.props;
const {measures} = this.state;
if (!data || data.length === 0) {
return null;
}
return (
<div className={ classes.root }>
<div className={ classes.measureSection }>
<div>{ measures[0] }</div>
<div>{ measures[1] }</div>
<div>{ measures[2] }</div>
<div>{ measures[3] }</div>
</div>
<BarGrid>
{ data.map((item, i) => (this.renderBar(item, i, data.length))) }
</BarGrid>
</div>
);
}
}
export default withStyles(style)(BarChart);
......@@ -2,6 +2,7 @@ import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import { translate } from 'react-i18next';
import { Link } from 'react-router-dom';
// Actions
import {loadInstitute} from 'actions/institutes';
......@@ -25,12 +26,12 @@ import PrettyDate from 'ui/common/time/PrettyDate';
import withWidth from '@material-ui/core/withWidth';
import {Breakpoint} from '@material-ui/core/styles/createBreakpoints';
import {CountryLink} from 'ui/genesys/Links';
import BarChart from 'ui/common/bar-chart';
interface IDisplayPageProps extends React.ClassAttributes<any> {
t: any;
width: Breakpoint;
code: string;
doi: string; // DOI comes from the route without the '10.'
institute: FaoInstituteDetails;
error: any;
loadInstitute: any;
......@@ -75,9 +76,8 @@ class DisplayPage extends React.Component<IDisplayPageProps, any> {
}
public render() {
const { error, institute, code, width } = this.props;
const { error, institute, code, width, t } = this.props;
const stillLoading: boolean = ! error && (! institute || (code && institute && institute.details.code !== code));
const isMobile = mobile.indexOf(width) !== -1;
let cropShortNameOverview;
......@@ -121,6 +121,15 @@ class DisplayPage extends React.Component<IDisplayPageProps, any> {
</PropertiesItem>
</Properties>
</MainSection>
{ institute.blurb && institute.blurb.body &&
<PageSection title="About">
<Properties>
<div style={ !isMobile ? {columnCount: 2} : {} } dangerouslySetInnerHTML={ {__html: institute.blurb.body} }/>
</Properties>
</PageSection>
}
{ institute.details.latitude !== null && institute.details.longitude !== null &&
<PageSection title="Location">
<Properties>
......@@ -220,11 +229,11 @@ class DisplayPage extends React.Component<IDisplayPageProps, any> {
</PageSection>
}
{ institute.blurb && institute.blurb.body &&
<PageSection title="About">
<Properties>
<div style={ !isMobile ? {columnCount: 2} : {} } dangerouslySetInnerHTML={ {__html: institute.blurb.body} }/>
</Properties>
{ institute.pdciStats && institute.pdciStats.histogram && institute.pdciStats.histogram.length > 0 &&
<PageSection title="PDCI: Passport data complex index">
<BarChart data={ institute.pdciStats.histogram.map((item, i) => ({key: i % 2 === 0 ? i / 2 : '', value: item })) }/>
<p className="mt-20">{ t('institute.Institute PDCI score', { count: institute.pdciStats.count, avg: institute.pdciStats.avg, min: institute.pdciStats.min, max: institute.pdciStats.max }) }</p>
<Link to="/content/passport-data-completeness-index">Read about Passport Data Completeness Index</Link>
</PageSection>
}
</PageContents>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment