Skip to content

Commit

Permalink
🐛 (explorer) merge grapher configs correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
sophiamersmann committed Oct 30, 2024
1 parent d2370af commit 3597b31
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 64 deletions.
6 changes: 3 additions & 3 deletions baker/siteRenderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -826,12 +826,12 @@ const getExplorerTitleByUrl = async (
if (url.queryStr) {
explorer.initDecisionMatrix(url.queryParams as ExplorerFullQueryParams)
return (
explorer.grapherConfig.title ??
(explorer.grapherConfig.grapherId
explorer.explorerGrapherConfig.title ??
(explorer.explorerGrapherConfig.grapherId
? (
await getEnrichedChartById(
knex,
explorer.grapherConfig.grapherId
explorer.explorerGrapherConfig.grapherId
)
)?.config?.title
: undefined)
Expand Down
54 changes: 19 additions & 35 deletions explorer/Explorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
isInIFrame,
keyBy,
keyMap,
mergeGrapherConfigs,
omitUndefinedValues,
parseIntOrUndefined,
PromiseCache,
Expand Down Expand Up @@ -350,7 +351,7 @@ export class Explorer
reaction(
() => [
this.entityPickerMetric,
this.explorerProgram.grapherConfig.tableSlug,
this.explorerProgram.explorerGrapherConfig.tableSlug,
],
() => this.updateEntityPickerTable()
)
Expand Down Expand Up @@ -446,33 +447,11 @@ export class Explorer
}
}

// TODO: method can be removed in #4076
@action.bound private updateGrapherFromExplorerCommon() {
const grapher = this.grapher
if (!grapher) return
const {
yScaleToggle,
yAxisMin,
facetYDomain,
relatedQuestionText,
relatedQuestionUrl,
mapTargetTime,
} = this.explorerProgram.grapherConfig

grapher.yAxis.canChangeScaleType = yScaleToggle
grapher.yAxis.min = yAxisMin
if (facetYDomain) {
grapher.yAxis.facetDomain = facetYDomain
}
if (relatedQuestionText && relatedQuestionUrl) {
grapher.relatedQuestions = [
{ text: relatedQuestionText, url: relatedQuestionUrl },
]
}
if (mapTargetTime) {
grapher.map.time = mapTargetTime
}
grapher.slug = this.explorerProgram.slug
if (!grapher.id) grapher.id = 0
}

@computed private get columnDefsWithoutTableSlugByIdOrSlug(): Record<
Expand Down Expand Up @@ -525,12 +504,14 @@ export class Explorer
const grapher = this.grapher
if (!grapher) return

const { grapherId } = this.explorerProgram.grapherConfig
const { grapherId } = this.explorerProgram.explorerGrapherConfig
const grapherConfig = this.grapherConfigs.get(grapherId!) ?? {}

const config: GrapherProgrammaticInterface = {
...grapherConfig,
...this.explorerProgram.grapherConfigOnlyGrapherProps,
...mergeGrapherConfigs(
grapherConfig,
this.explorerProgram.grapherConfig
),
bakedGrapherURL: BAKED_GRAPHER_URL,
dataApiUrl: DATA_API_URL,
hideEntityControls: this.showExplorerControls,
Expand Down Expand Up @@ -561,7 +542,7 @@ export class Explorer
xSlug,
colorSlug,
sizeSlug,
} = this.explorerProgram.grapherConfig
} = this.explorerProgram.explorerGrapherConfig

const yVariableIdsList = yVariableIds
.split(" ")
Expand All @@ -573,8 +554,10 @@ export class Explorer
{}

const config: GrapherProgrammaticInterface = {
...partialGrapherConfig,
...this.explorerProgram.grapherConfigOnlyGrapherProps,
...mergeGrapherConfigs(
partialGrapherConfig,
this.explorerProgram.grapherConfig
),
bakedGrapherURL: BAKED_GRAPHER_URL,
dataApiUrl: DATA_API_URL,
hideEntityControls: this.showExplorerControls,
Expand Down Expand Up @@ -660,7 +643,7 @@ export class Explorer
}

config.dimensions = dimensions
if (config.ySlugs && yVariableIds) config.ySlugs += " " + yVariableIds
if (ySlugs && yVariableIds) config.ySlugs = ySlugs + " " + yVariableIds

const inputTableTransformer = (table: OwidTable) => {
// add transformed (and intermediate) columns to the grapher table
Expand Down Expand Up @@ -722,10 +705,10 @@ export class Explorer
@action.bound private updateGrapherFromExplorerUsingColumnSlugs() {
const grapher = this.grapher
if (!grapher) return
const { tableSlug } = this.explorerProgram.grapherConfig
const { tableSlug } = this.explorerProgram.explorerGrapherConfig

const config: GrapherProgrammaticInterface = {
...this.explorerProgram.grapherConfigOnlyGrapherProps,
...this.explorerProgram.grapherConfig,
bakedGrapherURL: BAKED_GRAPHER_URL,
dataApiUrl: DATA_API_URL,
hideEntityControls: this.showExplorerControls,
Expand Down Expand Up @@ -1072,7 +1055,7 @@ export class Explorer
// so that when we start sorting by entity name we can infer that the column is a string column immediately.
const tableSlugToLoad = this.entityPickerMetric
? this.getTableSlugOfColumnSlug(this.entityPickerMetric)
: this.explorerProgram.grapherConfig.tableSlug
: this.explorerProgram.explorerGrapherConfig.tableSlug

this.entityPickerTableIsLoading = true
void this.futureEntityPickerTable.set(
Expand Down Expand Up @@ -1108,7 +1091,8 @@ export class Explorer

// In most cases, column slugs will be duplicated in the tables, e.g. entityName.
// Prefer the current Grapher table if it contains the column slug.
const grapherTableSlug = this.explorerProgram.grapherConfig.tableSlug
const grapherTableSlug =
this.explorerProgram.explorerGrapherConfig.tableSlug
if (
this.tableSlugHasColumnSlug(
grapherTableSlug,
Expand Down
27 changes: 21 additions & 6 deletions explorer/ExplorerProgram.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ columns\ttable1\ttable2\ttable3
describe("grapherconfig", () => {
it("can return a grapher config", () => {
expect(
new ExplorerProgram("test", `yScaleToggle\ttrue`).grapherConfig
.yScaleToggle
new ExplorerProgram("test", `yScaleToggle\ttrue`)
.explorerGrapherConfig.yScaleToggle
).toEqual(true)
const program = new ExplorerProgram(
"test",
Expand All @@ -118,7 +118,7 @@ columns\ttable1\ttable2\ttable3
\ttrue\tLine`
)
expect(program.currentlySelectedGrapherRow).toEqual(2)
expect(program.grapherConfig.yScaleToggle).toEqual(true)
expect(program.explorerGrapherConfig.yScaleToggle).toEqual(true)
})

it("can convert \\n to a newline", () => {
Expand All @@ -128,7 +128,7 @@ columns\ttable1\ttable2\ttable3
\tsubtitle\tLine Checkbox
\tThis is a\\ntwo-line subtitle\tLine`
)
expect(program.grapherConfig.subtitle).toEqual(
expect(program.explorerGrapherConfig.subtitle).toEqual(
"This is a\ntwo-line subtitle"
)
})
Expand All @@ -142,9 +142,24 @@ graphers
\tyScaleToggle\tLine Checkbox
\ttrue\tLine`
)
expect(program.grapherConfig.hasMapTab).toEqual(true)
expect(program.explorerGrapherConfig.hasMapTab).toEqual(true)
// Only parse white listed grapher props
expect((program.grapherConfig as any).table).toEqual(undefined)
expect((program.explorerGrapherConfig as any).table).toEqual(
undefined
)
})

it("can translate explorer-specific settings to valid config fields", () => {
const program = new ExplorerProgram(
"test",
`hasMapTab\ttrue
table\tfoo
graphers
\tyAxisMin\tLine Checkbox
\t1\tLine`
)
expect(program.explorerGrapherConfig.yAxisMin).toEqual(1)
expect(program.grapherConfig.yAxis?.min).toEqual(1)
})
})

Expand Down
61 changes: 43 additions & 18 deletions explorer/ExplorerProgram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
PromiseCache,
SerializedGridProgram,
trimObject,
omit,
mergeGrapherConfigs,
} from "@ourworldindata/utils"
import {
CellDef,
Expand Down Expand Up @@ -241,8 +241,8 @@ export class ExplorerProgram extends GridProgram {
// that use Grapher IDs as well as CSV data files to create charts,
// but we plan to drop support for mixed-content explorers in the future
get chartCreationMode(): ExplorerChartCreationMode {
const { decisionMatrix, grapherConfig } = this
const { grapherId } = grapherConfig
const { decisionMatrix, explorerGrapherConfig } = this
const { grapherId } = explorerGrapherConfig
const yVariableIdsColumn = decisionMatrix.table.get(
GrapherGrammar.yVariableIds.keyword
)
Expand Down Expand Up @@ -358,29 +358,54 @@ export class ExplorerProgram extends GridProgram {
return clone
}

get grapherConfig(): ExplorerGrapherInterface {
/**
* Grapher config for the currently selected row including global settings.
* Includes all columns that are part of the GrapherGrammar.
*/
get explorerGrapherConfig(): ExplorerGrapherInterface {
const rootObject = trimAndParseObject(this.tuplesObject, GrapherGrammar)

Object.keys(rootObject).forEach((key) => {
if (!GrapherGrammar[key]) delete rootObject[key]
})
let config = { ...rootObject }

const selectedGrapherRow = this.decisionMatrix.selectedRow
if (selectedGrapherRow && Object.keys(selectedGrapherRow).length) {
return { ...rootObject, ...selectedGrapherRow }
config = { ...config, ...selectedGrapherRow }
}

return rootObject
// remove all keys that are not part of the GrapherGrammar
Object.keys(config).forEach((key) => {
if (!GrapherGrammar[key]) delete config[key]
})

return config
}

get grapherConfigOnlyGrapherProps() {
return omit(this.grapherConfig, [
GrapherGrammar.yVariableIds.keyword,
GrapherGrammar.xVariableId.keyword,
GrapherGrammar.colorVariableId.keyword,
GrapherGrammar.sizeVariableId.keyword,
GrapherGrammar.mapTargetTime.keyword,
])
/**
* Grapher config for the currently selected row, with explorer-specific
* fields translated to valid GrapherInterface fields.
*
* For example, `yAxisMin` is translated to `{yAxis: {min: ... }}`
*/
get grapherConfig(): GrapherInterface {
const configs: GrapherInterface[] = []

const fields = Object.entries(this.explorerGrapherConfig)
for (const [field, value] of fields) {
const grammarDef = GrapherGrammar[field]
configs.push(grammarDef.toGrapherObject(value))
}

const merged = mergeGrapherConfigs(...configs)

// TODO: can be removed once relatedQuestions is refactored
const { relatedQuestionUrl, relatedQuestionText } =
this.explorerGrapherConfig
if (relatedQuestionUrl && relatedQuestionText) {
merged.relatedQuestions = [
{ url: relatedQuestionUrl, text: relatedQuestionText },
]
}

return merged
}

/**
Expand Down
Loading

0 comments on commit 3597b31

Please sign in to comment.