From ebd77e7e515f410406283e63f22c5905512945d2 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Thu, 14 Nov 2024 17:38:30 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A8=20(grapher)=20refactor=20chart=20t?= =?UTF-8?q?ype=20name=20and=20tab=20name=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adminSiteClient/ChartList.tsx | 13 +- adminSiteClient/EditorBasicTab.tsx | 11 +- adminSiteClient/EditorCustomizeTab.tsx | 8 +- adminSiteClient/GrapherConfigGridEditor.tsx | 5 +- adminSiteClient/VariableEditPage.tsx | 6 +- adminSiteServer/testPageRouter.tsx | 25 ++-- baker/updateChartEntities.ts | 6 +- .../1661264304751-MigrateSelectedData.ts | 12 +- db/model/Chart.ts | 4 +- db/model/Gdoc/GdocBase.ts | 4 +- db/model/Variable.ts | 4 +- devTools/graphersToGit/tasks.ts | 4 +- devTools/svgTester/chart-configurations.ts | 43 +++--- devTools/svgTester/dump-chart-ids.ts | 4 +- devTools/svgTester/utils.ts | 28 ++-- .../explorer/src/Explorer.jsdom.test.tsx | 8 +- .../explorer/src/Explorer.sample.tsx | 4 +- .../@ourworldindata/explorer/src/Explorer.tsx | 9 +- .../explorer/src/ExplorerProgram.ts | 4 +- .../explorer/src/GrapherGrammar.ts | 8 +- .../captionedChart/CaptionedChart.stories.tsx | 10 +- .../src/captionedChart/CaptionedChart.tsx | 7 +- .../grapher/src/chart/ChartTypeMap.tsx | 19 +-- .../grapher/src/chart/ChartTypeSwitcher.tsx | 6 +- .../grapher/src/chart/ChartUtils.tsx | 73 +++++----- .../grapher/src/color/ColorSchemes.ts | 24 ++-- .../grapher/src/controls/ChartIcons.tsx | 23 +-- .../grapher/src/controls/ContentSwitchers.tsx | 34 +++-- .../grapher/src/controls/SettingsMenu.tsx | 22 +-- .../src/controls/settings/AbsRelToggle.tsx | 10 +- .../grapher/src/core/Grapher.jsdom.test.ts | 93 ++++++------ .../grapher/src/core/Grapher.stories.tsx | 24 ++-- .../grapher/src/core/Grapher.tsx | 133 ++++++++++-------- .../grapher/src/core/GrapherConstants.ts | 4 +- .../core/GrapherWithChartTypes.jsdom.test.tsx | 4 +- .../src/core/LegacyToOwidTable.test.ts | 4 +- .../grapher/src/core/LegacyToOwidTable.ts | 6 +- .../src/dataTable/DataTable.jsdom.test.tsx | 6 +- .../grapher/src/dataTable/DataTable.sample.ts | 10 +- .../src/dataTable/DataTable.stories.tsx | 6 +- .../src/facetChart/FacetChart.stories.tsx | 8 +- .../grapher/src/facetChart/FacetChart.test.ts | 10 +- .../grapher/src/facetChart/FacetChart.tsx | 15 +- .../src/facetChart/FacetChartConstants.ts | 4 +- .../grapher/src/mapCharts/MapChart.sample.ts | 4 +- .../grapher/src/mapCharts/MapChart.tsx | 4 +- .../src/mapCharts/MapChartConstants.ts | 4 +- .../src/schema/migrations/migrations.ts | 6 +- .../MarimekkoChart.jsdom.test.tsx | 10 +- .../types/src/dbTypes/ChartConfigs.ts | 4 +- .../src/grapherTypes/GrapherConstants.ts | 53 +++++++ .../types/src/grapherTypes/GrapherTypes.ts | 66 ++------- packages/@ourworldindata/types/src/index.ts | 15 +- packages/@ourworldindata/utils/src/Util.ts | 6 +- .../utils/src/grapherConfigUtils.test.ts | 30 ++-- site/gdocs/components/Chart.tsx | 1 - .../components/KeyIndicatorCollection.tsx | 11 +- site/multiembedder/MultiEmbedder.tsx | 4 +- 58 files changed, 523 insertions(+), 460 deletions(-) diff --git a/adminSiteClient/ChartList.tsx b/adminSiteClient/ChartList.tsx index dccdf863c14..c3ed89386cc 100644 --- a/adminSiteClient/ChartList.tsx +++ b/adminSiteClient/ChartList.tsx @@ -4,9 +4,10 @@ import { runInAction, observable } from "mobx" import { bind } from "decko" import { AdminAppContext, AdminAppContextType } from "./AdminAppContext.js" import { - ChartTypeName, + GrapherChartType, GrapherInterface, - GrapherTabOption, + GRAPHER_CHART_TYPES, + GRAPHER_TAB_OPTIONS, } from "@ourworldindata/types" import { startCase, DbChartTagJoin } from "@ourworldindata/utils" import { References, getFullReferencesCount } from "./ChartEditor.js" @@ -24,7 +25,7 @@ export interface ChartListItem { tab: GrapherInterface["tab"] hasMapTab: GrapherInterface["hasMapTab"] - type?: ChartTypeName + type?: GrapherChartType hasChartTab: boolean lastEditedAt: string @@ -152,11 +153,11 @@ export function showChartType(chart: ChartListItem): string { if (!chartType) return "Map" - const displayType = ChartTypeName[chartType] - ? startCase(ChartTypeName[chartType]) + const displayType = GRAPHER_CHART_TYPES[chartType] + ? startCase(GRAPHER_CHART_TYPES[chartType]) : "Unknown" - if (chart.tab === GrapherTabOption.map) { + if (chart.tab === GRAPHER_TAB_OPTIONS.map) { if (chart.hasChartTab) return `Map + ${displayType}` else return "Map" } else { diff --git a/adminSiteClient/EditorBasicTab.tsx b/adminSiteClient/EditorBasicTab.tsx index 498fa1e2b8c..d10b6f76be7 100644 --- a/adminSiteClient/EditorBasicTab.tsx +++ b/adminSiteClient/EditorBasicTab.tsx @@ -9,9 +9,11 @@ import { } from "mobx" import { observer } from "mobx-react" import { - ChartTypeName, + GRAPHER_CHART_TYPES, EntitySelectionMode, StackMode, + ALL_GRAPHER_CHART_TYPES, + GrapherChartType, } from "@ourworldindata/types" import { DimensionSlot, @@ -359,7 +361,7 @@ export class EditorBasicTab< @action.bound onChartTypeChange(value: string) { const { grapher } = this.props.editor - const newChartType = value as ChartTypeName + const newChartType = value as GrapherChartType grapher.chartTypes = [newChartType] if (grapher.isMarimekko) { @@ -400,7 +402,6 @@ export class EditorBasicTab< render() { const { editor } = this.props const { grapher } = editor - const allChartTypes = Object.keys(ChartTypeName) const isIndicatorChart = isIndicatorChartEditorInstance(editor) @@ -412,7 +413,7 @@ export class EditorBasicTab< ({ + options={ALL_GRAPHER_CHART_TYPES.map((key) => ({ value: key, label: startCase(key), }))} @@ -423,7 +424,7 @@ export class EditorBasicTab< value={grapher.hasChartTab} onValue={(shouldHaveChartTab) => (grapher.chartTypes = shouldHaveChartTab - ? [ChartTypeName.LineChart] + ? [GRAPHER_CHART_TYPES.LineChart] : []) } /> diff --git a/adminSiteClient/EditorCustomizeTab.tsx b/adminSiteClient/EditorCustomizeTab.tsx index 2949b38a5d0..7f92dd1fb09 100644 --- a/adminSiteClient/EditorCustomizeTab.tsx +++ b/adminSiteClient/EditorCustomizeTab.tsx @@ -6,7 +6,7 @@ import { ColorSchemeName, FacetAxisDomain, FacetStrategy, - ChartTypeName, + GRAPHER_CHART_TYPES, } from "@ourworldindata/types" import { Grapher } from "@ourworldindata/grapher" import { @@ -161,7 +161,7 @@ export class ColorSchemeSelector extends React.Component<{ onBlur={this.onBlur} chartType={ this.props.grapher.chartType ?? - ChartTypeName.LineChart + GRAPHER_CHART_TYPES.LineChart } invertedColorScheme={!!grapher.invertColorScheme} additionalOptions={[ @@ -755,7 +755,9 @@ export class EditorCustomizeTab< {grapher.chartInstanceExceptMap.colorScale && ( >"$.hasMapTab" = "true"`) - tab = tab || GrapherTabOption.map + tab = tab || GRAPHER_TAB_OPTIONS.map } else { if (params.type === "LineChart") { query = query.andWhereRaw(`cc.chartType = "LineChart"`) @@ -160,7 +161,7 @@ async function propsFromQueryParams( type: params.type, }) } - tab = tab || GrapherTabOption.chart + tab = tab || GRAPHER_TAB_OPTIONS.chart } } @@ -168,26 +169,26 @@ async function propsFromQueryParams( query = query.andWhereRaw( `cc.full->>'$.yAxis.canChangeScaleType' = "true" OR cc.full->>'$.xAxis.canChangeScaleType' = "true"` ) - tab = GrapherTabOption.chart + tab = GRAPHER_TAB_OPTIONS.chart } if (params.comparisonLines) { query = query.andWhereRaw( `cc.full->'$.comparisonLines[0].yEquals' != ''` ) - tab = GrapherTabOption.chart + tab = GRAPHER_TAB_OPTIONS.chart } if (params.stackMode) { query = query.andWhereRaw(`cc.full->'$.stackMode' = :stackMode`, { stackMode: params.stackMode, }) - tab = GrapherTabOption.chart + tab = GRAPHER_TAB_OPTIONS.chart } if (params.relativeToggle) { query = query.andWhereRaw(`cc.full->>'$.hideRelativeToggle' = "false"`) - tab = GrapherTabOption.chart + tab = GRAPHER_TAB_OPTIONS.chart } if (params.categoricalLegend) { @@ -197,7 +198,7 @@ async function propsFromQueryParams( query = query.andWhereRaw( `json_length(cc.full->'$.map.colorScale.customCategoryColors') > 1` ) - tab = GrapherTabOption.map + tab = GRAPHER_TAB_OPTIONS.map } if (params.mixedTimeTypes) { @@ -237,9 +238,9 @@ async function propsFromQueryParams( query = query.andWhereRaw(`charts.id IN (${params.ids})`) } - if (tab === GrapherTabOption.map) { + if (tab === GRAPHER_TAB_OPTIONS.map) { query = query.andWhereRaw(`cc.full->>"$.hasMapTab" = "true"`) - } else if (tab === GrapherTabOption.chart) { + } else if (tab === GRAPHER_TAB_OPTIONS.chart) { query = query.andWhereRaw(`cc.chartType IS NOT NULL`) } diff --git a/baker/updateChartEntities.ts b/baker/updateChartEntities.ts index 10264e28155..49e582a71d8 100644 --- a/baker/updateChartEntities.ts +++ b/baker/updateChartEntities.ts @@ -9,7 +9,7 @@ import { ChartsXEntitiesTableName, DbPlainChart, GrapherInterface, - GrapherTabOption, + GRAPHER_TAB_OPTIONS, MultipleOwidVariableDataDimensionsMap, OwidVariableDataMetadataDimensions, DbRawChartConfig, @@ -97,7 +97,7 @@ const obtainAvailableEntitiesForGrapherConfig = async ( // If the grapher has a chart tab, then the available entities there are the "most interesting" ones to us if (grapher.hasChartTab) { - grapher.tab = GrapherTabOption.chart + grapher.tab = GRAPHER_TAB_OPTIONS.chart // If the grapher allows for changing or multi-selecting entities, then let's index all entities the // user can choose from. Otherwise, we'll just use the default-selected entities. @@ -112,7 +112,7 @@ const obtainAvailableEntitiesForGrapherConfig = async ( return grapher.tableForSelection.availableEntityNames as string[] else return grapher.selectedEntityNames ?? [] } else if (grapher.hasMapTab) { - grapher.tab = GrapherTabOption.map + grapher.tab = GRAPHER_TAB_OPTIONS.map // On a map tab, tableAfterAuthorTimelineAndActiveChartTransform contains all // mappable entities for which data is available return grapher.tableAfterAuthorTimelineAndActiveChartTransform diff --git a/db/migration/1661264304751-MigrateSelectedData.ts b/db/migration/1661264304751-MigrateSelectedData.ts index 5c8e73382ce..c7ae5880ac4 100644 --- a/db/migration/1661264304751-MigrateSelectedData.ts +++ b/db/migration/1661264304751-MigrateSelectedData.ts @@ -3,7 +3,7 @@ import { MigrationInterface, QueryRunner } from "typeorm" import { entityNameById } from "./data/entityNameById.js" -import { ChartTypeName } from "@ourworldindata/types" +import { GRAPHER_CHART_TYPES, GrapherChartType } from "@ourworldindata/types" type GrapherInterface = Record @@ -85,11 +85,11 @@ export class MigrateSelectedData1661264304751 implements MigrationInterface { } }) - const migrateDimensionsTypes: ChartTypeName[] = [ - ChartTypeName.Marimekko, - ChartTypeName.StackedArea, - ChartTypeName.StackedBar, - ChartTypeName.StackedDiscreteBar, + const migrateDimensionsTypes: GrapherChartType[] = [ + GRAPHER_CHART_TYPES.Marimekko, + GRAPHER_CHART_TYPES.StackedArea, + GRAPHER_CHART_TYPES.StackedBar, + GRAPHER_CHART_TYPES.StackedDiscreteBar, ] // Migrate order of dimensions. diff --git a/db/model/Chart.ts b/db/model/Chart.ts index e665f6301c0..7a74b18698d 100644 --- a/db/model/Chart.ts +++ b/db/model/Chart.ts @@ -13,7 +13,6 @@ import { } from "@ourworldindata/utils" import { GrapherInterface, - ChartTypeName, RelatedChart, DbPlainPostLink, DbPlainChart, @@ -22,6 +21,7 @@ import { DbPlainTag, DbRawChartConfig, DbEnrichedChartConfig, + GrapherChartType, } from "@ourworldindata/types" import { OpenAI } from "openai" import { @@ -556,7 +556,7 @@ export async function getChartVariableData( export const getMostViewedGrapherIdsByChartType = async ( knex: db.KnexReadonlyTransaction, - chartType: ChartTypeName, + chartType: GrapherChartType, count = 10 ): Promise => { const ids = await db.knexRaw<{ id: number }>( diff --git a/db/model/Gdoc/GdocBase.ts b/db/model/Gdoc/GdocBase.ts index 4dfacfe69f0..f0c5e036a38 100644 --- a/db/model/Gdoc/GdocBase.ts +++ b/db/model/Gdoc/GdocBase.ts @@ -19,7 +19,7 @@ import { OwidGdocMinimalPostInterface, urlToSlug, grabMetadataForGdocLinkedIndicator, - GrapherTabOption, + GRAPHER_TAB_OPTIONS, DbInsertPostGdocLink, DbPlainTag, formatDate, @@ -934,7 +934,7 @@ export async function makeGrapherLinkedChart( const resolvedSlug = config.slug ?? "" const resolvedTitle = config.title ?? "" const resolvedUrl = `${BAKED_GRAPHER_URL}/${resolvedSlug}` - const tab = config.tab ?? GrapherTabOption.chart + const tab = config.tab ?? GRAPHER_TAB_OPTIONS.chart const datapageIndicator = await getVariableOfDatapageIfApplicable(config) return { configType: ChartConfigType.Grapher, diff --git a/db/model/Variable.ts b/db/model/Variable.ts index c711945abb4..8c6d0afc081 100644 --- a/db/model/Variable.ts +++ b/db/model/Variable.ts @@ -23,7 +23,7 @@ import { OwidVariableMixedData, OwidVariableWithSourceAndDimension, OwidVariableId, - ChartTypeName, + GRAPHER_CHART_TYPES, DimensionProperty, GrapherInterface, DbRawVariable, @@ -880,7 +880,7 @@ export async function getVariableOfDatapageIfApplicable( // showing a data page. if ( yVariableIds.length === 1 && - (!grapher.chartTypes?.includes(ChartTypeName.ScatterPlot) || + (!grapher.chartTypes?.includes(GRAPHER_CHART_TYPES.ScatterPlot) || xVariableIds.length === 0) ) { const variableId = yVariableIds[0] diff --git a/devTools/graphersToGit/tasks.ts b/devTools/graphersToGit/tasks.ts index c5a95e87711..cc555c3ad30 100755 --- a/devTools/graphersToGit/tasks.ts +++ b/devTools/graphersToGit/tasks.ts @@ -2,7 +2,7 @@ import { CoreTable } from "@ourworldindata/core-table" import { - ChartTypeName, + GRAPHER_CHART_TYPES, ColorScaleConfig, Grapher, GrapherProgrammaticInterface, @@ -173,7 +173,7 @@ const dumpComplexSelections = async () => { : 0 return { grapherId: config.id, - type: config.type ?? ChartTypeName.LineChart, + type: config.type ?? GRAPHER_CHART_TYPES.LineChart, url: `https://ourworldindata.org/grapher/${config.slug}`, dimensionVariableCount, selectionVariableCount, diff --git a/devTools/svgTester/chart-configurations.ts b/devTools/svgTester/chart-configurations.ts index 8b2841bdc4c..f7de4b99909 100644 --- a/devTools/svgTester/chart-configurations.ts +++ b/devTools/svgTester/chart-configurations.ts @@ -1,10 +1,11 @@ import _ from "lodash" import { - ChartTypeName, + GRAPHER_CHART_TYPES, StackMode, ScaleType, FacetStrategy, GrapherQueryParams, + GrapherChartType, } from "@ourworldindata/types" import { cartesian } from "@ourworldindata/utils" @@ -32,8 +33,8 @@ const scaleTypeOptions = Object.values(ScaleType) const facetOptions = Object.values(FacetStrategy) const booleanOptions = Object.values(Boolean) -const VIEW_MATRIX_BY_CHART_TYPE: Record = { - [ChartTypeName.LineChart]: { +const VIEW_MATRIX_BY_CHART_TYPE: Record = { + [GRAPHER_CHART_TYPES.LineChart]: { tab: ["chart"], time: timeOptionsAll, stackMode: stackModeOptions, @@ -41,7 +42,7 @@ const VIEW_MATRIX_BY_CHART_TYPE: Record = { facet: facetOptions, uniformYAxis: booleanOptions, }, - [ChartTypeName.ScatterPlot]: { + [GRAPHER_CHART_TYPES.ScatterPlot]: { tab: ["chart"], time: timeOptionsAll, stackMode: stackModeOptions, @@ -50,38 +51,38 @@ const VIEW_MATRIX_BY_CHART_TYPE: Record = { endpointsOnly: booleanOptions, // zoomToSelection ignored for now }, - [ChartTypeName.DiscreteBar]: { + [GRAPHER_CHART_TYPES.DiscreteBar]: { tab: ["chart"], time: timePoints, facet: facetOptions, // uniformYAxis doesn't apply }, - [ChartTypeName.StackedDiscreteBar]: { + [GRAPHER_CHART_TYPES.StackedDiscreteBar]: { tab: ["chart"], time: timePoints, stackMode: stackModeOptions, facet: facetOptions, // uniformYAxis doesn't apply }, - [ChartTypeName.Marimekko]: { + [GRAPHER_CHART_TYPES.Marimekko]: { tab: ["chart"], time: timePoints, stackMode: stackModeOptions, showNoDataArea: booleanOptions, }, - [ChartTypeName.SlopeChart]: { + [GRAPHER_CHART_TYPES.SlopeChart]: { tab: ["chart"], time: timeSpan, yScale: scaleTypeOptions, }, - [ChartTypeName.StackedArea]: { + [GRAPHER_CHART_TYPES.StackedArea]: { tab: ["chart"], time: timeSpan, stackMode: stackModeOptions, facet: facetOptions, uniformYAxis: booleanOptions, }, - [ChartTypeName.StackedBar]: { + [GRAPHER_CHART_TYPES.StackedBar]: { tab: ["chart"], time: timeSpan, stackMode: stackModeOptions, @@ -94,16 +95,16 @@ const VIEW_MATRIX_BY_CHART_TYPE: Record = { // but some combinations don't make sense. this matrix is used to exclude those combinations. // for example, if a chart is not faceted, the uniformYAxis param doesn't apply const EXCLUDE_VIEWS_BY_CHART_TYPE: Record< - ChartTypeName, + GrapherChartType, Record[] > = { - [ChartTypeName.LineChart]: [ + [GRAPHER_CHART_TYPES.LineChart]: [ // sharing an axis only makes sense if a chart is faceted { facet: FacetStrategy.none, uniformYAxis: Boolean.true }, // log scale for percentage values doesn't make sense { stackMode: StackMode.relative, yScale: ScaleType.log }, ], - [ChartTypeName.ScatterPlot]: [ + [GRAPHER_CHART_TYPES.ScatterPlot]: [ // relative mode only makes sense if a time span is selected { time: TimePoint.earliest, stackMode: StackMode.relative }, { time: TimePoint.latest, stackMode: StackMode.relative }, @@ -116,15 +117,15 @@ const EXCLUDE_VIEWS_BY_CHART_TYPE: Record< { stackMode: StackMode.relative, yScale: ScaleType.log }, { stackMode: StackMode.relative, xScale: ScaleType.log }, ], - [ChartTypeName.DiscreteBar]: [], - [ChartTypeName.StackedDiscreteBar]: [], - [ChartTypeName.Marimekko]: [], - [ChartTypeName.SlopeChart]: [], - [ChartTypeName.StackedArea]: [ + [GRAPHER_CHART_TYPES.DiscreteBar]: [], + [GRAPHER_CHART_TYPES.StackedDiscreteBar]: [], + [GRAPHER_CHART_TYPES.Marimekko]: [], + [GRAPHER_CHART_TYPES.SlopeChart]: [], + [GRAPHER_CHART_TYPES.StackedArea]: [ // sharing an axis only makes sense if a chart is faceted { facet: FacetStrategy.none, uniformYAxis: Boolean.true }, ], - [ChartTypeName.StackedBar]: [ + [GRAPHER_CHART_TYPES.StackedBar]: [ // sharing an axis only makes sense if a chart is faceted { facet: FacetStrategy.none, uniformYAxis: Boolean.true }, ], @@ -135,7 +136,7 @@ export const queryStringsByChartType = Object.fromEntries( const combinations = explode(viewMatrix) const viewsToExclude = - EXCLUDE_VIEWS_BY_CHART_TYPE[chartType as ChartTypeName] + EXCLUDE_VIEWS_BY_CHART_TYPE[chartType as GrapherChartType] const validCombinations = combinations.filter((view) => viewsToExclude.every( (viewToExclude) => !_.isMatch(view, viewToExclude) @@ -145,7 +146,7 @@ export const queryStringsByChartType = Object.fromEntries( const queryStrings = validCombinations.map(toQueryStr) return [chartType, queryStrings] }) -) as Record +) as Record function toQueryStr(params: Record): string { return new URLSearchParams(params).toString() diff --git a/devTools/svgTester/dump-chart-ids.ts b/devTools/svgTester/dump-chart-ids.ts index c712903ad35..16055805e54 100644 --- a/devTools/svgTester/dump-chart-ids.ts +++ b/devTools/svgTester/dump-chart-ids.ts @@ -5,7 +5,7 @@ import parseArgs from "minimist" import { TransactionCloseMode, knexReadonlyTransaction } from "../../db/db.js" import { getMostViewedGrapherIdsByChartType } from "../../db/model/Chart.js" -import { allChartTypes } from "./utils.js" +import { ALL_GRAPHER_CHART_TYPES } from "@ourworldindata/types" const DEFAULT_OUT_FILE = "../owid-grapher-svgs/most-viewed-charts.txt" const CHART_COUNT_PER_TYPE = 25 @@ -15,7 +15,7 @@ async function main(parsedArgs: parseArgs.ParsedArgs) { const outFile = parsedArgs["o"] ?? DEFAULT_OUT_FILE const chartIds = await knexReadonlyTransaction(async (trx) => { - const promises = allChartTypes.flatMap((chartType) => + const promises = ALL_GRAPHER_CHART_TYPES.flatMap((chartType) => getMostViewedGrapherIdsByChartType( trx, chartType, diff --git a/devTools/svgTester/utils.ts b/devTools/svgTester/utils.ts index 21ac9162b4a..746e94a7bb6 100644 --- a/devTools/svgTester/utils.ts +++ b/devTools/svgTester/utils.ts @@ -1,7 +1,8 @@ import { - ChartTypeName, + GRAPHER_CHART_TYPES, + GrapherChartType, GrapherTabName, - GrapherTabOption, + ALL_GRAPHER_CHART_TYPES, } from "@ourworldindata/types" import { MultipleOwidVariableDataDimensionsMap, @@ -26,8 +27,6 @@ import { getHeapStatistics } from "v8" import { queryStringsByChartType } from "./chart-configurations.js" import * as d3 from "d3" -export const allChartTypes = Object.values(ChartTypeName) - // the owid-grapher-svgs repo is usually cloned as a sibling to the owid-grapher repo export const DEFAULT_CONFIGS_DIR = "../owid-grapher-svgs/configs" export const DEFAULT_REFERENCE_DIR = "../owid-grapher-svgs/svg" @@ -41,7 +40,7 @@ export const finished = util.promisify(stream.finished) // (A) export interface ChartWithQueryStr { id: number slug: string - type: ChartTypeName + type: GrapherChartType queryStr?: string } @@ -179,7 +178,7 @@ export async function selectChartIdsToProcess( options: { chartIdsFile?: string grapherIds?: number[] - chartTypes?: ChartTypeName[] + chartTypes?: GrapherChartType[] randomCount?: number } ): Promise { @@ -207,7 +206,7 @@ export async function findChartViewsToGenerate( const slug = grapherConfig.slug ?? chartId.toString() const chartType = - grapherConfig.chartTypes?.[0] ?? ChartTypeName.LineChart + grapherConfig.chartTypes?.[0] ?? GRAPHER_CHART_TYPES.LineChart const queryStrings = options.shouldTestAllViews ? queryStringsByChartType[chartType] @@ -237,7 +236,7 @@ export async function findValidChartIds( }: { chartIdsFile?: string grapherIds?: number[] - chartTypes?: ChartTypeName[] + chartTypes?: GrapherChartType[] } ): Promise { const validChartIds: number[] = [] @@ -286,7 +285,8 @@ export async function findValidChartIds( inDir, }) const chartType = - grapherConfig.chartTypes?.[0] ?? ChartTypeName.LineChart + grapherConfig.chartTypes?.[0] ?? + GRAPHER_CHART_TYPES.LineChart if (chartTypes.includes(chartType)) { validChartIds.push(grapherId) } @@ -297,17 +297,17 @@ export async function findValidChartIds( return validChartIds } -export function validateChartTypes(chartTypes: string[]): ChartTypeName[] { +export function validateChartTypes(chartTypes: string[]): GrapherChartType[] { const validChartTypes = chartTypes.filter( - (chartType): chartType is ChartTypeName => - allChartTypes.includes(chartType as any) + (chartType): chartType is GrapherChartType => + ALL_GRAPHER_CHART_TYPES.includes(chartType as any) ) const invalidChartTypes = chartTypes.filter( - (chartType) => !allChartTypes.includes(chartType as any) + (chartType) => !ALL_GRAPHER_CHART_TYPES.includes(chartType as any) ) if (invalidChartTypes.length) { console.warn( - `Invalid chart types given: ${invalidChartTypes}. Valid chart types are: ${allChartTypes}` + `Invalid chart types given: ${invalidChartTypes}. Valid chart types are: ${ALL_GRAPHER_CHART_TYPES}` ) } return _.uniq(validChartTypes) diff --git a/packages/@ourworldindata/explorer/src/Explorer.jsdom.test.tsx b/packages/@ourworldindata/explorer/src/Explorer.jsdom.test.tsx index 644852c0684..e35fcf581c0 100755 --- a/packages/@ourworldindata/explorer/src/Explorer.jsdom.test.tsx +++ b/packages/@ourworldindata/explorer/src/Explorer.jsdom.test.tsx @@ -8,7 +8,7 @@ import { import Enzyme from "enzyme" import Adapter from "@wojtekmaj/enzyme-adapter-react-17" -import { GrapherTabOption } from "@ourworldindata/types" +import { GRAPHER_TAB_OPTIONS } from "@ourworldindata/types" Enzyme.configure({ adapter: new Adapter() }) @@ -30,20 +30,20 @@ describe(Explorer, () => { explorer.onChangeChoice("Gas")("All GHGs (CO₂eq)") - if (explorer.grapher) explorer.grapher.tab = GrapherTabOption.table + if (explorer.grapher) explorer.grapher.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 = GrapherTabOption.chart + explorer.grapher.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 = GrapherTabOption.map + if (explorer.grapher) explorer.grapher.tab = GRAPHER_TAB_OPTIONS.map else throw Error("where's the grapher?") expect(explorer.queryParams.tab).toEqual("map") diff --git a/packages/@ourworldindata/explorer/src/Explorer.sample.tsx b/packages/@ourworldindata/explorer/src/Explorer.sample.tsx index a15b805a6f5..53cb8bff93e 100644 --- a/packages/@ourworldindata/explorer/src/Explorer.sample.tsx +++ b/packages/@ourworldindata/explorer/src/Explorer.sample.tsx @@ -1,6 +1,6 @@ import React from "react" import { DimensionProperty } from "@ourworldindata/utils" -import { GrapherTabOption } from "@ourworldindata/types" +import { GRAPHER_TAB_OPTIONS } from "@ourworldindata/types" import { GrapherProgrammaticInterface } from "@ourworldindata/grapher" import { Explorer, ExplorerProps } from "./Explorer.js" @@ -54,7 +54,7 @@ export const SampleExplorerOfGraphers = (props?: Partial) => { property: DimensionProperty.y, }, ], - tab: GrapherTabOption.chart, + tab: GRAPHER_TAB_OPTIONS.chart, owidDataset: new Map([ [ 142609, diff --git a/packages/@ourworldindata/explorer/src/Explorer.tsx b/packages/@ourworldindata/explorer/src/Explorer.tsx index c0595ae7285..09794a22202 100644 --- a/packages/@ourworldindata/explorer/src/Explorer.tsx +++ b/packages/@ourworldindata/explorer/src/Explorer.tsx @@ -8,8 +8,7 @@ import { TableSlug, GrapherInterface, GrapherQueryParams, - GrapherTabQueryParam, - GrapherTabName, + GRAPHER_TAB_QUERY_PARAMS, } from "@ourworldindata/types" import { OwidTable, @@ -455,14 +454,14 @@ export class Explorer } else if (this.grapher.validChartTypes.length > 0) { // otherwise, switch to the first chart tab newGrapherParams.tab = this.grapher.mapGrapherTabToQueryParam( - this.grapher.validChartTypes[0] as unknown as GrapherTabName + this.grapher.validChartTypes[0] ) } else if (this.grapher.hasMapTab) { // or switch to the map, if there is one - newGrapherParams.tab = GrapherTabQueryParam.WorldMap + newGrapherParams.tab = GRAPHER_TAB_QUERY_PARAMS.map } else { // if everything fails, switch to the table tab that is always available - newGrapherParams.tab = GrapherTabQueryParam.Table + newGrapherParams.tab = GRAPHER_TAB_QUERY_PARAMS.table } this.grapher.populateFromQueryParams(newGrapherParams) diff --git a/packages/@ourworldindata/explorer/src/ExplorerProgram.ts b/packages/@ourworldindata/explorer/src/ExplorerProgram.ts index 608382dff89..e547c6f08ba 100644 --- a/packages/@ourworldindata/explorer/src/ExplorerProgram.ts +++ b/packages/@ourworldindata/explorer/src/ExplorerProgram.ts @@ -8,7 +8,7 @@ import { FacetAxisDomain, GrapherInterface, AxisMinMaxValueStr, - ChartTypeName, + GrapherChartType, } from "@ourworldindata/types" import { CoreTable, @@ -65,7 +65,7 @@ interface ExplorerGrapherInterface extends GrapherInterface { relatedQuestionText?: string relatedQuestionUrl?: string mapTargetTime?: number - type?: ChartTypeName | "None" + type?: GrapherChartType | "None" } const ExplorerRootDef: CellDef = { diff --git a/packages/@ourworldindata/explorer/src/GrapherGrammar.ts b/packages/@ourworldindata/explorer/src/GrapherGrammar.ts index bbcb295f6a6..0f585645f78 100644 --- a/packages/@ourworldindata/explorer/src/GrapherGrammar.ts +++ b/packages/@ourworldindata/explorer/src/GrapherGrammar.ts @@ -1,9 +1,9 @@ import { - ChartTypeName, + GRAPHER_CHART_TYPES, ColorSchemeName, FacetAxisDomain, FacetStrategy, - GrapherTabOption, + GRAPHER_TAB_OPTIONS, MissingDataStrategy, StackMode, } from "@ourworldindata/types" @@ -65,7 +65,7 @@ export const GrapherGrammar: Grammar = { keyword: "type", description: `The type of chart to show such as LineChart or ScatterPlot. If set to None, then the chart tab is hidden.`, terminalOptions: toTerminalOptions([ - ...Object.values(ChartTypeName), + ...Object.values(GRAPHER_CHART_TYPES), "None", ]), toGrapherObject: (value) => ({ @@ -95,7 +95,7 @@ export const GrapherGrammar: Grammar = { ...EnumCellDef, keyword: "tab", description: "Which tab to show by default", - terminalOptions: toTerminalOptions(Object.values(GrapherTabOption)), + terminalOptions: toTerminalOptions(Object.values(GRAPHER_TAB_OPTIONS)), toGrapherObject: (value) => ({ tab: value }), }, xSlug: { diff --git a/packages/@ourworldindata/grapher/src/captionedChart/CaptionedChart.stories.tsx b/packages/@ourworldindata/grapher/src/captionedChart/CaptionedChart.stories.tsx index 63157d73e38..830ed484691 100644 --- a/packages/@ourworldindata/grapher/src/captionedChart/CaptionedChart.stories.tsx +++ b/packages/@ourworldindata/grapher/src/captionedChart/CaptionedChart.stories.tsx @@ -1,8 +1,8 @@ import { SynthesizeGDPTable } from "@ourworldindata/core-table" import { - ChartTypeName, + GRAPHER_CHART_TYPES, FacetStrategy, - GrapherTabOption, + GRAPHER_TAB_OPTIONS, SeriesStrategy, } from "@ourworldindata/types" import { DEFAULT_BOUNDS } from "@ourworldindata/utils" @@ -48,13 +48,13 @@ export const StaticLineChartForExport = (): React.ReactElement => { } export const MapChart = (): React.ReactElement => ( - + ) export const StackedArea = (): React.ReactElement => ( @@ -63,7 +63,7 @@ export const Scatter = (): React.ReactElement => ( diff --git a/packages/@ourworldindata/grapher/src/captionedChart/CaptionedChart.tsx b/packages/@ourworldindata/grapher/src/captionedChart/CaptionedChart.tsx index ec03ed8c7cb..3016ca8a62d 100644 --- a/packages/@ourworldindata/grapher/src/captionedChart/CaptionedChart.tsx +++ b/packages/@ourworldindata/grapher/src/captionedChart/CaptionedChart.tsx @@ -33,13 +33,14 @@ import { HeaderManager } from "../header/HeaderManager" import { SelectionArray } from "../selection/SelectionArray" import { EntityName, - ChartTypeName, + GRAPHER_CHART_TYPES, FacetStrategy, RelatedQuestionsConfig, Color, GrapherTabName, GRAPHER_MAP_TYPE, GrapherChartOrMapType, + GrapherChartType, } from "@ourworldindata/types" import { DataTable, DataTableManager } from "../dataTable/DataTable" import { @@ -82,7 +83,7 @@ export interface CaptionedChartManager activeTab?: GrapherTabName isOnMapTab?: boolean isOnTableTab?: boolean - activeChartType?: ChartTypeName + activeChartType?: GrapherChartType isLineChartThatTurnedIntoDiscreteBar?: boolean showEntitySelectionToggle?: boolean isExportingForSocialMedia?: boolean @@ -207,7 +208,7 @@ export class CaptionedChart extends React.Component { if (manager.isOnMapTab) return GRAPHER_MAP_TYPE if (manager.isOnChartTab) { return manager.isLineChartThatTurnedIntoDiscreteBar - ? ChartTypeName.DiscreteBar + ? GRAPHER_CHART_TYPES.DiscreteBar : manager.activeChartType } return undefined diff --git a/packages/@ourworldindata/grapher/src/chart/ChartTypeMap.tsx b/packages/@ourworldindata/grapher/src/chart/ChartTypeMap.tsx index 9fe6a92ef05..480dff70664 100644 --- a/packages/@ourworldindata/grapher/src/chart/ChartTypeMap.tsx +++ b/packages/@ourworldindata/grapher/src/chart/ChartTypeMap.tsx @@ -5,7 +5,7 @@ import { StackedAreaChart } from "../stackedCharts/StackedAreaChart" import { DiscreteBarChart } from "../barCharts/DiscreteBarChart" import { StackedBarChart } from "../stackedCharts/StackedBarChart" import { - ChartTypeName, + GRAPHER_CHART_TYPES, GrapherChartOrMapType, GRAPHER_MAP_TYPE, } from "@ourworldindata/types" @@ -31,15 +31,16 @@ export const ChartComponentClassMap = new Map< GrapherChartOrMapType, ChartComponentClass >([ - [ChartTypeName.DiscreteBar, DiscreteBarChart], - [ChartTypeName.LineChart, LineChart], - [ChartTypeName.SlopeChart, SlopeChart], - [ChartTypeName.StackedArea, StackedAreaChart], - [ChartTypeName.StackedBar, StackedBarChart], - [ChartTypeName.StackedDiscreteBar, StackedDiscreteBarChart], - [ChartTypeName.ScatterPlot, ScatterPlotChart], - [ChartTypeName.Marimekko, MarimekkoChart], + [GRAPHER_CHART_TYPES.DiscreteBar, DiscreteBarChart], + [GRAPHER_CHART_TYPES.LineChart, LineChart], + [GRAPHER_CHART_TYPES.SlopeChart, SlopeChart], + [GRAPHER_CHART_TYPES.StackedArea, StackedAreaChart], + [GRAPHER_CHART_TYPES.StackedBar, StackedBarChart], + [GRAPHER_CHART_TYPES.StackedDiscreteBar, StackedDiscreteBarChart], + [GRAPHER_CHART_TYPES.ScatterPlot, ScatterPlotChart], + [GRAPHER_CHART_TYPES.Marimekko, MarimekkoChart], [GRAPHER_MAP_TYPE, MapChart], ]) export const DefaultChartClass = LineChart as ChartComponentClass +export const defaultChartType = GRAPHER_CHART_TYPES.LineChart diff --git a/packages/@ourworldindata/grapher/src/chart/ChartTypeSwitcher.tsx b/packages/@ourworldindata/grapher/src/chart/ChartTypeSwitcher.tsx index 8afc64f6754..f583117e136 100644 --- a/packages/@ourworldindata/grapher/src/chart/ChartTypeSwitcher.tsx +++ b/packages/@ourworldindata/grapher/src/chart/ChartTypeSwitcher.tsx @@ -1,9 +1,9 @@ import React from "react" -import { ChartTypeName } from "@ourworldindata/types" +import { GRAPHER_CHART_TYPES } from "@ourworldindata/types" // Just a utility for testing export class ChartTypeSwitcher extends React.Component<{ - onChange: (chartType: ChartTypeName) => void + onChange: (chartType: GRAPHER_CHART_TYPES) => void }> { render(): React.ReactElement { return ( @@ -12,7 +12,7 @@ export class ChartTypeSwitcher extends React.Component<{ this.props.onChange(event.target.value as any) } > - {Object.values(ChartTypeName).map((value) => ( + {Object.values(GRAPHER_CHART_TYPES).map((value) => ( diff --git a/packages/@ourworldindata/grapher/src/chart/ChartUtils.tsx b/packages/@ourworldindata/grapher/src/chart/ChartUtils.tsx index 4a84f2b9721..51c340f6218 100644 --- a/packages/@ourworldindata/grapher/src/chart/ChartUtils.tsx +++ b/packages/@ourworldindata/grapher/src/chart/ChartUtils.tsx @@ -4,7 +4,7 @@ import { SeriesStrategy, EntityName, GrapherTabQueryParam, - ChartTypeName, + GRAPHER_CHART_TYPES, } from "@ourworldindata/types" import { LineChartSeries } from "../lineCharts/LineChartConstants" import { SelectionArray } from "../selection/SelectionArray" @@ -115,51 +115,48 @@ export function getShortNameForEntity(entityName: string): string | undefined { export function mapQueryParamToChartTypeName( chartTab: string -): ChartTypeName | undefined { +): GRAPHER_CHART_TYPES | undefined { switch (chartTab) { - case GrapherTabQueryParam.LineChart: - return ChartTypeName.LineChart - case GrapherTabQueryParam.SlopeChart: - return ChartTypeName.SlopeChart - case GrapherTabQueryParam.ScatterPlot: - return ChartTypeName.ScatterPlot - case GrapherTabQueryParam.StackedArea: - return ChartTypeName.StackedArea - case GrapherTabQueryParam.StackedBar: - return ChartTypeName.StackedBar - case GrapherTabQueryParam.DiscreteBar: - return ChartTypeName.DiscreteBar - case GrapherTabQueryParam.StackedDiscreteBar: - return ChartTypeName.StackedDiscreteBar - case GrapherTabQueryParam.Marimekko: - return ChartTypeName.Marimekko + case "LineChart": + return GRAPHER_CHART_TYPES.LineChart + case "SlopeChart": + return GRAPHER_CHART_TYPES.SlopeChart + case "ScatterPlot": + return GRAPHER_CHART_TYPES.ScatterPlot + case "StackedArea": + return GRAPHER_CHART_TYPES.StackedArea + case "StackedBar": + return GRAPHER_CHART_TYPES.StackedBar + case "DiscreteBar": + return GRAPHER_CHART_TYPES.DiscreteBar + case "StackedDiscreteBar": + return GRAPHER_CHART_TYPES.StackedDiscreteBar + case "Marimekko": + return GRAPHER_CHART_TYPES.Marimekko default: return undefined } } export function mapChartTypeNameToQueryParam( - chartType: ChartTypeName + chartType: GRAPHER_CHART_TYPES ): GrapherTabQueryParam { switch (chartType) { - case ChartTypeName.LineChart: - return GrapherTabQueryParam.LineChart - case ChartTypeName.SlopeChart: - return GrapherTabQueryParam.SlopeChart - case ChartTypeName.ScatterPlot: - return GrapherTabQueryParam.ScatterPlot - case ChartTypeName.StackedArea: - return GrapherTabQueryParam.StackedArea - case ChartTypeName.StackedBar: - return GrapherTabQueryParam.StackedBar - case ChartTypeName.DiscreteBar: - return GrapherTabQueryParam.DiscreteBar - case ChartTypeName.StackedDiscreteBar: - return GrapherTabQueryParam.StackedDiscreteBar - case ChartTypeName.Marimekko: - return GrapherTabQueryParam.Marimekko - // TODO: remove once stricter typed - default: - return GrapherTabQueryParam.LineChart + case GRAPHER_CHART_TYPES.LineChart: + return "line" + case GRAPHER_CHART_TYPES.SlopeChart: + return "slope" + case GRAPHER_CHART_TYPES.ScatterPlot: + return "scatter" + case GRAPHER_CHART_TYPES.StackedArea: + return "stacked-area" + case GRAPHER_CHART_TYPES.StackedBar: + return "stacked-bar" + case GRAPHER_CHART_TYPES.DiscreteBar: + return "discrete-bar" + case GRAPHER_CHART_TYPES.StackedDiscreteBar: + return "stacked-discrete-bar" + case GRAPHER_CHART_TYPES.Marimekko: + return "marimekko" } } diff --git a/packages/@ourworldindata/grapher/src/color/ColorSchemes.ts b/packages/@ourworldindata/grapher/src/color/ColorSchemes.ts index 376a1829055..7e553aee094 100644 --- a/packages/@ourworldindata/grapher/src/color/ColorSchemes.ts +++ b/packages/@ourworldindata/grapher/src/color/ColorSchemes.ts @@ -3,7 +3,7 @@ import { ColorScheme } from "./ColorScheme" import { match } from "ts-pattern" import { partition } from "@ourworldindata/utils" import { - ChartTypeName, + GRAPHER_CHART_TYPES, ColorSchemeInterface, ColorSchemeName, GRAPHER_MAP_TYPE, @@ -14,21 +14,21 @@ import { getColorBrewerScheme } from "./ColorBrewerSchemes.js" function getPreferredSchemesByType( type: GrapherChartOrMapType ): ColorSchemeName[] { - // This function could also be a Map but + // This function could also be a Map but // by doing it as a function usign ts-pattern.match we get compile - // time safety that all enum cases in ChartTypeName are always handled here + // time safety that all enum cases in GrapherChartOrMapType are always handled here return match(type) - .with(ChartTypeName.DiscreteBar, () => [ + .with(GRAPHER_CHART_TYPES.DiscreteBar, () => [ ColorSchemeName.SingleColorDenim, ColorSchemeName.SingleColorDustyCoral, ColorSchemeName.SingleColorPurple, ColorSchemeName.SingleColorTeal, ColorSchemeName.SingleColorDarkCopper, ]) - .with(ChartTypeName.LineChart, () => [ + .with(GRAPHER_CHART_TYPES.LineChart, () => [ ColorSchemeName.OwidDistinctLines, ]) - .with(ChartTypeName.Marimekko, () => [ + .with(GRAPHER_CHART_TYPES.Marimekko, () => [ ColorSchemeName.continents, ColorSchemeName.SingleColorDenim, ColorSchemeName.SingleColorDustyCoral, @@ -41,15 +41,15 @@ function getPreferredSchemesByType( ColorSchemeName.OwidCategoricalD, ColorSchemeName.OwidCategoricalE, ]) - .with(ChartTypeName.ScatterPlot, () => [ + .with(GRAPHER_CHART_TYPES.ScatterPlot, () => [ ColorSchemeName.continents, ColorSchemeName.OwidDistinctLines, ]) - .with(ChartTypeName.SlopeChart, () => [ + .with(GRAPHER_CHART_TYPES.SlopeChart, () => [ ColorSchemeName.continents, ColorSchemeName.OwidDistinctLines, ]) - .with(ChartTypeName.StackedArea, () => [ + .with(GRAPHER_CHART_TYPES.StackedArea, () => [ ColorSchemeName["owid-distinct"], ColorSchemeName.OwidCategoricalA, ColorSchemeName.OwidCategoricalB, @@ -62,7 +62,7 @@ function getPreferredSchemesByType( ColorSchemeName.SingleColorGradientDustyCoral, ColorSchemeName.SingleColorGradientDarkCopper, ]) - .with(ChartTypeName.StackedBar, () => [ + .with(GRAPHER_CHART_TYPES.StackedBar, () => [ ColorSchemeName["owid-distinct"], ColorSchemeName.OwidCategoricalA, ColorSchemeName.OwidCategoricalB, @@ -75,7 +75,7 @@ function getPreferredSchemesByType( ColorSchemeName.SingleColorGradientDustyCoral, ColorSchemeName.SingleColorGradientDarkCopper, ]) - .with(ChartTypeName.StackedDiscreteBar, () => [ + .with(GRAPHER_CHART_TYPES.StackedDiscreteBar, () => [ ColorSchemeName["owid-distinct"], ColorSchemeName.OwidCategoricalA, ColorSchemeName.OwidCategoricalB, @@ -133,7 +133,7 @@ const getAllColorSchemes = (): Map => { ) } -export function getColorSchemeForChartType(type: ChartTypeName): { +export function getColorSchemeForChartType(type: GrapherChartOrMapType): { [key in ColorSchemeName]: ColorScheme } { const preferred = new Set(getPreferredSchemesByType(type)) diff --git a/packages/@ourworldindata/grapher/src/controls/ChartIcons.tsx b/packages/@ourworldindata/grapher/src/controls/ChartIcons.tsx index 980c055edbf..b9198a89778 100644 --- a/packages/@ourworldindata/grapher/src/controls/ChartIcons.tsx +++ b/packages/@ourworldindata/grapher/src/controls/ChartIcons.tsx @@ -4,21 +4,22 @@ import { faChartBar, faChartLine, faChartColumn, - faEarthAmericas, } from "@fortawesome/free-solid-svg-icons" -import { ChartTypeName } from "@ourworldindata/types" +import { GRAPHER_CHART_TYPES } from "@ourworldindata/types" -export const chartIcons: Record = { +export const chartIcons: Record = { // line chart - [ChartTypeName.LineChart]: , + [GRAPHER_CHART_TYPES.LineChart]: , // bar charts - [ChartTypeName.DiscreteBar]: , - [ChartTypeName.StackedBar]: , - [ChartTypeName.StackedDiscreteBar]: , + [GRAPHER_CHART_TYPES.DiscreteBar]: , + [GRAPHER_CHART_TYPES.StackedBar]: , + [GRAPHER_CHART_TYPES.StackedDiscreteBar]: ( + + ), // scatter - [ChartTypeName.ScatterPlot]: ( + [GRAPHER_CHART_TYPES.ScatterPlot]: ( = { ), // marimekko - [ChartTypeName.Marimekko]: ( + [GRAPHER_CHART_TYPES.Marimekko]: ( = { ), // stacked area - [ChartTypeName.StackedArea]: ( + [GRAPHER_CHART_TYPES.StackedArea]: ( = { ), // slope chart - [ChartTypeName.SlopeChart]: ( + [GRAPHER_CHART_TYPES.SlopeChart]: ( - case GrapherTabName.WorldMap: + case GRAPHER_TAB_NAMES.WorldMap: return default: const chartIcon = isLineChartThatTurnedIntoDiscreteBar - ? chartIcons[ChartTypeName.DiscreteBar] - : chartIcons[tab as unknown as ChartTypeName] + ? chartIcons[GRAPHER_CHART_TYPES.DiscreteBar] + : chartIcons[tab] return chartIcon } } @@ -184,28 +188,28 @@ function makeTabLabelText( hasMultipleChartTypes?: boolean } ): string { - if (tab === GrapherTabName.Table) return "Table" - if (tab === GrapherTabName.WorldMap) return "Map" + if (tab === GRAPHER_TAB_NAMES.Table) return "Table" + if (tab === GRAPHER_TAB_NAMES.WorldMap) return "Map" if (!options.hasMultipleChartTypes) return "Chart" switch (tab) { - case GrapherTabName.LineChart: + case GRAPHER_TAB_NAMES.LineChart: return options.isLineChartThatTurnedIntoDiscreteBar ? "Bar" : "Line" - case GrapherTabName.SlopeChart: + case GRAPHER_TAB_NAMES.SlopeChart: return "Slope" // chart type labels are preliminary - case GrapherTabName.ScatterPlot: + case GRAPHER_TAB_NAMES.ScatterPlot: return "Scatter" - case GrapherTabName.StackedArea: + case GRAPHER_TAB_NAMES.StackedArea: return "Stacked area" - case GrapherTabName.StackedBar: + case GRAPHER_TAB_NAMES.StackedBar: return "Stacked bar" - case GrapherTabName.DiscreteBar: + case GRAPHER_TAB_NAMES.DiscreteBar: return "Bar" - case GrapherTabName.StackedDiscreteBar: + case GRAPHER_TAB_NAMES.StackedDiscreteBar: return "Stacked bar" - case GrapherTabName.Marimekko: + case GRAPHER_TAB_NAMES.Marimekko: return "Marimekko" default: return "Chart" diff --git a/packages/@ourworldindata/grapher/src/controls/SettingsMenu.tsx b/packages/@ourworldindata/grapher/src/controls/SettingsMenu.tsx index 7613fde4322..4843094e14a 100644 --- a/packages/@ourworldindata/grapher/src/controls/SettingsMenu.tsx +++ b/packages/@ourworldindata/grapher/src/controls/SettingsMenu.tsx @@ -4,7 +4,12 @@ import { observer } from "mobx-react" import classnames from "classnames" import { FontAwesomeIcon } from "@fortawesome/react-fontawesome/index.js" import { faGear } from "@fortawesome/free-solid-svg-icons" -import { EntityName, ChartTypeName, FacetStrategy } from "@ourworldindata/types" +import { + EntityName, + GRAPHER_CHART_TYPES, + FacetStrategy, + GrapherChartType, +} from "@ourworldindata/types" import { DEFAULT_BOUNDS } from "@ourworldindata/utils" import { SelectionArray } from "../selection/SelectionArray" import { ChartDimension } from "../chart/ChartDimension" @@ -43,7 +48,7 @@ const { StackedDiscreteBar, StackedBar, Marimekko, -} = ChartTypeName +} = GRAPHER_CHART_TYPES export interface SettingsMenuManager extends AbsRelToggleManager, @@ -64,7 +69,7 @@ export interface SettingsMenuManager hideTableFilterToggle?: boolean // chart state - activeChartType?: ChartTypeName + activeChartType?: GrapherChartType isRelativeMode?: boolean selection?: SelectionArray | EntityName[] canChangeAddOrHighlightEntities?: boolean @@ -101,8 +106,8 @@ export class SettingsMenu extends React.Component<{ return test.showSettingsMenuToggle } - @computed get chartType(): ChartTypeName { - return this.manager.activeChartType ?? ChartTypeName.LineChart + @computed get chartType(): GrapherChartType { + return this.manager.activeChartType ?? GRAPHER_CHART_TYPES.LineChart } @computed get maxWidth(): number { @@ -112,7 +117,8 @@ export class SettingsMenu extends React.Component<{ @computed get showYScaleToggle(): boolean | undefined { if (this.manager.hideYScaleToggle) return false if (this.manager.isRelativeMode) return false - if ([StackedArea, StackedBar].includes(this.chartType)) return false // We currently do not have these charts with log scale + if ([StackedArea, StackedBar].includes(this.chartType as any)) + return false // We currently do not have these charts with log scale return this.manager.yAxis.canChangeScaleType } @@ -161,7 +167,7 @@ export class SettingsMenu extends React.Component<{ ScatterPlot, LineChart, Marimekko, - ].includes(this.chartType) + ].includes(this.chartType as any) } @computed get showFacetControl(): boolean { @@ -184,7 +190,7 @@ export class SettingsMenu extends React.Component<{ StackedBar, StackedDiscreteBar, LineChart, - ].includes(this.chartType) + ].includes(this.chartType as any) const hasProjection = filledDimensions.some( (dim) => dim.display.isProjection diff --git a/packages/@ourworldindata/grapher/src/controls/settings/AbsRelToggle.tsx b/packages/@ourworldindata/grapher/src/controls/settings/AbsRelToggle.tsx index fd9e6c17a55..b90e825960b 100644 --- a/packages/@ourworldindata/grapher/src/controls/settings/AbsRelToggle.tsx +++ b/packages/@ourworldindata/grapher/src/controls/settings/AbsRelToggle.tsx @@ -1,15 +1,19 @@ import React from "react" import { computed, action } from "mobx" import { observer } from "mobx-react" -import { ChartTypeName, StackMode } from "@ourworldindata/types" +import { + GRAPHER_CHART_TYPES, + GrapherChartType, + StackMode, +} from "@ourworldindata/types" import { LabeledSwitch } from "@ourworldindata/components" -const { LineChart, ScatterPlot } = ChartTypeName +const { LineChart, ScatterPlot } = GRAPHER_CHART_TYPES export interface AbsRelToggleManager { stackMode?: StackMode relativeToggleLabel?: string - activeChartType?: ChartTypeName + activeChartType?: GrapherChartType } @observer diff --git a/packages/@ourworldindata/grapher/src/core/Grapher.jsdom.test.ts b/packages/@ourworldindata/grapher/src/core/Grapher.jsdom.test.ts index 956e6dd4e00..e96211f7d67 100755 --- a/packages/@ourworldindata/grapher/src/core/Grapher.jsdom.test.ts +++ b/packages/@ourworldindata/grapher/src/core/Grapher.jsdom.test.ts @@ -2,15 +2,15 @@ import { Grapher, GrapherProgrammaticInterface } from "../core/Grapher" import { defaultGrapherConfig } from "../schema/defaultGrapherConfig" import { - ChartTypeName, + GRAPHER_CHART_TYPES, EntitySelectionMode, - GrapherTabOption, + GRAPHER_TAB_OPTIONS, ScaleType, GrapherInterface, GrapherQueryParams, LegacyGrapherInterface, LegacyGrapherQueryParams, - GrapherTabName, + GRAPHER_TAB_NAMES, } from "@ourworldindata/types" import { TimeBoundValue, @@ -72,7 +72,7 @@ it("can get dimension slots", () => { const grapher = new Grapher() expect(grapher.dimensionSlots.length).toBe(2) - grapher.chartTypes = [ChartTypeName.ScatterPlot] + grapher.chartTypes = [GRAPHER_CHART_TYPES.ScatterPlot] expect(grapher.dimensionSlots.length).toBe(4) }) @@ -99,7 +99,7 @@ it("a bad chart type does not crash grapher", () => { }) it("does not preserve defaults in the object (except for the schema)", () => { - expect(new Grapher({ tab: GrapherTabOption.chart }).toObject()).toEqual({ + expect(new Grapher({ tab: GRAPHER_TAB_OPTIONS.chart }).toObject()).toEqual({ $schema: defaultGrapherConfig.$schema, // TODO: ideally, selectedEntityNames is not serialised for an empty object @@ -212,24 +212,24 @@ it("can generate a url with country selection even if there is no entity code", describe("hasTimeline", () => { it("charts with timeline", () => { const grapher = new Grapher(legacyConfig) - grapher.chartTypes = [ChartTypeName.LineChart] + grapher.chartTypes = [GRAPHER_CHART_TYPES.LineChart] expect(grapher.hasTimeline).toBeTruthy() - grapher.chartTypes = [ChartTypeName.SlopeChart] + grapher.chartTypes = [GRAPHER_CHART_TYPES.SlopeChart] expect(grapher.hasTimeline).toBeTruthy() - grapher.chartTypes = [ChartTypeName.StackedArea] + grapher.chartTypes = [GRAPHER_CHART_TYPES.StackedArea] expect(grapher.hasTimeline).toBeTruthy() - grapher.chartTypes = [ChartTypeName.StackedBar] + grapher.chartTypes = [GRAPHER_CHART_TYPES.StackedBar] expect(grapher.hasTimeline).toBeTruthy() - grapher.chartTypes = [ChartTypeName.DiscreteBar] + grapher.chartTypes = [GRAPHER_CHART_TYPES.DiscreteBar] expect(grapher.hasTimeline).toBeTruthy() }) it("map tab has timeline even if chart doesn't", () => { const grapher = new Grapher(legacyConfig) grapher.hideTimeline = true - grapher.chartTypes = [ChartTypeName.LineChart] + grapher.chartTypes = [GRAPHER_CHART_TYPES.LineChart] expect(grapher.hasTimeline).toBeFalsy() - grapher.tab = GrapherTabOption.map + grapher.tab = GRAPHER_TAB_OPTIONS.map expect(grapher.hasTimeline).toBeTruthy() grapher.map.hideTimeline = true expect(grapher.hasTimeline).toBeFalsy() @@ -380,7 +380,7 @@ describe("authors can use maxTime", () => { const table = SynthesizeGDPTable({ timeRange: [2000, 2010] }) const grapher = new Grapher({ table, - chartTypes: [ChartTypeName.DiscreteBar], + chartTypes: [GRAPHER_CHART_TYPES.DiscreteBar], selectedEntityNames: table.availableEntityNames, maxTime: 2005, ySlugs: "GDP", @@ -396,7 +396,7 @@ describe("line chart to bar chart and bar chart race", () => { it("can create a new line chart with different start and end times", () => { expect( grapher.typeExceptWhenLineChartAndSingleTimeThenWillBeBarChart - ).toEqual(ChartTypeName.LineChart) + ).toEqual(GRAPHER_CHART_TYPES.LineChart) expect(grapher.endHandleTimeBound).toBeGreaterThan( grapher.startHandleTimeBound ) @@ -408,13 +408,13 @@ describe("line chart to bar chart and bar chart race", () => { expect( grapher.typeExceptWhenLineChartAndSingleTimeThenWillBeBarChart - ).toEqual(ChartTypeName.LineChart) + ).toEqual(GRAPHER_CHART_TYPES.LineChart) grapher.startHandleTimeBound = 2000 grapher.endHandleTimeBound = 2000 expect( grapher.typeExceptWhenLineChartAndSingleTimeThenWillBeBarChart - ).toEqual(ChartTypeName.DiscreteBar) + ).toEqual(GRAPHER_CHART_TYPES.DiscreteBar) it("still has a timeline even though its now a bar chart", () => { expect(grapher.hasTimeline).toBe(true) @@ -450,7 +450,7 @@ describe("line chart to bar chart and bar chart race", () => { ) expect( grapher.typeExceptWhenLineChartAndSingleTimeThenWillBeBarChart - ).toEqual(ChartTypeName.LineChart) + ).toEqual(GRAPHER_CHART_TYPES.LineChart) }) it("turns into a bar chart when constrained start & end handles are equal", () => { @@ -458,7 +458,7 @@ describe("line chart to bar chart and bar chart race", () => { grapher.endHandleTimeBound = Infinity expect( grapher.typeExceptWhenLineChartAndSingleTimeThenWillBeBarChart - ).toEqual(ChartTypeName.DiscreteBar) + ).toEqual(GRAPHER_CHART_TYPES.DiscreteBar) }) }) @@ -483,7 +483,7 @@ describe("urls", () => { isPublished: true, slug: "foo", bakedGrapherURL: "/grapher", - tab: GrapherTabOption.map, + tab: GRAPHER_TAB_OPTIONS.map, }) expect(grapher.embedUrl).toEqual("/grapher/foo?tab=map") }) @@ -514,67 +514,78 @@ describe("urls", () => { it("parses tab=table correctly", () => { const grapher = new Grapher() grapher.populateFromQueryParams({ tab: "table" }) - expect(grapher.activeTab).toEqual(GrapherTabName.Table) + expect(grapher.activeTab).toEqual(GRAPHER_TAB_NAMES.Table) }) it("parses tab=map correctly", () => { const grapher = new Grapher() grapher.populateFromQueryParams({ tab: "map" }) - expect(grapher.activeTab).toEqual(GrapherTabName.WorldMap) + expect(grapher.activeTab).toEqual(GRAPHER_TAB_NAMES.Map) }) it("parses tab=chart correctly", () => { - const grapher = new Grapher({ chartTypes: [ChartTypeName.ScatterPlot] }) + const grapher = new Grapher({ + chartTypes: [GRAPHER_CHART_TYPES.ScatterPlot], + }) grapher.populateFromQueryParams({ tab: "chart" }) - expect(grapher.activeTab).toEqual(GrapherTabName.ScatterPlot) + expect(grapher.activeTab).toEqual(GRAPHER_TAB_NAMES.ScatterPlot) }) it("parses tab=line and tab=slope correctly", () => { const grapher = new Grapher({ - chartTypes: [ChartTypeName.LineChart, ChartTypeName.SlopeChart], + chartTypes: [ + GRAPHER_CHART_TYPES.LineChart, + GRAPHER_CHART_TYPES.SlopeChart, + ], }) grapher.populateFromQueryParams({ tab: "line" }) - expect(grapher.activeTab).toEqual(GrapherTabName.LineChart) + expect(grapher.activeTab).toEqual(GRAPHER_TAB_NAMES.LineChart) grapher.populateFromQueryParams({ tab: "slope" }) - expect(grapher.activeTab).toEqual(GrapherTabName.SlopeChart) + expect(grapher.activeTab).toEqual(GRAPHER_TAB_NAMES.SlopeChart) }) it("switches to the first chart tab if the given chart isn't available", () => { const grapher = new Grapher({ - chartTypes: [ChartTypeName.LineChart, ChartTypeName.SlopeChart], + chartTypes: [ + GRAPHER_CHART_TYPES.LineChart, + GRAPHER_CHART_TYPES.SlopeChart, + ], }) grapher.populateFromQueryParams({ tab: "bar" }) - expect(grapher.activeTab).toEqual(GrapherTabName.LineChart) + expect(grapher.activeTab).toEqual(GRAPHER_TAB_NAMES.LineChart) }) it("switches to the map tab if no chart is available", () => { const grapher = new Grapher({ chartTypes: [], hasMapTab: true }) grapher.populateFromQueryParams({ tab: "line" }) - expect(grapher.activeTab).toEqual(GrapherTabName.WorldMap) + expect(grapher.activeTab).toEqual(GRAPHER_TAB_NAMES.Map) }) it("switches to the table tab if it's the only tab available", () => { const grapher = new Grapher({ chartTypes: [] }) grapher.populateFromQueryParams({ tab: "line" }) - expect(grapher.activeTab).toEqual(GrapherTabName.Table) + expect(grapher.activeTab).toEqual(GRAPHER_TAB_NAMES.Table) }) it("adds tab=chart to the URL if there is a single chart tab", () => { const grapher = new Grapher({ hasMapTab: true, - tab: GrapherTabOption.map, + tab: GRAPHER_TAB_OPTIONS.map, }) - grapher.setTab(GrapherTabName.LineChart) + grapher.setTab(GRAPHER_TAB_NAMES.LineChart) expect(grapher.changedParams.tab).toEqual("chart") }) it("adds the chart type name as tab query param if there are multiple chart tabs", () => { const grapher = new Grapher({ - chartTypes: [ChartTypeName.LineChart, ChartTypeName.SlopeChart], + chartTypes: [ + GRAPHER_CHART_TYPES.LineChart, + GRAPHER_CHART_TYPES.SlopeChart, + ], hasMapTab: true, - tab: GrapherTabOption.map, + tab: GRAPHER_TAB_OPTIONS.map, }) - grapher.setTab(GrapherTabName.LineChart) + grapher.setTab(GRAPHER_TAB_NAMES.LineChart) expect(grapher.changedParams.tab).toEqual("line") }) }) @@ -902,7 +913,7 @@ describe("year parameter (applies to map only)", () => { }) it(`encode ${test.name}`, () => { const params = toQueryParams({ - tab: GrapherTabOption.map, + tab: GRAPHER_TAB_OPTIONS.map, map: { time: test.param }, }) expect(params.time).toEqual(test.query) @@ -968,7 +979,7 @@ describe("year parameter (applies to map only)", () => { it(`encode ${test.name}`, () => { const grapher = getGrapher() grapher.updateFromObject({ - tab: GrapherTabOption.map, + tab: GRAPHER_TAB_OPTIONS.map, map: { time: test.param }, }) const params = grapher.changedParams @@ -986,7 +997,7 @@ it("correctly identifies activeColumnSlugs", () => { `) const grapher = new Grapher({ table, - chartTypes: [ChartTypeName.ScatterPlot], + chartTypes: [GRAPHER_CHART_TYPES.ScatterPlot], xSlug: "gdp", ySlugs: "child_mortality", colorSlug: "continent", @@ -1024,7 +1035,7 @@ it("considers map tolerance before using column tolerance", () => { const grapher = new Grapher({ table, ySlugs: "gdp", - tab: GrapherTabOption.map, + tab: GRAPHER_TAB_OPTIONS.map, hasMapTab: true, map: new MapConfig({ timeTolerance: 1, columnSlug: "gdp", time: 2002 }), }) @@ -1084,7 +1095,7 @@ describe("tableForSelection", () => { const grapher = new Grapher({ table, - chartTypes: [ChartTypeName.ScatterPlot], + chartTypes: [GRAPHER_CHART_TYPES.ScatterPlot], excludedEntities: [3], xSlug: "x", ySlugs: "y", @@ -1120,7 +1131,7 @@ it("handles tolerance when there are gaps in ScatterPlot data", () => { const grapher = new Grapher({ table, - chartTypes: [ChartTypeName.ScatterPlot], + chartTypes: [GRAPHER_CHART_TYPES.ScatterPlot], xSlug: "x", ySlugs: "y", minTime: 1999, diff --git a/packages/@ourworldindata/grapher/src/core/Grapher.stories.tsx b/packages/@ourworldindata/grapher/src/core/Grapher.stories.tsx index 84248560305..e7b31d2b84b 100644 --- a/packages/@ourworldindata/grapher/src/core/Grapher.stories.tsx +++ b/packages/@ourworldindata/grapher/src/core/Grapher.stories.tsx @@ -6,9 +6,9 @@ import { BlankOwidTable, } from "@ourworldindata/core-table" import { - ChartTypeName, + GRAPHER_CHART_TYPES, FacetStrategy, - GrapherTabOption, + GRAPHER_TAB_OPTIONS, } from "@ourworldindata/types" import { action, observable } from "mobx" import { observer } from "mobx-react" @@ -49,7 +49,7 @@ export const Line = (): React.ReactElement => export const SlopeChart = (): React.ReactElement => { const model = { - chartTypes: [ChartTypeName.SlopeChart], + chartTypes: [GRAPHER_CHART_TYPES.SlopeChart], ...basics, } return @@ -57,7 +57,7 @@ export const SlopeChart = (): React.ReactElement => { export const ScatterPlot = (): React.ReactElement => { const model = { - chartTypes: [ChartTypeName.ScatterPlot], + chartTypes: [GRAPHER_CHART_TYPES.ScatterPlot], ...basics, } return @@ -65,7 +65,7 @@ export const ScatterPlot = (): React.ReactElement => { export const DiscreteBar = (): React.ReactElement => { const model = { - chartTypes: [ChartTypeName.DiscreteBar], + chartTypes: [GRAPHER_CHART_TYPES.DiscreteBar], ...basics, } return @@ -73,7 +73,7 @@ export const DiscreteBar = (): React.ReactElement => { export const StackedBar = (): React.ReactElement => { const model = { - chartTypes: [ChartTypeName.StackedBar], + chartTypes: [GRAPHER_CHART_TYPES.StackedBar], ...basics, } return @@ -81,7 +81,7 @@ export const StackedBar = (): React.ReactElement => { export const StackedArea = (): React.ReactElement => { const model = { - chartTypes: [ChartTypeName.StackedArea], + chartTypes: [GRAPHER_CHART_TYPES.StackedArea], ...basics, } return @@ -90,14 +90,14 @@ export const StackedArea = (): React.ReactElement => { export const MapFirst = (): React.ReactElement => { const model = { ...basics, - tab: GrapherTabOption.map, + tab: GRAPHER_TAB_OPTIONS.map, } return } export const BlankGrapher = (): React.ReactElement => { const model = { - tab: GrapherTabOption.map, + tab: GRAPHER_TAB_OPTIONS.map, table: BlankOwidTable(), hasMapTab: true, } @@ -114,7 +114,7 @@ export const NoMap = (): React.ReactElement => { export const Faceting = (): React.ReactElement => { const model = { - chartTypes: [ChartTypeName.StackedArea], + chartTypes: [GRAPHER_CHART_TYPES.StackedArea], facet: FacetStrategy.entity, ...basics, } @@ -141,11 +141,11 @@ class PerfGrapher extends React.Component { @observable.ref table = basics.table! - @action.bound private changeChartType(type: ChartTypeName): void { + @action.bound private changeChartType(type: GRAPHER_CHART_TYPES): void { this.chartTypeName = type } - @observable chartTypeName = ChartTypeName.LineChart + @observable chartTypeName = GRAPHER_CHART_TYPES.LineChart render(): React.ReactElement { const key = Math.random() // I do this hack to force a rerender until can re-add the grapher model/grapher view that we used to have. @breck 10/29/2020 diff --git a/packages/@ourworldindata/grapher/src/core/Grapher.tsx b/packages/@ourworldindata/grapher/src/core/Grapher.tsx index eaf418865fd..3810d9773b9 100644 --- a/packages/@ourworldindata/grapher/src/core/Grapher.tsx +++ b/packages/@ourworldindata/grapher/src/core/Grapher.tsx @@ -73,8 +73,7 @@ import { sumTextWrapHeights, } from "@ourworldindata/components" import { - ChartTypeName, - GrapherTabOption, + GrapherChartType, ScaleType, StackMode, EntitySelectionMode, @@ -107,7 +106,12 @@ import { Color, GRAPHER_QUERY_PARAM_KEYS, GrapherTabName, - GrapherTabQueryParam, + GRAPHER_CHART_TYPES, + GRAPHER_TAB_OPTIONS, + GRAPHER_TAB_NAMES, + GRAPHER_TAB_QUERY_PARAMS, + GrapherTabOption, + // GRAPHER_TAB_NAMES, } from "@ourworldindata/types" import { BlankOwidTable, @@ -357,7 +361,9 @@ export class Grapher SlopeChartManager { @observable.ref $schema = defaultGrapherConfig.$schema - @observable.ref chartTypes = [ChartTypeName.LineChart] + @observable.ref chartTypes: GrapherChartType[] = [ + GRAPHER_CHART_TYPES.LineChart, + ] @observable.ref id?: number = undefined @observable.ref version = 1 @observable.ref slug?: string = undefined @@ -392,8 +398,8 @@ export class Grapher @observable.ref zoomToSelection?: boolean = undefined @observable.ref showYearLabels?: boolean = undefined // Always show year in labels for bar charts @observable.ref hasMapTab = false - @observable.ref tab = GrapherTabOption.chart - @observable.ref chartTab?: ChartTypeName // TODO: remove map from ChartTypeName + @observable.ref tab: GrapherTabOption = GRAPHER_TAB_OPTIONS.chart + @observable.ref chartTab?: GrapherChartType @observable.ref isPublished?: boolean = undefined @observable.ref baseColorScheme?: ColorSchemeName = undefined @observable.ref invertColorScheme?: boolean = undefined @@ -698,22 +704,26 @@ export class Grapher } @computed get activeTab(): GrapherTabName { - if (this.tab === GrapherTabOption.table) return GrapherTabName.Table - if (this.tab === GrapherTabOption.map) return GrapherTabName.WorldMap - if (this.chartTab) return this.chartTab as unknown as GrapherTabName - return ( - (this.validChartTypes[0] as unknown as GrapherTabName) ?? - GrapherTabName.LineChart - ) + if (this.tab === GRAPHER_TAB_OPTIONS.table) + return GRAPHER_TAB_NAMES.Table + if (this.tab === GRAPHER_TAB_OPTIONS.map) + return GRAPHER_TAB_NAMES.WorldMap + if (this.chartTab) return this.chartTab + return this.validChartTypes[0] ?? GRAPHER_TAB_NAMES.LineChart } - @computed get activeChartType(): ChartTypeName | undefined { + @computed get activeChartType(): GrapherChartType | undefined { if (!this.isOnChartTab) return undefined - return this.activeTab as unknown as ChartTypeName + if ( + this.activeTab === GRAPHER_TAB_NAMES.Table || + this.activeTab === GRAPHER_TAB_NAMES.WorldMap + ) + return undefined + return this.activeTab } - @computed get chartType(): ChartTypeName { - return this.validChartTypes[0] ?? ChartTypeName.LineChart + @computed get chartType(): GrapherChartType { + return this.validChartTypes[0] ?? GRAPHER_CHART_TYPES.LineChart } @computed get hasChartTab(): boolean { @@ -721,15 +731,15 @@ export class Grapher } @computed get isOnChartTab(): boolean { - return this.tab === GrapherTabOption.chart + return this.tab === GRAPHER_TAB_OPTIONS.chart } @computed get isOnMapTab(): boolean { - return this.tab === GrapherTabOption.map + return this.tab === GRAPHER_TAB_OPTIONS.map } @computed get isOnTableTab(): boolean { - return this.tab === GrapherTabOption.table + return this.tab === GRAPHER_TAB_OPTIONS.table } @computed get isOnChartOrMapTab(): boolean { @@ -1295,15 +1305,15 @@ export class Grapher } @action.bound setTab(newTab: GrapherTabName): void { - if (newTab === GrapherTabName.Table) { - this.tab = GrapherTabOption.table + if (newTab === GRAPHER_TAB_NAMES.Table) { + this.tab = GRAPHER_TAB_OPTIONS.table this.chartTab = undefined - } else if (newTab === GrapherTabName.WorldMap) { - this.tab = GrapherTabOption.map + } else if (newTab === GRAPHER_TAB_NAMES.WorldMap) { + this.tab = GRAPHER_TAB_OPTIONS.map this.chartTab = undefined } else { - this.tab = GrapherTabOption.chart - this.chartTab = newTab as unknown as ChartTypeName + this.tab = GRAPHER_TAB_OPTIONS.chart + this.chartTab = newTab } } @@ -1521,7 +1531,7 @@ export class Grapher }) } - @computed get validChartTypes(): ChartTypeName[] { + @computed get validChartTypes(): GrapherChartType[] { const { chartTypes } = this if (chartTypes.length <= 1) return chartTypes @@ -1539,8 +1549,8 @@ export class Grapher @computed get availableTabs(): GrapherTabName[] { return [ - this.hasTableTab && GrapherTabName.Table, - this.hasMapTab && GrapherTabName.WorldMap, + this.hasTableTab && GRAPHER_TAB_NAMES.Table, + this.hasMapTab && GRAPHER_TAB_NAMES.WorldMap, ...this.validChartTypes, ].filter(identity) as GrapherTabName[] } @@ -1567,7 +1577,7 @@ export class Grapher return !!( !this.forceHideAnnotationFieldsInTitle?.entity && - this.tab === GrapherTabOption.chart && + this.tab === GRAPHER_TAB_OPTIONS.chart && (seriesStrategy !== SeriesStrategy.entity || !this.showLegend) && selectedEntityNames.length === 1 && (showEntityAnnotation || @@ -1641,15 +1651,15 @@ export class Grapher switch (this.tab) { // the map tab has its own `hideTimeline` option - case GrapherTabOption.map: + case GRAPHER_TAB_OPTIONS.map: return !this.map.hideTimeline // use the chart-level `hideTimeline` option - case GrapherTabOption.chart: + case GRAPHER_TAB_OPTIONS.chart: return !this.hideTimeline // use the chart-level `hideTimeline` option for the table, with some exceptions - case GrapherTabOption.table: + case GRAPHER_TAB_OPTIONS.table: // always show the timeline for charts that plot time on the x-axis if (this.hasTimeDimension) return true return !this.hideTimeline @@ -1924,36 +1934,36 @@ export class Grapher } @computed - get typeExceptWhenLineChartAndSingleTimeThenWillBeBarChart(): ChartTypeName { + get typeExceptWhenLineChartAndSingleTimeThenWillBeBarChart(): GrapherChartType { // Switch to bar chart if a single year is selected. Todo: do we want to do this? return this.isLineChartThatTurnedIntoDiscreteBar - ? ChartTypeName.DiscreteBar - : this.chartType ?? ChartTypeName.LineChart + ? GRAPHER_CHART_TYPES.DiscreteBar + : this.chartType ?? GRAPHER_CHART_TYPES.LineChart } @computed get isLineChart(): boolean { - return this.chartType === ChartTypeName.LineChart + return this.chartType === GRAPHER_CHART_TYPES.LineChart } @computed get isScatter(): boolean { - return this.chartType === ChartTypeName.ScatterPlot + return this.chartType === GRAPHER_CHART_TYPES.ScatterPlot } @computed get isStackedArea(): boolean { - return this.chartType === ChartTypeName.StackedArea + return this.chartType === GRAPHER_CHART_TYPES.StackedArea } @computed get isSlopeChart(): boolean { - return this.chartType === ChartTypeName.SlopeChart + return this.chartType === GRAPHER_CHART_TYPES.SlopeChart } @computed get isDiscreteBar(): boolean { - return this.chartType === ChartTypeName.DiscreteBar + return this.chartType === GRAPHER_CHART_TYPES.DiscreteBar } @computed get isStackedBar(): boolean { - return this.chartType === ChartTypeName.StackedBar + return this.chartType === GRAPHER_CHART_TYPES.StackedBar } @computed get isMarimekko(): boolean { - return this.chartType === ChartTypeName.Marimekko + return this.chartType === GRAPHER_CHART_TYPES.Marimekko } @computed get isStackedDiscreteBar(): boolean { - return this.chartType === ChartTypeName.StackedDiscreteBar + return this.chartType === GRAPHER_CHART_TYPES.StackedDiscreteBar } @computed get isLineChartThatTurnedIntoDiscreteBar(): boolean { @@ -3203,21 +3213,21 @@ export class Grapher private mapQueryParamToGrapherTab(tab: string): GrapherTabName | undefined { const { validChartTypes, hasMapTab } = this - if (tab === GrapherTabQueryParam.Table) { - return GrapherTabName.Table + if (tab === GRAPHER_TAB_QUERY_PARAMS.table) { + return GRAPHER_TAB_NAMES.Table } - if (tab === GrapherTabQueryParam.WorldMap) { - return GrapherTabName.WorldMap + if (tab === GRAPHER_TAB_QUERY_PARAMS.map) { + return GRAPHER_TAB_NAMES.WorldMap } const defaultChartType = validChartTypes[0] - if (tab === GrapherTabQueryParam.Chart) { + if (tab === GRAPHER_TAB_QUERY_PARAMS.chart) { if (defaultChartType) { - return defaultChartType as unknown as GrapherTabName + return defaultChartType } else if (hasMapTab) { - return GrapherTabName.WorldMap + return GRAPHER_TAB_NAMES.WorldMap } else { - return GrapherTabName.Table + return GRAPHER_TAB_NAMES.Table } } @@ -3226,24 +3236,25 @@ export class Grapher if (!chartTypeName) return undefined if (validChartTypes.includes(chartTypeName)) { - return chartTypeName as unknown as GrapherTabName + return chartTypeName } else if (defaultChartType) { - return defaultChartType as unknown as GrapherTabName + return defaultChartType } else if (hasMapTab) { - return GrapherTabName.WorldMap + return GRAPHER_TAB_NAMES.WorldMap } else { - return GrapherTabName.Table + return GRAPHER_TAB_NAMES.Table } } mapGrapherTabToQueryParam(tab: GrapherTabName): string { - if (tab === GrapherTabName.Table) return GrapherTabQueryParam.Table - if (tab === GrapherTabName.WorldMap) - return GrapherTabQueryParam.WorldMap + if (tab === GRAPHER_TAB_NAMES.Table) + return GRAPHER_TAB_QUERY_PARAMS.table + if (tab === GRAPHER_TAB_NAMES.WorldMap) + return GRAPHER_TAB_QUERY_PARAMS.map - if (!this.hasMultipleChartTypes) return GrapherTabQueryParam.Chart + if (!this.hasMultipleChartTypes) return GRAPHER_TAB_QUERY_PARAMS.chart - return mapChartTypeNameToQueryParam(tab as unknown as ChartTypeName) + return mapChartTypeNameToQueryParam(tab) } @computed.struct get allParams(): GrapherQueryParams { diff --git a/packages/@ourworldindata/grapher/src/core/GrapherConstants.ts b/packages/@ourworldindata/grapher/src/core/GrapherConstants.ts index 2c80e8c26f4..3e180507425 100644 --- a/packages/@ourworldindata/grapher/src/core/GrapherConstants.ts +++ b/packages/@ourworldindata/grapher/src/core/GrapherConstants.ts @@ -1,4 +1,4 @@ -import { ChartTypeName } from "@ourworldindata/types" +import { GRAPHER_CHART_TYPES } from "@ourworldindata/types" import type { GrapherProgrammaticInterface } from "./Grapher" export const GRAPHER_EMBEDDED_FIGURE_ATTR = "data-grapher-src" @@ -101,5 +101,5 @@ export const grapherInterfaceWithHiddenTabs: GrapherProgrammaticInterface = { } export const validChartTypeCombinations = [ - [ChartTypeName.LineChart, ChartTypeName.SlopeChart], + [GRAPHER_CHART_TYPES.LineChart, GRAPHER_CHART_TYPES.SlopeChart], ] diff --git a/packages/@ourworldindata/grapher/src/core/GrapherWithChartTypes.jsdom.test.tsx b/packages/@ourworldindata/grapher/src/core/GrapherWithChartTypes.jsdom.test.tsx index 467fa2af3c4..6a4c8bb65b1 100755 --- a/packages/@ourworldindata/grapher/src/core/GrapherWithChartTypes.jsdom.test.tsx +++ b/packages/@ourworldindata/grapher/src/core/GrapherWithChartTypes.jsdom.test.tsx @@ -8,7 +8,7 @@ import { import { Grapher, GrapherProgrammaticInterface } from "../core/Grapher" import { MapChart } from "../mapCharts/MapChart" import { legacyMapGrapher } from "../mapCharts/MapChart.sample" -import { ChartTypeName } from "@ourworldindata/types" +import { GRAPHER_CHART_TYPES } from "@ourworldindata/types" describe("grapher and map charts", () => { describe("map time tolerance plus query string works with a map chart", () => { @@ -50,7 +50,7 @@ const basicGrapherConfig: GrapherProgrammaticInterface = { describe("grapher and discrete bar charts", () => { const grapher = new Grapher({ - chartTypes: [ChartTypeName.DiscreteBar], + chartTypes: [GRAPHER_CHART_TYPES.DiscreteBar], ...basicGrapherConfig, }) expect(grapher.chartInstance.series.length).toBeGreaterThan(0) diff --git a/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.test.ts b/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.test.ts index c292f2ad16a..c7cac1c958b 100755 --- a/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.test.ts +++ b/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.test.ts @@ -1,7 +1,7 @@ #! /usr/bin/env jest import { - ChartTypeName, + GRAPHER_CHART_TYPES, OwidColumnDef, OwidTableSlugs, StandardOwidColumnDefs, @@ -466,7 +466,7 @@ describe(legacyToOwidTableAndDimensions, () => { it("joins targetTime", () => { const scatterLegacyGrapherConfig = { ...legacyGrapherConfig, - chartTypes: [ChartTypeName.ScatterPlot], + chartTypes: [GRAPHER_CHART_TYPES.ScatterPlot], } const { table } = legacyToOwidTableAndDimensions( diff --git a/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.ts b/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.ts index 19e1bd42d86..bce764a7966 100644 --- a/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.ts +++ b/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.ts @@ -1,7 +1,7 @@ // todo: Remove this file when we've migrated OWID data and OWID charts to next version import { - ChartTypeName, + GRAPHER_CHART_TYPES, ColumnTypeNames, CoreColumnDef, StandardOwidColumnDefs, @@ -200,8 +200,8 @@ export const legacyToOwidTableAndDimensions = ( const targetTime = dimension?.targetYear const chartType = grapherConfig.chartTypes?.[0] if ( - (chartType === ChartTypeName.ScatterPlot || - chartType === ChartTypeName.Marimekko) && + (chartType === GRAPHER_CHART_TYPES.ScatterPlot || + chartType === GRAPHER_CHART_TYPES.Marimekko) && isNumber(targetTime) ) { variableTable = variableTable diff --git a/packages/@ourworldindata/grapher/src/dataTable/DataTable.jsdom.test.tsx b/packages/@ourworldindata/grapher/src/dataTable/DataTable.jsdom.test.tsx index c52f0c833af..de5bcd27e37 100755 --- a/packages/@ourworldindata/grapher/src/dataTable/DataTable.jsdom.test.tsx +++ b/packages/@ourworldindata/grapher/src/dataTable/DataTable.jsdom.test.tsx @@ -3,7 +3,7 @@ import React from "react" import { DataTable } from "./DataTable" -import { ChartTypeName, GrapherTabOption } from "@ourworldindata/types" +import { GRAPHER_CHART_TYPES, GRAPHER_TAB_OPTIONS } from "@ourworldindata/types" import { childMortalityGrapher, GrapherWithIncompleteData, @@ -70,8 +70,8 @@ describe("when you select a range of years", () => { let view: ReactWrapper beforeAll(() => { const grapher = childMortalityGrapher({ - chartTypes: [ChartTypeName.LineChart], - tab: GrapherTabOption.table, + chartTypes: [GRAPHER_CHART_TYPES.LineChart], + tab: GRAPHER_TAB_OPTIONS.table, }) grapher.timelineHandleTimeBounds = [1950, 2019] diff --git a/packages/@ourworldindata/grapher/src/dataTable/DataTable.sample.ts b/packages/@ourworldindata/grapher/src/dataTable/DataTable.sample.ts index 5bf81c3a0bc..885b71afdf8 100644 --- a/packages/@ourworldindata/grapher/src/dataTable/DataTable.sample.ts +++ b/packages/@ourworldindata/grapher/src/dataTable/DataTable.sample.ts @@ -1,6 +1,6 @@ import { DimensionProperty } from "@ourworldindata/utils" import { Grapher } from "../core/Grapher" -import { GrapherTabOption, GrapherInterface } from "@ourworldindata/types" +import { GRAPHER_TAB_OPTIONS, GrapherInterface } from "@ourworldindata/types" import { TestMetadata, createOwidTestDataset, @@ -38,7 +38,7 @@ export const childMortalityGrapher = ( ] return new Grapher({ hasMapTab: true, - tab: GrapherTabOption.map, + tab: GRAPHER_TAB_OPTIONS.map, dimensions, ...props, owidDataset: createOwidTestDataset([ @@ -85,7 +85,7 @@ export const GrapherWithIncompleteData = ( }, ] return new Grapher({ - tab: GrapherTabOption.table, + tab: GRAPHER_TAB_OPTIONS.table, dimensions, ...props, owidDataset: createOwidTestDataset([{ metadata, data }]), @@ -125,7 +125,7 @@ export const GrapherWithAggregates = ( }, ] return new Grapher({ - tab: GrapherTabOption.table, + tab: GRAPHER_TAB_OPTIONS.table, dimensions, ...props, owidDataset: createOwidTestDataset([ @@ -169,7 +169,7 @@ export const GrapherWithMultipleVariablesAndMultipleYears = ( } return new Grapher({ - tab: GrapherTabOption.table, + tab: GRAPHER_TAB_OPTIONS.table, dimensions, ...props, owidDataset: createOwidTestDataset([ diff --git a/packages/@ourworldindata/grapher/src/dataTable/DataTable.stories.tsx b/packages/@ourworldindata/grapher/src/dataTable/DataTable.stories.tsx index e0279bfaf88..71094ea0ee8 100644 --- a/packages/@ourworldindata/grapher/src/dataTable/DataTable.stories.tsx +++ b/packages/@ourworldindata/grapher/src/dataTable/DataTable.stories.tsx @@ -1,7 +1,7 @@ import React from "react" import { DataTable, DataTableManager } from "./DataTable" import { SynthesizeGDPTable } from "@ourworldindata/core-table" -import { ChartTypeName, GrapherTabOption } from "@ourworldindata/types" +import { GRAPHER_CHART_TYPES, GRAPHER_TAB_OPTIONS } from "@ourworldindata/types" import { childMortalityGrapher, GrapherWithIncompleteData, @@ -88,8 +88,8 @@ export const FromLegacy = (): React.ReactElement => { export const FromLegacyWithTimeRange = (): React.ReactElement => { const grapher = childMortalityGrapher({ - type: ChartTypeName.LineChart, - tab: GrapherTabOption.chart, + type: GRAPHER_CHART_TYPES.LineChart, + tab: GRAPHER_TAB_OPTIONS.chart, }) grapher.startHandleTimeBound = 1950 grapher.endHandleTimeBound = 2019 diff --git a/packages/@ourworldindata/grapher/src/facetChart/FacetChart.stories.tsx b/packages/@ourworldindata/grapher/src/facetChart/FacetChart.stories.tsx index 486b5149c2f..de7b17fc0ce 100644 --- a/packages/@ourworldindata/grapher/src/facetChart/FacetChart.stories.tsx +++ b/packages/@ourworldindata/grapher/src/facetChart/FacetChart.stories.tsx @@ -6,7 +6,7 @@ import { SynthesizeGDPTable, } from "@ourworldindata/core-table" import { Bounds } from "@ourworldindata/utils" -import { ChartTypeName, FacetStrategy } from "../core/GrapherConstants" +import { GRAPHER_CHART_TYPES, FacetStrategy } from "../core/GrapherConstants" import { ChartManager } from "../chart/ChartManager" // See https://storybook.js.org/docs/react/essentials/controls for Control Types @@ -34,7 +34,7 @@ export const OneMetricOneCountryPerChart = (): React.ReactElement => { @@ -49,7 +49,7 @@ export const MultipleMetricsOneCountryPerChart = (): React.ReactElement => { { { } const chart = new FacetChart({ manager, - chartTypeName: ChartTypeName.LineChart, + chartTypeName: GRAPHER_CHART_TYPES.LineChart, }) const yAxisConfigs = chart.placedSeries.map( (series) => series.manager.yAxisConfig @@ -165,7 +165,7 @@ describe("config overrides", () => { } const chart = new FacetChart({ manager, - chartTypeName: ChartTypeName.LineChart, + chartTypeName: GRAPHER_CHART_TYPES.LineChart, }) it("preserves config passed from manager", () => { @@ -187,7 +187,7 @@ describe("config overrides", () => { } const chart = new FacetChart({ manager: newManager, - chartTypeName: ChartTypeName.LineChart, + chartTypeName: GRAPHER_CHART_TYPES.LineChart, }) expect(chart.placedSeries[0].manager.yAxisConfig?.nice).toEqual(true) }) @@ -231,7 +231,7 @@ describe("global legend", () => { } const chart = new FacetChart({ manager, - chartTypeName: ChartTypeName.LineChart, + chartTypeName: GRAPHER_CHART_TYPES.LineChart, }) const legend = chart.categoricalLegendData diff --git a/packages/@ourworldindata/grapher/src/facetChart/FacetChart.tsx b/packages/@ourworldindata/grapher/src/facetChart/FacetChart.tsx index 3983634dbc6..64baa4d0a65 100644 --- a/packages/@ourworldindata/grapher/src/facetChart/FacetChart.tsx +++ b/packages/@ourworldindata/grapher/src/facetChart/FacetChart.tsx @@ -23,7 +23,7 @@ import { shortenForTargetWidth } from "@ourworldindata/components" import { action, computed, observable } from "mobx" import { BASE_FONT_SIZE } from "../core/GrapherConstants" import { - ChartTypeName, + GRAPHER_CHART_TYPES, FacetAxisDomain, FacetStrategy, SeriesColorMap, @@ -137,8 +137,8 @@ export class FacetChart return this.props.manager } - @computed private get chartTypeName(): ChartTypeName { - return this.props.chartTypeName ?? ChartTypeName.LineChart + @computed private get chartTypeName(): GRAPHER_CHART_TYPES { + return this.props.chartTypeName ?? GRAPHER_CHART_TYPES.LineChart } @computed get failMessage(): string { @@ -357,8 +357,8 @@ export class FacetChart return ( this.uniformYAxis && ![ - ChartTypeName.StackedDiscreteBar, - ChartTypeName.DiscreteBar, + GRAPHER_CHART_TYPES.StackedDiscreteBar, + GRAPHER_CHART_TYPES.DiscreteBar, ].includes(this.chartTypeName) ) } @@ -367,7 +367,7 @@ export class FacetChart return ( this.uniformXAxis && // TODO: do this for stacked area charts and line charts as well? - this.chartTypeName === ChartTypeName.StackedBar && + this.chartTypeName === GRAPHER_CHART_TYPES.StackedBar && this.facetCount >= SHARED_X_AXIS_MIN_FACET_COUNT ) } @@ -611,7 +611,8 @@ export class FacetChart if (!hasBins) return false if (isNumericLegend) return true if ( - this.props.chartTypeName === ChartTypeName.StackedDiscreteBar && + this.props.chartTypeName === + GRAPHER_CHART_TYPES.StackedDiscreteBar && this.facetStrategy === FacetStrategy.metric ) { return false diff --git a/packages/@ourworldindata/grapher/src/facetChart/FacetChartConstants.ts b/packages/@ourworldindata/grapher/src/facetChart/FacetChartConstants.ts index 1b69756f109..61da277dca1 100644 --- a/packages/@ourworldindata/grapher/src/facetChart/FacetChartConstants.ts +++ b/packages/@ourworldindata/grapher/src/facetChart/FacetChartConstants.ts @@ -1,6 +1,6 @@ import { ChartSeries } from "../chart/ChartInterface" import { ChartManager } from "../chart/ChartManager" -import { ChartTypeName } from "@ourworldindata/types" +import { GrapherChartType } from "@ourworldindata/types" import { Bounds } from "@ourworldindata/utils" export interface FacetChartManager extends ChartManager { @@ -9,7 +9,7 @@ export interface FacetChartManager extends ChartManager { export interface FacetChartProps { bounds?: Bounds - chartTypeName?: ChartTypeName + chartTypeName?: GrapherChartType manager: FacetChartManager } diff --git a/packages/@ourworldindata/grapher/src/mapCharts/MapChart.sample.ts b/packages/@ourworldindata/grapher/src/mapCharts/MapChart.sample.ts index a118a1d6969..c656ab25c9f 100644 --- a/packages/@ourworldindata/grapher/src/mapCharts/MapChart.sample.ts +++ b/packages/@ourworldindata/grapher/src/mapCharts/MapChart.sample.ts @@ -1,10 +1,10 @@ import { DimensionProperty } from "@ourworldindata/utils" import { GrapherProgrammaticInterface } from "../core/Grapher" -import { GrapherTabOption } from "@ourworldindata/types" +import { GRAPHER_TAB_OPTIONS } from "@ourworldindata/types" export const legacyMapGrapher: GrapherProgrammaticInterface = { hasMapTab: true, - tab: GrapherTabOption.map, + tab: GRAPHER_TAB_OPTIONS.map, map: { timeTolerance: 5, }, diff --git a/packages/@ourworldindata/grapher/src/mapCharts/MapChart.tsx b/packages/@ourworldindata/grapher/src/mapCharts/MapChart.tsx index b8d9343a8fc..b0d76247685 100644 --- a/packages/@ourworldindata/grapher/src/mapCharts/MapChart.tsx +++ b/packages/@ourworldindata/grapher/src/mapCharts/MapChart.tsx @@ -55,7 +55,7 @@ import { getCountriesByProjection } from "./WorldRegionsToProjection" import { ColorSchemeName, MapProjectionName, - GrapherTabOption, + GRAPHER_TAB_OPTIONS, SeriesName, EntityName, } from "@ourworldindata/types" @@ -289,7 +289,7 @@ export class MapChart if (!ev.shiftKey) { this.selectionArray.setSelectedEntities([entityName]) - this.manager.tab = GrapherTabOption.chart + this.manager.tab = GRAPHER_TAB_OPTIONS.chart if ( this.manager.isLineChartThatTurnedIntoDiscreteBar && this.manager.hasTimeline diff --git a/packages/@ourworldindata/grapher/src/mapCharts/MapChartConstants.ts b/packages/@ourworldindata/grapher/src/mapCharts/MapChartConstants.ts index 3e974d98c62..c585d641d7b 100644 --- a/packages/@ourworldindata/grapher/src/mapCharts/MapChartConstants.ts +++ b/packages/@ourworldindata/grapher/src/mapCharts/MapChartConstants.ts @@ -4,7 +4,7 @@ import { MapProjectionName, Color, Time, - ChartTypeName, + GrapherChartType, GrapherTabOption, SeriesName, } from "@ourworldindata/types" @@ -57,7 +57,7 @@ export interface MapChartManager extends ChartManager { mapColumnSlug?: ColumnSlug mapIsClickable?: boolean tab?: GrapherTabOption // Used to switch to chart tab on map click - type?: ChartTypeName // Used to determine the "Click to select" text in MapTooltip + type?: GrapherChartType // Used to determine the "Click to select" text in MapTooltip isLineChartThatTurnedIntoDiscreteBar?: boolean // Used to determine whether to reset the timeline on map click hasTimeline?: boolean // Used to determine whether to reset the timeline on map click resetHandleTimeBounds?: () => void // Used to reset the timeline on map click diff --git a/packages/@ourworldindata/grapher/src/schema/migrations/migrations.ts b/packages/@ourworldindata/grapher/src/schema/migrations/migrations.ts index 2a860c0cb9a..e64a8161603 100644 --- a/packages/@ourworldindata/grapher/src/schema/migrations/migrations.ts +++ b/packages/@ourworldindata/grapher/src/schema/migrations/migrations.ts @@ -15,7 +15,7 @@ import { getSchemaVersion, isLatestVersion, } from "./helpers" -import { ChartTypeName } from "@ourworldindata/types" +import { GRAPHER_CHART_TYPES } from "@ourworldindata/types" // see https://github.com/owid/owid-grapher/commit/26f2a0d1790c71bdda7e12f284ca552945d2f6ef const migrateFrom001To002 = ( @@ -64,11 +64,11 @@ const migrateFrom004To005 = ( const migrateFrom005To006 = ( config: AnyConfigWithValidSchema ): AnyConfigWithValidSchema => { - const { type = ChartTypeName.LineChart, hasChartTab = true } = config + const { type = GRAPHER_CHART_TYPES.LineChart, hasChartTab = true } = config // add types field if (!hasChartTab) config.chartTypes = [] - else if (type !== ChartTypeName.LineChart) config.chartTypes = [type] + else if (type !== GRAPHER_CHART_TYPES.LineChart) config.chartTypes = [type] // remove deprecated fields delete config.type diff --git a/packages/@ourworldindata/grapher/src/stackedCharts/MarimekkoChart.jsdom.test.tsx b/packages/@ourworldindata/grapher/src/stackedCharts/MarimekkoChart.jsdom.test.tsx index 306f5376524..c20ed644b8f 100644 --- a/packages/@ourworldindata/grapher/src/stackedCharts/MarimekkoChart.jsdom.test.tsx +++ b/packages/@ourworldindata/grapher/src/stackedCharts/MarimekkoChart.jsdom.test.tsx @@ -4,7 +4,7 @@ import { Bounds, ColumnTypeNames } from "@ourworldindata/utils" import { OwidTable } from "@ourworldindata/core-table" import { DefaultColorScheme } from "../color/CustomSchemes" import { Grapher } from "../core/Grapher" -import { ChartTypeName } from "@ourworldindata/types" +import { GRAPHER_CHART_TYPES } from "@ourworldindata/types" import { MarimekkoChart } from "./MarimekkoChart" import { BarShape, PlacedItem } from "./MarimekkoChartConstants" it("can filter years correctly", () => { @@ -23,7 +23,7 @@ it("can filter years correctly", () => { // TODO: why is it ySlugs and xSlug here instead of yColumnSlugs and xColumnSlug? Unify when we have config migrations? const manager = { - chartTypes: [ChartTypeName.Marimekko], + chartTypes: [GRAPHER_CHART_TYPES.Marimekko], table, selection: table.availableEntityNames, ySlugs: "percentBelow2USD", @@ -133,7 +133,7 @@ it("shows no data points at the end", () => { // TODO: why is it ySlugs and xSlug here instead of yColumnSlugs and xColumnSlug? Unify when we have config migrations? const manager = { - chartTypes: [ChartTypeName.Marimekko], + chartTypes: [GRAPHER_CHART_TYPES.Marimekko], table, selection: table.availableEntityNames, ySlugs: "percentBelow2USD", @@ -233,7 +233,7 @@ test("interpolation works as expected", () => { // TODO: why is it ySlugs and xSlug here instead of yColumnSlugs and xColumnSlug? Unify when we have config migrations? const manager = { - chartTypes: [ChartTypeName.Marimekko], + chartTypes: [GRAPHER_CHART_TYPES.Marimekko], table, selection: table.availableEntityNames, ySlugs: "percentBelow2USD", @@ -344,7 +344,7 @@ it("can deal with y columns with missing values", () => { // TODO: why is it ySlugs and xSlug here instead of yColumnSlugs and xColumnSlug? Unify when we have config migrations? const manager = { - chartTypes: [ChartTypeName.Marimekko], + chartTypes: [GRAPHER_CHART_TYPES.Marimekko], table, selection: table.availableEntityNames, ySlugs: "percentBelow2USD percentBelow10USD", diff --git a/packages/@ourworldindata/types/src/dbTypes/ChartConfigs.ts b/packages/@ourworldindata/types/src/dbTypes/ChartConfigs.ts index b6a6e29b936..05e9df99261 100644 --- a/packages/@ourworldindata/types/src/dbTypes/ChartConfigs.ts +++ b/packages/@ourworldindata/types/src/dbTypes/ChartConfigs.ts @@ -1,6 +1,6 @@ import { Base64String, JsonString } from "../domainTypes/Various.js" import { - ChartTypeName, + GrapherChartType, GrapherInterface, } from "../grapherTypes/GrapherTypes.js" @@ -11,7 +11,7 @@ export interface DbInsertChartConfig { full: JsonString fullMd5?: Base64String slug?: string | null - chartType?: ChartTypeName | null + chartType?: GrapherChartType | null createdAt?: Date updatedAt?: Date | null } diff --git a/packages/@ourworldindata/types/src/grapherTypes/GrapherConstants.ts b/packages/@ourworldindata/types/src/grapherTypes/GrapherConstants.ts index 4819852969b..85a07bc9288 100644 --- a/packages/@ourworldindata/types/src/grapherTypes/GrapherConstants.ts +++ b/packages/@ourworldindata/types/src/grapherTypes/GrapherConstants.ts @@ -3,3 +3,56 @@ export const EPOCH_DATE = "2020-01-21" /** The "plot" is a chart without any header, footer or controls */ export const IDEAL_PLOT_ASPECT_RATIO = 1.8 + +export const GRAPHER_MAP_TYPE = "WorldMap" + +export const GRAPHER_CHART_TYPES = { + LineChart: "LineChart", + ScatterPlot: "ScatterPlot", + StackedArea: "StackedArea", + DiscreteBar: "DiscreteBar", + StackedDiscreteBar: "StackedDiscreteBar", + SlopeChart: "SlopeChart", + StackedBar: "StackedBar", + Marimekko: "Marimekko", +} as const + +export const ALL_GRAPHER_CHART_TYPES = Object.values(GRAPHER_CHART_TYPES) + +export const GRAPHER_TAB_NAMES = { + Table: "Table", + WorldMap: "WorldMap", + + // chart types + LineChart: "LineChart", + ScatterPlot: "ScatterPlot", + StackedArea: "StackedArea", + DiscreteBar: "DiscreteBar", + StackedDiscreteBar: "StackedDiscreteBar", + SlopeChart: "SlopeChart", + StackedBar: "StackedBar", + Marimekko: "Marimekko", +} as const + +export const GRAPHER_TAB_OPTIONS = { + table: "table", + map: "map", + chart: "chart", +} as const + +export const GRAPHER_TAB_QUERY_PARAMS = { + // generic params + table: "table", + map: "map", + chart: "chart", + + // chart types + line: "line", + scatter: "scatter", + "stacked-area": "stacked-area", + "discrete-bar": "discrete-bar", + "stacked-discrete-bar": "stacked-discrete-bar", + slope: "slope", + "stacked-bar": "stacked-bar", + marimekko: "marimekko", +} as const diff --git a/packages/@ourworldindata/types/src/grapherTypes/GrapherTypes.ts b/packages/@ourworldindata/types/src/grapherTypes/GrapherTypes.ts index 00fc9eb93c1..d2d0fdbca68 100644 --- a/packages/@ourworldindata/types/src/grapherTypes/GrapherTypes.ts +++ b/packages/@ourworldindata/types/src/grapherTypes/GrapherTypes.ts @@ -7,6 +7,13 @@ import { AxisAlign, Position } from "../domainTypes/Layout.js" import { Integer, QueryParams } from "../domainTypes/Various.js" import { DetailDictionary } from "../gdocTypes/Gdoc.js" import { observable } from "mobx" +import { + GRAPHER_CHART_TYPES, + GRAPHER_MAP_TYPE, + GRAPHER_TAB_NAMES, + GRAPHER_TAB_OPTIONS, + GRAPHER_TAB_QUERY_PARAMS, +} from "./GrapherConstants.js" export interface Box { x: number @@ -120,22 +127,6 @@ export enum ToleranceStrategy { forwards = "forwards", } -export const GRAPHER_MAP_TYPE = "WorldMap" -type GrapherMapType = typeof GRAPHER_MAP_TYPE - -export enum ChartTypeName { - LineChart = "LineChart", - ScatterPlot = "ScatterPlot", - StackedArea = "StackedArea", - DiscreteBar = "DiscreteBar", - StackedDiscreteBar = "StackedDiscreteBar", - SlopeChart = "SlopeChart", - StackedBar = "StackedBar", - Marimekko = "Marimekko", -} - -export type GrapherChartOrMapType = ChartTypeName | GrapherMapType - export enum AxisMinMaxValueStr { auto = "auto", } @@ -176,42 +167,13 @@ export type SeriesName = string export type SeriesColorMap = Map -export enum GrapherTabOption { - chart = "chart", - map = "map", - table = "table", -} - -export enum GrapherTabQueryParam { - Chart = "chart", - Table = "table", - WorldMap = "map", - - // chart types - LineChart = "line", - ScatterPlot = "scatter", - StackedArea = "stacked-area", - DiscreteBar = "discrete-bar", - StackedDiscreteBar = "stacked-discrete-bar", - SlopeChart = "slope", - StackedBar = "stacked-bar", - Marimekko = "marimekko", -} - -export enum GrapherTabName { - Table = "Table", - WorldMap = "WorldMap", +export type GrapherMapType = typeof GRAPHER_MAP_TYPE +export type GrapherChartType = keyof typeof GRAPHER_CHART_TYPES +export type GrapherChartOrMapType = GrapherChartType | GrapherMapType - // chart types - LineChart = "LineChart", - ScatterPlot = "ScatterPlot", - StackedArea = "StackedArea", - DiscreteBar = "DiscreteBar", - StackedDiscreteBar = "StackedDiscreteBar", - SlopeChart = "SlopeChart", - StackedBar = "StackedBar", - Marimekko = "Marimekko", -} +export type GrapherTabOption = keyof typeof GRAPHER_TAB_OPTIONS +export type GrapherTabQueryParam = keyof typeof GRAPHER_TAB_QUERY_PARAMS +export type GrapherTabName = keyof typeof GRAPHER_TAB_NAMES export interface RelatedQuestionsConfig { text: string @@ -563,7 +525,7 @@ export interface MapConfigInterface { // under the same rendering conditions it ought to remain visually identical export interface GrapherInterface extends SortConfig { $schema?: string - chartTypes?: ChartTypeName[] + chartTypes?: GrapherChartType[] id?: number version?: number slug?: string diff --git a/packages/@ourworldindata/types/src/index.ts b/packages/@ourworldindata/types/src/index.ts index 1549a9e7851..36ab0e166cd 100644 --- a/packages/@ourworldindata/types/src/index.ts +++ b/packages/@ourworldindata/types/src/index.ts @@ -44,6 +44,12 @@ export { export { IDEAL_PLOT_ASPECT_RATIO, EPOCH_DATE, + GRAPHER_MAP_TYPE, + GRAPHER_CHART_TYPES, + GRAPHER_TAB_NAMES, + GRAPHER_TAB_OPTIONS, + GRAPHER_TAB_QUERY_PARAMS, + ALL_GRAPHER_CHART_TYPES, } from "./grapherTypes/GrapherConstants.js" export { @@ -74,12 +80,11 @@ export { type ColorScaleConfigInterface, ColorSchemeName, colorScaleConfigDefaults, - ChartTypeName, type GrapherChartOrMapType, - GRAPHER_MAP_TYPE, - GrapherTabOption, - GrapherTabName, - GrapherTabQueryParam, + type GrapherTabOption, + type GrapherTabName, + type GrapherTabQueryParam, + type GrapherChartType, StackMode, EntitySelectionMode, ScatterPointLabelStrategy, diff --git a/packages/@ourworldindata/utils/src/Util.ts b/packages/@ourworldindata/utils/src/Util.ts index 33a97b41f9e..2315c722058 100644 --- a/packages/@ourworldindata/utils/src/Util.ts +++ b/packages/@ourworldindata/utils/src/Util.ts @@ -175,8 +175,8 @@ import { TagGraphRootName, TagGraphNode, GrapherInterface, - ChartTypeName, DimensionProperty, + GRAPHER_CHART_TYPES, } from "@ourworldindata/types" import { PointVector } from "./PointVector.js" import React from "react" @@ -1971,8 +1971,8 @@ export function getParentVariableIdFromChartConfig( ): number | undefined { const { chartTypes, dimensions } = config - const chartType = chartTypes?.[0] ?? ChartTypeName.LineChart - if (chartType === ChartTypeName.ScatterPlot) return undefined + const chartType = chartTypes?.[0] ?? GRAPHER_CHART_TYPES.LineChart + if (chartType === GRAPHER_CHART_TYPES.ScatterPlot) return undefined if (!dimensions) return undefined const yVariableIds = dimensions diff --git a/packages/@ourworldindata/utils/src/grapherConfigUtils.test.ts b/packages/@ourworldindata/utils/src/grapherConfigUtils.test.ts index 882b0d74326..0b879541c0d 100644 --- a/packages/@ourworldindata/utils/src/grapherConfigUtils.test.ts +++ b/packages/@ourworldindata/utils/src/grapherConfigUtils.test.ts @@ -3,8 +3,8 @@ import { DimensionProperty, GrapherInterface, - GrapherTabOption, MapProjectionName, + GRAPHER_TAB_OPTIONS, } from "@ourworldindata/types" import { mergeGrapherConfigs, @@ -243,14 +243,14 @@ describe(diffGrapherConfigs, () => { it("drops redundant entries", () => { expect( diffGrapherConfigs( - { tab: GrapherTabOption.map }, - { tab: GrapherTabOption.map } + { tab: GRAPHER_TAB_OPTIONS.map }, + { tab: GRAPHER_TAB_OPTIONS.map } ) ).toEqual({}) expect( diffGrapherConfigs( - { tab: GrapherTabOption.chart, title: "Chart" }, - { tab: GrapherTabOption.chart, title: "Reference chart" } + { tab: GRAPHER_TAB_OPTIONS.chart, title: "Chart" }, + { tab: GRAPHER_TAB_OPTIONS.chart, title: "Reference chart" } ) ).toEqual({ title: "Chart" }) }) @@ -260,7 +260,7 @@ describe(diffGrapherConfigs, () => { diffGrapherConfigs( { title: "Chart", - tab: GrapherTabOption.chart, + tab: GRAPHER_TAB_OPTIONS.chart, map: { projection: MapProjectionName.World, hideTimeline: true, @@ -268,7 +268,7 @@ describe(diffGrapherConfigs, () => { }, { title: "Reference chart", - tab: GrapherTabOption.chart, + tab: GRAPHER_TAB_OPTIONS.chart, map: { projection: MapProjectionName.World, hideTimeline: false, @@ -279,14 +279,14 @@ describe(diffGrapherConfigs, () => { expect( diffGrapherConfigs( { - tab: GrapherTabOption.chart, + tab: GRAPHER_TAB_OPTIONS.chart, map: { projection: MapProjectionName.World, hideTimeline: true, }, }, { - tab: GrapherTabOption.chart, + tab: GRAPHER_TAB_OPTIONS.chart, map: { projection: MapProjectionName.World, hideTimeline: true, @@ -300,11 +300,11 @@ describe(diffGrapherConfigs, () => { expect( diffGrapherConfigs( { - tab: GrapherTabOption.chart, + tab: GRAPHER_TAB_OPTIONS.chart, title: "Chart", subtitle: undefined, }, - { tab: GrapherTabOption.chart, title: "Reference chart" } + { tab: GRAPHER_TAB_OPTIONS.chart, title: "Reference chart" } ) ).toEqual({ title: "Chart" }) }) @@ -361,12 +361,12 @@ describe(diffGrapherConfigs, () => { it("is idempotent", () => { const config: GrapherInterface = { - tab: GrapherTabOption.chart, + tab: GRAPHER_TAB_OPTIONS.chart, title: "Chart", subtitle: undefined, } const reference: GrapherInterface = { - tab: GrapherTabOption.chart, + tab: GRAPHER_TAB_OPTIONS.chart, title: "Reference chart", } const diffedOnce = diffGrapherConfigs(config, reference) @@ -378,12 +378,12 @@ describe(diffGrapherConfigs, () => { describe("diff+merge", () => { it("are consistent", () => { const config: GrapherInterface = { - tab: GrapherTabOption.chart, + tab: GRAPHER_TAB_OPTIONS.chart, title: "Chart", subtitle: "Chart subtitle", } const reference: GrapherInterface = { - tab: GrapherTabOption.chart, + tab: GRAPHER_TAB_OPTIONS.chart, title: "Reference chart", } const diffedAndMerged = mergeGrapherConfigs( diff --git a/site/gdocs/components/Chart.tsx b/site/gdocs/components/Chart.tsx index c4070b96c38..b4a239370c6 100644 --- a/site/gdocs/components/Chart.tsx +++ b/site/gdocs/components/Chart.tsx @@ -9,7 +9,6 @@ import { ChartControlKeyword, ChartTabKeyword, EnrichedBlockChart, - identity, Url, merge, excludeUndefined, diff --git a/site/gdocs/components/KeyIndicatorCollection.tsx b/site/gdocs/components/KeyIndicatorCollection.tsx index 8539a5a70b3..e2347ac622b 100644 --- a/site/gdocs/components/KeyIndicatorCollection.tsx +++ b/site/gdocs/components/KeyIndicatorCollection.tsx @@ -13,6 +13,7 @@ import { import { EnrichedBlockKeyIndicatorCollection, EnrichedBlockKeyIndicator, + GRAPHER_TAB_OPTIONS, GrapherTabOption, } from "@ourworldindata/types" import { Url, urlToSlug, commafyNumber } from "@ourworldindata/utils" @@ -26,9 +27,9 @@ import { Button } from "@ourworldindata/components" const HEIGHT_ANIMATION_DURATION_IN_SECONDS = 0.4 const tabIconMap: Record = { - [GrapherTabOption.chart]: faChartLine, - [GrapherTabOption.map]: faEarthAmericas, - [GrapherTabOption.table]: faTable, + [GRAPHER_TAB_OPTIONS.chart]: faChartLine, + [GRAPHER_TAB_OPTIONS.map]: faEarthAmericas, + [GRAPHER_TAB_OPTIONS.table]: faTable, } export default function KeyIndicatorCollection({ @@ -247,7 +248,7 @@ function KeyIndicatorHeader({ ? queryParams.tab : undefined const activeTab = - tabFromQueryParams || linkedChart.tab || GrapherTabOption.chart + tabFromQueryParams || linkedChart.tab || GRAPHER_TAB_OPTIONS.chart const source = block.source || linkedIndicator.attributionShort @@ -357,5 +358,5 @@ function isElementAtTopOfViewport(element: HTMLElement): boolean { } function isValidGrapherTab(tab: string): tab is GrapherTabOption { - return Object.values(GrapherTabOption).includes(tab as GrapherTabOption) + return Object.values(GRAPHER_TAB_OPTIONS).includes(tab as GrapherTabOption) } diff --git a/site/multiembedder/MultiEmbedder.tsx b/site/multiembedder/MultiEmbedder.tsx index b9c6d085164..8e898583290 100644 --- a/site/multiembedder/MultiEmbedder.tsx +++ b/site/multiembedder/MultiEmbedder.tsx @@ -15,7 +15,7 @@ import { getWindowUrl, isPresent, Url, - GrapherTabOption, + GRAPHER_TAB_OPTIONS, merge, MultiDimDataPageConfig, extractMultiDimChoicesFromQueryStr, @@ -214,7 +214,7 @@ class MultiEmbedder { localConfig.tab = queryParams.tab ?? grapherPageConfig.tab ?? - GrapherTabOption.chart + GRAPHER_TAB_OPTIONS.chart } const config = merge(