Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(modal):customizability of chart modal #1704

Merged
7 changes: 3 additions & 4 deletions packages/core/src/model/alluvial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ export class AlluvialChartModel extends ChartModelCartesian {

// Sort array by source to get a close depiction of the alluvial chart
displayData.sort((a: any, b: any) => a['source'].localeCompare(b['source']))

const result = [
['Source', 'Target', 'Value'],
const headingLabels = ['Source', 'Target', 'Value']
const tableData = [
...displayData.map((datum: any) => [datum['source'], datum['target'], datum['value']])
]

return result
return super.formatTable(headingLabels, tableData)
}
}
15 changes: 7 additions & 8 deletions packages/core/src/model/binned-charts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,17 @@ export class ChartModelBinned extends ChartModelCartesian {
const { groupMapsTo } = options.data

const binnedStackedData = this.getBinnedStackedData()

const result = [
[
get(options, 'bins.rangeLabel') || 'Range',
...binnedStackedData.map((datum) => get(datum, `0.${groupMapsTo}`))
],
const headingLabels = [
get(options, 'bins.rangeLabel') || 'Range',
...binnedStackedData.map(datum => get(datum, `0.${groupMapsTo}`))
]
const tableData = [
...get(binnedStackedData, 0).map((d, i) => [
`${get(d, 'data.x0')} – ${get(d, 'data.x1')}`,
...binnedStackedData.map((datum) => get(datum[i], `data.${get(datum[i], groupMapsTo)}`))
...binnedStackedData.map(datum => get(datum[i], `data.${get(datum[i], groupMapsTo)}`))
])
]

return result
return super.formatTable(headingLabels, tableData)
}
}
10 changes: 5 additions & 5 deletions packages/core/src/model/boxplot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ export class BoxplotChartModel extends ChartModelCartesian {

const boxplotData = this.getBoxplotData()

const result = [
['Group', 'Minimum', 'Q1', 'Median', 'Q3', 'Maximum', 'IQR', 'Outlier(s)'],
...boxplotData.map((datum) => {
const headingLabels = ['Group', 'Minimum', 'Q1', 'Median', 'Q3', 'Maximum', 'IQR', 'Outlier(s)']
const tableData = [
...boxplotData.map(datum => {
let outliers = getProperty(datum, 'outliers')
if (outliers === null || outliers.length === 0) {
outliers = ['–']
Expand All @@ -111,14 +111,14 @@ export class BoxplotChartModel extends ChartModelCartesian {
getProperty(datum, 'quartiles', 'q_25') !== null
? (
getProperty(datum, 'quartiles', 'q_75') - getProperty(datum, 'quartiles', 'q_25')
).toLocaleString()
).toLocaleString()
: '–',
outliers.map((d: any) => d.toLocaleString()).join(',')
]
})
]

return result
return super.formatTable(headingLabels, tableData)
}

protected setColorClassNames() {
Expand Down
7 changes: 3 additions & 4 deletions packages/core/src/model/bullet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ export class BulletChartModel extends ChartModelCartesian {
const rangeIdentifier = this.services.cartesianScales.getRangeIdentifier()

const performanceAreaTitles = getProperty(options, 'bullet', 'performanceAreaTitles')

const result = [
['Title', 'Group', 'Value', 'Target', 'Percentage', 'Performance'],
const headingLabels = ['Title', 'Group', 'Value', 'Target', 'Percentage', 'Performance']
const tableData = [
...displayData.map((datum: any) => [
datum['title'],
datum[groupMapsTo],
Expand All @@ -50,6 +49,6 @@ export class BulletChartModel extends ChartModelCartesian {
])
]

return result
return super.formatTable(headingLabels, tableData)
}
}
96 changes: 41 additions & 55 deletions packages/core/src/model/cartesian-charts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { format } from 'date-fns'
import { cloneDeep, uniq } from 'lodash-es'
import { getProperty } from '@/tools'
import { ChartModel } from './model'
Expand Down Expand Up @@ -32,18 +31,20 @@ export class ChartModelCartesian extends ChartModel {
scales.secondaryRange = cartesianScales.secondaryRangeAxisPosition
}

Object.keys(scales).forEach((scale: 'primaryDomain' | 'primaryRange' | 'secondaryDomain' | 'secondaryRange') => {
const position = scales[scale]
if (cartesianScales.scales[position]) {
scales[scale] = {
position: position,
label: cartesianScales.getScaleLabel(position),
identifier: getProperty(options, 'axes', position, 'mapsTo')
Object.keys(scales).forEach(
(scale: 'primaryDomain' | 'primaryRange' | 'secondaryDomain' | 'secondaryRange') => {
const position = scales[scale]
if (cartesianScales.scales[position]) {
scales[scale] = {
position: position,
label: cartesianScales.getScaleLabel(position),
identifier: getProperty(options, 'axes', position, 'mapsTo')
}
} else {
scales[scale] = null
}
} else {
scales[scale] = null
}
})
)

return scales
}
Expand All @@ -52,53 +53,38 @@ export class ChartModelCartesian extends ChartModel {
const displayData = this.getDisplayData()
const options = this.getOptions()
const { groupMapsTo } = options.data

const { cartesianScales } = this.services
const { primaryDomain, primaryRange, secondaryDomain, secondaryRange } =
this.assignRangeAndDomains()

const domainScaleType = cartesianScales.getDomainAxisScaleType()
let domainValueFormatter: any
if (domainScaleType === ScaleTypes.TIME) {
domainValueFormatter = (d: any) => format(d, 'MMM d, yyyy')
}

const result = [
[
'Group',
primaryDomain.label,
primaryRange.label,
...(secondaryDomain ? [secondaryDomain.label] : []),
...(secondaryRange ? [secondaryRange.label] : [])
],
...displayData.map((datum: any) => [
datum[groupMapsTo],
datum[primaryDomain.identifier] === null
? '–'
: domainValueFormatter
? domainValueFormatter(datum[primaryDomain.identifier])
: datum[primaryDomain.identifier],
datum[primaryRange.identifier] === null || isNaN(datum[primaryRange.identifier])
? '–'
: datum[primaryRange.identifier].toLocaleString(),
...(secondaryDomain
? [
datum[secondaryDomain.identifier] === null
? '–'
: datum[secondaryDomain.identifier]
]
: []),
...(secondaryRange
? [
datum[secondaryRange.identifier] === null || isNaN(datum[secondaryRange.identifier])
? '–'
: datum[secondaryRange.identifier]
]
: [])
])
const headingLabels = [
'Group',
primaryDomain.label,
primaryRange.label,
...(secondaryDomain ? [secondaryDomain.label] : []),
...(secondaryRange ? [secondaryRange.label] : [])
]

return result
const tableData = displayData.map((datum: any) => [
datum[groupMapsTo],
datum[primaryDomain.identifier] === null ? '–' : datum[primaryDomain.identifier],
datum[primaryRange.identifier] === null || isNaN(datum[primaryRange.identifier])
? '–'
: datum[primaryRange.identifier].toLocaleString(),
...(secondaryDomain
? [
datum[secondaryDomain.identifier] === null
? '–'
: datum[secondaryDomain.identifier]
]
: []),
...(secondaryRange
? [
datum[secondaryRange.identifier] === null || isNaN(datum[secondaryRange.identifier])
? '–'
: datum[secondaryRange.identifier]
]
: [])
])

return super.formatTable(headingLabels, tableData)
}

setData(newData: any) {
Expand Down
13 changes: 6 additions & 7 deletions packages/core/src/model/choropleth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ export class ChoroplethModel extends ChartModel {
*
* May need to provide users with the option to pass in keys to create dictionary with
*/
options.geoData.objects.countries.geometries.forEach((country) => {
options.geoData.objects.countries.geometries.forEach(country => {
this._matrix[country.properties.NAME] = country
})

data.forEach((value) => {
data.forEach(value => {
if (this._matrix[value.name]) {
this._matrix[value.name]['value'] = value.value || null
} else {
Expand All @@ -68,17 +68,16 @@ export class ChoroplethModel extends ChartModel {
*/
getTabularDataArray() {
const displayData = this.getDisplayData()

const result = [
['Country ID', 'Country Name', 'Value'],
...displayData.map((datum) => [
const headingLabels = ['Country ID', 'Country Name', 'Value']
const tableData = [
...displayData.map(datum => [
datum['id'] === null ? '–' : datum['id'],
datum['name'],
datum['value']
])
]

return result
return super.formatTable(headingLabels, tableData)
}

// Uses quantize scale to return class names
Expand Down
9 changes: 5 additions & 4 deletions packages/core/src/model/circle-pack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,19 @@ export class CirclePackChartModel extends ChartModel {
getTabularDataArray() {
const displayData = this.getDisplayData()

const result = [['Child', 'Parent', 'Value']]
const headingLabels = ['Child', 'Parent', 'Value']
const tableData = []

displayData.forEach((datum: any) => {
let value = datum.value ? datum.value : 0
if (datum.children) {
// Call recursive function
value += this.getChildrenDatums(datum.children, datum.name, result, 0)
value += this.getChildrenDatums(datum.children, datum.name, tableData, 0)
}
result.push(['–', datum.name, value])
tableData.push(['–', datum.name, value])
})

return result
return super.formatTable(headingLabels, tableData)
}

/**
Expand Down
7 changes: 3 additions & 4 deletions packages/core/src/model/gauge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ export class GaugeChartModel extends ChartModel {
const displayData = this.getDisplayData()
const options = this.getOptions()
const { groupMapsTo } = options.data

const result = [
['Group', 'Value'],
const headingLabels = ['Group', 'Value']
const tableData = [
...displayData.map((datum: any) => [
datum[groupMapsTo],
datum['value'] === null ? '–' : datum['value'].toLocaleString()
])
]

return result
return super.formatTable(headingLabels, tableData)
}
}
18 changes: 8 additions & 10 deletions packages/core/src/model/heatmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { AxisFlavor, ScaleTypes } from '@/interfaces/enums'
import { getColorScale } from '@/services'
import { ChartModelCartesian } from './cartesian-charts'


/** The gauge chart model layer */
export class HeatmapModel extends ChartModelCartesian {
axisFlavor = AxisFlavor.HOVERABLE
Expand Down Expand Up @@ -216,8 +215,8 @@ export class HeatmapModel extends ChartModelCartesian {
const rangeIdentifier = this.services.cartesianScales.getRangeIdentifier()

const arr: any[] = []
uniqueDomain.forEach((domain) => {
uniqueRange.forEach((range) => {
uniqueDomain.forEach(domain => {
uniqueRange.forEach(range => {
const element: any = {
value: this._matrix[domain][range].value,
index: this._matrix[domain][range].index
Expand All @@ -241,27 +240,26 @@ export class HeatmapModel extends ChartModelCartesian {
const { primaryDomain, primaryRange } = this.assignRangeAndDomains()

let domainValueFormatter: any

const result = [
[primaryDomain.label, primaryRange.label, 'Value'],
const headingLabels = [primaryDomain.label, primaryRange.label, 'Value']
const tableData = [
...displayData.map((datum: any) => [
datum[primaryDomain.identifier] === null
? '–'
: domainValueFormatter
? domainValueFormatter(datum[primaryDomain.identifier])
: datum[primaryDomain.identifier],
? domainValueFormatter(datum[primaryDomain.identifier])
: datum[primaryDomain.identifier],
datum[primaryRange.identifier] === null
? '–'
: datum[primaryRange.identifier].toLocaleString(),
datum['value']
])
]

return result
return super.formatTable(headingLabels, tableData)
}

// Uses quantize scale to return class names
getColorClassName(configs: { value?: number, originalClassName?: string }) {
getColorClassName(configs: { value?: number; originalClassName?: string }) {
return `${configs.originalClassName} ${this._colorScale(configs.value as number)}`
}

Expand Down
22 changes: 9 additions & 13 deletions packages/core/src/model/meter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ export class MeterChartModel extends ChartModel {
const boundedValue = getProperty(options, 'meter', 'proportional')
? totalValue
: totalValue > 100
? 100
: totalValue
? 100
: totalValue

// user needs to supply ranges
const allRanges = getProperty(options, 'meter', 'status', 'ranges')
Expand All @@ -73,24 +73,20 @@ export class MeterChartModel extends ChartModel {
const { groupMapsTo } = options.data
const status = this.getStatus()
const proportional = getProperty(options, 'meter', 'proportional')

let result: ChartTabularData = []
let headingLabels = []
let tableData: ChartTabularData = []
let domainMax: number
// Display the appropriate columns and fields depending on the type of meter
if (proportional === null) {
domainMax = 100
const datum = displayData[0]

result = [
['Group', 'Value', ...(status ? ['Status'] : [])],
[datum[groupMapsTo], datum['value'], ...(status ? [status] : [])]
]
headingLabels = ['Group', 'Value', ...(status ? ['Status'] : [])]
tableData = [[datum[groupMapsTo], datum['value'], ...(status ? [status] : [])]]
} else {
const total = getProperty(proportional, 'total')
domainMax = total ? total : this.getMaximumDomain(displayData)

result = [
['Group', 'Value', 'Percentage of total'],
headingLabels = ['Group', 'Value', 'Percentage of total']
tableData = [
...displayData.map((datum: any) => [
datum[groupMapsTo],
datum['value'],
Expand All @@ -99,6 +95,6 @@ export class MeterChartModel extends ChartModel {
]
}

return result
return super.formatTable(headingLabels, tableData)
}
}