diff --git a/src/Controllers/ChartListController.js b/src/Controllers/ChartListController.js new file mode 100644 index 0000000..1dbc8ac --- /dev/null +++ b/src/Controllers/ChartListController.js @@ -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 \ No newline at end of file diff --git a/src/Controllers/CreateChartController.js b/src/Controllers/CreateChartController.js new file mode 100644 index 0000000..582a1aa --- /dev/null +++ b/src/Controllers/CreateChartController.js @@ -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 diff --git a/src/Models/Chart/Chart.js b/src/Models/Chart/Chart.js index 46d6b5c..dd0b53d 100644 --- a/src/Models/Chart/Chart.js +++ b/src/Models/Chart/Chart.js @@ -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 } diff --git a/src/Models/Chart/ChartjsDataset.js b/src/Models/Chart/ChartjsDataset.js index dd35feb..e47de47 100644 --- a/src/Models/Chart/ChartjsDataset.js +++ b/src/Models/Chart/ChartjsDataset.js @@ -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() }], diff --git a/src/Models/Chart/Charts.js b/src/Models/Chart/Charts.js new file mode 100644 index 0000000..e73a8da --- /dev/null +++ b/src/Models/Chart/Charts.js @@ -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 diff --git a/src/Models/Chart/FocusChart.js b/src/Models/Chart/FocusChart.js new file mode 100644 index 0000000..cd2d954 --- /dev/null +++ b/src/Models/Chart/FocusChart.js @@ -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 diff --git a/src/views/Chart/ChartViewer.js b/src/views/Chart/ChartViewer.js index 44b3dad..2610d13 100644 --- a/src/views/Chart/ChartViewer.js +++ b/src/views/Chart/ChartViewer.js @@ -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 + return } - 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 (
- + /> */} {this.renderChart()}
) diff --git a/src/views/ChartList/ChartList.js b/src/views/ChartList/ChartList.js new file mode 100644 index 0000000..0833cb9 --- /dev/null +++ b/src/views/ChartList/ChartList.js @@ -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 => ) + return chartListElements + } + + render = () => { + return ( +
+ + + {this.state.adding ? : ''} + { this.renderListItemElements() } + +
+ ) + } +} + +export default ChartList diff --git a/src/views/ChartList/ChartListItem.js b/src/views/ChartList/ChartListItem.js new file mode 100644 index 0000000..73fb1b1 --- /dev/null +++ b/src/views/ChartList/ChartListItem.js @@ -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 ( + + + { chart.label } + {`${chart.table} grouped by ${chart.groupByValue}`} + + + { this.controller.deleteChart(chart.id) }} + style={{ cursor: 'pointer' }}> + Delete + + { this.controller.selectChartToView(chart.id) }} + style={{ cursor: 'pointer' }}> + View + + + + ) + } +} + +export default ChartListItem diff --git a/src/views/CreateChart/CreateChartForm.js b/src/views/CreateChart/CreateChartForm.js new file mode 100644 index 0000000..5ee7df0 --- /dev/null +++ b/src/views/CreateChart/CreateChartForm.js @@ -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 ( +
+
Create Graph
+ + +
+ + + + + + + +
+
+
+ ) + } +} + +export default CreateChartForm diff --git a/src/views/ListViewer/ListViewer.js b/src/views/ListViewer/ListViewer.js index 2f0b165..7983407 100644 --- a/src/views/ListViewer/ListViewer.js +++ b/src/views/ListViewer/ListViewer.js @@ -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: () => }, - { menuItem: 'Nodules', render: () => } + { menuItem: 'Nodules', render: () => }, + { menuItem: 'Charts', render: () => } ] } render = () => {