feat: three axis chart

This commit is contained in:
ysandler 2020-08-09 23:38:08 -05:00 committed by Joshua Shoemaker
parent 0b5a0466b7
commit eb775a5b89
8 changed files with 1872 additions and 1351 deletions

View File

@ -1,4 +1,5 @@
export default {
oneAxisCharts: ['line', 'bar', 'radar', 'doughnut', 'pie', 'polar'],
twoAxisCharts: ['scatter'] /*'bubble', 'scatter', 'area', 'mixed' */
twoAxisCharts: ['scatter'],
threeAxisCharts: ['bubble'] /* 'mixed' */
}

View File

@ -7,6 +7,8 @@ class Chart {
this.table = props.table
this.type = props.type
this.reportValue = props.reportValue
this.xAxis = props.xAxis
this.yAxis = props.yAxis
}
get id () {
@ -38,6 +40,14 @@ class Chart {
return this._reportValue
}
get xAxis () {
return this._xAxis
}
get yAxis () {
return this._yAxis
}
set reportValue (value) {
this._reportValue = value || this._reportValue
return this._reportValue
@ -56,6 +66,16 @@ class Chart {
else this._chartType = null
}
set xAxis (value) {
this._xAxis = value
return this._xAxis
}
set yAxis (value) {
this._yAxis = value
return this._yAxis
}
_validateChartType = type => {
const allChartTypes = Object.values(chartTypes).flat()
if (allChartTypes.includes(type)) return true

View File

@ -1,6 +1,7 @@
import { uuid } from 'uuidv4'
import OneAxisChart from '../../Models/Chart/OneAxisChart'
import TwoAxisChart from '../../Models/Chart/TwoAxisChart'
import ThreeAxisChart from '../../Models/Chart/ThreeAxisChart'
import chartTypes from '../../Constants/chartTypes'
let instance = null
@ -16,6 +17,7 @@ class Charts {
let newChart = null
if (chartTypes.oneAxisCharts.includes(chart.type)) newChart = this._generateOneAxisChart(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)
}
@ -66,6 +68,19 @@ class Charts {
})
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

View 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

View File

@ -3,14 +3,11 @@ import Chart from './Chart'
class TwoAxisChart extends Chart {
constructor (props) {
super(props)
this.xAxis = props.xAxis
this.yAxis = props.yAxis
this.rows = props.table.export()
}
get scatter () {
const rows = this.table.export()
const data = rows.map(r => {
const data = this.rows.map(r => {
return { x: r[this.xAxis], y: r[this.yAxis] }
})

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react'
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 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 === '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 === 'bubble') return <Bubble data={chart[chart.type]} width={600} height={600} ref={this.chart} />
}
render = () => {

View File

@ -109,7 +109,7 @@ class CreateChartForm extends Component {
}
renderConfigOptions = () => {
const { oneAxisCharts, twoAxisCharts } = chartTypes
const { oneAxisCharts, twoAxisCharts, threeAxisCharts } = chartTypes
const { chartType } = this.state
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
}

File diff suppressed because it is too large Load Diff