From 971b72c3fd15af97396e91d74d04dd3f1fcb2068 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Tue, 19 Mar 2024 13:14:46 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20(grapher)=20support=20ordinal=20col?= =?UTF-8?q?umns?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core-table/src/CoreTableColumns.ts | 13 +++++ .../grapher/src/core/LegacyToOwidTable.ts | 51 +++++++++++++++++-- .../@ourworldindata/types/src/OwidVariable.ts | 4 ++ .../types/src/domainTypes/CoreTableTypes.ts | 4 ++ packages/@ourworldindata/types/src/index.ts | 1 + 5 files changed, 70 insertions(+), 3 deletions(-) diff --git a/packages/@ourworldindata/core-table/src/CoreTableColumns.ts b/packages/@ourworldindata/core-table/src/CoreTableColumns.ts index 8e50270822e..3c9199a295c 100644 --- a/packages/@ourworldindata/core-table/src/CoreTableColumns.ts +++ b/packages/@ourworldindata/core-table/src/CoreTableColumns.ts @@ -588,6 +588,18 @@ class BooleanColumn extends AbstractCoreColumn { } } +class OrdinalColumn extends CategoricalColumn { + @imemo get allowedValuesSorted(): string[] | undefined { + return this.def.sort + } + + @imemo get sortedUniqNonEmptyStringVals(): string[] { + return this.allowedValuesSorted + ? this.allowedValuesSorted + : super.sortedUniqNonEmptyStringVals + } +} + abstract class AbstractColumnWithNumberFormatting< T extends PrimitiveType, > extends AbstractCoreColumn { @@ -882,6 +894,7 @@ export const ColumnTypeMap = { String: StringColumn, SeriesAnnotation: SeriesAnnotationColumn, Categorical: CategoricalColumn, + Ordinal: OrdinalColumn, Region: RegionColumn, Continent: ContinentColumn, NumberOrString: NumberOrStringColumn, diff --git a/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.ts b/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.ts index a1ea941193b..9814e74f0a9 100644 --- a/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.ts +++ b/packages/@ourworldindata/grapher/src/core/LegacyToOwidTable.ts @@ -8,6 +8,7 @@ import { OwidTableSlugs, OwidColumnDef, LegacyGrapherInterface, + OwidVariableDimensions, } from "@ourworldindata/types" import { OwidTable, @@ -33,6 +34,7 @@ import { ColumnSlug, EPOCH_DATE, OwidChartDimensionInterface, + OwidVariableType, } from "@ourworldindata/utils" export const legacyToOwidTableAndDimensions = ( @@ -545,6 +547,37 @@ const fullJoinTables = ( ) } +const variableTypeToColumnType = (type: OwidVariableType): ColumnTypeNames => { + switch (type) { + case "ordinal": + return ColumnTypeNames.Ordinal + // TODO + // case "string": + // return ColumnTypeNames.String + // case "float": + // case "int": + // return ColumnTypeNames.Numeric + // case "mixed": + default: + return ColumnTypeNames.NumberOrString + } +} + +const getSortFromDimensions = ( + dimensions: OwidVariableDimensions +): string[] | undefined => { + const values = dimensions.values?.values + if (!values) return + + const sort = values + .map((value) => value.name) + .filter((name): name is string => name !== undefined) + + if (sort.length === 0) return + + return sort +} + const columnDefFromOwidVariable = ( variable: OwidVariableWithSourceAndDimension ): OwidColumnDef => { @@ -574,6 +607,19 @@ const columnDefFromOwidVariable = ( const isContinent = variable.id === 123 const name = isContinent ? "Continent" : variable.name + // The column's type + const type = isContinent + ? ColumnTypeNames.Continent + : variable.type + ? variableTypeToColumnType(variable.type) + : ColumnTypeNames.NumberOrString + + // Sorted values for ordinal columns + const sort = + type === ColumnTypeNames.Ordinal + ? getSortFromDimensions(variable.dimensions) + : undefined + return { name, slug, @@ -604,9 +650,8 @@ const columnDefFromOwidVariable = ( owidVariableId: variable.id, owidProcessingLevel: variable.processingLevel, owidSchemaVersion: variable.schemaVersion, - type: isContinent - ? ColumnTypeNames.Continent - : ColumnTypeNames.NumberOrString, + type, + sort, } } diff --git a/packages/@ourworldindata/types/src/OwidVariable.ts b/packages/@ourworldindata/types/src/OwidVariable.ts index a49e227733a..c0785a2be85 100644 --- a/packages/@ourworldindata/types/src/OwidVariable.ts +++ b/packages/@ourworldindata/types/src/OwidVariable.ts @@ -30,6 +30,7 @@ export interface OwidVariableWithSource { updatePeriodDays?: number datasetVersion?: string licenses?: OwidLicense[] + type?: OwidVariableType // omitted: // code @@ -107,6 +108,7 @@ export interface OwidVariableDimension { export interface OwidVariableDimensions { years: OwidVariableDimension entities: OwidVariableDimension + values?: OwidVariableDimension } export type OwidVariableDataMetadataDimensions = { @@ -129,3 +131,5 @@ export type OwidVariableDimensionValueFull = export interface OwidEntityKey { [id: string]: OwidVariableDimensionValuePartial } + +export type OwidVariableType = "string" | "float" | "int" | "mixed" | "ordinal" diff --git a/packages/@ourworldindata/types/src/domainTypes/CoreTableTypes.ts b/packages/@ourworldindata/types/src/domainTypes/CoreTableTypes.ts index cba466fdb50..2df5e36c638 100644 --- a/packages/@ourworldindata/types/src/domainTypes/CoreTableTypes.ts +++ b/packages/@ourworldindata/types/src/domainTypes/CoreTableTypes.ts @@ -151,6 +151,7 @@ export enum ColumnTypeNames { Region = "Region", SeriesAnnotation = "SeriesAnnotation", Categorical = "Categorical", + Ordinal = "Ordinal", Continent = "Continent", EntityName = "EntityName", EntityId = "EntityId", @@ -207,6 +208,9 @@ export interface CoreColumnDef extends ColumnColorScale { descriptionFromProducer?: string note?: string // Any internal notes the author wants to record for display in admin interfaces + // Sorted values (in case of ordinal data) + sort?: string[] + // Color color?: Color // A column can have a fixed color for use in charts where the columns are series diff --git a/packages/@ourworldindata/types/src/index.ts b/packages/@ourworldindata/types/src/index.ts index 543dae7d134..aa635cb11d7 100644 --- a/packages/@ourworldindata/types/src/index.ts +++ b/packages/@ourworldindata/types/src/index.ts @@ -370,6 +370,7 @@ export { type OwidProcessingLevel, type IndicatorTitleWithFragments, joinTitleFragments, + type OwidVariableType, } from "./OwidVariable.js" export type { OwidSource } from "./OwidSource.js"