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 headers = ['Source', 'Target', 'Value']
const cells = [
...displayData.map((datum: any) => [datum['source'], datum['target'], datum['value']])
]

return result
return super.formatTable({ headers, cells })
}
}
12 changes: 6 additions & 6 deletions packages/core/src/model/binned-charts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ export class ChartModelBinned extends ChartModelCartesian {

const binnedStackedData = this.getBinnedStackedData()

const result = [
[
get(options, 'bins.rangeLabel') || 'Range',
...binnedStackedData.map(datum => get(datum, `0.${groupMapsTo}`))
],
const headers = [
get(options, 'bins.rangeLabel') || 'Range',
...binnedStackedData.map(datum => get(datum, `0.${groupMapsTo}`))
]
const cells = [
...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)}`))
])
]

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

const boxplotData = this.getBoxplotData()

const result = [
['Group', 'Minimum', 'Q1', 'Median', 'Q3', 'Maximum', 'IQR', 'Outlier(s)'],
const headers = ['Group', 'Minimum', 'Q1', 'Median', 'Q3', 'Maximum', 'IQR', 'Outlier(s)']
const cells = [
...boxplotData.map(datum => {
let outliers = getProperty(datum, 'outliers')
if (outliers === null || outliers.length === 0) {
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({ headers, cells })
}

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 headers = ['Title', 'Group', 'Value', 'Target', 'Percentage', 'Performance']
const cells = [
...displayData.map((datum: any) => [
datum['title'],
datum[groupMapsTo],
Expand All @@ -50,6 +49,6 @@ export class BulletChartModel extends ChartModelCartesian {
])
]

return result
return super.formatTable({ headers, cells })
}
}
73 changes: 29 additions & 44 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/format'
import { cloneDeep, uniq } from 'lodash-es'
import { getProperty } from '@/tools'
import { ChartModel } from './model'
Expand Down Expand Up @@ -54,53 +53,39 @@ 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 headers = [
'Group',
primaryDomain.label,
primaryRange.label,
...(secondaryDomain ? [secondaryDomain.label] : []),
...(secondaryRange ? [secondaryRange.label] : [])
]

return result
const cells = 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({ headers, cells })
}

setData(newData: any) {
Expand Down
7 changes: 3 additions & 4 deletions packages/core/src/model/choropleth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,16 @@ export class ChoroplethModel extends ChartModel {
*/
getTabularDataArray() {
const displayData = this.getDisplayData()

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

return result
return super.formatTable({ headers, cells })
}

// 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 headers = ['Child', 'Parent', 'Value']
const cells = []

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, cells, 0)
}
result.push(['–', datum.name, value])
cells.push(['–', datum.name, value])
})

return result
return super.formatTable({ headers, cells })
}

/**
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 headers = ['Group', 'Value']
const cells = [
...displayData.map((datum: any) => [
datum[groupMapsTo],
datum['value'] === null ? '–' : datum['value'].toLocaleString()
])
]

return result
return super.formatTable({ headers, cells })
}
}
8 changes: 4 additions & 4 deletions packages/core/src/model/heatmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,23 +240,23 @@ export class HeatmapModel extends ChartModelCartesian {
const { primaryDomain, primaryRange } = this.assignRangeAndDomains()

let domainValueFormatter: any

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

datum[primaryRange.identifier] === null
? '–'
: datum[primaryRange.identifier].toLocaleString(),
datum['value']
])
]

return result
return super.formatTable({ headers, cells })
}

// Uses quantize scale to return class names
Expand Down
18 changes: 7 additions & 11 deletions packages/core/src/model/meter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 headers = []
let cells: 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] : [])]
]
headers = ['Group', 'Value', ...(status ? ['Status'] : [])]
cells = [[datum[groupMapsTo], datum['value'], ...(status ? [status] : [])]]
} else {
const total = getProperty(proportional, 'total')
domainMax = total ? total : this.getMaximumDomain(displayData)

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

return result
return super.formatTable({ headers, cells })
}
}
27 changes: 27 additions & 0 deletions packages/core/src/model/model.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { format } from 'date-fns'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend this for better bundling with date-fns@3...

import { format } from 'date-fns/format'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RiyaJethwa could you pls take a look at this as well?

import { bin as d3Bin, scaleOrdinal, stack, stackOffsetDiverging } from 'd3'
import { cloneDeep, fromPairs, groupBy, merge, uniq } from 'lodash-es'
import { getProperty, updateLegendAdditionalItems } from '@/tools'
Expand Down Expand Up @@ -54,6 +55,31 @@ export class ChartModel {
this.services = services
}

formatTable({ headers, cells }) {
const options = this.getOptions()
const tableHeadingFormatter = getProperty(options, 'tabularRepModal', 'tableHeadingFormatter')
const tableCellFormatter = getProperty(options, 'tabularRepModal', 'tableCellFormatter')
const { cartesianScales } = this.services
const domainScaleType = cartesianScales?.getDomainAxisScaleType()
let domainValueFormatter: any

if (domainScaleType === ScaleTypes.TIME) {
domainValueFormatter = (d: any) => format(d, 'MMM d, yyyy')
}
const result = [
typeof tableHeadingFormatter === 'function' ? tableHeadingFormatter(headers) : headers,
...(typeof tableCellFormatter === 'function'
? tableCellFormatter(cells)
: cells.map((data: (string | number)[]) => {
if (domainValueFormatter) {
data[1] = domainValueFormatter(data[1]) as string
}
return data
}))
]
return result
}

getAllDataFromDomain(groups?: any) {
if (!this.getData()) {
return null
Expand Down Expand Up @@ -676,6 +702,7 @@ export class ChartModel {
}

getTabularDataArray(): ChartTabularData {
//apply tableFormatter
return []
}

Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/model/pie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ export class PieChartModel extends ChartModel {
const { groupMapsTo } = options.data
const { valueMapsTo } = options.pie

const result = [
['Group', 'Value'],
const headers = ['Group', 'Value']
const cells = [
...displayData.map((datum: any) => [
datum[groupMapsTo],
datum[valueMapsTo] === null ? '–' : datum[valueMapsTo].toLocaleString()
])
]

return result
return super.formatTable({ headers, cells })
}

sanitize(data: any) {
Expand Down
7 changes: 3 additions & 4 deletions packages/core/src/model/radar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ export class RadarChartModel extends ChartModelCartesian {
const { angle, value } = getProperty(options, 'radar', 'axes')

const additionalHeaders = getProperty(groupedData, '0', 'data').map((d: any) => d[angle])

const result = [
['Group', ...additionalHeaders],
const headers = ['Group', ...additionalHeaders]
const cells = [
...groupedData.map(datum => {
return [
datum['name'],
Expand All @@ -31,6 +30,6 @@ export class RadarChartModel extends ChartModelCartesian {
})
]

return result
return super.formatTable({ headers, cells })
}
}
Loading