Skip to content

Commit

Permalink
Preserve selected tab when switching mdim dimensions
Browse files Browse the repository at this point in the history
  • Loading branch information
rakyi committed Feb 21, 2025
1 parent 94656e8 commit d4b98e6
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 31 deletions.
22 changes: 5 additions & 17 deletions packages/@ourworldindata/explorer/src/Explorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
TableSlug,
GrapherInterface,
GrapherQueryParams,
GRAPHER_TAB_QUERY_PARAMS,
} from "@ourworldindata/types"
import {
OwidTable,
Expand All @@ -28,6 +27,7 @@ import {
DEFAULT_GRAPHER_ENTITY_TYPE,
GrapherAnalytics,
FocusArray,
getNextTabParamWhenSwitchingGrapher,
} from "@ourworldindata/grapher"
import {
Bounds,
Expand Down Expand Up @@ -448,22 +448,10 @@ export class Explorer

this.updateGrapherFromExplorer()

if (this.grapher.availableTabs.includes(previousTab)) {
// preserve the previous tab if that's still available in the new view
newGrapherParams.tab =
this.grapher.mapGrapherTabToQueryParam(previousTab)
} else if (this.grapher.validChartTypes.length > 0) {
// otherwise, switch to the first chart tab
newGrapherParams.tab = this.grapher.mapGrapherTabToQueryParam(
this.grapher.validChartTypes[0]
)
} else if (this.grapher.hasMapTab) {
// or switch to the map, if there is one
newGrapherParams.tab = GRAPHER_TAB_QUERY_PARAMS.map
} else {
// if everything fails, switch to the table tab that is always available
newGrapherParams.tab = GRAPHER_TAB_QUERY_PARAMS.table
}
newGrapherParams.tab = getNextTabParamWhenSwitchingGrapher(
this.grapher,
previousTab
)

this.grapher.populateFromQueryParams(newGrapherParams)

Expand Down
19 changes: 19 additions & 0 deletions packages/@ourworldindata/grapher/src/core/Grapher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3866,3 +3866,22 @@ export const getErrorMessageRelatedQuestionUrl = (
undefined
: undefined
}

export function getNextTabParamWhenSwitchingGrapher(
grapher: Grapher,
previousTab: GrapherTabName
): string {
if (grapher.availableTabs.includes(previousTab)) {
// preserve the previous tab if that's still available in the new view
return grapher.mapGrapherTabToQueryParam(previousTab)
} else if (grapher.validChartTypes.length > 0) {
// otherwise, switch to the first chart tab
return grapher.mapGrapherTabToQueryParam(grapher.validChartTypes[0])
} else if (grapher.hasMapTab) {
// or switch to the map, if there is one
return GRAPHER_TAB_QUERY_PARAMS.map
} else {
// if everything fails, switch to the table tab that is always available
return GRAPHER_TAB_QUERY_PARAMS.table
}
}
1 change: 1 addition & 0 deletions packages/@ourworldindata/grapher/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export {
type GrapherProgrammaticInterface,
type GrapherManager,
getErrorMessageRelatedQuestionUrl,
getNextTabParamWhenSwitchingGrapher,
} from "./core/Grapher"
export { GrapherAnalytics, EventCategory } from "./core/GrapherAnalytics"
import fuzzysort from "fuzzysort"
Expand Down
48 changes: 39 additions & 9 deletions site/multiDim/MultiDimDataPageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
Grapher,
GrapherAnalytics,
GrapherProgrammaticInterface,
getNextTabParamWhenSwitchingGrapher,
getVariableMetadataRoute,
} from "@ourworldindata/grapher"
import {
Expand Down Expand Up @@ -34,6 +35,7 @@ import {
import {
DataPageRelatedResearch,
FaqEntryKeyedByGdocIdAndFragmentId,
GrapherTabName,
ImageMetadata,
MultiDimDataPageConfigEnriched,
MultiDimDimensionChoices,
Expand Down Expand Up @@ -267,6 +269,16 @@ export const MultiDimDataPageContent = ({
// TODO we should probably fix that? seems sensible? change GrapherFigureView around a bit to use the actual grapher inst? or pass a GrapherProgrammaticInterface to it instead?
const [grapherInst, setGrapherInst] = useState<Grapher | null>(null)

const [previousGrapherConfig, setPreviousGrapherConfig] =
useState<GrapherInterface | null>(null)
const [previousTab, setPreviousTab] = useState<GrapherTabName | null>(null)

function handleUpdateSettings(newSettings: MultiDimDimensionChoices) {
setPreviousGrapherConfig(grapherConfigComputed)
setPreviousTab(grapherInst?.activeTab ?? null)
setCurrentSettings(newSettings)
}

// De-mobx grapher.changedParams by transforming it into React state
const grapherChangedParams = useMobxStateToReactState(
useCallback(() => grapherInst?.changedParams, [grapherInst]),
Expand All @@ -286,13 +298,27 @@ export const MultiDimDataPageContent = ({

const bounds = useElementBounds(grapherFigureRef)

const queryStr = useMemo(
() =>
grapherChangedParams !== undefined
? multiDimStateToQueryStr(grapherChangedParams, currentSettings)
: initialQueryStr,
[grapherChangedParams, currentSettings, initialQueryStr]
)
const queryStr = useMemo(() => {
if (grapherChangedParams !== undefined) {
const params = {
...grapherChangedParams,
}
if (grapherInst && previousTab) {
params.tab = getNextTabParamWhenSwitchingGrapher(
grapherInst,
previousTab
)
}
return multiDimStateToQueryStr(params, currentSettings)
}
return initialQueryStr
}, [
currentSettings,
grapherChangedParams,
grapherInst,
initialQueryStr,
previousTab,
])

useEffect(() => {
setWindowQueryStr(queryStr ?? "")
Expand All @@ -311,7 +337,10 @@ export const MultiDimDataPageContent = ({
manager: {}, // Don't resize while data is loading.
}

if (!grapherConfigIsReady) return baseConfig
// Use previous config if available to avoid unnecessary re-renders/jank
// instead of using the baseConfig just for a split second before the
// new config is ready.
if (!grapherConfigIsReady) return previousGrapherConfig ?? baseConfig
const variables = currentView?.indicators?.["y"]
const editUrl =
variables?.length === 1
Expand All @@ -331,6 +360,7 @@ export const MultiDimDataPageContent = ({
bounds,
canonicalUrl,
currentView?.indicators,
previousGrapherConfig,
])

const hasTopicTags = !!config.config.topicTags?.length
Expand Down Expand Up @@ -392,7 +422,7 @@ export const MultiDimDataPageContent = ({
<MultiDimSettingsPanel
config={config}
currentSettings={currentSettings}
updateSettings={setCurrentSettings}
onUpdateSettings={handleUpdateSettings}
/>
</div>
</div>
Expand Down
10 changes: 5 additions & 5 deletions site/multiDim/MultiDimDataPageSettingsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ const DimensionDropdown = (props: {
export const MultiDimSettingsPanel = (props: {
config: MultiDimDataPageConfig
currentSettings: MultiDimDimensionChoices
updateSettings?: (currentSettings: MultiDimDimensionChoices) => void
onUpdateSettings: (currentSettings: MultiDimDimensionChoices) => void
}) => {
const { config, currentSettings, updateSettings } = props
const { config, currentSettings, onUpdateSettings } = props

const { dimensions } = config

Expand All @@ -150,10 +150,10 @@ export const MultiDimSettingsPanel = (props: {
config.filterToAvailableChoices(resolvedCurrentSettings)

if (!isEqual(selectedChoices, resolvedCurrentSettings))
updateSettings?.(selectedChoices)
onUpdateSettings(selectedChoices)
if (!isEqual(dimensionsWithAvailableChoices, availableSettings))
setAvailableSettings(dimensionsWithAvailableChoices)
}, [resolvedCurrentSettings, config, updateSettings, availableSettings])
}, [resolvedCurrentSettings, config, onUpdateSettings, availableSettings])

return (
<div className="md-settings-row">
Expand All @@ -166,7 +166,7 @@ export const MultiDimSettingsPanel = (props: {
dimension={dim}
currentChoiceSlug={resolvedCurrentSettings[dim.slug]}
onChange={(slug, value) =>
updateSettings?.({
onUpdateSettings({
...resolvedCurrentSettings,
[slug]: value,
})
Expand Down

0 comments on commit d4b98e6

Please sign in to comment.