Skip to content

Commit

Permalink
enhance(multi-dim): bake variable id -> config uuid map
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelgerber authored and danyx23 committed Sep 10, 2024
1 parent 4c94b5a commit 2eb9f96
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 15 deletions.
23 changes: 23 additions & 0 deletions baker/MultiDimBaker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import React from "react"
import { BAKED_BASE_URL } from "../settings/clientSettings.js"
import { getTagToSlugMap } from "./GrapherBakingUtils.js"
import {
getGrapherConfigIdsForVariables,
getVariableIdsByCatalogPath,
getVariableMetadata,
} from "../db/model/Variable.js"
Expand All @@ -38,6 +39,20 @@ import {
getMultiDimDataPageBySlug,
} from "../db/model/MultiDimDataPage.js"

const getGrapherConfigIdsByVariableIds = async (
knex: db.KnexReadonlyTransaction,
variableIds: number[]
): Promise<Record<number, string | null>> => {
const rows = await getGrapherConfigIdsForVariables(knex, variableIds)

return Object.fromEntries(
rows.map((row) => [
row.id,
row.grapherConfigIdAdmin ?? row.grapherConfigIdETL,
])
)
}

const resolveMultiDimDataPageCatalogPathsToIndicatorIds = async (
knex: db.KnexReadonlyTransaction,
rawConfig: MultiDimDataPageConfigRaw
Expand Down Expand Up @@ -206,6 +221,13 @@ export const renderMultiDimDataPageFromConfig = async (
await resolveMultiDimDataPageCatalogPathsToIndicatorIds(knex, rawConfig)
const config = MultiDimDataPageConfig.fromObject(preProcessedConfig)

// GET VARIABLE GRAPHER CONFIG UUIDS
const relevantVariableIds = getRelevantVariableIds(preProcessedConfig)
const variableIdToGrapherConfigMap = await getGrapherConfigIdsByVariableIds(
knex,
Array.from(relevantVariableIds)
)

// FAQs
const variableMetaDict =
await getRelevantVariableMetadata(preProcessedConfig)
Expand All @@ -224,6 +246,7 @@ export const renderMultiDimDataPageFromConfig = async (
const props = {
configObj: config.config,
tagToSlugMap: minimalTagToSlugMap,
variableIdToGrapherConfigMap,
faqEntries,
primaryTopic,
}
Expand Down
19 changes: 19 additions & 0 deletions db/model/Variable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,25 @@ interface VariableWithGrapherConfigs {
etl?: ChartConfigPair
}

type VariableWithGrapherConfigIds = Pick<
DbRawVariable,
"id" | "grapherConfigIdAdmin" | "grapherConfigIdETL"
>
export async function getGrapherConfigIdsForVariables(
knex: db.KnexReadonlyTransaction,
variableIds: number[]
): Promise<VariableWithGrapherConfigIds[]> {
const rows: VariableWithGrapherConfigIds[] = await knex(VariablesTableName)
.select([
"id",
"grapherConfigIdAdmin",
"grapherConfigIdETL",
] as (keyof DbRawVariable)[])
.whereIn("id", variableIds)

return rows
}

export async function getGrapherConfigsForVariable(
knex: db.KnexReadonlyTransaction,
variableId: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface Dimension {
name: string
group?: string
description?: string
multi_select?: boolean
// multi_select?: boolean
choices: Choice[]
}

Expand Down Expand Up @@ -83,6 +83,7 @@ export interface MultiDimDataPageProps {
tagToSlugMap?: Record<string, string>
faqEntries?: FaqEntryKeyedByGdocIdAndFragmentId
primaryTopic?: PrimaryTopic | undefined
variableIdToGrapherConfigMap?: Record<number, string | null>

initialQueryStr?: string
canonicalUrl?: string
Expand Down
87 changes: 73 additions & 14 deletions site/multiDim/MultiDimDataPageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
MultiDimDataPageConfig,
extractMultiDimChoicesFromQueryStr,
multiDimStateToQueryStr,
omit,
} from "@ourworldindata/utils"
import cx from "classnames"
import { DebugProvider } from "../gdocs/DebugContext.js"
Expand Down Expand Up @@ -101,6 +102,13 @@ const cachedGetVariableMetadata = memoize(
)
)

const cachedGetGrapherConfigByUuid = memoize(
(grapherConfigUuid: string): Promise<GrapherInterface> =>
fetch(`/grapher/by-uuid/${grapherConfigUuid}.config.json`).then(
(resp) => resp.json()
)
)

const useTitleFragments = (config: MultiDimDataPageConfig) => {
const title = config.config.title
return useMemo(
Expand All @@ -127,34 +135,70 @@ const useView = (
}

const useVarDatapageData = (
currentView: View<IndicatorsAfterPreProcessing> | undefined
currentView: View<IndicatorsAfterPreProcessing> | undefined,
variableIdToGrapherConfigMap: Record<number, string | null> | undefined
) => {
const [varDatapageData, setVarDatapageData] =
useState<DataPageDataV2 | null>(null)
const [grapherConfig, setGrapherConfig] = useState<GrapherInterface | null>(
null
)
const [grapherConfigIsReady, setGrapherConfigIsReady] = useState(false)

useEffect(() => {
setGrapherConfigIsReady(false)
setGrapherConfig(null)
setVarDatapageData(null)
const yIndicatorOrIndicators = currentView?.indicators?.["y"]
const variableId = Array.isArray(yIndicatorOrIndicators)
? yIndicatorOrIndicators[0]
: yIndicatorOrIndicators
if (!variableId) return
const variableMetadata = cachedGetVariableMetadata(variableId)

variableMetadata
.then((json) => getDatapageDataV2(json, currentView?.config))
.then(setVarDatapageData)
const datapageDataPromise = cachedGetVariableMetadata(variableId).then(
(json) => getDatapageDataV2(json, currentView?.config)
)
const grapherConfigUuid = variableIdToGrapherConfigMap?.[variableId]
const grapherConfigPromise = grapherConfigUuid
? cachedGetGrapherConfigByUuid(grapherConfigUuid)
: null

Promise.allSettled([datapageDataPromise, grapherConfigPromise])
.then(([datapageData, grapherConfig]) => {
if (datapageData.status === "rejected")
throw new Error(
`Fetching variable by uuid failed: ${grapherConfigUuid}`,
{ cause: datapageData.reason }
)

setVarDatapageData(datapageData.value)
setGrapherConfig(
grapherConfig.status === "fulfilled"
? grapherConfig.value
: null
)
setGrapherConfigIsReady(true)
})
.catch(console.error)
}, [currentView?.indicators, currentView?.config])
}, [
currentView?.indicators,
currentView?.config,
variableIdToGrapherConfigMap,
])

return { varDatapageData }
return {
varDatapageData,
varGrapherConfig: grapherConfig,
grapherConfigIsReady,
}
}

export const MultiDimDataPageContent = ({
// _datapageData,
configObj,
// isPreviewing = false,
faqEntries,
variableIdToGrapherConfigMap,
primaryTopic,
canonicalUrl = "{URL}", // when we bake pages to their proper url this will be set correctly but on preview pages we leave this undefined
tagToSlugMap,
Expand All @@ -179,7 +223,8 @@ export const MultiDimDataPageContent = ({
})

const { currentView, dimensionsConfig } = useView(currentSettings, config)
const { varDatapageData } = useVarDatapageData(currentView)
const { varDatapageData, varGrapherConfig, grapherConfigIsReady } =
useVarDatapageData(currentView, variableIdToGrapherConfigMap)

// This is the ACTUAL grapher instance being used, because GrapherFigureView/GrapherWithFallback are doing weird things and are not actually using the grapher instance we pass into it
// and therefore we can not access the grapher state (e.g. tab, selection) from the grapher instance we pass into it
Expand Down Expand Up @@ -207,15 +252,27 @@ export const MultiDimDataPageContent = ({
}, [queryStr])

const grapherConfigComputed = useMemo(() => {
const baseConfig: GrapherProgrammaticInterface = {
isEmbeddedInAnOwidPage: true,
selectedEntityNames: config.config.defaultSelection ?? [],
bounds,
}

if (!grapherConfigIsReady) return baseConfig
return {
...varGrapherConfig,
...currentView?.config,
dimensions: dimensionsConfig,
isEmbeddedInADataPage: true,
selectedEntityNames: config.config.defaultSelection ?? [],

bounds,
...baseConfig,
} as GrapherProgrammaticInterface
}, [currentView, dimensionsConfig, bounds, config])
}, [
varGrapherConfig,
grapherConfigIsReady,
currentView,
dimensionsConfig,
bounds,
config,
])

const hasTopicTags = !!config.config.topicTags?.length

Expand Down Expand Up @@ -293,7 +350,9 @@ export const MultiDimDataPageContent = ({
>
<figure data-grapher-src ref={grapherFigureRef}>
<Grapher
key={JSON.stringify(currentView)}
key={JSON.stringify(
omit(grapherConfigComputed, ["bounds"])
)}
{...grapherConfigComputed}
queryStr={queryStr}
getGrapherInstance={setGrapherInst}
Expand Down

0 comments on commit 2eb9f96

Please sign in to comment.