feat: basic chart rendering

This commit is contained in:
ysandler 2020-08-05 20:26:29 -05:00 committed by Joshua Shoemaker
parent ab29b45a4e
commit e2817b1fae
7 changed files with 255 additions and 16 deletions

75
package-lock.json generated
View File

@ -1853,9 +1853,9 @@
}
},
"@types/uuid": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.0.0.tgz",
"integrity": "sha512-xSQfNcvOiE5f9dyd4Kzxbof1aTrLobL278pGLKOZI6esGfZ7ts9Ka16CzIN6Y8hFHE1C7jIBZokULhK1bOgjRw=="
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.0.1.tgz",
"integrity": "sha512-2kE8rEFgJpbBAPw5JghccEevQb0XVU0tewF/8h7wPQTeCtoJ6h8qmBIwuzUVm2MutmzC/cpCkwxudixoNYDp1A=="
},
"@types/yargs": {
"version": "13.0.9",
@ -3376,6 +3376,32 @@
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
},
"chart.js": {
"version": "2.9.3",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.3.tgz",
"integrity": "sha512-+2jlOobSk52c1VU6fzkh3UwqHMdSlgH1xFv9FKMqHiNCpXsGPQa/+81AFa+i3jZ253Mq9aAycPwDjnn1XbRNNw==",
"requires": {
"chartjs-color": "^2.1.0",
"moment": "^2.10.2"
}
},
"chartjs-color": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz",
"integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==",
"requires": {
"chartjs-color-string": "^0.6.0",
"color-convert": "^1.9.3"
}
},
"chartjs-color-string": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz",
"integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==",
"requires": {
"color-name": "^1.0.0"
}
},
"chokidar": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
@ -7988,9 +8014,9 @@
}
},
"lovelacejs": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/lovelacejs/-/lovelacejs-0.1.6.tgz",
"integrity": "sha512-n/dDWtkzIC6ORUMU2M6Y2j1QFbXo/qD6GC9uZyyHPBIn3QwN7ZHvEplBJWyhy3nAzm0bD8SpIfJVjyIClw8qXg=="
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/lovelacejs/-/lovelacejs-0.2.1.tgz",
"integrity": "sha512-bjIsYHmhCZnxY4/8QxrOdIICrnm1ebgnMsf1bDKIibyem5Fns/meRyyLfbz0CxXWOHdb826tbDqTvB+LNW/j0w=="
},
"lower-case": {
"version": "2.0.1",
@ -8377,6 +8403,11 @@
"minimist": "^1.2.5"
}
},
"moment": {
"version": "2.27.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz",
"integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ=="
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@ -10421,6 +10452,22 @@
"whatwg-fetch": "^3.0.0"
}
},
"react-chartjs-2": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-2.10.0.tgz",
"integrity": "sha512-1MjWEkUn8LLFf6GVyYUOrruJTW3yVU5hlEJOwGj3MiokuC+jH/BahjWVGAMonbe9UYbEIUbd2Rn36iVlC0Hb7w==",
"requires": {
"lodash": "^4.17.19",
"prop-types": "^15.7.2"
},
"dependencies": {
"lodash": {
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
}
}
},
"react-dev-utils": {
"version": "10.2.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-10.2.1.tgz",
@ -12847,18 +12894,18 @@
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"uuidv4": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.1.1.tgz",
"integrity": "sha512-ZplGb1SHFMVH3l7PUQl2Uwo+FpJQV6IPOoU+MjjbqrNYQolqbGwv+/sn9F+AGMsMOgGz3r9JN3ztGUi0VzMxmw==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.2.tgz",
"integrity": "sha512-cIwuSIzx+StdJSkLYKDLje7mDfYvK88RNZuVdpCFWujf2bOIDLGCum8vY88KDNLhcFaQGWLBVHYl8U3wlqseQg==",
"requires": {
"@types/uuid": "8.0.0",
"uuid": "8.2.0"
"@types/uuid": "8.0.1",
"uuid": "8.3.0"
},
"dependencies": {
"uuid": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz",
"integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q=="
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz",
"integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ=="
}
}
},

View File

