@buildcanada/charts 0.1.0 → 0.2.0
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 +9 -24
- 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/ContentSwitchers.tsx +1 -1
- 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 +47 -50
- 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 +13 -13
- 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 +4 -4
- 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/SlopeChartHelpers.ts +1 -1
- 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/tabs/Tabs.tsx +1 -1
- 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 +3 -3
- 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 +51 -51
- 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/LICENSE.md +0 -8
- package/README.md +0 -113
- package/src/types/OwidVariable.ts +0 -133
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
omitUndefinedValues,
|
|
10
10
|
isPresent,
|
|
11
11
|
dayjs,
|
|
12
|
-
|
|
12
|
+
Source,
|
|
13
13
|
formatValue,
|
|
14
14
|
checkIsVeryShortUnit,
|
|
15
15
|
TickFormattingOptions,
|
|
16
|
-
|
|
16
|
+
VariableDisplayConfigInterface,
|
|
17
17
|
ColumnSlug,
|
|
18
18
|
PrimitiveType,
|
|
19
19
|
imemo,
|
|
@@ -29,16 +29,16 @@ import {
|
|
|
29
29
|
ColumnTypeNames,
|
|
30
30
|
CoreColumnDef,
|
|
31
31
|
EntityName,
|
|
32
|
-
|
|
32
|
+
VariableRow,
|
|
33
33
|
ErrorValue,
|
|
34
|
-
|
|
34
|
+
VariableRoundingMode,
|
|
35
35
|
} from "../types/index.js"
|
|
36
36
|
import { ErrorValueTypes, isNotErrorValue } from "./ErrorValues.js"
|
|
37
37
|
import {
|
|
38
38
|
getOriginalStartTimeColumnSlug,
|
|
39
39
|
getOriginalTimeColumnSlug,
|
|
40
40
|
getOriginalValueColumnSlug,
|
|
41
|
-
} from "./
|
|
41
|
+
} from "./TableUtil.js"
|
|
42
42
|
import * as R from "remeda"
|
|
43
43
|
|
|
44
44
|
export abstract class AbstractCoreColumn<JS_TYPE extends PrimitiveType> {
|
|
@@ -86,7 +86,7 @@ export abstract class AbstractCoreColumn<JS_TYPE extends PrimitiveType> {
|
|
|
86
86
|
return this.def.toleranceStrategy
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
@imemo get display():
|
|
89
|
+
@imemo get display(): VariableDisplayConfigInterface | undefined {
|
|
90
90
|
return this.def.display
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -130,18 +130,18 @@ export abstract class AbstractCoreColumn<JS_TYPE extends PrimitiveType> {
|
|
|
130
130
|
return this.originalTimeColumn.formatValue(time)
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
@imemo get roundingMode():
|
|
133
|
+
@imemo get roundingMode(): VariableRoundingMode {
|
|
134
134
|
return (
|
|
135
|
-
this.display?.roundingMode ??
|
|
135
|
+
this.display?.roundingMode ?? VariableRoundingMode.decimalPlaces
|
|
136
136
|
)
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
@imemo get roundsToFixedDecimals(): boolean {
|
|
140
|
-
return this.roundingMode ===
|
|
140
|
+
return this.roundingMode === VariableRoundingMode.decimalPlaces
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
@imemo get roundsToSignificantFigures(): boolean {
|
|
144
|
-
return this.roundingMode ===
|
|
144
|
+
return this.roundingMode === VariableRoundingMode.significantFigures
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
@imemo get numDecimalPlaces(): number {
|
|
@@ -418,7 +418,7 @@ export abstract class AbstractCoreColumn<JS_TYPE extends PrimitiveType> {
|
|
|
418
418
|
return this.jsType === "string" ? values.sort() : sortNumeric(values)
|
|
419
419
|
}
|
|
420
420
|
|
|
421
|
-
get source():
|
|
421
|
+
get source(): Source {
|
|
422
422
|
const { def } = this
|
|
423
423
|
return {
|
|
424
424
|
name: def.sourceName,
|
|
@@ -465,7 +465,7 @@ export abstract class AbstractCoreColumn<JS_TYPE extends PrimitiveType> {
|
|
|
465
465
|
|
|
466
466
|
// todo: remove? Should not be on CoreTable
|
|
467
467
|
// assumes table is sorted by time
|
|
468
|
-
@imemo get
|
|
468
|
+
@imemo get dataRows(): VariableRow<JS_TYPE>[] {
|
|
469
469
|
const entities = this.allEntityNames
|
|
470
470
|
const times = this.allTimes
|
|
471
471
|
const values = this.values
|
|
@@ -483,12 +483,12 @@ export abstract class AbstractCoreColumn<JS_TYPE extends PrimitiveType> {
|
|
|
483
483
|
}
|
|
484
484
|
|
|
485
485
|
// todo: remove? Should not be on CoreTable
|
|
486
|
-
@imemo get
|
|
486
|
+
@imemo get dataRowsByEntityName(): Map<
|
|
487
487
|
EntityName,
|
|
488
|
-
|
|
488
|
+
VariableRow<JS_TYPE>[]
|
|
489
489
|
> {
|
|
490
|
-
const map = new Map<EntityName,
|
|
491
|
-
this.
|
|
490
|
+
const map = new Map<EntityName, VariableRow<JS_TYPE>[]>()
|
|
491
|
+
this.dataRows.forEach((row) => {
|
|
492
492
|
if (!map.has(row.entityName)) map.set(row.entityName, [])
|
|
493
493
|
map.get(row.entityName)!.push(row)
|
|
494
494
|
})
|
|
@@ -496,15 +496,15 @@ export abstract class AbstractCoreColumn<JS_TYPE extends PrimitiveType> {
|
|
|
496
496
|
}
|
|
497
497
|
|
|
498
498
|
// todo: remove? Should not be on CoreTable
|
|
499
|
-
@imemo get
|
|
499
|
+
@imemo get dataRowByEntityNameAndTime(): Map<
|
|
500
500
|
EntityName,
|
|
501
|
-
Map<Time,
|
|
501
|
+
Map<Time, VariableRow<JS_TYPE>>
|
|
502
502
|
> {
|
|
503
503
|
const valueByEntityNameAndTime = new Map<
|
|
504
504
|
EntityName,
|
|
505
|
-
Map<Time,
|
|
505
|
+
Map<Time, VariableRow<JS_TYPE>>
|
|
506
506
|
>()
|
|
507
|
-
this.
|
|
507
|
+
this.dataRows.forEach((row) => {
|
|
508
508
|
if (!valueByEntityNameAndTime.has(row.entityName))
|
|
509
509
|
valueByEntityNameAndTime.set(row.entityName, new Map())
|
|
510
510
|
valueByEntityNameAndTime.get(row.entityName)!.set(row.time, row)
|
|
@@ -515,7 +515,7 @@ export abstract class AbstractCoreColumn<JS_TYPE extends PrimitiveType> {
|
|
|
515
515
|
// todo: remove? Should not be on CoreTable
|
|
516
516
|
@imemo get valuesByTime(): Map<Time, JS_TYPE[]> {
|
|
517
517
|
const map = new Map<Time, JS_TYPE[]>()
|
|
518
|
-
this.
|
|
518
|
+
this.dataRows.forEach((row) => {
|
|
519
519
|
if (!map.has(row.time)) map.set(row.time, [])
|
|
520
520
|
map.get(row.time)!.push(row.value)
|
|
521
521
|
})
|
|
@@ -528,7 +528,7 @@ export abstract class AbstractCoreColumn<JS_TYPE extends PrimitiveType> {
|
|
|
528
528
|
Time,
|
|
529
529
|
Map<EntityName, JS_TYPE>
|
|
530
530
|
>()
|
|
531
|
-
this.
|
|
531
|
+
this.dataRows.forEach((row) => {
|
|
532
532
|
if (!valueByTimeAndEntityName.has(row.time))
|
|
533
533
|
valueByTimeAndEntityName.set(row.time, new Map())
|
|
534
534
|
valueByTimeAndEntityName
|
|
@@ -548,7 +548,7 @@ export abstract class AbstractCoreColumn<JS_TYPE extends PrimitiveType> {
|
|
|
548
548
|
EntityName,
|
|
549
549
|
Map<Time, JS_TYPE>
|
|
550
550
|
>()
|
|
551
|
-
this.
|
|
551
|
+
this.dataRows.forEach((row) => {
|
|
552
552
|
if (!valueByEntityNameAndTime.has(row.entityName))
|
|
553
553
|
valueByEntityNameAndTime.set(row.entityName, new Map())
|
|
554
554
|
valueByEntityNameAndTime
|
|
@@ -758,7 +758,7 @@ class CurrencyColumn extends NumericColumn {
|
|
|
758
758
|
options?: TickFormattingOptions
|
|
759
759
|
): string {
|
|
760
760
|
return super.formatValue(value, {
|
|
761
|
-
roundingMode:
|
|
761
|
+
roundingMode: VariableRoundingMode.decimalPlaces,
|
|
762
762
|
numDecimalPlaces: 0,
|
|
763
763
|
unit: this.shortUnit,
|
|
764
764
|
...options,
|
|
@@ -12,10 +12,10 @@ import {
|
|
|
12
12
|
ColumnTypeNames,
|
|
13
13
|
CoreColumnDef,
|
|
14
14
|
ErrorValue,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
EntityCodeColumnDef,
|
|
16
|
+
EntityIdColumnDef,
|
|
17
|
+
EntityNameColumnDef,
|
|
18
|
+
ChartsTableSlugs,
|
|
19
19
|
} from "../types/index.js"
|
|
20
20
|
import { ErrorValueTypes, DroppedForTesting } from "./ErrorValues.js"
|
|
21
21
|
|
|
@@ -135,9 +135,9 @@ export const guessColumnDefFromSlugAndRow = (
|
|
|
135
135
|
name: "Year",
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
if (slug ===
|
|
139
|
-
if (slug ===
|
|
140
|
-
if (slug ===
|
|
138
|
+
if (slug === ChartsTableSlugs.entityName) return EntityNameColumnDef
|
|
139
|
+
if (slug === ChartsTableSlugs.entityCode) return EntityCodeColumnDef
|
|
140
|
+
if (slug === ChartsTableSlugs.entityId) return EntityIdColumnDef
|
|
141
141
|
|
|
142
142
|
if (slug === "date")
|
|
143
143
|
return {
|
|
@@ -3,28 +3,28 @@ import {
|
|
|
3
3
|
sampleFrom,
|
|
4
4
|
getRandomNumberGenerator,
|
|
5
5
|
countries,
|
|
6
|
-
|
|
6
|
+
VariableDisplayConfigInterface,
|
|
7
7
|
ColumnSlug,
|
|
8
8
|
} from "../utils/index.js"
|
|
9
9
|
import {
|
|
10
10
|
TimeRange,
|
|
11
11
|
ColumnTypeNames,
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
ColumnDef,
|
|
13
|
+
ChartsTableSlugs,
|
|
14
14
|
} from "../types/index.js"
|
|
15
|
-
import {
|
|
15
|
+
import { ChartsTable } from "./ChartsTable.js"
|
|
16
16
|
|
|
17
17
|
interface SynthOptions {
|
|
18
18
|
entityCount: number
|
|
19
19
|
entityNames: string[]
|
|
20
20
|
timeRange: TimeRange
|
|
21
|
-
columnDefs:
|
|
21
|
+
columnDefs: ColumnDef[]
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
const
|
|
24
|
+
const SynthesizeChartsTable = (
|
|
25
25
|
options?: Partial<SynthOptions>,
|
|
26
26
|
seed = Date.now()
|
|
27
|
-
):
|
|
27
|
+
): ChartsTable => {
|
|
28
28
|
const finalOptions: SynthOptions = {
|
|
29
29
|
entityNames: [],
|
|
30
30
|
entityCount: 2,
|
|
@@ -35,10 +35,10 @@ const SynthesizeOwidTable = (
|
|
|
35
35
|
const { entityCount, columnDefs, timeRange, entityNames } = finalOptions
|
|
36
36
|
const colSlugs = (
|
|
37
37
|
[
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
ChartsTableSlugs.entityName,
|
|
39
|
+
ChartsTableSlugs.entityCode,
|
|
40
|
+
ChartsTableSlugs.entityId,
|
|
41
|
+
ChartsTableSlugs.year,
|
|
42
42
|
] as ColumnSlug[]
|
|
43
43
|
).concat(columnDefs.map((col) => col.slug!))
|
|
44
44
|
|
|
@@ -67,7 +67,7 @@ const SynthesizeOwidTable = (
|
|
|
67
67
|
.join("\n")
|
|
68
68
|
})
|
|
69
69
|
|
|
70
|
-
return new
|
|
70
|
+
return new ChartsTable(
|
|
71
71
|
`${colSlugs.join(",")}\n${rows.join("\n")}`,
|
|
72
72
|
columnDefs
|
|
73
73
|
)
|
|
@@ -76,8 +76,8 @@ const SynthesizeOwidTable = (
|
|
|
76
76
|
export const SynthesizeNonCountryTable = (
|
|
77
77
|
options?: Partial<SynthOptions>,
|
|
78
78
|
seed = Date.now()
|
|
79
|
-
):
|
|
80
|
-
|
|
79
|
+
): ChartsTable =>
|
|
80
|
+
SynthesizeChartsTable(
|
|
81
81
|
{
|
|
82
82
|
entityNames: ["Fire", "Earthquake", "Tornado"],
|
|
83
83
|
columnDefs: [
|
|
@@ -110,9 +110,9 @@ export enum SampleColumnSlugs {
|
|
|
110
110
|
export const SynthesizeGDPTable = (
|
|
111
111
|
options?: Partial<SynthOptions>,
|
|
112
112
|
seed = Date.now(),
|
|
113
|
-
display?:
|
|
114
|
-
):
|
|
115
|
-
|
|
113
|
+
display?: VariableDisplayConfigInterface
|
|
114
|
+
): ChartsTable =>
|
|
115
|
+
SynthesizeChartsTable(
|
|
116
116
|
{
|
|
117
117
|
columnDefs: [
|
|
118
118
|
{
|
|
@@ -173,8 +173,8 @@ const SynthSource = (
|
|
|
173
173
|
export const SynthesizeFruitTable = (
|
|
174
174
|
options?: Partial<SynthOptions>,
|
|
175
175
|
seed = Date.now()
|
|
176
|
-
):
|
|
177
|
-
|
|
176
|
+
): ChartsTable =>
|
|
177
|
+
SynthesizeChartsTable(
|
|
178
178
|
{
|
|
179
179
|
columnDefs: [
|
|
180
180
|
{
|
|
@@ -209,7 +209,7 @@ export const SynthesizeFruitTableWithNonPositives = (
|
|
|
209
209
|
options?: Partial<SynthOptions>,
|
|
210
210
|
howManyNonPositives = 20,
|
|
211
211
|
seed = Date.now()
|
|
212
|
-
):
|
|
212
|
+
): ChartsTable => {
|
|
213
213
|
const rand = getRandomNumberGenerator(-1000, 0)
|
|
214
214
|
return SynthesizeFruitTable(options, seed).replaceRandomCells(
|
|
215
215
|
howManyNonPositives,
|
|
@@ -225,7 +225,7 @@ export const SynthesizeFruitTableWithStringValues = (
|
|
|
225
225
|
options?: Partial<SynthOptions>,
|
|
226
226
|
howMany = 20,
|
|
227
227
|
seed = Date.now()
|
|
228
|
-
):
|
|
228
|
+
): ChartsTable => {
|
|
229
229
|
return SynthesizeFruitTable(options, seed).replaceRandomCells(
|
|
230
230
|
howMany,
|
|
231
231
|
[SampleColumnSlugs.Fruit, SampleColumnSlugs.Vegetables],
|
|
@@ -237,9 +237,9 @@ export const SynthesizeFruitTableWithStringValues = (
|
|
|
237
237
|
export const SynthesizeProjectedPopulationTable = (
|
|
238
238
|
options?: Partial<SynthOptions>,
|
|
239
239
|
seed = Date.now(),
|
|
240
|
-
display?:
|
|
241
|
-
):
|
|
242
|
-
|
|
240
|
+
display?: VariableDisplayConfigInterface
|
|
241
|
+
): ChartsTable =>
|
|
242
|
+
SynthesizeChartsTable(
|
|
243
243
|
{
|
|
244
244
|
columnDefs: [
|
|
245
245
|
{
|
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
ColumnSlug,
|
|
3
3
|
ColumnTypeNames,
|
|
4
4
|
CoreColumnDef,
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
ColumnDef,
|
|
6
|
+
ChartsTableSlugs,
|
|
7
7
|
} from "../types/index.js"
|
|
8
8
|
import { CoreTable } from "./CoreTable.js"
|
|
9
9
|
|
|
10
10
|
export function timeColumnSlugFromColumnDef(
|
|
11
|
-
def:
|
|
12
|
-
):
|
|
13
|
-
return def.isDailyMeasurement ?
|
|
11
|
+
def: ColumnDef
|
|
12
|
+
): ChartsTableSlugs.day | ChartsTableSlugs.year {
|
|
13
|
+
return def.isDailyMeasurement ? ChartsTableSlugs.day : ChartsTableSlugs.year
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export function makeOriginalTimeSlugFromColumnSlug(slug: ColumnSlug): string {
|
package/src/core-table/index.ts
CHANGED
|
@@ -7,7 +7,7 @@ export {
|
|
|
7
7
|
SynthesizeFruitTableWithNonPositives,
|
|
8
8
|
SynthesizeFruitTableWithStringValues,
|
|
9
9
|
SynthesizeProjectedPopulationTable,
|
|
10
|
-
} from "./
|
|
10
|
+
} from "./TableSynthesizers.js"
|
|
11
11
|
|
|
12
12
|
export {
|
|
13
13
|
type CoreColumn,
|
|
@@ -17,7 +17,7 @@ export {
|
|
|
17
17
|
TimeColumn,
|
|
18
18
|
} from "./CoreTableColumns.js"
|
|
19
19
|
|
|
20
|
-
export {
|
|
20
|
+
export { ChartsTable, BlankChartsTable } from "./ChartsTable.js"
|
|
21
21
|
|
|
22
22
|
export {
|
|
23
23
|
DroppedForTesting,
|
|
@@ -71,7 +71,7 @@ export {
|
|
|
71
71
|
makeOriginalValueSlugFromColumnSlug,
|
|
72
72
|
getOriginalTimeColumnSlug,
|
|
73
73
|
toPercentageColumnDef,
|
|
74
|
-
} from "./
|
|
74
|
+
} from "./TableUtil.js"
|
|
75
75
|
|
|
76
76
|
export {
|
|
77
77
|
insertMissingValuePlaceholders,
|
|
@@ -114,7 +114,7 @@ export const ColumnGrammar: Grammar<ColumnCellDef> = {
|
|
|
114
114
|
...StringCellDef,
|
|
115
115
|
keyword: "dataPublishedBy",
|
|
116
116
|
description:
|
|
117
|
-
"For academic papers this should be a complete reference. For institutional projects, detail the project or report. For data
|
|
117
|
+
"For academic papers this should be a complete reference. For institutional projects, detail the project or report. For data modified extensively, list the organization as the publishers and provide the name of the person in charge of the calculation.",
|
|
118
118
|
},
|
|
119
119
|
dataPublisherSource: {
|
|
120
120
|
...StringCellDef,
|
|
@@ -2,13 +2,13 @@ import { DimensionProperty } from "../utils/index.js"
|
|
|
2
2
|
import { GRAPHER_TAB_CONFIG_OPTIONS } from "../types/index.js"
|
|
3
3
|
import {
|
|
4
4
|
GrapherProgrammaticInterface,
|
|
5
|
-
|
|
5
|
+
legacyToChartsTableAndDimensionsWithMandatorySlug,
|
|
6
6
|
} from "../grapher/index.js"
|
|
7
7
|
import { Explorer, ExplorerProps } from "./Explorer.js"
|
|
8
8
|
|
|
9
9
|
const SampleExplorerOfGraphersProgram = `explorerTitle CO₂ Data Explorer
|
|
10
10
|
isPublished false
|
|
11
|
-
explorerSubtitle Download the complete
|
|
11
|
+
explorerSubtitle Download the complete CO₂ and GHG Emissions Dataset.
|
|
12
12
|
subNavId co2
|
|
13
13
|
time earliest..latest
|
|
14
14
|
selection China United States India United Kingdom World
|
|
@@ -46,7 +46,7 @@ graphers
|
|
|
46
46
|
4244 Nitrous oxide Production-based Per capita false`
|
|
47
47
|
|
|
48
48
|
// Generate realistic CO2 per capita emissions data (tonnes per person)
|
|
49
|
-
// Based on approximate real-world trends from
|
|
49
|
+
// Based on approximate real-world trends from CO2 data
|
|
50
50
|
function generateCO2PerCapitaData() {
|
|
51
51
|
const startYear = 1990
|
|
52
52
|
const endYear = 2024
|
|
@@ -93,7 +93,7 @@ function generateCO2PerCapitaData() {
|
|
|
93
93
|
{
|
|
94
94
|
id: 5,
|
|
95
95
|
name: "World",
|
|
96
|
-
code: "
|
|
96
|
+
code: "WRL",
|
|
97
97
|
// Global average rose from ~4 to ~4.7 tonnes
|
|
98
98
|
baseValue: 4.0,
|
|
99
99
|
trend: (year: number) =>
|
|
@@ -140,7 +140,7 @@ function generateCO2PerCapitaData() {
|
|
|
140
140
|
export const SampleExplorerOfGraphers = (props?: Partial<ExplorerProps>) => {
|
|
141
141
|
const title = "CO₂ emissions per capita"
|
|
142
142
|
const co2Data = generateCO2PerCapitaData()
|
|
143
|
-
const
|
|
143
|
+
const dataset = new Map([[142609, co2Data]])
|
|
144
144
|
const dimensions = [
|
|
145
145
|
{
|
|
146
146
|
variableId: 142609,
|
|
@@ -153,8 +153,8 @@ export const SampleExplorerOfGraphers = (props?: Partial<ExplorerProps>) => {
|
|
|
153
153
|
dimensions,
|
|
154
154
|
tab: GRAPHER_TAB_CONFIG_OPTIONS.chart,
|
|
155
155
|
}
|
|
156
|
-
first.table =
|
|
157
|
-
|
|
156
|
+
first.table = legacyToChartsTableAndDimensionsWithMandatorySlug(
|
|
157
|
+
dataset,
|
|
158
158
|
dimensions,
|
|
159
159
|
{}
|
|
160
160
|
)
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
ArchiveContext,
|
|
7
7
|
ColumnTypeNames,
|
|
8
8
|
CoreColumnDef,
|
|
9
|
-
|
|
9
|
+
ColumnDef,
|
|
10
10
|
SortOrder,
|
|
11
11
|
TableSlug,
|
|
12
12
|
GrapherInterface,
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
GRAPHER_TAB_QUERY_PARAMS,
|
|
16
16
|
} from "../types/index.js"
|
|
17
17
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
ChartsTable,
|
|
19
|
+
BlankChartsTable,
|
|
20
20
|
extractPotentialDataSlugsFromTransform,
|
|
21
21
|
} from "../core-table/index.js"
|
|
22
22
|
import {
|
|
@@ -82,7 +82,7 @@ export interface ExplorerProps extends SerializedGridProgram {
|
|
|
82
82
|
grapherConfigs?: GrapherInterface[]
|
|
83
83
|
partialGrapherConfigs?: GrapherInterface[]
|
|
84
84
|
queryStr?: string
|
|
85
|
-
|
|
85
|
+
isEmbeddedInPage?: boolean
|
|
86
86
|
isInStandalonePage?: boolean
|
|
87
87
|
isPreview?: boolean
|
|
88
88
|
canonicalUrl?: string
|
|
@@ -204,7 +204,7 @@ export class Explorer
|
|
|
204
204
|
analytics = new GrapherAnalytics()
|
|
205
205
|
grapherState: GrapherState
|
|
206
206
|
isOnArchivalPage: boolean
|
|
207
|
-
inputTableTransformer = (table:
|
|
207
|
+
inputTableTransformer = (table: ChartsTable) => table
|
|
208
208
|
|
|
209
209
|
constructor(props: ExplorerProps) {
|
|
210
210
|
super(props)
|
|
@@ -240,7 +240,7 @@ export class Explorer
|
|
|
240
240
|
bounds: props.bounds,
|
|
241
241
|
enableKeyboardShortcuts: this.props.isInStandalonePage,
|
|
242
242
|
manager: this,
|
|
243
|
-
|
|
243
|
+
isEmbeddedInPage: this.props.isEmbeddedInPage,
|
|
244
244
|
adminBaseUrl: this.adminBaseUrl,
|
|
245
245
|
canHideExternalControlsInEmbed: true,
|
|
246
246
|
archiveContext: props.archiveContext,
|
|
@@ -272,7 +272,7 @@ export class Explorer
|
|
|
272
272
|
...explorerConstants,
|
|
273
273
|
grapherConfigs,
|
|
274
274
|
partialGrapherConfigs,
|
|
275
|
-
|
|
275
|
+
isEmbeddedInPage: false,
|
|
276
276
|
isInStandalonePage: true,
|
|
277
277
|
archiveContext,
|
|
278
278
|
}
|
|
@@ -535,7 +535,7 @@ export class Explorer
|
|
|
535
535
|
)
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
-
@action.bound private setGrapherTable(table:
|
|
538
|
+
@action.bound private setGrapherTable(table: ChartsTable) {
|
|
539
539
|
this.grapherState.inputTable = this.inputTableTransformer(table)
|
|
540
540
|
}
|
|
541
541
|
|
|
@@ -548,7 +548,7 @@ export class Explorer
|
|
|
548
548
|
return !this.isNarrow
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
-
private futureGrapherTable = new PromiseSwitcher<
|
|
551
|
+
private futureGrapherTable = new PromiseSwitcher<ChartsTable>({
|
|
552
552
|
onResolve: (table) => this.setGrapherTable(table),
|
|
553
553
|
onReject: (error) => this.grapher?.setError(error),
|
|
554
554
|
})
|
|
@@ -570,12 +570,12 @@ export class Explorer
|
|
|
570
570
|
|
|
571
571
|
@computed private get columnDefsWithoutTableSlugByIdOrSlug(): Record<
|
|
572
572
|
number | string,
|
|
573
|
-
|
|
573
|
+
ColumnDef
|
|
574
574
|
> {
|
|
575
575
|
const { columnDefsWithoutTableSlug } = this.explorerProgram
|
|
576
576
|
return _.keyBy(
|
|
577
577
|
columnDefsWithoutTableSlug,
|
|
578
|
-
(def:
|
|
578
|
+
(def: ColumnDef) => def.variableId ?? def.slug
|
|
579
579
|
)
|
|
580
580
|
}
|
|
581
581
|
|
|
@@ -606,7 +606,7 @@ export class Explorer
|
|
|
606
606
|
const baseVariableIdsAndColumnSlugs =
|
|
607
607
|
this.getBaseColumnsForColumnWithTransform(slug)
|
|
608
608
|
const slugsInColumnBlock: string[] = columnDefsWithoutTableSlug
|
|
609
|
-
.filter((def) => !def.
|
|
609
|
+
.filter((def) => !def.variableId)
|
|
610
610
|
.map((def) => def.slug)
|
|
611
611
|
return baseVariableIdsAndColumnSlugs.filter(
|
|
612
612
|
(variableIdOrColumnSlug) =>
|
|
@@ -645,7 +645,7 @@ export class Explorer
|
|
|
645
645
|
|
|
646
646
|
grapherState.setAuthoredVersion(config)
|
|
647
647
|
grapherState.reset()
|
|
648
|
-
grapherState.inputTable =
|
|
648
|
+
grapherState.inputTable = BlankChartsTable()
|
|
649
649
|
grapherState.updateFromObject(config)
|
|
650
650
|
if (!config.table) {
|
|
651
651
|
const loadFn =
|
|
@@ -657,7 +657,7 @@ export class Explorer
|
|
|
657
657
|
archiveContext: this.props.archiveContext,
|
|
658
658
|
noCache: this.props.isPreview,
|
|
659
659
|
loadMetadataOnly: this.props.loadMetadataOnly,
|
|
660
|
-
}).then((
|
|
660
|
+
}).then((dataTable) => (dataTable ? dataTable : BlankChartsTable()))
|
|
661
661
|
// We use the PromiseSwitcher here to make sure that only the last
|
|
662
662
|
// of several user triggered load operations in quick succession
|
|
663
663
|
// will actually set the table.
|
|
@@ -788,7 +788,7 @@ export class Explorer
|
|
|
788
788
|
config.dimensions = dimensions
|
|
789
789
|
if (ySlugs && yVariableIds) config.ySlugs = ySlugs + " " + yVariableIds
|
|
790
790
|
|
|
791
|
-
this.inputTableTransformer = (table:
|
|
791
|
+
this.inputTableTransformer = (table: ChartsTable) => {
|
|
792
792
|
// add transformed (and intermediate) columns to the grapher table
|
|
793
793
|
if (uniqueSlugsInGrapherRow.length) {
|
|
794
794
|
const allColumnSlugs = _.uniq(
|
|
@@ -811,7 +811,7 @@ export class Explorer
|
|
|
811
811
|
}
|
|
812
812
|
|
|
813
813
|
// update column definitions with manually provided properties
|
|
814
|
-
table = table.updateDefs((def:
|
|
814
|
+
table = table.updateDefs((def: ColumnDef) => {
|
|
815
815
|
const manuallyProvidedDef =
|
|
816
816
|
this.columnDefsWithoutTableSlugByIdOrSlug[def.slug] ?? {}
|
|
817
817
|
const mergedDef = { ...def, ...manuallyProvidedDef }
|
|
@@ -836,7 +836,7 @@ export class Explorer
|
|
|
836
836
|
if (dimensions.length === 0) {
|
|
837
837
|
// If dimensions are empty, explicitly set the table to an empty table
|
|
838
838
|
// so we don't end up confusingly showing stale data from a previous chart
|
|
839
|
-
grapherState.inputTable =
|
|
839
|
+
grapherState.inputTable = BlankChartsTable()
|
|
840
840
|
} else {
|
|
841
841
|
const loadFn =
|
|
842
842
|
this.props.loadInputTableForConfig ?? fetchInputTableForConfig
|
|
@@ -847,7 +847,7 @@ export class Explorer
|
|
|
847
847
|
dataApiUrl: this.props.dataApiUrl,
|
|
848
848
|
noCache: this.props.isPreview,
|
|
849
849
|
loadMetadataOnly: this.props.loadMetadataOnly,
|
|
850
|
-
}).then((
|
|
850
|
+
}).then((dataTable) => (dataTable ? dataTable : BlankChartsTable()))
|
|
851
851
|
// We use the PromiseSwitcher here to make sure that only the last
|
|
852
852
|
// of several user triggered load operations in quick succession
|
|
853
853
|
// will actually set the table.
|
|
@@ -880,7 +880,7 @@ export class Explorer
|
|
|
880
880
|
this.grapher?.clearErrors()
|
|
881
881
|
// Set a table immediately. A BlankTable shows a loading animation.
|
|
882
882
|
this.setGrapherTable(
|
|
883
|
-
|
|
883
|
+
BlankChartsTable(tableSlug, `Loading table '${tableSlug}'`)
|
|
884
884
|
)
|
|
885
885
|
// We use the PromiseSwitcher here to make sure that only the last
|
|
886
886
|
// of several user triggered load operations in quick succession
|
|
@@ -1007,7 +1007,7 @@ export class Explorer
|
|
|
1007
1007
|
}
|
|
1008
1008
|
|
|
1009
1009
|
@computed private get showExplorerControls() {
|
|
1010
|
-
if (!this.props.
|
|
1010
|
+
if (!this.props.isEmbeddedInPage && !this.isInIFrame) return true
|
|
1011
1011
|
// Only allow hiding controls on embedded pages
|
|
1012
1012
|
return !(
|
|
1013
1013
|
this.explorerProgram.hideControls ||
|
|
@@ -1120,7 +1120,7 @@ export class Explorer
|
|
|
1120
1120
|
Explorer: true,
|
|
1121
1121
|
"mobile-explorer": this.isNarrow,
|
|
1122
1122
|
HideControls: !showExplorerControls,
|
|
1123
|
-
"is-embed": this.props.
|
|
1123
|
+
"is-embed": this.props.isEmbeddedInPage,
|
|
1124
1124
|
})}
|
|
1125
1125
|
>
|
|
1126
1126
|
{showHeaderElement && this.renderHeaderElement()}
|
|
@@ -1169,10 +1169,10 @@ export class Explorer
|
|
|
1169
1169
|
this.initialQueryParams.pickerMetric
|
|
1170
1170
|
entityPickerSort: SortOrder | undefined = this.initialQueryParams.pickerSort
|
|
1171
1171
|
|
|
1172
|
-
entityPickerTable:
|
|
1172
|
+
entityPickerTable: ChartsTable | undefined = undefined
|
|
1173
1173
|
entityPickerTableIsLoading: boolean = false
|
|
1174
1174
|
|
|
1175
|
-
private futureEntityPickerTable = new PromiseSwitcher<
|
|
1175
|
+
private futureEntityPickerTable = new PromiseSwitcher<ChartsTable>({
|
|
1176
1176
|
onResolve: (table) => {
|
|
1177
1177
|
this.entityPickerTable = table
|
|
1178
1178
|
this.entityPickerTableIsLoading = false
|
|
@@ -74,8 +74,8 @@ export const GetAllExplorersRoute = "allExplorers.json"
|
|
|
74
74
|
|
|
75
75
|
export const GetAllExplorersTagsRoute = "allExplorersTags.json"
|
|
76
76
|
|
|
77
|
-
export const EXPLORERS_ROUTE_FOLDER = "explorers" // Url path:
|
|
78
|
-
export const EXPLORERS_GIT_CMS_FOLDER = "explorers" // Disk path:
|
|
77
|
+
export const EXPLORERS_ROUTE_FOLDER = "explorers" // Url path: /{explorers}
|
|
78
|
+
export const EXPLORERS_GIT_CMS_FOLDER = "explorers" // Disk path: git-content/{explorers}
|
|
79
79
|
export const EXPLORERS_PREVIEW_ROUTE = `${EXPLORERS_ROUTE_FOLDER}/preview`
|
|
80
80
|
|
|
81
81
|
export interface ExplorersRouteResponse {
|
|
@@ -27,8 +27,8 @@ export const ExplorerGrammar: Grammar = {
|
|
|
27
27
|
...UrlCellDef,
|
|
28
28
|
keyword: "table",
|
|
29
29
|
valuePlaceholder: "",
|
|
30
|
-
regex: new RegExp(`(${UrlCellDef.regex?.source ?? ""}|^[\\w -()]+$)`), // URL or
|
|
31
|
-
description: "A link to a CSV or TSV or the name of
|
|
30
|
+
regex: new RegExp(`(${UrlCellDef.regex?.source ?? ""}|^[\\w -()]+$)`), // URL or dataset name
|
|
31
|
+
description: "A link to a CSV or TSV or the name of a dataset.",
|
|
32
32
|
positionalCellDefs: [
|
|
33
33
|
{
|
|
34
34
|
...SlugDeclarationCellDef,
|
|
@@ -85,7 +85,7 @@ export const ExplorerGrammar: Grammar = {
|
|
|
85
85
|
keyword: "googleSheet",
|
|
86
86
|
valuePlaceholder: "https://docs.google.com/spreadsheets/d/1qeX...",
|
|
87
87
|
description:
|
|
88
|
-
"Create a Google Sheet, share it with
|
|
88
|
+
"Create a Google Sheet, share it with your team, then put the link here.",
|
|
89
89
|
},
|
|
90
90
|
downloadDataLink: {
|
|
91
91
|
...UrlCellDef,
|