feat: create chart instances
This commit is contained in:
parent
318104aa9e
commit
a81cdb473b
24
src/Controllers/ChartListController.js
Normal file
24
src/Controllers/ChartListController.js
Normal file
@ -0,0 +1,24 @@
|
||||
import Charts from '../Models/Chart/Charts'
|
||||
import FocusChart from '../Models/Chart/FocusChart'
|
||||
|
||||
class ChartListController {
|
||||
constructor() {
|
||||
this.charts = new Charts()
|
||||
this.focusChart = new FocusChart()
|
||||
this.updatedChartsEvent = new Event('updateCharts')
|
||||
this.setSelectedChartEvent = new Event('setSelectedChart')
|
||||
}
|
||||
|
||||
deleteChart = id => {
|
||||
this.charts.removeById(id)
|
||||
document.dispatchEvent(this.updatedChartsEvent)
|
||||
}
|
||||
|
||||
selectChartToView = id => {
|
||||
const chart = this.charts.getById(id)
|
||||
this.focusChart.chart = chart
|
||||
document.dispatchEvent(this.setSelectedChartEvent)
|
||||
}
|
||||
}
|
||||
|
||||
export default ChartListController
|
||||
20
src/Controllers/CreateChartController.js
Normal file
20
src/Controllers/CreateChartController.js
Normal file
@ -0,0 +1,20 @@
|
||||
import Charts from '../Models/Chart/Charts'
|
||||
|
||||
class CreateTableController {
|
||||
constructor() {
|
||||
this.charts = new Charts()
|
||||
this.updatedChartsEvent = new Event('updateCharts')
|
||||
}
|
||||
|
||||
addNewChart = chart => {
|
||||
this.charts.addNewChart({
|
||||
label: chart.label,
|
||||
type: chart.type,
|
||||
table: chart.table,
|
||||
groupByValue: chart.groupByValue,
|
||||
})
|
||||
document.dispatchEvent(this.updatedChartsEvent)
|
||||
}
|
||||
}
|
||||
|
||||
export default CreateTableController
|
||||
10
src/Models/Chart/Chart.js
vendored
10
src/Models/Chart/Chart.js
vendored
@ -2,12 +2,22 @@ import chartTypes from '../../Constants/chartTypes'
|
||||
|
||||
class Chart {
|
||||
constructor (props) {
|
||||
this.id = props.id
|
||||
this.label = props.label
|
||||
this.table = props.table
|
||||
this.type = props.type
|
||||
this.groupByValue = props.groupByValue
|
||||
}
|
||||
|
||||
get id () {
|
||||
return this._id
|
||||
}
|
||||
|
||||
set id (newId) {
|
||||
this._id = newId
|
||||
return this._id
|
||||
}
|
||||
|
||||
get data () {
|
||||
return this.table.rows
|
||||
}
|
||||
|
||||
@ -2,11 +2,10 @@ import Chart from './Chart.js'
|
||||
import { GroupByNodule } from 'lovelacejs'
|
||||
|
||||
class ChartJsDataset extends Chart {
|
||||
get props () {
|
||||
|
||||
get doughnut () {
|
||||
const groupByNodule = new GroupByNodule({
|
||||
id: this.table.id,
|
||||
label: `${this.table.label} groupedBy ${this.groupByValue}`,
|
||||
id: this.id,
|
||||
label: `${this.label} groupedBy ${this.groupByValue}`,
|
||||
tables: [this.table],
|
||||
groupByValue: this.groupByValue
|
||||
}).export()
|
||||
@ -21,7 +20,7 @@ class ChartJsDataset extends Chart {
|
||||
return {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: this.label,
|
||||
label: `${this.label} groupedBy ${this.groupByValue}`,
|
||||
data: groupByCounts,
|
||||
backgroundColor: this._getbackgroundColors()
|
||||
}],
|
||||
|
||||
56
src/Models/Chart/Charts.js
Normal file
56
src/Models/Chart/Charts.js
Normal file
@ -0,0 +1,56 @@
|
||||
import { uuid } from 'uuidv4'
|
||||
import ChartJsDataset from '../../Models/Chart/ChartjsDataset'
|
||||
|
||||
let instance = null
|
||||
|
||||
class Charts {
|
||||
constructor () {
|
||||
if (!instance) instance = this
|
||||
this.collection = []
|
||||
return instance
|
||||
}
|
||||
|
||||
addNewChart = chart => {
|
||||
let newChart = null
|
||||
if (chart.type === 'bar') newChart = this._generateChartJsDataset(chart)
|
||||
if (chart.type === 'doughnut') newChart = this._generateChartJsDataset(chart)
|
||||
|
||||
if (newChart) this.collection.push(newChart)
|
||||
}
|
||||
|
||||
getById = id => this.collection.find(t => id === t.id)
|
||||
|
||||
getByLabel = label => this.collection.find(t => label === t.label)
|
||||
|
||||
getCollectionProps = () => {
|
||||
const charts = this.collection
|
||||
const chartProps = charts.map(c => {
|
||||
return {
|
||||
id: c.id,
|
||||
label: c.label,
|
||||
table: c.table.label,
|
||||
type: c.type,
|
||||
groupByValue: c.groupByValue
|
||||
}
|
||||
})
|
||||
return chartProps
|
||||
}
|
||||
|
||||
removeById = id => {
|
||||
const indexToRemove = this.collection.findIndex(t => t.id === id)
|
||||
if (indexToRemove > -1) this.collection.splice(indexToRemove, 1)
|
||||
}
|
||||
|
||||
_generateChartJsDataset = chart => {
|
||||
const newChart = new ChartJsDataset({
|
||||
id: chart.id || uuid(),
|
||||
label: chart.label,
|
||||
type: chart.type,
|
||||
table: chart.table,
|
||||
groupByValue: chart.groupByValue
|
||||
})
|
||||
return newChart
|
||||
}
|
||||
}
|
||||
|
||||
export default Charts
|
||||
20
src/Models/Chart/FocusChart.js
Normal file
20
src/Models/Chart/FocusChart.js
Normal file
@ -0,0 +1,20 @@
|
||||
let instance = null
|
||||
|
||||
class FocusChart {
|
||||
constructor (chart) {
|
||||
if (instance === null) instance = this
|
||||
this._value = chart
|
||||
return instance
|
||||
}
|
||||
|
||||
set chart (chart) {
|
||||
this._value = chart
|
||||
return this._value
|
||||
}
|
||||
|
||||
get chart () {
|
||||
return this._value
|
||||
}
|
||||
}
|
||||
|
||||
export default FocusChart
|
||||
@ -1,70 +1,64 @@
|
||||
import React, { Component } from 'react'
|
||||
import ChartJsDataset from '../../Models/Chart/ChartjsDataset'
|
||||
import FocusTable from '../../Models/FocusTable'
|
||||
import FocusChart from '../../Models/Chart/FocusChart'
|
||||
import { Doughnut } from 'react-chartjs-2'
|
||||
import { Dropdown } from 'semantic-ui-react'
|
||||
|
||||
class ChartViewer extends Component {
|
||||
constructor () {
|
||||
super ()
|
||||
this.focusTable = new FocusTable()
|
||||
this.focusChart = new FocusChart()
|
||||
this.state = {
|
||||
table: null,
|
||||
chart: null,
|
||||
groupByValue: ''
|
||||
}
|
||||
|
||||
document.addEventListener('setSelectedTable', this.setFocusTable)
|
||||
document.addEventListener('setSelectedChart', this.setFocusChart)
|
||||
}
|
||||
|
||||
handleGroupByChange = (e, value) => {
|
||||
this.setState({ groupByValue: value.value })
|
||||
}
|
||||
|
||||
setFocusTable = () => {
|
||||
const focusTable = this.focusTable.table
|
||||
if (focusTable) {
|
||||
setFocusChart = () => {
|
||||
const focusChart = this.focusChart.chart
|
||||
if (focusChart) {
|
||||
this.setState({
|
||||
table: focusTable,
|
||||
headers: this.renderGroupByOptions()
|
||||
chart: focusChart,
|
||||
// headers: this.renderGroupByOptions()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
renderChart = () => {
|
||||
if (!this.state.table) return
|
||||
const chart = new ChartJsDataset({
|
||||
label: this.state.label,
|
||||
type: 'bar',
|
||||
table: this.state.table,
|
||||
groupByValue: this.state.groupByValue
|
||||
})
|
||||
const { chart } = this.state
|
||||
if (!chart) return
|
||||
// console.log(chart)
|
||||
|
||||
console.log(chart)
|
||||
|
||||
return <Doughnut data={chart.props} width={600} height={600} />
|
||||
return <Doughnut data={chart[chart.type]} width={600} height={600} />
|
||||
}
|
||||
|
||||
renderGroupByOptions = () => {
|
||||
const focusTable = this.focusTable.table
|
||||
if (!focusTable) return []
|
||||
// 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
|
||||
}
|
||||
// const headers = focusTable.headers
|
||||
// const options = headers.map(h => {
|
||||
// return {key: h, text: h, value: h}
|
||||
// })
|
||||
// return options
|
||||
// }
|
||||
|
||||
render = () => {
|
||||
return (
|
||||
<div className='ChartViewer'>
|
||||
<Dropdown
|
||||
{/* <Dropdown
|
||||
placeholder='Select Value to Report'
|
||||
fluid
|
||||
selection
|
||||
options={this.state.headers}
|
||||
onChange={this.handleGroupByChange}
|
||||
/>
|
||||
/> */}
|
||||
{this.renderChart()}
|
||||
</div>
|
||||
)
|
||||
|
||||
52
src/views/ChartList/ChartList.js
Normal file
52
src/views/ChartList/ChartList.js
Normal file
@ -0,0 +1,52 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Card, Button, Icon } from 'semantic-ui-react'
|
||||
import CreateChartForm from '../CreateChart/CreateChartForm'
|
||||
import ChartListItem from './ChartListItem'
|
||||
// import './TableList.css'
|
||||
|
||||
import Charts from '../../Models/Chart/Charts'
|
||||
import ChartListController from '../../Controllers/ChartListController'
|
||||
|
||||
class ChartList extends Component {
|
||||
constructor () {
|
||||
super()
|
||||
|
||||
this.charts = new Charts()
|
||||
this.controller = new ChartListController()
|
||||
this.state = {
|
||||
adding: false,
|
||||
charts: this.charts.getCollectionProps()
|
||||
}
|
||||
|
||||
document.addEventListener('updateCharts', this.updateChartList)
|
||||
}
|
||||
|
||||
toggleAddingTable = () => { this.setState({ adding: !this.state.adding }) }
|
||||
|
||||
updateChartList = () => {
|
||||
this.setState({charts: this.charts.getCollectionProps()})
|
||||
}
|
||||
|
||||
renderListItemElements = () => {
|
||||
const { charts } = this.state
|
||||
const chartListElements = charts.map(c => <ChartListItem key={c.id} chart={c} /> )
|
||||
return chartListElements
|
||||
}
|
||||
|
||||
render = () => {
|
||||
return (
|
||||
<div className='TableList'>
|
||||
<Card.Group>
|
||||
<Button animated primary style={{ width: '100%', display: 'block' }} onClick={this.toggleAddingTable}>
|
||||
<Button.Content visible>Add Chart</Button.Content>
|
||||
<Button.Content hidden><Icon name='add' /></Button.Content>
|
||||
</Button>
|
||||
{this.state.adding ? <CreateChartForm /> : ''}
|
||||
{ this.renderListItemElements() }
|
||||
</Card.Group>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ChartList
|
||||
38
src/views/ChartList/ChartListItem.js
Normal file
38
src/views/ChartList/ChartListItem.js
Normal file
@ -0,0 +1,38 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Card, Icon } from 'semantic-ui-react'
|
||||
// import './TableList.css'
|
||||
|
||||
import ChartListController from '../../Controllers/ChartListController'
|
||||
|
||||
class ChartListItem extends Component {
|
||||
constructor () {
|
||||
super()
|
||||
this.controller = new ChartListController()
|
||||
}
|
||||
|
||||
render = () => {
|
||||
const { chart } = this.props
|
||||
return (
|
||||
<Card key={chart.id} id={chart.id} style={{ width: '380px' }}>
|
||||
<Card.Content>
|
||||
<Card.Header>{ chart.label }</Card.Header>
|
||||
<Card.Meta>{`${chart.table} grouped by ${chart.groupByValue}`}</Card.Meta>
|
||||
</Card.Content>
|
||||
<Card.Content extra>
|
||||
<span
|
||||
onClick={() => { this.controller.deleteChart(chart.id) }}
|
||||
style={{ cursor: 'pointer' }}>
|
||||
Delete <Icon name='trash' />
|
||||
</span>
|
||||
<span
|
||||
onClick={() => { this.controller.selectChartToView(chart.id) }}
|
||||
style={{ cursor: 'pointer' }}>
|
||||
View <Icon name='table' />
|
||||
</span>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ChartListItem
|
||||
156
src/views/CreateChart/CreateChartForm.js
Normal file
156
src/views/CreateChart/CreateChartForm.js
Normal file
@ -0,0 +1,156 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Button, Input, Header, Dropdown } from 'semantic-ui-react'
|
||||
// import './CreateNodule.css'
|
||||
|
||||
import Tables from '../../Models/Tables'
|
||||
import Nodules from '../../Models/Nodules'
|
||||
import CreateChartController from '../../Controllers/CreateChartController'
|
||||
import chartTypes from '../../Constants/chartTypes'
|
||||
|
||||
|
||||
class CreateChartForm extends Component {
|
||||
constructor () {
|
||||
super()
|
||||
this.tables = new Tables()
|
||||
|
||||
this.state = {
|
||||
chartType: '',
|
||||
selectedTableId: '',
|
||||
tables: this.tables.getCollectionProps(),
|
||||
groupByValue: '',
|
||||
headers : []
|
||||
}
|
||||
|
||||
this.tables = new Tables()
|
||||
this.nodules = new Nodules()
|
||||
this.controller = new CreateChartController()
|
||||
|
||||
this.chartLabelInput = React.createRef()
|
||||
this.groupByValueInput = React.createRef()
|
||||
|
||||
document.addEventListener('updateTables', this.updateTableList)
|
||||
}
|
||||
|
||||
clearInput = () => {
|
||||
this.setState({ noduleType: '' })
|
||||
}
|
||||
|
||||
getChartTypeDropdownOptions = () => {
|
||||
return chartTypes.map(t => {
|
||||
return {key: t, text: t, value: t}
|
||||
})
|
||||
}
|
||||
|
||||
handleChartTypeChange = (e, value) => {
|
||||
this.setState({ chartType: value.value })
|
||||
}
|
||||
|
||||
handleGroupByChange = (e, value) => {
|
||||
this.setState({ groupByValue: value.value })
|
||||
}
|
||||
|
||||
handleSelectedTableChange = (e, value) => {
|
||||
const selectedTable = this.tables.getById(value.value)
|
||||
this.setState({
|
||||
selectedTableId: value.value,
|
||||
headers: selectedTable.headers
|
||||
})
|
||||
}
|
||||
|
||||
getTableDropDownOptions = () => {
|
||||
const { tables } = this.state
|
||||
const tableDropdownOptions = tables.map(t => {
|
||||
return {
|
||||
key: t.id,
|
||||
value: t.id,
|
||||
text: t.label
|
||||
}
|
||||
})
|
||||
return tableDropdownOptions
|
||||
}
|
||||
|
||||
getGroupByDropDownOptions = () => {
|
||||
const { headers } = this.state
|
||||
const tableDropdownOptions = headers.map(h => {
|
||||
return {
|
||||
key: h,
|
||||
value: h,
|
||||
text: h
|
||||
}
|
||||
})
|
||||
return tableDropdownOptions
|
||||
}
|
||||
|
||||
handleSubmit = () => {
|
||||
const { chartType, selectedTableId, groupByValue } = this.state
|
||||
|
||||
const chartLabel = this.chartLabelInput.current.inputRef.current.value
|
||||
// const groupByValue = this.groupByValueInput.current.inputRef.current.value
|
||||
const table = this.tables.getById(selectedTableId)
|
||||
this.controller.addNewChart({
|
||||
label: chartLabel,
|
||||
type: chartType,
|
||||
table: table,
|
||||
groupByValue: groupByValue
|
||||
})
|
||||
|
||||
this.clearInput()
|
||||
}
|
||||
|
||||
updateTableList = () => {
|
||||
this.setState({tables: this.tables.getCollectionProps()})
|
||||
}
|
||||
|
||||
render = () => {
|
||||
return (
|
||||
<div className='CreateNodule'>
|
||||
<Header as='h3'>Create Graph</Header>
|
||||
|
||||
<Input
|
||||
placeholder='Chart Label'
|
||||
ref={this.chartLabelInput}
|
||||
icon='tags'
|
||||
style={{ width: '300px' }}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<Dropdown
|
||||
value ={this.state.chartType}
|
||||
placeholder='Select a Chart Type'
|
||||
options={this.getChartTypeDropdownOptions()}
|
||||
fluid
|
||||
selection
|
||||
style={{ width: '300px' }}
|
||||
onChange={this.handleChartTypeChange}
|
||||
/>
|
||||
|
||||
<Dropdown
|
||||
value ={this.state.selectedTable}
|
||||
placeholder='Select a Table'
|
||||
options={this.getTableDropDownOptions()}
|
||||
fluid
|
||||
selection
|
||||
style={{ width: '300px' }}
|
||||
onChange={this.handleSelectedTableChange}
|
||||
/>
|
||||
|
||||
<Dropdown
|
||||
value ={this.state.selectedTable}
|
||||
placeholder='Group By'
|
||||
options={this.getGroupByDropDownOptions()}
|
||||
fluid
|
||||
selection
|
||||
style={{ width: '300px' }}
|
||||
onChange={this.handleGroupByChange}
|
||||
/>
|
||||
|
||||
<div className='creatTableFormSubmitButtons'>
|
||||
<Button content='Cancel' secondary />
|
||||
<Button content='Confirm' primary onClick={this.handleSubmit} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default CreateChartForm
|
||||
@ -3,13 +3,15 @@ import TableList from '../TableList/TableList'
|
||||
import NoduleList from '../NoduleList/NoduleList'
|
||||
import './ListViewer.css'
|
||||
import { Tab } from 'semantic-ui-react'
|
||||
import ChartList from '../ChartList/ChartList'
|
||||
|
||||
class ListViewer extends Component {
|
||||
constructor () {
|
||||
super()
|
||||
this.panes = [
|
||||
{ menuItem: 'Tables', render: () => <Tab.Pane><TableList /></Tab.Pane> },
|
||||
{ menuItem: 'Nodules', render: () => <Tab.Pane><NoduleList /></Tab.Pane> }
|
||||
{ menuItem: 'Nodules', render: () => <Tab.Pane><NoduleList /></Tab.Pane> },
|
||||
{ menuItem: 'Charts', render: () => <Tab.Pane><ChartList /></Tab.Pane> }
|
||||
]
|
||||
}
|
||||
render = () => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user