@ -6,13 +6,15 @@
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"lovelacejs": "^0.1.6",
"chart.js": "^2.9.3",
"lovelacejs": "^0.2.1",
"react": "^16.13.1",
"react-chartjs-2": "^2.10.0",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1",
"semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^0.88.2",
"uuidv4": "^6.1.1"
"uuidv4": "^6.2.2"
},
"scripts": {
"start": "react-scripts start",

View File

@ -0,0 +1,3 @@
export default [
'line', 'bar', 'radar', 'doughnut', 'pie', 'bubble', 'scatter', 'area', 'mixed'
]

55
src/Models/Chart/Chart.js vendored Normal file
View File

@ -0,0 +1,55 @@
import chartTypes from '../../Constants/chartTypes'
class Chart {
constructor (props) {
this.label = props.label
this.table = props.table
this.type = props.type
this.groupByValue = props.groupByValue
}
get data () {
return this.table.rows
}
get labels () {
return this.table.headers
}
get table () {
return this._table
}
get type () {
return this._chartType
}
get groupByValue () {
return this._groupByValue
}
set groupByValue (value) {
this._groupByValue = value || this._groupByValue
return this._groupByValue
}
set table (table) {
if (!table) this._table = null
else if (table.type === 'Table') this._table = table
else if (table.type === 'Nodule') this._table = table.asTable()
else this._table = null
}
set type (value) {
const isChartTypeValid = this._validateChartType(value)
if (isChartTypeValid) this._chartType = value
else this._chartType = null
}
_validateChartType = type => {
if (chartTypes.includes(type)) return true
else return false
}
}
export default Chart

View File

@ -0,0 +1,56 @@
import Chart from './Chart.js'
import { GroupByNodule } from 'lovelacejs'
class ChartJsChart extends Chart {
constructor (props) {
super(props)
}
get props () {
const groupByNodule = new GroupByNodule({
id: this.table.id,
label: `${this.table.label} groupedBy something`,
tables: [this.table],
groupByValue: this.groupByValue
}).export()
const labels = Object.keys(groupByNodule)
let groupByCounts = []
for (let key in groupByNodule) {
groupByCounts.push(groupByNodule[key].length)
}
return {
labels: labels,
datasets: [{
label: this.label,
data: groupByCounts,
backgroundColor: this._getbackgroundColors()
}],
}
// return [{
// label: this.label,
// data: groupByCounts,
// backgroundColor: this._getbackgroundColors()
// }]
}
_generateRandomRGBNumber () {
const max = 255
const min = 0
return Math.round(Math.random() * (max - min) - min)
}
_getbackgroundColors () {
const labels = this.labels
const backgroundColors = labels.map(l => {
return `rgb(${this._generateRandomRGBNumber()}, ${this._generateRandomRGBNumber()}, ${this._generateRandomRGBNumber()})`
})
return backgroundColors
}
}
export default ChartJsChart

View File

@ -4,6 +4,7 @@ import 'semantic-ui-css/semantic.min.css'
import DataTable from './DataTable/DataTable'
import ListViewer from './ListViewer/ListViewer'
import Nav from './Nav/Nav'
import ChartViewer from './Chart/ChartViewer'
class App extends Component {
render = () => {
@ -13,6 +14,7 @@ class App extends Component {
<div className='Workspace'>
<ListViewer />
<DataTable />
<ChartViewer />
</div>
</div>
)

View File

@ -0,0 +1,74 @@
import React, { Component } from 'react'
import ChartJsChart from '../../Models/Chart/ChartjsChart'
import FocusTable from '../../Models/FocusTable'
import { Doughnut } from 'react-chartjs-2'
import { Dropdown } from 'semantic-ui-react'
class ChartViewer extends Component {
constructor () {
super ()
this.focusTable = new FocusTable()
this.state = {
table: null,
groupByValue: ''
}
document.addEventListener('setSelectedTable', this.setFocusTable)
}
handleGroupByChange = (e, value) => {
this.setState({ groupByValue: value.value })
}
setFocusTable = () => {
const focusTable = this.focusTable.table
if (focusTable) {
this.setState({
table: focusTable,
headers: this.renderGroupByOptions()
})
}
}
renderChart = () => {
if (!this.state.table) return
const chart = new ChartJsChart({
label: 'test chart',
type: 'bar',
table: this.state.table,
groupByValue: this.state.groupByValue
})
console.log(chart.props)
return <Doughnut data={chart.props} width={600} height={600} />
}
renderGroupByOptions = () => {
const focusTable = this.focusTable.table
if (!focusTable) return []
const headers = focusTable.headers
const options = headers.map(h => {
return {key: h, text: h, value: h}
})
return options
}
render = () => {
return (
<div className='ChartViewer'>
<Dropdown
placeholder='Select a Comparison Type'
fluid
selection
options={this.state.headers}
onChange={this.handleGroupByChange}
/>
{this.renderChart()}
</div>
)
}
}
export default ChartViewer