diff --git a/adminSiteServer/testPageRouter.tsx b/adminSiteServer/testPageRouter.tsx index 8dbd771c3ff..4b85718654b 100644 --- a/adminSiteServer/testPageRouter.tsx +++ b/adminSiteServer/testPageRouter.tsx @@ -131,8 +131,8 @@ async function propsFromQueryParams( const page = params.page ? expectInt(params.page) : params.random - ? Math.floor(1 + Math.random() * 180) // Sample one of 180 pages. Some charts won't ever get picked but good enough. - : 1 + ? Math.floor(1 + Math.random() * 180) // Sample one of 180 pages. Some charts won't ever get picked but good enough. + : 1 const perPage = parseIntOrUndefined(params.perPage) ?? 20 const ids = parseIntArrayOrUndefined(params.ids) const datasetIds = parseIntArrayOrUndefined(params.datasetIds) @@ -807,7 +807,6 @@ getPlainRouteWithROTransaction( res.send(svg) } ) - testPageRouter.get("/explorers", async (req, res) => { let explorers = await explorerAdminServer.getAllPublishedExplorers() const viewProps = getViewPropsFromQueryParams(req.query) diff --git a/packages/@ourworldindata/explorer/src/Explorer.jsdom.test.tsx b/packages/@ourworldindata/explorer/src/Explorer.jsdom.test.tsx index e35fcf581c0..7eaa5d8de65 100755 --- a/packages/@ourworldindata/explorer/src/Explorer.jsdom.test.tsx +++ b/packages/@ourworldindata/explorer/src/Explorer.jsdom.test.tsx @@ -30,26 +30,28 @@ describe(Explorer, () => { explorer.onChangeChoice("Gas")("All GHGs (CO₂eq)") - if (explorer.grapher) explorer.grapher.tab = GRAPHER_TAB_OPTIONS.table + if (explorer.grapher?.grapherState) + explorer.grapher.grapherState.tab = GRAPHER_TAB_OPTIONS.table else throw Error("where's the grapher?") expect(explorer.queryParams.tab).toEqual("table") explorer.onChangeChoice("Gas")("CO₂") expect(explorer.queryParams.tab).toEqual("table") - explorer.grapher.tab = GRAPHER_TAB_OPTIONS.chart + explorer.grapher.grapherState.tab = GRAPHER_TAB_OPTIONS.chart }) it("switches to first tab if current tab does not exist in new view", () => { const explorer = element.instance() as Explorer expect(explorer.queryParams.tab).toBeUndefined() - if (explorer.grapher) explorer.grapher.tab = GRAPHER_TAB_OPTIONS.map + if (explorer.grapher?.grapherState) + explorer.grapher.grapherState.tab = GRAPHER_TAB_OPTIONS.map else throw Error("where's the grapher?") expect(explorer.queryParams.tab).toEqual("map") explorer.onChangeChoice("Gas")("All GHGs (CO₂eq)") - expect(explorer.grapher.tab).toEqual("chart") + expect(explorer.grapher?.grapherState.tab).toEqual("chart") expect(explorer.queryParams.tab).toEqual(undefined) }) @@ -85,10 +87,10 @@ describe("inline data explorer", () => { expect(explorer.queryParams).toMatchObject({ Test: "Scatter", }) - expect(explorer.grapher?.xSlug).toEqual("x") - expect(explorer.grapher?.ySlugs).toEqual("y") - expect(explorer.grapher?.colorSlug).toEqual("color") - expect(explorer.grapher?.sizeSlug).toEqual("size") + expect(explorer.grapher?.grapherState?.xSlug).toEqual("x") + expect(explorer.grapher?.grapherState?.ySlugs).toEqual("y") + expect(explorer.grapher?.grapherState?.colorSlug).toEqual("color") + expect(explorer.grapher?.grapherState?.sizeSlug).toEqual("size") }) it("clears column slugs that don't exist in current row", () => { @@ -96,9 +98,9 @@ describe("inline data explorer", () => { expect(explorer.queryParams).toMatchObject({ Test: "Line", }) - expect(explorer.grapher?.xSlug).toEqual(undefined) - expect(explorer.grapher?.ySlugs).toEqual("y") - expect(explorer.grapher?.colorSlug).toEqual(undefined) - expect(explorer.grapher?.sizeSlug).toEqual(undefined) + expect(explorer.grapher?.grapherState?.xSlug).toEqual(undefined) + expect(explorer.grapher?.grapherState?.ySlugs).toEqual("y") + expect(explorer.grapher?.grapherState?.colorSlug).toEqual(undefined) + expect(explorer.grapher?.grapherState?.sizeSlug).toEqual(undefined) }) }) diff --git a/packages/@ourworldindata/explorer/src/Explorer.tsx b/packages/@ourworldindata/explorer/src/Explorer.tsx index c74a1aa1fb3..42b9764e11f 100644 --- a/packages/@ourworldindata/explorer/src/Explorer.tsx +++ b/packages/@ourworldindata/explorer/src/Explorer.tsx @@ -27,6 +27,7 @@ import { SlideShowManager, DEFAULT_GRAPHER_ENTITY_TYPE, GrapherAnalytics, + GrapherState, FocusArray, } from "@ourworldindata/grapher" import { @@ -194,15 +195,23 @@ export class Explorer GrapherManager { analytics = new GrapherAnalytics() + grapherState: GrapherState constructor(props: ExplorerProps) { super(props) this.explorerProgram = ExplorerProgram.fromJson( props ).initDecisionMatrix(this.initialQueryParams) - this.grapher = new Grapher({ - bounds: props.bounds, + this.grapherState = new GrapherState({ staticBounds: props.staticBounds, + bounds: props.bounds, + enableKeyboardShortcuts: true, + manager: this, + isEmbeddedInAnOwidPage: this.props.isEmbeddedInAnOwidPage, + adminBaseUrl: this.adminBaseUrl, + }) + this.grapher = new Grapher({ + grapherState: this.grapherState, }) } // caution: do a ctrl+f to find untyped usages @@ -331,7 +340,7 @@ export class Explorer if (this.props.isInStandalonePage) this.setCanonicalUrl() - this.grapher?.populateFromQueryParams(url.queryParams) + this.grapher?.grapherState?.populateFromQueryParams(url.queryParams) exposeInstanceOnWindow(this, "explorer") this.setUpIntersectionObserver() @@ -352,7 +361,7 @@ export class Explorer this.explorerProgram.indexViewsSeparately && document.location.search ) { - document.title = `${this.grapher.displayTitle} - Our World in Data` + document.title = `${this.grapher?.grapherState.displayTitle} - Our World in Data` } } @@ -429,7 +438,7 @@ export class Explorer return // todo: can we remove this? this.initSlideshow() - const oldGrapherParams = this.grapher.changedParams + const oldGrapherParams = this.grapher?.grapherState.changedParams this.persistedGrapherQueryParamsBySelectedRow.set( oldSelectedRow, oldGrapherParams @@ -441,23 +450,26 @@ export class Explorer ), country: oldGrapherParams.country, region: oldGrapherParams.region, - time: this.grapher.timeParam, + time: this.grapher?.grapherState.timeParam, } - const previousTab = this.grapher.activeTab + const previousTab = this.grapher?.grapherState.activeTab this.updateGrapherFromExplorer() - if (this.grapher.availableTabs.includes(previousTab)) { + if (this.grapher?.grapherState.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) { + this.grapher?.grapherState.mapGrapherTabToQueryParam( + previousTab + ) + } else if (this.grapher?.grapherState.validChartTypes.length > 0) { // otherwise, switch to the first chart tab - newGrapherParams.tab = this.grapher.mapGrapherTabToQueryParam( - this.grapher.validChartTypes[0] - ) - } else if (this.grapher.hasMapTab) { + newGrapherParams.tab = + this.grapher?.grapherState.mapGrapherTabToQueryParam( + this.grapher?.grapherState.validChartTypes[0] + ) + } else if (this.grapher?.grapherState.hasMapTab) { // or switch to the map, if there is one newGrapherParams.tab = GRAPHER_TAB_QUERY_PARAMS.map } else { @@ -465,7 +477,7 @@ export class Explorer newGrapherParams.tab = GRAPHER_TAB_QUERY_PARAMS.table } - this.grapher.populateFromQueryParams(newGrapherParams) + this.grapher?.grapherState.populateFromQueryParams(newGrapherParams) this.analytics.logExplorerView( this.explorerProgram.slug, @@ -475,7 +487,7 @@ export class Explorer @action.bound private setGrapherTable(table: OwidTable) { if (this.grapher) { - this.grapher.inputTable = table + this.grapher.grapherState.inputTable = table this.grapher.appendNewEntitySelectionOptions() } } @@ -573,9 +585,9 @@ export class Explorer config.selectedEntityNames = this.selection.selectedEntityNames } - grapher.setAuthoredVersion(config) + grapher?.grapherState.setAuthoredVersion(config) grapher.reset() - grapher.updateFromObject(config) + grapher?.grapherState.updateFromObject(config) // grapher.downloadData() } @@ -737,9 +749,9 @@ export class Explorer return table } - grapher.setAuthoredVersion(config) + grapher?.grapherState.setAuthoredVersion(config) grapher.reset() - grapher.updateFromObject(config) + grapher?.grapherState.updateFromObject(config) if (dimensions.length === 0) { // If dimensions are empty, explicitly set the table to an empty table // so we don't end up confusingly showing stale data from a previous chart @@ -770,9 +782,9 @@ export class Explorer config.selectedEntityNames = this.selection.selectedEntityNames } - grapher.setAuthoredVersion(config) + grapher?.grapherState.setAuthoredVersion(config) grapher.reset() - grapher.updateFromObject(config) + grapher?.grapherState.updateFromObject(config) // Clear any error messages, they are likely to be related to dataset loading. this.grapher?.clearErrors() @@ -806,7 +818,7 @@ export class Explorer let url = Url.fromQueryParams( omitUndefinedValues({ - ...this.grapher.changedParams, + ...this.grapher?.grapherState.changedParams, pickerSort: this.entityPickerSort, pickerMetric: this.entityPickerMetric, hideControls: this.initialQueryParams.hideControls || undefined, @@ -1027,16 +1039,7 @@ export class Explorer this.isNarrow && this.mobileCustomizeButton}