@buildcanada/charts 0.1.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/components/Button/Button.scss +17 -17
- package/src/components/Button/Button.tsx +4 -4
- package/src/components/MarkdownTextWrap/MarkdownTextWrap.tsx +1 -1
- package/src/components/index.ts +1 -1
- package/src/components/stubs/DataCitation.tsx +1 -1
- package/src/components/stubs/IndicatorKeyData.tsx +1 -1
- package/src/components/stubs/IndicatorProcessing.tsx +1 -1
- package/src/components/stubs/IndicatorSources.tsx +1 -1
- package/src/components/styles/colors.scss +1 -1
- package/src/components/styles/mixins.scss +5 -5
- package/src/core-table/{OwidTable.ts → ChartsTable.ts} +31 -31
- package/src/core-table/CoreTable.ts +12 -12
- package/src/core-table/CoreTableColumns.ts +24 -24
- package/src/core-table/CoreTableUtils.ts +7 -7
- package/src/core-table/{OwidTableSynthesizers.ts → TableSynthesizers.ts} +24 -24
- package/src/core-table/{OwidTableUtil.ts → TableUtil.ts} +5 -5
- package/src/core-table/index.ts +3 -3
- package/src/explorer/ColumnGrammar.ts +1 -1
- package/src/explorer/Explorer.sample.ts +7 -7
- package/src/explorer/Explorer.scss +1 -1
- package/src/explorer/Explorer.tsx +23 -23
- package/src/explorer/ExplorerConstants.ts +2 -2
- package/src/explorer/ExplorerGrammar.ts +3 -3
- package/src/explorer/ExplorerProgram.ts +21 -18
- package/src/explorer/ExplorerUtils.ts +1 -1
- package/src/explorer/gridLang/readme.md +1 -1
- package/src/grapher/axis/Axis.ts +3 -3
- package/src/grapher/barCharts/DiscreteBarChart.tsx +2 -2
- package/src/grapher/barCharts/DiscreteBarChartState.ts +8 -8
- package/src/grapher/captionedChart/Logos.tsx +11 -13
- package/src/grapher/captionedChart/LogosSVG.tsx +2 -2
- package/src/grapher/chart/ChartAreaContent.tsx +1 -1
- package/src/grapher/chart/ChartDimension.ts +15 -15
- package/src/grapher/chart/ChartInterface.ts +6 -6
- package/src/grapher/chart/ChartManager.ts +3 -3
- package/src/grapher/chart/ChartUtils.tsx +3 -3
- package/src/grapher/color/ColorConstants.ts +2 -2
- package/src/grapher/color/ColorScale.ts +4 -4
- package/src/grapher/color/ColorSchemes.ts +26 -26
- package/src/grapher/color/CustomSchemes.ts +227 -227
- package/src/grapher/controls/DataTableFilterDropdown.tsx +2 -2
- package/src/grapher/controls/MapZoomDropdown.tsx +3 -3
- package/src/grapher/controls/ShareMenu.tsx +1 -1
- package/src/grapher/controls/entityPicker/EntityPicker.tsx +8 -8
- package/src/grapher/controls/entityPicker/EntityPickerConstants.ts +3 -3
- package/src/grapher/controls/globalEntitySelector/GlobalEntitySelector.tsx +1 -1
- package/src/grapher/core/EntitiesByRegionType.ts +4 -4
- package/src/grapher/core/EntityUrlBuilder.ts +2 -2
- package/src/grapher/core/FetchingGrapher.tsx +4 -4
- package/src/grapher/core/Grapher.tsx +10 -10
- package/src/grapher/core/GrapherState.tsx +46 -46
- package/src/grapher/core/GrapherUseHelpers.tsx +4 -4
- package/src/grapher/core/{LegacyToOwidTable.ts → LegacyToChartsTable.ts} +100 -100
- package/src/grapher/core/loadGrapherTableHelpers.ts +13 -13
- package/src/grapher/core/loadVariable.ts +5 -5
- package/src/grapher/dataTable/DataTable.sample.ts +12 -12
- package/src/grapher/dataTable/DataTable.tsx +22 -22
- package/src/grapher/dataTable/DataTableConstants.ts +9 -9
- package/src/grapher/entitySelector/EntitySelector.tsx +12 -12
- package/src/grapher/facet/FacetChart.tsx +4 -4
- package/src/grapher/facet/FacetMap.tsx +6 -6
- package/src/grapher/footer/Footer.tsx +4 -4
- package/src/grapher/footer/FooterManager.ts +2 -2
- package/src/grapher/header/Header.tsx +5 -5
- package/src/grapher/header/HeaderManager.ts +1 -1
- package/src/grapher/index.ts +8 -8
- package/src/grapher/lineCharts/LineChartHelpers.ts +3 -3
- package/src/grapher/lineCharts/LineChartState.ts +9 -9
- package/src/grapher/mapCharts/ChoroplethGlobe.tsx +1 -1
- package/src/grapher/mapCharts/GlobeController.ts +9 -9
- package/src/grapher/mapCharts/MapChartState.ts +16 -16
- package/src/grapher/mapCharts/MapSparkline.tsx +5 -5
- package/src/grapher/mapCharts/MapTooltip.tsx +13 -13
- package/src/grapher/modal/DownloadModal.scss +3 -3
- package/src/grapher/modal/DownloadModal.tsx +24 -29
- package/src/grapher/modal/SourcesDescriptions.scss +1 -1
- package/src/grapher/modal/SourcesKeyDataTable.tsx +2 -2
- package/src/grapher/modal/SourcesModal.tsx +15 -15
- package/src/grapher/scatterCharts/ScatterPlotChart.tsx +2 -2
- package/src/grapher/scatterCharts/ScatterPlotChartConstants.ts +2 -2
- package/src/grapher/scatterCharts/ScatterPlotChartState.ts +8 -8
- package/src/grapher/scatterCharts/ScatterSizeLegend.tsx +2 -2
- package/src/grapher/scatterCharts/ScatterUtils.ts +2 -2
- package/src/grapher/schema/grapher-schema.009.yaml +18 -18
- package/src/grapher/schema/migrations/migrations.ts +4 -4
- package/src/grapher/selection/MapSelectionArray.ts +1 -1
- package/src/grapher/selection/readme.md +1 -1
- package/src/grapher/slopeCharts/SlopeChartConstants.ts +3 -3
- package/src/grapher/slopeCharts/SlopeChartState.ts +10 -10
- package/src/grapher/stackedCharts/AbstractStackedChartState.ts +8 -8
- package/src/grapher/stackedCharts/MarimekkoChart.tsx +5 -5
- package/src/grapher/stackedCharts/MarimekkoChartConstants.ts +2 -2
- package/src/grapher/stackedCharts/MarimekkoChartState.ts +12 -12
- package/src/grapher/stackedCharts/StackedBarChartState.ts +1 -1
- package/src/grapher/stackedCharts/StackedConstants.ts +2 -2
- package/src/grapher/stackedCharts/StackedDiscreteBarChartState.ts +12 -12
- package/src/grapher/stackedCharts/StackedDiscreteBars.tsx +2 -2
- package/src/grapher/testData/{OwidTestData.sample.ts → TestData.sample.ts} +7 -7
- package/src/grapher/testData/{OwidTestData.ts → TestData.ts} +5 -5
- package/src/index.ts +7 -7
- package/src/types/{OwidOrigin.ts → Origin.ts} +3 -3
- package/src/types/{OwidSource.ts → Source.ts} +1 -1
- package/src/types/Variable.ts +133 -0
- package/src/types/{OwidVariableDisplayConfigInterface.ts → VariableDisplayConfigInterface.ts} +11 -11
- package/src/types/domainTypes/ContentGraph.ts +2 -2
- package/src/types/domainTypes/CoreTableTypes.ts +29 -29
- package/src/types/domainTypes/Posts.ts +2 -2
- package/src/types/domainTypes/Search.ts +6 -6
- package/src/types/domainTypes/Various.ts +1 -1
- package/src/types/gdocTypes/Gdoc.ts +42 -42
- package/src/types/grapherTypes/GrapherTypes.ts +21 -21
- package/src/types/index.ts +50 -50
- package/src/utils/MultiDimDataPageConfig.ts +1 -1
- package/src/utils/Util.ts +61 -55
- package/src/utils/{OwidVariable.ts → Variable.ts} +15 -15
- package/src/utils/formatValue.ts +12 -12
- package/src/utils/image.ts +12 -12
- package/src/utils/index.ts +5 -5
- package/src/utils/metadataHelpers.ts +19 -19
- package/src/utils/regions.ts +9 -9
- package/src/types/OwidVariable.ts +0 -133
|
@@ -4,7 +4,7 @@ import { observer } from "mobx-react"
|
|
|
4
4
|
import { Dropdown } from "./Dropdown"
|
|
5
5
|
import { EntityName } from "../../utils/index.js"
|
|
6
6
|
import { DataTableConfig } from "../dataTable/DataTableConstants"
|
|
7
|
-
import {
|
|
7
|
+
import { ChartsTable } from "../../core-table/index.js"
|
|
8
8
|
import { SelectionArray } from "../selection/SelectionArray"
|
|
9
9
|
import { makeSelectionArray } from "../chart/ChartUtils"
|
|
10
10
|
import {
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
|
|
15
15
|
export interface DataTableFilterDropdownManager {
|
|
16
16
|
dataTableConfig: DataTableConfig
|
|
17
|
-
tableForDisplay:
|
|
17
|
+
tableForDisplay: ChartsTable
|
|
18
18
|
isOnTableTab?: boolean
|
|
19
19
|
dataTableSelection?: SelectionArray | EntityName[]
|
|
20
20
|
canChangeAddOrHighlightEntities?: boolean
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
GlobeRegionName,
|
|
12
12
|
mappableCountries,
|
|
13
13
|
MapRegionName,
|
|
14
|
-
|
|
14
|
+
checkIsIncomeGroupName,
|
|
15
15
|
getUserCountryInformation,
|
|
16
16
|
regions,
|
|
17
17
|
} from "../../utils/index.js"
|
|
@@ -114,7 +114,7 @@ export class MapZoomDropdown extends React.Component<{
|
|
|
114
114
|
this.manager.globeController?.rotateToCountry(selected.value)
|
|
115
115
|
})
|
|
116
116
|
.with("continent", () => {
|
|
117
|
-
this.manager.globeController?.
|
|
117
|
+
this.manager.globeController?.rotateToContinent(
|
|
118
118
|
selected.value as GlobeRegionName
|
|
119
119
|
)
|
|
120
120
|
})
|
|
@@ -205,7 +205,7 @@ export class MapZoomDropdown extends React.Component<{
|
|
|
205
205
|
|
|
206
206
|
const countryRegionsWithoutIncomeGroups = localCountryInfo.regions
|
|
207
207
|
? localCountryInfo.regions.filter(
|
|
208
|
-
(region) => !
|
|
208
|
+
(region) => !checkIsIncomeGroupName(region)
|
|
209
209
|
)
|
|
210
210
|
: []
|
|
211
211
|
|
|
@@ -70,7 +70,7 @@ const canUseShareApi = (manager: ShareApiManager): boolean => {
|
|
|
70
70
|
// So, on Android and iOS, we want to just show the system-level share dialog
|
|
71
71
|
// immediately when the user clicks the share button, rather than showing our
|
|
72
72
|
// own menu.
|
|
73
|
-
// See
|
|
73
|
+
// See # legacy issue 3446
|
|
74
74
|
// -@marcelgerber, 2024-04-24
|
|
75
75
|
export const shouldShareUsingShareApi = (manager: ShareApiManager): boolean =>
|
|
76
76
|
(isAndroid() || isIOS()) && canUseShareApi(manager)
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
SortOrder,
|
|
23
23
|
EntityName,
|
|
24
24
|
CoreColumnDef,
|
|
25
|
-
|
|
25
|
+
ChartsTableSlugs,
|
|
26
26
|
} from "../../../utils/index.js"
|
|
27
27
|
import classnames from "classnames"
|
|
28
28
|
import { scaleLinear, ScaleLinear } from "d3-scale"
|
|
@@ -34,7 +34,7 @@ import { Dropdown, BasicDropdownOption } from "../Dropdown"
|
|
|
34
34
|
import {
|
|
35
35
|
ColumnTypeMap,
|
|
36
36
|
CoreColumn,
|
|
37
|
-
|
|
37
|
+
ChartsTable,
|
|
38
38
|
} from "../../../core-table/index.js"
|
|
39
39
|
import { EntityPickerManager } from "./EntityPickerConstants"
|
|
40
40
|
import { SelectionArray } from "../../selection/SelectionArray"
|
|
@@ -209,13 +209,13 @@ export class EntityPicker extends React.Component<EntityPickerProps> {
|
|
|
209
209
|
)
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
@computed private get metricTable():
|
|
212
|
+
@computed private get metricTable(): ChartsTable | undefined {
|
|
213
213
|
if (this.metric === undefined) return undefined
|
|
214
214
|
|
|
215
215
|
// If the slug is "entityName", then try to get it from grapherTable first, because it might
|
|
216
216
|
// not be present in pickerTable (for indicator-powered explorers, for example).
|
|
217
217
|
if (
|
|
218
|
-
this.metric ===
|
|
218
|
+
this.metric === ChartsTableSlugs.entityName &&
|
|
219
219
|
this.grapherTable?.has(this.metric)
|
|
220
220
|
)
|
|
221
221
|
return this.grapherTable
|
|
@@ -242,7 +242,7 @@ export class EntityPicker extends React.Component<EntityPickerProps> {
|
|
|
242
242
|
const userEntityCodes = [
|
|
243
243
|
localCountryInfo.code,
|
|
244
244
|
...(localCountryInfo.regions ?? []),
|
|
245
|
-
"
|
|
245
|
+
"WRL",
|
|
246
246
|
]
|
|
247
247
|
|
|
248
248
|
const userRegionNames = _.sortBy(
|
|
@@ -290,11 +290,11 @@ export class EntityPicker extends React.Component<EntityPickerProps> {
|
|
|
290
290
|
})
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
@computed private get grapherTable():
|
|
293
|
+
@computed private get grapherTable(): ChartsTable | undefined {
|
|
294
294
|
return this.manager.grapherTable
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
-
@computed private get pickerTable():
|
|
297
|
+
@computed private get pickerTable(): ChartsTable | undefined {
|
|
298
298
|
return this.manager.entityPickerTable
|
|
299
299
|
}
|
|
300
300
|
|
|
@@ -546,7 +546,7 @@ export class EntityPicker extends React.Component<EntityPickerProps> {
|
|
|
546
546
|
// If columnSlug is undefined, we're sorting by relevance, which is (mostly) by country name.
|
|
547
547
|
// If the column is currently missing (not loaded yet), assume it is numeric.
|
|
548
548
|
columnSlug !== undefined &&
|
|
549
|
-
columnSlug !==
|
|
549
|
+
columnSlug !== ChartsTableSlugs.entityName &&
|
|
550
550
|
(col === undefined ||
|
|
551
551
|
col.isMissing ||
|
|
552
552
|
col instanceof ColumnTypeMap.Numeric)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ColumnSlug } from "../../../utils/index.js"
|
|
2
2
|
import { GrapherAnalytics } from "../../core/GrapherAnalytics"
|
|
3
|
-
import {
|
|
3
|
+
import { ChartsTable } from "../../../core-table/index.js"
|
|
4
4
|
import { CoreColumnDef, EntityName, SortOrder } from "../../../types/index.js"
|
|
5
5
|
import { MapConfig } from "../../mapCharts/MapConfig"
|
|
6
6
|
|
|
@@ -13,9 +13,9 @@ export interface EntityPickerManager {
|
|
|
13
13
|
}) => void
|
|
14
14
|
requiredColumnSlugs?: ColumnSlug[] // If this param is provided, and an entity does not have a value for 1+, it will show as unavailable.
|
|
15
15
|
entityPickerColumnDefs?: CoreColumnDef[]
|
|
16
|
-
entityPickerTable?:
|
|
16
|
+
entityPickerTable?: ChartsTable
|
|
17
17
|
entityPickerTableIsLoading?: boolean
|
|
18
|
-
grapherTable?:
|
|
18
|
+
grapherTable?: ChartsTable
|
|
19
19
|
entityType?: string
|
|
20
20
|
analytics?: GrapherAnalytics
|
|
21
21
|
availableEntityNames?: EntityName[]
|
|
@@ -15,7 +15,7 @@ type CustomAggregateSource = (typeof customAggregateSources)[number]
|
|
|
15
15
|
|
|
16
16
|
const entityRegionTypes = [
|
|
17
17
|
"countries",
|
|
18
|
-
"continents", //
|
|
18
|
+
"continents", // geographic continents
|
|
19
19
|
"incomeGroups",
|
|
20
20
|
"historicalCountries", // e.g. USSR, Austria-Hungary
|
|
21
21
|
...aggregateSources,
|
|
@@ -32,7 +32,7 @@ export type EntityNamesByRegionType = Map<EntityRegionType, EntityName[]>
|
|
|
32
32
|
|
|
33
33
|
export const entityRegionTypeLabels: Record<EntityRegionType, string> = {
|
|
34
34
|
countries: "Countries",
|
|
35
|
-
continents: "Continents", //
|
|
35
|
+
continents: "Continents", // Geographic continents
|
|
36
36
|
incomeGroups: "Income groups",
|
|
37
37
|
historicalCountries: "Historical countries and regions", // e.g. USSR, Austria-Hungary
|
|
38
38
|
|
|
@@ -128,9 +128,9 @@ export function groupEntityNamesByRegionType(
|
|
|
128
128
|
>()
|
|
129
129
|
for (const entityName of availableEntityNames) {
|
|
130
130
|
// The regions file includes a definedBy field for aggregates,
|
|
131
|
-
// which could be used here. However,
|
|
131
|
+
// which could be used here. However, external aggregate regions aren't
|
|
132
132
|
// standardized, meaning we might miss some entities.
|
|
133
|
-
// Instead, we rely on the convention that
|
|
133
|
+
// Instead, we rely on the convention that external regions
|
|
134
134
|
// are suffixed with (source) and check the entity name.
|
|
135
135
|
const match = entityName.match(/\(([^)]+)\)$/)
|
|
136
136
|
const sourceCandidate = match?.[1].toLowerCase().replaceAll(" ", "")
|
|
@@ -7,8 +7,8 @@ import { codeToEntityName, entityNameToCode } from "./EntityCodes"
|
|
|
7
7
|
*
|
|
8
8
|
* Implemented: May 2020
|
|
9
9
|
*
|
|
10
|
-
* See PR discussion on how we decided on ~ (tilde):
|
|
11
|
-
* And the initial issue (Facebook rewriting our URLs):
|
|
10
|
+
* See PR discussion on how we decided on ~ (tilde): # legacy PR 446
|
|
11
|
+
* And the initial issue (Facebook rewriting our URLs): # legacy issue 397
|
|
12
12
|
*
|
|
13
13
|
* In short:
|
|
14
14
|
*
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GrapherInterface,
|
|
3
|
-
|
|
3
|
+
VariableDataMetadataDimensions,
|
|
4
4
|
ArchiveContext,
|
|
5
|
-
|
|
5
|
+
VariableId,
|
|
6
6
|
} from "../../types/index.js"
|
|
7
7
|
import React from "react"
|
|
8
8
|
import { Grapher, GrapherProgrammaticInterface } from "./Grapher.js"
|
|
@@ -36,8 +36,8 @@ export function FetchingGrapher(
|
|
|
36
36
|
const grapherState = useMaybeGlobalGrapherStateRef({
|
|
37
37
|
...props.config,
|
|
38
38
|
additionalDataLoaderFn: (
|
|
39
|
-
varId:
|
|
40
|
-
): Promise<
|
|
39
|
+
varId: VariableId
|
|
40
|
+
): Promise<VariableDataMetadataDimensions> =>
|
|
41
41
|
loadVariableDataAndMetadata(varId, props.dataApiUrl, {
|
|
42
42
|
noCache: props.noCache,
|
|
43
43
|
}),
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
sampleFrom,
|
|
16
16
|
exposeInstanceOnWindow,
|
|
17
17
|
QueryParams,
|
|
18
|
-
|
|
18
|
+
MultipleVariableDataDimensionsMap,
|
|
19
19
|
Bounds,
|
|
20
20
|
strToQueryParams,
|
|
21
21
|
queryParamsToStr,
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
GrapherVariant,
|
|
36
36
|
Time,
|
|
37
37
|
} from "../../types/index.js"
|
|
38
|
-
import {
|
|
38
|
+
import { ChartsTable } from "../../core-table/index.js"
|
|
39
39
|
import {
|
|
40
40
|
GRAPHER_LOADED_EVENT_NAME,
|
|
41
41
|
GrapherModal,
|
|
@@ -54,7 +54,7 @@ import { Command, CommandPalette } from "../controls/CommandPalette"
|
|
|
54
54
|
import { EmbedModal } from "../modal/EmbedModal"
|
|
55
55
|
import Mousetrap from "mousetrap"
|
|
56
56
|
import { SelectionArray } from "../selection/SelectionArray"
|
|
57
|
-
import {
|
|
57
|
+
import { legacyToChartsTableAndDimensionsWithMandatorySlug } from "./LegacyToChartsTable"
|
|
58
58
|
import classnames from "classnames"
|
|
59
59
|
import { SidePanel } from "../sidePanel/SidePanel"
|
|
60
60
|
import { EntitySelector } from "../entitySelector/EntitySelector"
|
|
@@ -77,7 +77,7 @@ export const DEFAULT_MS_PER_TICK = 100
|
|
|
77
77
|
export interface GrapherProgrammaticInterface extends GrapherInterface {
|
|
78
78
|
queryStr?: string
|
|
79
79
|
bounds?: Bounds
|
|
80
|
-
table?:
|
|
80
|
+
table?: ChartsTable
|
|
81
81
|
baseUrl?: string
|
|
82
82
|
bakedGrapherURL?: string
|
|
83
83
|
adminBaseUrl?: string
|
|
@@ -104,7 +104,7 @@ export interface GrapherProgrammaticInterface extends GrapherInterface {
|
|
|
104
104
|
|
|
105
105
|
enableKeyboardShortcuts?: boolean
|
|
106
106
|
bindUrlToWindow?: boolean
|
|
107
|
-
|
|
107
|
+
isEmbeddedInPage?: boolean
|
|
108
108
|
isEmbeddedInADataPage?: boolean
|
|
109
109
|
isConfigReady?: boolean
|
|
110
110
|
isDataReady?: boolean
|
|
@@ -152,7 +152,7 @@ export class Grapher extends React.Component<GrapherProps> {
|
|
|
152
152
|
// stored on Grapher so state is preserved when switching to full-screen mode
|
|
153
153
|
|
|
154
154
|
private legacyVariableDataJson:
|
|
155
|
-
|
|
|
155
|
+
| MultipleVariableDataDimensionsMap
|
|
156
156
|
| undefined = undefined
|
|
157
157
|
private hasLoggedGAViewEvent = false
|
|
158
158
|
private hasBeenVisible = false
|
|
@@ -177,26 +177,26 @@ export class Grapher extends React.Component<GrapherProps> {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
@action.bound private _setInputTable(
|
|
180
|
-
json:
|
|
180
|
+
json: MultipleVariableDataDimensionsMap,
|
|
181
181
|
legacyConfig: Partial<LegacyGrapherInterface>
|
|
182
182
|
): void {
|
|
183
183
|
// TODO grapher model: switch this to downloading multiple data and metadata files
|
|
184
184
|
|
|
185
185
|
const startMark = performance.now()
|
|
186
|
-
const tableWithColors =
|
|
186
|
+
const tableWithColors = legacyToChartsTableAndDimensionsWithMandatorySlug(
|
|
187
187
|
json,
|
|
188
188
|
legacyConfig.dimensions ?? [],
|
|
189
189
|
legacyConfig.selectedEntityColors
|
|
190
190
|
)
|
|
191
191
|
this.grapherState.createPerformanceMeasurement(
|
|
192
|
-
"
|
|
192
|
+
"legacyToChartsTableAndDimensions",
|
|
193
193
|
startMark
|
|
194
194
|
)
|
|
195
195
|
|
|
196
196
|
this.grapherState.inputTable = tableWithColors
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
@action
|
|
199
|
+
@action rebuildInputChartsTable(): void {
|
|
200
200
|
// TODO grapher model: switch this to downloading multiple data and metadata files
|
|
201
201
|
if (!this.legacyVariableDataJson) return
|
|
202
202
|
this._setInputTable(
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
reactRenderToStringClientOnly,
|
|
5
5
|
} from "../../components/index.js"
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
ChartsTable,
|
|
8
|
+
BlankChartsTable,
|
|
9
9
|
CoreColumn,
|
|
10
10
|
ColumnTypeMap,
|
|
11
11
|
} from "../../core-table/index.js"
|
|
@@ -51,13 +51,13 @@ import {
|
|
|
51
51
|
GRAPHER_MAP_TYPE,
|
|
52
52
|
GrapherVariant,
|
|
53
53
|
SeriesColorMap,
|
|
54
|
-
|
|
54
|
+
ChartDimensionInterface,
|
|
55
55
|
DimensionProperty,
|
|
56
56
|
DetailsMarker,
|
|
57
57
|
EnrichedDetail,
|
|
58
58
|
ProjectionColumnInfo,
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
ColumnDef,
|
|
60
|
+
VariableRow,
|
|
61
61
|
SortConfig,
|
|
62
62
|
Color,
|
|
63
63
|
GlobeRegionName,
|
|
@@ -95,7 +95,7 @@ import {
|
|
|
95
95
|
timeBoundToTimeBoundString,
|
|
96
96
|
getRegionByName,
|
|
97
97
|
checkIsCountry,
|
|
98
|
-
|
|
98
|
+
checkIsContinent,
|
|
99
99
|
checkIsIncomeGroup,
|
|
100
100
|
checkHasMembers,
|
|
101
101
|
sortNumeric,
|
|
@@ -330,17 +330,17 @@ export class GrapherState {
|
|
|
330
330
|
externalQueryParams: QueryParams = {}
|
|
331
331
|
private framePaddingHorizontal = GRAPHER_FRAME_PADDING_HORIZONTAL
|
|
332
332
|
private framePaddingVertical = GRAPHER_FRAME_PADDING_VERTICAL
|
|
333
|
-
_inputTable:
|
|
333
|
+
_inputTable: ChartsTable = new ChartsTable()
|
|
334
334
|
|
|
335
335
|
// TODO Daniel: probably obsolete?
|
|
336
336
|
// @observable.ref interpolatedSortColumnsBySlug:
|
|
337
337
|
// | CoreColumnBySlug
|
|
338
338
|
// | undefined = {}
|
|
339
|
-
get inputTable():
|
|
339
|
+
get inputTable(): ChartsTable {
|
|
340
340
|
return this._inputTable
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
-
@action set inputTable(table:
|
|
343
|
+
@action set inputTable(table: ChartsTable) {
|
|
344
344
|
this._inputTable = table
|
|
345
345
|
|
|
346
346
|
if (this.manager?.selection?.hasSelection) {
|
|
@@ -355,7 +355,7 @@ export class GrapherState {
|
|
|
355
355
|
@computed get dataTableSlugs(): ColumnSlug[] {
|
|
356
356
|
return this.tableSlugs ? this.tableSlugs.split(" ") : this.newSlugs
|
|
357
357
|
}
|
|
358
|
-
|
|
358
|
+
isEmbeddedInPage?: boolean = false
|
|
359
359
|
isEmbeddedInADataPage?: boolean = false
|
|
360
360
|
|
|
361
361
|
// These are explicitly set to `false` if FetchingGrapher or some other
|
|
@@ -523,11 +523,11 @@ export class GrapherState {
|
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
this._additionalDataLoaderFn = options.additionalDataLoaderFn
|
|
526
|
-
this.
|
|
526
|
+
this.isEmbeddedInPage = options.isEmbeddedInPage ?? false
|
|
527
527
|
this.isEmbeddedInADataPage = options.isEmbeddedInADataPage ?? false
|
|
528
528
|
|
|
529
529
|
this._inputTable =
|
|
530
|
-
options.table ??
|
|
530
|
+
options.table ?? BlankChartsTable(`initialGrapherTable`)
|
|
531
531
|
this.initialOptions = options
|
|
532
532
|
this.analytics = new GrapherAnalytics(this.initialOptions.env ?? "")
|
|
533
533
|
this.selection =
|
|
@@ -900,7 +900,7 @@ export class GrapherState {
|
|
|
900
900
|
}
|
|
901
901
|
|
|
902
902
|
// table that is used for display in the table tab
|
|
903
|
-
@computed get tableForDisplay():
|
|
903
|
+
@computed get tableForDisplay(): ChartsTable {
|
|
904
904
|
let table = this.table
|
|
905
905
|
|
|
906
906
|
if (!this.isReady || !this.isOnTableTab) return table
|
|
@@ -918,7 +918,7 @@ export class GrapherState {
|
|
|
918
918
|
return table
|
|
919
919
|
}
|
|
920
920
|
|
|
921
|
-
@computed get filteredTableForDisplay():
|
|
921
|
+
@computed get filteredTableForDisplay(): ChartsTable {
|
|
922
922
|
let table = this.tableForDisplay
|
|
923
923
|
const { filter } = this.dataTableConfig
|
|
924
924
|
|
|
@@ -945,7 +945,7 @@ export class GrapherState {
|
|
|
945
945
|
return table
|
|
946
946
|
}
|
|
947
947
|
|
|
948
|
-
@computed get tableForSelection():
|
|
948
|
+
@computed get tableForSelection(): ChartsTable {
|
|
949
949
|
// This table specifies which entities can be selected in the charts EntitySelectorModal.
|
|
950
950
|
// It should contain all entities that can be selected, and none more.
|
|
951
951
|
// Depending on the chart type, the criteria for being able to select an entity are
|
|
@@ -981,7 +981,7 @@ export class GrapherState {
|
|
|
981
981
|
* since it's more efficient to run them on a table that has been filtered
|
|
982
982
|
* by selected entities.
|
|
983
983
|
*/
|
|
984
|
-
@computed get tableAfterColorAndSizeToleranceApplication():
|
|
984
|
+
@computed get tableAfterColorAndSizeToleranceApplication(): ChartsTable {
|
|
985
985
|
let table = this.inputTable
|
|
986
986
|
|
|
987
987
|
if (this.hasScatter && this.sizeColumnSlug) {
|
|
@@ -1010,7 +1010,7 @@ export class GrapherState {
|
|
|
1010
1010
|
|
|
1011
1011
|
// If an author sets a timeline or entity filter, run it early in the pipeline
|
|
1012
1012
|
// so to the charts it's as if the filtered times and entities do not exist
|
|
1013
|
-
@computed get tableAfterAuthorTimelineAndEntityFilter():
|
|
1013
|
+
@computed get tableAfterAuthorTimelineAndEntityFilter(): ChartsTable {
|
|
1014
1014
|
let table = this.tableAfterColorAndSizeToleranceApplication
|
|
1015
1015
|
|
|
1016
1016
|
// Filter entities
|
|
@@ -1032,7 +1032,7 @@ export class GrapherState {
|
|
|
1032
1032
|
}
|
|
1033
1033
|
|
|
1034
1034
|
@computed
|
|
1035
|
-
get tableAfterAuthorTimelineAndActiveChartTransform():
|
|
1035
|
+
get tableAfterAuthorTimelineAndActiveChartTransform(): ChartsTable {
|
|
1036
1036
|
const table = this.table
|
|
1037
1037
|
if (!this.isReady || !this.isOnChartOrMapTab) return table
|
|
1038
1038
|
|
|
@@ -1088,11 +1088,11 @@ export class GrapherState {
|
|
|
1088
1088
|
return this.chartState.series.map((series) => series.seriesName)
|
|
1089
1089
|
}
|
|
1090
1090
|
|
|
1091
|
-
@computed get table():
|
|
1091
|
+
@computed get table(): ChartsTable {
|
|
1092
1092
|
return this.tableAfterAuthorTimelineAndEntityFilter
|
|
1093
1093
|
}
|
|
1094
1094
|
@computed
|
|
1095
|
-
private get tableAfterAllTransformsAndFilters():
|
|
1095
|
+
private get tableAfterAllTransformsAndFilters(): ChartsTable {
|
|
1096
1096
|
const { startTime, endTime } = this
|
|
1097
1097
|
const table = this.tableAfterAuthorTimelineAndActiveChartTransform
|
|
1098
1098
|
|
|
@@ -1115,7 +1115,7 @@ export class GrapherState {
|
|
|
1115
1115
|
return table.filterByTimeRange(startTime, endTime)
|
|
1116
1116
|
}
|
|
1117
1117
|
|
|
1118
|
-
@computed get transformedTable():
|
|
1118
|
+
@computed get transformedTable(): ChartsTable {
|
|
1119
1119
|
return this.tableAfterAllTransformsAndFilters
|
|
1120
1120
|
}
|
|
1121
1121
|
isExportingToSvgOrPng = false
|
|
@@ -1204,11 +1204,11 @@ export class GrapherState {
|
|
|
1204
1204
|
}
|
|
1205
1205
|
|
|
1206
1206
|
@computed get isUserLoggedInAsAdmin(): boolean {
|
|
1207
|
-
// This cookie is set by visiting
|
|
1208
|
-
// There is an iframe on
|
|
1207
|
+
// This cookie is set by visiting an identifyadmin endpoint on the static site.
|
|
1208
|
+
// There is an iframe on the admin site to trigger a visit to that page.
|
|
1209
1209
|
try {
|
|
1210
1210
|
// Cookie access can be restricted by iframe sandboxing, in which case the below code will throw an error
|
|
1211
|
-
// see
|
|
1211
|
+
// see # legacy PR 2452
|
|
1212
1212
|
return !!Cookies.get(CookieKey.isAdmin)
|
|
1213
1213
|
} catch {
|
|
1214
1214
|
return false
|
|
@@ -1414,9 +1414,9 @@ export class GrapherState {
|
|
|
1414
1414
|
)
|
|
1415
1415
|
}
|
|
1416
1416
|
|
|
1417
|
-
@computed get
|
|
1417
|
+
@computed get shouldLinkToSource(): boolean {
|
|
1418
1418
|
if (
|
|
1419
|
-
this.
|
|
1419
|
+
this.isEmbeddedInPage ||
|
|
1420
1420
|
this.isExportingToSvgOrPng ||
|
|
1421
1421
|
!this.isInIFrame
|
|
1422
1422
|
)
|
|
@@ -1425,9 +1425,9 @@ export class GrapherState {
|
|
|
1425
1425
|
return true
|
|
1426
1426
|
}
|
|
1427
1427
|
|
|
1428
|
-
@computed get
|
|
1428
|
+
@computed get hasLegacyLogo(): boolean {
|
|
1429
1429
|
return (
|
|
1430
|
-
!this.hideLogo && (this.logo === undefined || this.logo === "
|
|
1430
|
+
!this.hideLogo && (this.logo === undefined || this.logo === "legacy")
|
|
1431
1431
|
)
|
|
1432
1432
|
}
|
|
1433
1433
|
@computed get hasFatalErrors(): boolean {
|
|
@@ -1726,12 +1726,12 @@ export class GrapherState {
|
|
|
1726
1726
|
@computed.struct get filledDimensions(): ChartDimension[] {
|
|
1727
1727
|
return this.isReady ? this.dimensions : []
|
|
1728
1728
|
}
|
|
1729
|
-
@action.bound addDimension(config:
|
|
1729
|
+
@action.bound addDimension(config: ChartDimensionInterface): void {
|
|
1730
1730
|
this.dimensions.push(new ChartDimension(config, this))
|
|
1731
1731
|
}
|
|
1732
1732
|
@action.bound setDimensionsForProperty(
|
|
1733
1733
|
property: DimensionProperty,
|
|
1734
|
-
newConfigs:
|
|
1734
|
+
newConfigs: ChartDimensionInterface[]
|
|
1735
1735
|
): void {
|
|
1736
1736
|
let newDimensions: ChartDimension[] = []
|
|
1737
1737
|
this.dimensionSlots.forEach((slot) => {
|
|
@@ -1744,7 +1744,7 @@ export class GrapherState {
|
|
|
1744
1744
|
this.dimensions = newDimensions
|
|
1745
1745
|
}
|
|
1746
1746
|
@action.bound setDimensionsFromConfigs(
|
|
1747
|
-
configs:
|
|
1747
|
+
configs: ChartDimensionInterface[]
|
|
1748
1748
|
): void {
|
|
1749
1749
|
this.dimensions = configs.map(
|
|
1750
1750
|
(config) => new ChartDimension(config, this)
|
|
@@ -2187,7 +2187,7 @@ export class GrapherState {
|
|
|
2187
2187
|
|
|
2188
2188
|
if (xColumnSlug !== undefined) {
|
|
2189
2189
|
const xColumn = this.inputTable.get(xColumnSlug)
|
|
2190
|
-
.def as
|
|
2190
|
+
.def as ColumnDef
|
|
2191
2191
|
// exclude population variable if it's used as the x dimension in a marimekko
|
|
2192
2192
|
if (
|
|
2193
2193
|
!hasMarimekko ||
|
|
@@ -2199,7 +2199,7 @@ export class GrapherState {
|
|
|
2199
2199
|
// exclude population variable if it's used as the size dimension in a scatter plot
|
|
2200
2200
|
if (sizeColumnSlug !== undefined) {
|
|
2201
2201
|
const sizeColumn = this.inputTable.get(sizeColumnSlug)
|
|
2202
|
-
.def as
|
|
2202
|
+
.def as ColumnDef
|
|
2203
2203
|
if (!isPopulationVariableETLPath(sizeColumn?.catalogPath ?? ""))
|
|
2204
2204
|
columnSlugs.push(sizeColumnSlug)
|
|
2205
2205
|
}
|
|
@@ -2272,7 +2272,7 @@ export class GrapherState {
|
|
|
2272
2272
|
|
|
2273
2273
|
const uniqueDatasetNames = _.uniq(
|
|
2274
2274
|
excludeUndefined(
|
|
2275
|
-
yColumns.map((col) => (col.def as
|
|
2275
|
+
yColumns.map((col) => (col.def as ColumnDef).datasetName)
|
|
2276
2276
|
)
|
|
2277
2277
|
)
|
|
2278
2278
|
|
|
@@ -2500,10 +2500,10 @@ export class GrapherState {
|
|
|
2500
2500
|
}
|
|
2501
2501
|
|
|
2502
2502
|
// Filter data to what can be display on the map (across all times)
|
|
2503
|
-
@computed get mappableData():
|
|
2503
|
+
@computed get mappableData(): VariableRow<any>[] {
|
|
2504
2504
|
return this.inputTable
|
|
2505
2505
|
.get(this.mapColumnSlug)
|
|
2506
|
-
.
|
|
2506
|
+
.dataRows.filter((row) => isOnTheMap(row.entityName))
|
|
2507
2507
|
}
|
|
2508
2508
|
@computed get isMobile(): boolean {
|
|
2509
2509
|
return isMobile()
|
|
@@ -2566,7 +2566,7 @@ export class GrapherState {
|
|
|
2566
2566
|
// For these, defer to the bounds that are set externally
|
|
2567
2567
|
if (
|
|
2568
2568
|
this.isEmbeddedInADataPage ||
|
|
2569
|
-
this.
|
|
2569
|
+
this.isEmbeddedInPage ||
|
|
2570
2570
|
this.manager ||
|
|
2571
2571
|
isInIFrame
|
|
2572
2572
|
)
|
|
@@ -3055,9 +3055,9 @@ export class GrapherState {
|
|
|
3055
3055
|
@computed get isRelatedQuestionTargetDifferentFromCurrentPage(): boolean {
|
|
3056
3056
|
// comparing paths rather than full URLs for this to work as
|
|
3057
3057
|
// expected on local and staging where the origin (e.g.
|
|
3058
|
-
//
|
|
3059
|
-
// been entered in the related question URL field
|
|
3060
|
-
//
|
|
3058
|
+
// staging.example.com) doesn't match the production origin that has
|
|
3059
|
+
// been entered in the related question URL field, and yet should
|
|
3060
|
+
// still yield a match.
|
|
3061
3061
|
// - Note that this won't work on production previews (where the
|
|
3062
3062
|
// path is /admin/posts/preview/ID)
|
|
3063
3063
|
const { relatedQuestions = [], hasRelatedQuestion } = this
|
|
@@ -3249,7 +3249,7 @@ export class GrapherState {
|
|
|
3249
3249
|
let url = Url.fromURL(baseUrl)
|
|
3250
3250
|
// We want to preserve the tab in the embed URL so that if we change the
|
|
3251
3251
|
// default view of the chart, it won't change existing embeds.
|
|
3252
|
-
// See
|
|
3252
|
+
// See # legacy issue 2805
|
|
3253
3253
|
const { tab } = this.allParams
|
|
3254
3254
|
if (tab && !url.queryParams.tab) {
|
|
3255
3255
|
url = url.updateQueryParams({ tab })
|
|
@@ -3351,12 +3351,12 @@ export class GrapherState {
|
|
|
3351
3351
|
// Rotate to the selected country
|
|
3352
3352
|
this.globeController.rotateToCountry(region.name)
|
|
3353
3353
|
this.mapConfig.region = MapRegionName.World
|
|
3354
|
-
} else if (
|
|
3355
|
-
// Rotate to the selected
|
|
3354
|
+
} else if (checkIsContinent(region)) {
|
|
3355
|
+
// Rotate to the selected continent
|
|
3356
3356
|
const regionName = MAP_REGION_NAMES[
|
|
3357
3357
|
region.name
|
|
3358
3358
|
] as GlobeRegionName
|
|
3359
|
-
this.globeController.
|
|
3359
|
+
this.globeController.rotateToContinent(regionName)
|
|
3360
3360
|
this.mapConfig.region = regionName
|
|
3361
3361
|
} else if (checkIsIncomeGroup(region)) {
|
|
3362
3362
|
// Switch back to the 2d map if an income group is selected
|
|
@@ -3411,7 +3411,7 @@ export class GrapherState {
|
|
|
3411
3411
|
if (!region) return false
|
|
3412
3412
|
|
|
3413
3413
|
// Don't mute the selected continent
|
|
3414
|
-
if (
|
|
3414
|
+
if (checkIsContinent(region))
|
|
3415
3415
|
return region.name !== MAP_REGION_LABELS[this.mapConfig.region]
|
|
3416
3416
|
|
|
3417
3417
|
const countriesInRegion = getCountriesByRegion(
|
|
@@ -3517,7 +3517,7 @@ export class GrapherState {
|
|
|
3517
3517
|
if (
|
|
3518
3518
|
this.frameBounds.width > 940 &&
|
|
3519
3519
|
// don't use the panel if the grapher is embedded
|
|
3520
|
-
((!this.isInIFrame && !this.
|
|
3520
|
+
((!this.isInIFrame && !this.isEmbeddedInPage) ||
|
|
3521
3521
|
// unless we're in full-screen mode
|
|
3522
3522
|
this.isInFullScreenMode)
|
|
3523
3523
|
)
|
|
@@ -6,8 +6,8 @@ import { GrapherProgrammaticInterface } from "../index.js"
|
|
|
6
6
|
import { FetchingGrapher } from "./FetchingGrapher.js"
|
|
7
7
|
import {
|
|
8
8
|
ArchiveContext,
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
VariableDataMetadataDimensions,
|
|
10
|
+
VariableId,
|
|
11
11
|
} from "../../types/index.js"
|
|
12
12
|
import { loadVariableDataAndMetadata } from "./loadVariable.js"
|
|
13
13
|
import { createRoot } from "react-dom/client"
|
|
@@ -74,8 +74,8 @@ export function renderGrapherIntoContainer(
|
|
|
74
74
|
const grapherConfigWithBounds = {
|
|
75
75
|
...config,
|
|
76
76
|
additionalDataLoaderFn: (
|
|
77
|
-
varId:
|
|
78
|
-
): Promise<
|
|
77
|
+
varId: VariableId
|
|
78
|
+
): Promise<VariableDataMetadataDimensions> =>
|
|
79
79
|
loadVariableDataAndMetadata(varId, dataApiUrl, { noCache }),
|
|
80
80
|
}
|
|
81
81
|
|