feat: three axis chart
This commit is contained in:
parent
0b5a0466b7
commit
eb775a5b89
@ -1,4 +1,5 @@
|
|||||||
export default {
|
export default {
|
||||||
oneAxisCharts: ['line', 'bar', 'radar', 'doughnut', 'pie', 'polar'],
|
oneAxisCharts: ['line', 'bar', 'radar', 'doughnut', 'pie', 'polar'],
|
||||||
twoAxisCharts: ['scatter'] /*'bubble', 'scatter', 'area', 'mixed' */
|
twoAxisCharts: ['scatter'],
|
||||||
|
threeAxisCharts: ['bubble'] /* 'mixed' */
|
||||||
}
|
}
|
||||||
|
20
src/Models/Chart/Chart.js
vendored
20
src/Models/Chart/Chart.js
vendored
@ -7,6 +7,8 @@ class Chart {
|
|||||||
this.table = props.table
|
this.table = props.table
|
||||||
this.type = props.type
|
this.type = props.type
|
||||||
this.reportValue = props.reportValue
|
this.reportValue = props.reportValue
|
||||||
|
this.xAxis = props.xAxis
|
||||||
|
this.yAxis = props.yAxis
|
||||||
}
|
}
|
||||||
|
|
||||||
get id () {
|
get id () {
|
||||||
@ -38,6 +40,14 @@ class Chart {
|
|||||||
return this._reportValue
|
return this._reportValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get xAxis () {
|
||||||
|
return this._xAxis
|
||||||
|
}
|
||||||
|
|
||||||
|
get yAxis () {
|
||||||
|
return this._yAxis
|
||||||
|
}
|
||||||
|
|
||||||
set reportValue (value) {
|
set reportValue (value) {
|
||||||
this._reportValue = value || this._reportValue
|
this._reportValue = value || this._reportValue
|
||||||
return this._reportValue
|
return this._reportValue
|
||||||
@ -56,6 +66,16 @@ class Chart {
|
|||||||
else this._chartType = null
|
else this._chartType = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set xAxis (value) {
|
||||||
|
this._xAxis = value
|
||||||
|
return this._xAxis
|
||||||
|
}
|
||||||
|
|
||||||
|
set yAxis (value) {
|
||||||
|
this._yAxis = value
|
||||||
|
return this._yAxis
|
||||||
|
}
|
||||||
|
|
||||||
_validateChartType = type => {
|
_validateChartType = type => {
|
||||||
const allChartTypes = Object.values(chartTypes).flat()
|
const allChartTypes = Object.values(chartTypes).flat()
|
||||||
if (allChartTypes.includes(type)) return true
|
if (allChartTypes.includes(type)) return true
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { uuid } from 'uuidv4'
|
import { uuid } from 'uuidv4'
|
||||||
import OneAxisChart from '../../Models/Chart/OneAxisChart'
|
import OneAxisChart from '../../Models/Chart/OneAxisChart'
|
||||||
import TwoAxisChart from '../../Models/Chart/TwoAxisChart'
|
import TwoAxisChart from '../../Models/Chart/TwoAxisChart'
|
||||||
|
import ThreeAxisChart from '../../Models/Chart/ThreeAxisChart'
|
||||||
import chartTypes from '../../Constants/chartTypes'
|
import chartTypes from '../../Constants/chartTypes'
|
||||||
|
|
||||||
let instance = null
|
let instance = null
|
||||||
@ -16,6 +17,7 @@ class Charts {
|
|||||||
let newChart = null
|
let newChart = null
|
||||||
if (chartTypes.oneAxisCharts.includes(chart.type)) newChart = this._generateOneAxisChart(chart)
|
if (chartTypes.oneAxisCharts.includes(chart.type)) newChart = this._generateOneAxisChart(chart)
|
||||||
if (chartTypes.twoAxisCharts.includes(chart.type)) newChart = this._generateTwoAxisChart(chart)
|
if (chartTypes.twoAxisCharts.includes(chart.type)) newChart = this._generateTwoAxisChart(chart)
|
||||||
|
if (chartTypes.threeAxisCharts.includes(chart.type)) newChart = this._generateThreeAxisChart(chart)
|
||||||
|
|
||||||
if (newChart) this.collection.push(newChart)
|
if (newChart) this.collection.push(newChart)
|
||||||
}
|
}
|
||||||
@ -66,6 +68,19 @@ class Charts {
|
|||||||
})
|
})
|
||||||
return newChart
|
return newChart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_generateThreeAxisChart = chart => {
|
||||||
|
const newChart = new ThreeAxisChart({
|
||||||
|
id: chart.id || uuid(),
|
||||||
|
label: chart.label,
|
||||||
|
type: chart.type,
|
||||||
|
table: chart.table,
|
||||||
|
xAxis: chart.xAxis,
|
||||||
|
yAxis: chart.yAxis,
|
||||||
|
reportValue: chart.reportValue
|
||||||
|
})
|
||||||
|
return newChart
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Charts
|
export default Charts
|
||||||
|
52
src/Models/Chart/ThreeAxisChart.js
Normal file
52
src/Models/Chart/ThreeAxisChart.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import Chart from './Chart.js'
|
||||||
|
import { GroupByNodule } from 'lovelacejs'
|
||||||
|
|
||||||
|
class ThreeAxisChart extends Chart {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.chartSize = 600
|
||||||
|
this.rows = props.table.export()
|
||||||
|
this.scale = props.scale || 3.5
|
||||||
|
|
||||||
|
|
||||||
|
const reportValues = this.rows.map(r => {
|
||||||
|
return r[this.reportValue]
|
||||||
|
})
|
||||||
|
this.largestValue = Math.max(...reportValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
get bubble () {
|
||||||
|
const data = this.rows.map(r => {
|
||||||
|
return { x: r[this.xAxis], y: r[this.yAxis], r: this.calculateReportValueScale(r[this.reportValue]) }
|
||||||
|
})
|
||||||
|
|
||||||
|
const pointColor = { r: this._generateRandomRGBNumber(), g: this._generateRandomRGBNumber(), b: this._generateRandomRGBNumber(), a: 0.2 }
|
||||||
|
|
||||||
|
return {
|
||||||
|
labels: [this.xAxis, this.yAxis],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: this.reportValue,
|
||||||
|
data: data,
|
||||||
|
borderColor: `rgba(255, 255, 255, 0.3)`,
|
||||||
|
backgroundColor: `rgba(${pointColor.r}, ${pointColor.g}, ${pointColor.b}, 0.6)`
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateReportValueScale = (reportValue) => {
|
||||||
|
const scale = 3.5
|
||||||
|
const size = (reportValue / this.largestValue) * 100
|
||||||
|
return Math.round(size / scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
_generateRandomRGBNumber () {
|
||||||
|
const max = 255
|
||||||
|
const min = 0
|
||||||
|
return Math.round(Math.random() * (max - min) - min)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ThreeAxisChart
|
@ -3,14 +3,11 @@ import Chart from './Chart'
|
|||||||
class TwoAxisChart extends Chart {
|
class TwoAxisChart extends Chart {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.xAxis = props.xAxis
|
|
||||||
this.yAxis = props.yAxis
|
|
||||||
this.rows = props.table.export()
|
this.rows = props.table.export()
|
||||||
}
|
}
|
||||||
|
|
||||||
get scatter () {
|
get scatter () {
|
||||||
const rows = this.table.export()
|
const data = this.rows.map(r => {
|
||||||
const data = rows.map(r => {
|
|
||||||
return { x: r[this.xAxis], y: r[this.yAxis] }
|
return { x: r[this.xAxis], y: r[this.yAxis] }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import FocusChart from '../../Models/Chart/FocusChart'
|
import FocusChart from '../../Models/Chart/FocusChart'
|
||||||
import { Doughnut, Bar, Line, Pie, Polar, Radar, Scatter } from 'react-chartjs-2'
|
import { Doughnut, Bar, Line, Pie, Polar, Radar, Scatter, Bubble } from 'react-chartjs-2'
|
||||||
import { Button } from 'semantic-ui-react'
|
import { Button } from 'semantic-ui-react'
|
||||||
import download from 'downloadjs'
|
import download from 'downloadjs'
|
||||||
|
|
||||||
@ -49,6 +49,7 @@ class ChartViewer extends Component {
|
|||||||
if (chart.type === 'polar') return <Polar data={chart[chart.type]} width={600} height={600} ref={this.chart} />
|
if (chart.type === 'polar') return <Polar data={chart[chart.type]} width={600} height={600} ref={this.chart} />
|
||||||
if (chart.type === 'radar') return <Radar data={chart[chart.type]} width={600} height={600} ref={this.chart} />
|
if (chart.type === 'radar') return <Radar data={chart[chart.type]} width={600} height={600} ref={this.chart} />
|
||||||
if (chart.type === 'scatter') return <Scatter data={chart[chart.type]} width={600} height={600} ref={this.chart} />
|
if (chart.type === 'scatter') return <Scatter data={chart[chart.type]} width={600} height={600} ref={this.chart} />
|
||||||
|
if (chart.type === 'bubble') return <Bubble data={chart[chart.type]} width={600} height={600} ref={this.chart} />
|
||||||
}
|
}
|
||||||
|
|
||||||
render = () => {
|
render = () => {
|
||||||
|
@ -109,7 +109,7 @@ class CreateChartForm extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderConfigOptions = () => {
|
renderConfigOptions = () => {
|
||||||
const { oneAxisCharts, twoAxisCharts } = chartTypes
|
const { oneAxisCharts, twoAxisCharts, threeAxisCharts } = chartTypes
|
||||||
const { chartType } = this.state
|
const { chartType } = this.state
|
||||||
|
|
||||||
let configElements = []
|
let configElements = []
|
||||||
@ -148,6 +148,41 @@ class CreateChartForm extends Component {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
else if (threeAxisCharts.includes(chartType)) {
|
||||||
|
configElements.push(
|
||||||
|
<Dropdown
|
||||||
|
value ={this.state.xAxisValue}
|
||||||
|
placeholder='X-Axis'
|
||||||
|
options={this.getHeaderDropDownOptions()}
|
||||||
|
fluid
|
||||||
|
selection
|
||||||
|
style={{ width: '300px' }}
|
||||||
|
onChange={this.handleXAxisChange}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
configElements.push(
|
||||||
|
<Dropdown
|
||||||
|
value ={this.state.yAxisValue}
|
||||||
|
placeholder='Y-Axis'
|
||||||
|
options={this.getHeaderDropDownOptions()}
|
||||||
|
fluid
|
||||||
|
selection
|
||||||
|
style={{ width: '300px' }}
|
||||||
|
onChange={this.handleYAxisChange}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
configElements.push(
|
||||||
|
<Dropdown
|
||||||
|
value ={this.state.reportValue}
|
||||||
|
placeholder='Report By'
|
||||||
|
options={this.getHeaderDropDownOptions()}
|
||||||
|
fluid
|
||||||
|
selection
|
||||||
|
style={{ width: '300px' }}
|
||||||
|
onChange={this.handleReportValueChange}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
return configElements
|
return configElements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user