Skip to content

Commit

Permalink
Feat/chart upgrades (#3154)
Browse files Browse the repository at this point in the history
* fix wording in charts

* Wording and name and label switch

* fix dashboard tab

* Added drop down to select users in dashboard

* pie chart and small fixes

* deepscan issues

* prop validations

* prop validations - for real

* fix codesmells

* small issues

* added fixes in dashboard

* Fixed comments in PR

* Removed options from components in the panel

* BarChart now with a single aggregation method

* Other charts upgraded with single agg

* Fix changing one chart to another

* remove codesmells

* refactor pie chart

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
persas and mergify[bot] authored Nov 21, 2023
1 parent 0c9bdac commit bc8dccb
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 98 deletions.
11 changes: 8 additions & 3 deletions server/modules/reporting/api/reportingApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,16 @@ export const init = (app) => {
const limit = chartSpec.chartType === 'scatterPlot' ? 10000 : null

// Modify the query to include aggregation if chartType is barChart
if (chartSpec.chartType === 'barChart' && chartSpec.query && chartSpec.query.metric && chartSpec.query.groupBy) {
if (
chartSpec.chartType === 'barChart' &&
chartSpec.query &&
chartSpec.query.metric &&
chartSpec.query.groupBy &&
chartSpec.query.aggregation
) {
const groupByFieldUuid = chartSpec.query.groupBy.field_uuid
const metricFieldUuid = chartSpec.query.metric.field_uuid
const aggregateFunction = chartSpec.query.metric.aggregate
const aggregateFunction = chartSpec.query.aggregation.type
const mode = 'aggregate'

query = Query.assocDimensions([groupByFieldUuid])(query)
Expand All @@ -59,7 +65,6 @@ export const init = (app) => {

query = Query.assocMode(mode)(query)
}

const data = await SurveyRdbService.fetchViewData({ user, surveyId, cycle, query, limit })

const chartResult = await generateChart({ chartSpec, data })
Expand Down
4 changes: 4 additions & 0 deletions webapp/views/App/views/Data/Charts/Charts.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const Charts = () => {
}
}, [spec, chartData])

useEffect(() => {
updateSpec(JSON.stringify({ ...spec, query: {}, chart: {} }))
}, [spec.chartType])

return (
<div className={classNames('charts', { 'full-screen': fullScreen })}>
<div className="charts_header">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const BarChart = ({ specs, originalData }) => {
const chartRef = useRef()

useEffect(() => {
if (!specs?.query?.metric || !specs?.query?.groupBy) return
if (!specs?.query?.metric || !specs?.query?.groupBy || !specs?.query?.aggregation) return

const groupByField = specs.query.groupBy.field

Expand All @@ -16,8 +16,8 @@ const BarChart = ({ specs, originalData }) => {
if (originalData?.chartResult) {
data = originalData.chartResult.map((item) => ({
groupBy: item[groupByField],
[`${specs.query.metric.field}_${specs.query.metric.aggregate || 'sum'}`]: parseFloat(
item[`${specs.query.metric.field}_${specs.query.metric.aggregate || 'sum'}`]
[`${specs.query.metric.field}_${specs.query.aggregation.type || 'sum'}`]: parseFloat(
item[`${specs.query.metric.field}_${specs.query.aggregation.type || 'sum'}`]
),
}))
} else {
Expand All @@ -27,7 +27,7 @@ const BarChart = ({ specs, originalData }) => {
renderBarChart(
data,
specs,
[`${specs.query.metric.field}_${specs.query.metric.aggregate || 'sum'}`],
[`${specs.query.metric.field}_${specs.query.aggregation.type || 'sum'}`],
groupByField,
chartRef
)
Expand All @@ -47,6 +47,9 @@ BarChart.propTypes = {
groupBy: PropTypes.shape({
field: PropTypes.string.isRequired,
}).isRequired,
aggregation: PropTypes.shape({
type: PropTypes.string.isRequired,
}).isRequired,
}).isRequired,
}).isRequired,
originalData: PropTypes.shape({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const PieChart = ({ specs, originalData }) => {
}

const drawPie = (svg, data, pie, radius, colorScale, categoryField, innerRadiusPercentage) => {
const innerRadius = (radius * innerRadiusPercentage) / 100 // Calculate inner radius based on the percentage
const innerRadius = (radius * innerRadiusPercentage) / 100
const arc = d3.arc().innerRadius(innerRadius).outerRadius(radius)

const pieData = pie(data)
Expand All @@ -115,8 +115,8 @@ const PieChart = ({ specs, originalData }) => {
const appendChartTitle = (svgContainer, width, margin, titleSize, title) => {
svgContainer
.append('text')
.attr('x', (width + margin.left + margin.right) / 2) // Center the title in the SVG container
.attr('y', margin.top / 2) // Position the title in the middle of the top margin
.attr('x', (width + margin.left + margin.right) / 2)
.attr('y', margin.top / 2)
.attr('text-anchor', 'middle')
.style('font-size', titleSize + 'px')
.text(title)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const processData = (originalData, specs) => {
const groupByField = specs?.query?.groupBy?.field
const metricField = specs?.query?.metric?.field
const aggregateType = specs?.query?.metric?.aggregate
const aggregateType = specs?.query?.aggregation?.type || 'sum'

let aggregatedData = {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,18 +203,6 @@ Metric.propTypes = {
const MetricBlock = ({ config, configItemsByPath, configActions, blockPath, dimensions, block }) => {
const { title, subtitle } = block

const options = useMemo(() => {
const metrics = configItemsByPath?.[blockPath]?.value || []
return (block.options || dimensions).filter((option) => !metrics.some((metric) => metric.key === option.key))
}, [dimensions, block, configItemsByPath, blockPath])

const flatOptions = useMemo(() => {
const metrics = configItemsByPath?.[blockPath]?.value || []
return (block.options || options.flatMap((d) => d.options)).filter(
(option) => !metrics.some((metric) => metric.key === option.key)
)
}, [options, block, configItemsByPath, blockPath])

const metrics = useMemo(() => configItemsByPath?.[blockPath]?.value || [], [configItemsByPath, blockPath])

return (
Expand Down Expand Up @@ -251,7 +239,6 @@ const MetricBlock = ({ config, configItemsByPath, configActions, blockPath, dime
/>
))}
</div>
<span className="block__number-options">{flatOptions.length} Option(s)</span>
</div>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useCallback, useMemo } from 'react'
import PropTypes from 'prop-types'

import { uuidv4 } from '@core/uuid'

Expand All @@ -14,11 +15,15 @@ const icons = {

const useOptionsAndDefaultValues = ({ block, dimensions }) => {
const { optionsParams = {} } = block
const { filter = [] } = optionsParams
const { filter = [], options: predefinedOptions = [] } = optionsParams

const options = useMemo(() => {
const _filter = (option) => (filter.length > 0 && option.type ? filter.includes(option.type) : true)

if (predefinedOptions.length > 0) {
return predefinedOptions
}

if (block.options) {
return block.options.filter(_filter)
}
Expand All @@ -28,10 +33,14 @@ const useOptionsAndDefaultValues = ({ block, dimensions }) => {
options: (dimension.options || []).filter(_filter),
})
)
}, [dimensions, block, filter])

const flatOptions = useMemo(() => block.options || options.flatMap((d) => d.options), [options, block])
}, [dimensions, block, filter, predefinedOptions])

const flatOptions = useMemo(() => {
if (predefinedOptions.length > 0) {
return predefinedOptions
}
return block.options || options.flatMap((d) => d.options)
}, [options, block, predefinedOptions])
return { options, flatOptions }
}

Expand Down Expand Up @@ -94,9 +103,18 @@ const SelectBlock = ({ configItemsByPath, configActions, blockPath, dimensions,
defaultSelection={defaultValues}
/>
)}
<span className="block__number-options">{flatOptions.length} Option(s)</span>
</div>
)
}

SelectBlock.propTypes = {
configItemsByPath: PropTypes.object.isRequired,
configActions: PropTypes.object.isRequired,
blockPath: PropTypes.string.isRequired,
dimensions: PropTypes.array.isRequired,
block: PropTypes.object.isRequired,
onChange: PropTypes.func,
values: PropTypes.object,
}

export default SelectBlock
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,6 @@ SingleCustomPopover.propTypes = {
const SingleMetricBlock = ({ config, configItemsByPath, configActions, blockPath, dimensions, block }) => {
const { title, subtitle } = block

const options = useMemo(() => block.options || dimensions, [dimensions, block])
const flatOptions = useMemo(() => block.options || options.flatMap((d) => d.options), [options, block])

const metric = useMemo(() => configItemsByPath?.[blockPath]?.value[0] || null, [configItemsByPath, blockPath])

return (
Expand Down Expand Up @@ -164,7 +161,6 @@ const SingleMetricBlock = ({ config, configItemsByPath, configActions, blockPath
/>
)}
</div>
<span className="block__number-options">{flatOptions.length} Option(s)</span>
</div>
)
}
Expand Down
49 changes: 39 additions & 10 deletions webapp/views/App/views/Data/Charts/state/chartTypes/bar/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TitleBlock, ShowLegendBlock, MaxHeightBlock, GroupByBlock, MetricBlock } from '../../blocks'
import { TitleBlock, ShowLegendBlock, MaxHeightBlock, GroupByBlock } from '../../blocks'
import { valuesToCalculations, valuesToSpec, sliderBlock } from '../../blocks/common'

const bar = {
Expand Down Expand Up @@ -39,18 +39,16 @@ const bar = {
return newSpec
},
}),
metric: MetricBlock({
metric: GroupByBlock({
id: 'metric',
title: 'Metric',
subtitle: 'Select the metric to measure the data ( Y axis )',
valuesToSpec: ({ spec = {}, key, configItemsByPath }) => {
const columnValues = configItemsByPath[`${key}.column`]?.value
const aggregationValues = configItemsByPath[`${key}.aggregation`]?.value
const transform = valuesToCalculations(columnValues, '-')
const aggTransform = valuesToCalculations(aggregationValues, '-')

optionsParams: { filter: ['quantitative'] },
valuesToSpec: ({ spec = {}, value = [] }) => {
const transform = valuesToCalculations(value)
const metric = {
field: transform.as,
field_uuid: transform.key,
aggregate: aggTransform.as,
type: 'quantitative',
}

Expand All @@ -64,8 +62,39 @@ const bar = {
return newSpec
},
}),
aggregation: GroupByBlock({
id: 'aggregation',
title: 'Aggregation Method',
subtitle: '',
isMulti: false,
optionsParams: {
options: [
{ value: 'average', label: 'Average', name: 'avg', type: 'aggregation' },
{ value: 'count', label: 'Count', name: 'count', type: 'aggregation' },
{ value: 'max', label: 'Maximum', name: 'max', type: 'aggregation' },
{ value: 'median', label: 'Median', name: 'median', type: 'aggregation' },
{ value: 'min', label: 'Minimum', name: 'min', type: 'aggregation' },
{ value: 'sum', label: 'Sum', name: 'sum', type: 'aggregation' },
],
},
valuesToSpec: ({ spec = {}, value = [] }) => {
const transform = valuesToCalculations(value)
const aggregation = {
type: transform.as,
}

const newSpec = {
...spec,
query: {
...spec.query,
aggregation,
},
}
return newSpec
},
}),
},
order: ['groupBy', 'metric'],
order: ['groupBy', 'metric', 'aggregation'],
},
other: {
title: 'Custom Chart',
Expand Down
10 changes: 10 additions & 0 deletions webapp/views/App/views/Data/Charts/state/chartTypes/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const aggregationOptions = {
options: [
{ value: 'average', label: 'Average', name: 'avg', type: 'aggregation' },
{ value: 'count', label: 'Count', name: 'count', type: 'aggregation' },
{ value: 'max', label: 'Maximum', name: 'max', type: 'aggregation' },
{ value: 'median', label: 'Median', name: 'median', type: 'aggregation' },
{ value: 'min', label: 'Minimum', name: 'min', type: 'aggregation' },
{ value: 'sum', label: 'Sum', name: 'sum', type: 'aggregation' },
],
}
58 changes: 33 additions & 25 deletions webapp/views/App/views/Data/Charts/state/chartTypes/pie/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TitleBlock, ShowLegendBlock, MetricBlock, GroupByBlock } from '../../blocks'
import { TitleBlock, ShowLegendBlock, GroupByBlock } from '../../blocks'
import { valuesToCalculations } from '../../blocks/common'
import { aggregationOptions } from '../common'

const pie = {
selector: {
Expand All @@ -21,49 +22,56 @@ const pie = {
blocks: {
groupBy: GroupByBlock({
valuesToSpec: ({ value = [], spec = {} }) => {
const transform = valuesToCalculations(value)
const groupBy = {
field_uuid: transform.key,
field: transform.as,
type: 'nominal',
}
const { key: field_uuid, as: field } = valuesToCalculations(value)
const groupBy = { field_uuid, field, type: 'nominal' }

const newSpec = {
return {
...spec,
query: {
...spec.query,
groupBy,
},
}
return newSpec
},
}),
metric: MetricBlock({
valuesToSpec: ({ spec = {}, key, configItemsByPath }) => {
const columnValues = configItemsByPath[`${key}.column`]?.value
const aggregationValues = configItemsByPath[`${key}.aggregation`]?.value
const transform = valuesToCalculations(columnValues, '-')
const aggTransform = valuesToCalculations(aggregationValues, '-')

const metric = {
field: transform.as,
field_uuid: transform.key,
aggregate: aggTransform.as,
type: 'quantitative',
}
metric: GroupByBlock({
id: 'metric',
title: 'Metric',
subtitle: '',
optionsParams: { filter: ['quantitative'] },
valuesToSpec: ({ spec = {}, value = [] }) => {
const { as: field, key: field_uuid } = valuesToCalculations(value)
const metric = { field, field_uuid, type: 'quantitative' }

const newSpec = {
return {
...spec,
query: {
...spec.query,
metric,
},
}
return newSpec
},
}),
aggregation: GroupByBlock({
id: 'aggregation',
title: 'Aggregation Method',
subtitle: '',
isMulti: false,
optionsParams: {
options: aggregationOptions,
},
valuesToSpec: ({ spec = {}, value = [] }) => ({
...spec,
query: {
...spec.query,
aggregation: {
type: valuesToCalculations(value).as,
},
},
}),
}),
},
order: ['groupBy', 'metric'],
order: ['groupBy', 'metric', 'aggregation'],
},
other: {
title: 'Custom Chart',
Expand Down
Loading

0 comments on commit bc8dccb

Please sign in to comment.