@buildcanada/charts 0.1.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/LICENSE.md +8 -0
- package/README.md +113 -0
- package/package.json +137 -0
- package/src/components/BodyPortal/BodyPortal.tsx +40 -0
- package/src/components/Button/Button.scss +110 -0
- package/src/components/Button/Button.tsx +101 -0
- package/src/components/Checkbox.scss +93 -0
- package/src/components/Checkbox.tsx +47 -0
- package/src/components/ExpandableToggle/ExpandableToggle.scss +123 -0
- package/src/components/ExpandableToggle/ExpandableToggle.tsx +60 -0
- package/src/components/GrapherTabIcon.tsx +156 -0
- package/src/components/GrapherTrendArrow.scss +16 -0
- package/src/components/GrapherTrendArrow.tsx +30 -0
- package/src/components/Halo/Halo.tsx +44 -0
- package/src/components/LabeledSwitch/LabeledSwitch.scss +109 -0
- package/src/components/LabeledSwitch/LabeledSwitch.tsx +62 -0
- package/src/components/MarkdownTextWrap/MarkdownTextWrap.tsx +1173 -0
- package/src/components/OverlayHeader.scss +18 -0
- package/src/components/OverlayHeader.tsx +29 -0
- package/src/components/RadioButton.scss +69 -0
- package/src/components/RadioButton.tsx +42 -0
- package/src/components/SimpleMarkdownText.tsx +89 -0
- package/src/components/TextInput.scss +17 -0
- package/src/components/TextInput.tsx +19 -0
- package/src/components/TextWrap/TextWrap.tsx +361 -0
- package/src/components/TextWrap/TextWrapUtils.ts +32 -0
- package/src/components/closeButton/CloseButton.scss +40 -0
- package/src/components/closeButton/CloseButton.tsx +27 -0
- package/src/components/index.ts +70 -0
- package/src/components/loadingIndicator/LoadingIndicator.scss +40 -0
- package/src/components/loadingIndicator/LoadingIndicator.tsx +28 -0
- package/src/components/markdown/remarkPlainLinks.ts +36 -0
- package/src/components/reactUtil.ts +20 -0
- package/src/components/stubs/CodeSnippet.tsx +19 -0
- package/src/components/stubs/DataCitation.tsx +16 -0
- package/src/components/stubs/IndicatorKeyData.tsx +45 -0
- package/src/components/stubs/IndicatorProcessing.tsx +15 -0
- package/src/components/stubs/IndicatorSources.tsx +15 -0
- package/src/components/styles/colors.scss +113 -0
- package/src/components/styles/mixins.scss +630 -0
- package/src/components/styles/typography.scss +579 -0
- package/src/components/styles/util.scss +89 -0
- package/src/components/styles/variables.scss +208 -0
- package/src/config/ChartsConfig.ts +163 -0
- package/src/config/ChartsProvider.tsx +157 -0
- package/src/config/index.ts +20 -0
- package/src/core-table/CoreTable.ts +1355 -0
- package/src/core-table/CoreTableColumns.ts +973 -0
- package/src/core-table/CoreTableUtils.ts +793 -0
- package/src/core-table/ErrorValues.ts +73 -0
- package/src/core-table/OwidTable.ts +1175 -0
- package/src/core-table/OwidTableSynthesizers.ts +272 -0
- package/src/core-table/OwidTableUtil.ts +76 -0
- package/src/core-table/Transforms.ts +484 -0
- package/src/core-table/index.ts +82 -0
- package/src/explorer/ColumnGrammar.ts +217 -0
- package/src/explorer/Explorer.sample.ts +212 -0
- package/src/explorer/Explorer.scss +148 -0
- package/src/explorer/Explorer.tsx +1283 -0
- package/src/explorer/ExplorerConstants.ts +85 -0
- package/src/explorer/ExplorerControls.scss +156 -0
- package/src/explorer/ExplorerControls.tsx +210 -0
- package/src/explorer/ExplorerDecisionMatrix.ts +471 -0
- package/src/explorer/ExplorerGrammar.ts +161 -0
- package/src/explorer/ExplorerProgram.ts +568 -0
- package/src/explorer/ExplorerUtils.ts +59 -0
- package/src/explorer/GrapherGrammar.ts +387 -0
- package/src/explorer/gridLang/GrammarUtils.ts +121 -0
- package/src/explorer/gridLang/GridCell.ts +298 -0
- package/src/explorer/gridLang/GridLangConstants.ts +255 -0
- package/src/explorer/gridLang/GridProgram.ts +311 -0
- package/src/explorer/gridLang/readme.md +17 -0
- package/src/explorer/index.ts +69 -0
- package/src/explorer/readme.md +19 -0
- package/src/explorer/urlMigrations/CO2UrlMigration.ts +46 -0
- package/src/explorer/urlMigrations/CovidUrlMigration.ts +37 -0
- package/src/explorer/urlMigrations/EnergyUrlMigration.ts +41 -0
- package/src/explorer/urlMigrations/ExplorerPageUrlMigrationSpec.ts +12 -0
- package/src/explorer/urlMigrations/ExplorerUrlMigrationUtils.ts +45 -0
- package/src/explorer/urlMigrations/ExplorerUrlMigrations.ts +33 -0
- package/src/explorer/urlMigrations/LegacyCovidUrlMigration.ts +144 -0
- package/src/explorer/urlMigrations/readme.md +39 -0
- package/src/grapher/axis/Axis.ts +973 -0
- package/src/grapher/axis/AxisConfig.ts +179 -0
- package/src/grapher/axis/AxisViews.tsx +597 -0
- package/src/grapher/barCharts/DiscreteBarChart.tsx +728 -0
- package/src/grapher/barCharts/DiscreteBarChartConstants.ts +60 -0
- package/src/grapher/barCharts/DiscreteBarChartHelpers.ts +338 -0
- package/src/grapher/barCharts/DiscreteBarChartState.ts +354 -0
- package/src/grapher/barCharts/DiscreteBarChartThumbnail.tsx +34 -0
- package/src/grapher/captionedChart/CaptionedChart.scss +61 -0
- package/src/grapher/captionedChart/CaptionedChart.tsx +523 -0
- package/src/grapher/captionedChart/Logos.tsx +141 -0
- package/src/grapher/captionedChart/LogosSVG.tsx +16 -0
- package/src/grapher/captionedChart/StaticChartRasterizer.tsx +178 -0
- package/src/grapher/captionedChart/assets/buildcanada-logo-square.svg +15 -0
- package/src/grapher/captionedChart/assets/buildcanada-logo.svg +15 -0
- package/src/grapher/captionedChart/assets/canadaspends.svg +7 -0
- package/src/grapher/captionedChart/readme.md +14 -0
- package/src/grapher/chart/Chart.tsx +62 -0
- package/src/grapher/chart/ChartAreaContent.tsx +172 -0
- package/src/grapher/chart/ChartDimension.ts +121 -0
- package/src/grapher/chart/ChartInterface.ts +83 -0
- package/src/grapher/chart/ChartManager.ts +113 -0
- package/src/grapher/chart/ChartTabs.ts +178 -0
- package/src/grapher/chart/ChartTypeMap.tsx +158 -0
- package/src/grapher/chart/ChartTypeSwitcher.tsx +26 -0
- package/src/grapher/chart/ChartUtils.tsx +364 -0
- package/src/grapher/chart/DimensionSlot.ts +45 -0
- package/src/grapher/chart/StaticChartWrapper.tsx +94 -0
- package/src/grapher/chart/guidedChartUtils.ts +82 -0
- package/src/grapher/color/BinningStrategies.ts +484 -0
- package/src/grapher/color/BinningStrategyEqualSizeBins.ts +132 -0
- package/src/grapher/color/BinningStrategyLogarithmic.ts +121 -0
- package/src/grapher/color/CategoricalColorAssigner.ts +97 -0
- package/src/grapher/color/ColorBrewerSchemes.ts +80 -0
- package/src/grapher/color/ColorConstants.ts +20 -0
- package/src/grapher/color/ColorScale.ts +339 -0
- package/src/grapher/color/ColorScaleBin.ts +147 -0
- package/src/grapher/color/ColorScaleConfig.ts +204 -0
- package/src/grapher/color/ColorScheme.ts +137 -0
- package/src/grapher/color/ColorSchemes.ts +149 -0
- package/src/grapher/color/ColorUtils.ts +86 -0
- package/src/grapher/color/CustomSchemes.ts +1772 -0
- package/src/grapher/color/readme.md +84 -0
- package/src/grapher/comparisonLine/ComparisonLine.tsx +31 -0
- package/src/grapher/comparisonLine/ComparisonLineConstants.ts +11 -0
- package/src/grapher/comparisonLine/ComparisonLineGenerator.ts +60 -0
- package/src/grapher/comparisonLine/ComparisonLineHelpers.ts +10 -0
- package/src/grapher/comparisonLine/CustomComparisonLine.tsx +159 -0
- package/src/grapher/comparisonLine/VerticalComparisonLine.tsx +208 -0
- package/src/grapher/controls/ActionButtons.scss +97 -0
- package/src/grapher/controls/ActionButtons.tsx +453 -0
- package/src/grapher/controls/CommandPalette.scss +50 -0
- package/src/grapher/controls/CommandPalette.tsx +74 -0
- package/src/grapher/controls/ContentSwitchers.scss +93 -0
- package/src/grapher/controls/ContentSwitchers.tsx +238 -0
- package/src/grapher/controls/Controls.scss +158 -0
- package/src/grapher/controls/DataTableFilterDropdown.scss +7 -0
- package/src/grapher/controls/DataTableFilterDropdown.tsx +168 -0
- package/src/grapher/controls/DataTableSearchField.scss +3 -0
- package/src/grapher/controls/DataTableSearchField.tsx +76 -0
- package/src/grapher/controls/Dropdown.scss +252 -0
- package/src/grapher/controls/Dropdown.tsx +235 -0
- package/src/grapher/controls/EntitySelectionToggle.tsx +135 -0
- package/src/grapher/controls/MapRegionDropdown.scss +3 -0
- package/src/grapher/controls/MapRegionDropdown.tsx +104 -0
- package/src/grapher/controls/MapResetButton.tsx +115 -0
- package/src/grapher/controls/MapZoomDropdown.scss +9 -0
- package/src/grapher/controls/MapZoomDropdown.tsx +270 -0
- package/src/grapher/controls/MapZoomToSelectionButton.tsx +87 -0
- package/src/grapher/controls/SearchField.scss +78 -0
- package/src/grapher/controls/SearchField.tsx +63 -0
- package/src/grapher/controls/SettingsMenu.scss +191 -0
- package/src/grapher/controls/SettingsMenu.tsx +399 -0
- package/src/grapher/controls/ShareMenu.scss +58 -0
- package/src/grapher/controls/ShareMenu.tsx +304 -0
- package/src/grapher/controls/SortIcon.tsx +39 -0
- package/src/grapher/controls/VerticalScrollContainer.tsx +263 -0
- package/src/grapher/controls/controlsRow/ControlsRow.tsx +168 -0
- package/src/grapher/controls/dropdown-icons.scss +4 -0
- package/src/grapher/controls/entityPicker/EntityPicker.scss +255 -0
- package/src/grapher/controls/entityPicker/EntityPicker.tsx +816 -0
- package/src/grapher/controls/entityPicker/EntityPickerConstants.ts +23 -0
- package/src/grapher/controls/globalEntitySelector/GlobalEntitySelector.scss +129 -0
- package/src/grapher/controls/globalEntitySelector/GlobalEntitySelector.tsx +463 -0
- package/src/grapher/controls/globalEntitySelector/GlobalEntitySelectorConstants.ts +3 -0
- package/src/grapher/controls/globalEntitySelector/readme.md +17 -0
- package/src/grapher/controls/settings/AbsRelToggle.tsx +64 -0
- package/src/grapher/controls/settings/AxisScaleToggle.tsx +53 -0
- package/src/grapher/controls/settings/FacetStrategySelector.tsx +110 -0
- package/src/grapher/controls/settings/FacetYDomainToggle.tsx +51 -0
- package/src/grapher/controls/settings/NoDataAreaToggle.tsx +38 -0
- package/src/grapher/controls/settings/ZoomToggle.tsx +36 -0
- package/src/grapher/core/EntitiesByRegionType.ts +174 -0
- package/src/grapher/core/EntityCodes.ts +19 -0
- package/src/grapher/core/EntityUrlBuilder.ts +200 -0
- package/src/grapher/core/FetchingGrapher.tsx +156 -0
- package/src/grapher/core/Grapher.tsx +760 -0
- package/src/grapher/core/GrapherAnalytics.ts +229 -0
- package/src/grapher/core/GrapherConstants.ts +173 -0
- package/src/grapher/core/GrapherState.tsx +3659 -0
- package/src/grapher/core/GrapherUrl.ts +184 -0
- package/src/grapher/core/GrapherUrlMigrations.ts +29 -0
- package/src/grapher/core/GrapherUseHelpers.tsx +147 -0
- package/src/grapher/core/LegacyToOwidTable.ts +841 -0
- package/src/grapher/core/grapher.entry.ts +5 -0
- package/src/grapher/core/grapher.scss +257 -0
- package/src/grapher/core/loadGrapherTableHelpers.ts +116 -0
- package/src/grapher/core/loadVariable.ts +104 -0
- package/src/grapher/core/relatedQuestion.ts +12 -0
- package/src/grapher/core/typography.scss +206 -0
- package/src/grapher/dataTable/DataTable.sample.ts +206 -0
- package/src/grapher/dataTable/DataTable.scss +249 -0
- package/src/grapher/dataTable/DataTable.tsx +1332 -0
- package/src/grapher/dataTable/DataTableConstants.ts +186 -0
- package/src/grapher/entitySelector/EntitySelector.scss +255 -0
- package/src/grapher/entitySelector/EntitySelector.tsx +1838 -0
- package/src/grapher/facet/FacetChart.tsx +943 -0
- package/src/grapher/facet/FacetChartConstants.ts +24 -0
- package/src/grapher/facet/FacetChartUtils.ts +51 -0
- package/src/grapher/facet/FacetMap.tsx +604 -0
- package/src/grapher/facet/FacetMapConstants.ts +23 -0
- package/src/grapher/facet/readme.md +13 -0
- package/src/grapher/focus/FocusArray.ts +79 -0
- package/src/grapher/footer/Footer.scss +63 -0
- package/src/grapher/footer/Footer.tsx +809 -0
- package/src/grapher/footer/FooterManager.ts +44 -0
- package/src/grapher/fullScreen/FullScreen.scss +11 -0
- package/src/grapher/fullScreen/FullScreen.tsx +61 -0
- package/src/grapher/header/Header.scss +35 -0
- package/src/grapher/header/Header.tsx +372 -0
- package/src/grapher/header/HeaderManager.ts +28 -0
- package/src/grapher/index.ts +157 -0
- package/src/grapher/interaction/InteractionState.ts +60 -0
- package/src/grapher/legend/HorizontalColorLegends.tsx +923 -0
- package/src/grapher/legend/LegendInteractionState.ts +40 -0
- package/src/grapher/legend/VerticalColorLegend.tsx +295 -0
- package/src/grapher/lineCharts/LineChart.tsx +968 -0
- package/src/grapher/lineCharts/LineChartConstants.ts +89 -0
- package/src/grapher/lineCharts/LineChartHelpers.ts +184 -0
- package/src/grapher/lineCharts/LineChartState.ts +394 -0
- package/src/grapher/lineCharts/LineChartThumbnail.tsx +437 -0
- package/src/grapher/lineCharts/Lines.tsx +258 -0
- package/src/grapher/lineLegend/LineLegend.tsx +723 -0
- package/src/grapher/lineLegend/LineLegendConstants.ts +9 -0
- package/src/grapher/lineLegend/LineLegendFilterAlgorithms.ts +143 -0
- package/src/grapher/lineLegend/LineLegendHelpers.ts +253 -0
- package/src/grapher/lineLegend/LineLegendTypes.ts +32 -0
- package/src/grapher/mapCharts/CanadaTopology.ts +17922 -0
- package/src/grapher/mapCharts/ChoroplethGlobe.tsx +949 -0
- package/src/grapher/mapCharts/ChoroplethMap.tsx +662 -0
- package/src/grapher/mapCharts/GeoFeatures.ts +184 -0
- package/src/grapher/mapCharts/GlobeController.ts +496 -0
- package/src/grapher/mapCharts/MapAnnotationPlacements.json +1040 -0
- package/src/grapher/mapCharts/MapAnnotationPlacements.ts +31 -0
- package/src/grapher/mapCharts/MapAnnotations.ts +723 -0
- package/src/grapher/mapCharts/MapChart.sample.ts +59 -0
- package/src/grapher/mapCharts/MapChart.scss +5 -0
- package/src/grapher/mapCharts/MapChart.tsx +720 -0
- package/src/grapher/mapCharts/MapChartConstants.ts +260 -0
- package/src/grapher/mapCharts/MapChartState.ts +416 -0
- package/src/grapher/mapCharts/MapChartThumbnail.tsx +25 -0
- package/src/grapher/mapCharts/MapComponents.tsx +338 -0
- package/src/grapher/mapCharts/MapConfig.ts +156 -0
- package/src/grapher/mapCharts/MapHelpers.ts +181 -0
- package/src/grapher/mapCharts/MapProjections.ts +49 -0
- package/src/grapher/mapCharts/MapSparkline.tsx +257 -0
- package/src/grapher/mapCharts/MapTooltip.scss +49 -0
- package/src/grapher/mapCharts/MapTooltip.tsx +409 -0
- package/src/grapher/mapCharts/MapTopology.ts +1766 -0
- package/src/grapher/mapCharts/d3-bboxCollide.js +204 -0
- package/src/grapher/mapCharts/d3-geo-projection.ts +198 -0
- package/src/grapher/modal/DownloadIcons.tsx +39 -0
- package/src/grapher/modal/DownloadModal.scss +300 -0
- package/src/grapher/modal/DownloadModal.tsx +1226 -0
- package/src/grapher/modal/EmbedModal.scss +40 -0
- package/src/grapher/modal/EmbedModal.tsx +160 -0
- package/src/grapher/modal/EntitySelectorModal.tsx +59 -0
- package/src/grapher/modal/Modal.scss +31 -0
- package/src/grapher/modal/Modal.tsx +90 -0
- package/src/grapher/modal/ModalHeader.scss +12 -0
- package/src/grapher/modal/ModalHeader.tsx +16 -0
- package/src/grapher/modal/SourcesDescriptions.scss +87 -0
- package/src/grapher/modal/SourcesDescriptions.tsx +89 -0
- package/src/grapher/modal/SourcesKeyDataTable.scss +49 -0
- package/src/grapher/modal/SourcesKeyDataTable.tsx +87 -0
- package/src/grapher/modal/SourcesModal.scss +301 -0
- package/src/grapher/modal/SourcesModal.tsx +568 -0
- package/src/grapher/noDataModal/NoDataModal.tsx +125 -0
- package/src/grapher/scatterCharts/ConnectedScatterLegend.tsx +143 -0
- package/src/grapher/scatterCharts/MultiColorPolyline.tsx +129 -0
- package/src/grapher/scatterCharts/NoDataSection.scss +14 -0
- package/src/grapher/scatterCharts/NoDataSection.tsx +56 -0
- package/src/grapher/scatterCharts/ScatterPlotChart.tsx +792 -0
- package/src/grapher/scatterCharts/ScatterPlotChartConstants.ts +157 -0
- package/src/grapher/scatterCharts/ScatterPlotChartState.ts +678 -0
- package/src/grapher/scatterCharts/ScatterPlotChartThumbnail.tsx +155 -0
- package/src/grapher/scatterCharts/ScatterPlotTooltip.tsx +560 -0
- package/src/grapher/scatterCharts/ScatterPoints.tsx +153 -0
- package/src/grapher/scatterCharts/ScatterPointsWithLabels.tsx +708 -0
- package/src/grapher/scatterCharts/ScatterSizeLegend.tsx +327 -0
- package/src/grapher/scatterCharts/ScatterUtils.ts +265 -0
- package/src/grapher/scatterCharts/Triangle.tsx +41 -0
- package/src/grapher/schema/README.md +33 -0
- package/src/grapher/schema/defaultGrapherConfig.ts +100 -0
- package/src/grapher/schema/grapher-schema.009.yaml +781 -0
- package/src/grapher/schema/migrations/helpers.ts +58 -0
- package/src/grapher/schema/migrations/migrate.ts +75 -0
- package/src/grapher/schema/migrations/migrations.ts +158 -0
- package/src/grapher/selection/MapSelectionArray.ts +99 -0
- package/src/grapher/selection/SelectionArray.ts +71 -0
- package/src/grapher/selection/readme.md +16 -0
- package/src/grapher/sidePanel/SidePanel.scss +10 -0
- package/src/grapher/sidePanel/SidePanel.tsx +23 -0
- package/src/grapher/slideInDrawer/SlideInDrawer.scss +57 -0
- package/src/grapher/slideInDrawer/SlideInDrawer.tsx +125 -0
- package/src/grapher/slideshowController/SlideShowController.tsx +43 -0
- package/src/grapher/slideshowController/readme.md +7 -0
- package/src/grapher/slopeCharts/MarkX.tsx +45 -0
- package/src/grapher/slopeCharts/Slope.tsx +102 -0
- package/src/grapher/slopeCharts/SlopeChart.tsx +1152 -0
- package/src/grapher/slopeCharts/SlopeChartConstants.ts +33 -0
- package/src/grapher/slopeCharts/SlopeChartHelpers.ts +73 -0
- package/src/grapher/slopeCharts/SlopeChartState.ts +392 -0
- package/src/grapher/slopeCharts/SlopeChartThumbnail.tsx +368 -0
- package/src/grapher/stackedCharts/AbstractStackedChartState.ts +370 -0
- package/src/grapher/stackedCharts/MarimekkoBars.tsx +190 -0
- package/src/grapher/stackedCharts/MarimekkoBarsForOneEntity.tsx +168 -0
- package/src/grapher/stackedCharts/MarimekkoChart.tsx +1144 -0
- package/src/grapher/stackedCharts/MarimekkoChartConstants.ts +112 -0
- package/src/grapher/stackedCharts/MarimekkoChartHelpers.ts +21 -0
- package/src/grapher/stackedCharts/MarimekkoChartState.ts +465 -0
- package/src/grapher/stackedCharts/MarimekkoChartThumbnail.tsx +168 -0
- package/src/grapher/stackedCharts/MarimekkoInternalLabels.tsx +124 -0
- package/src/grapher/stackedCharts/StackedAreaChart.tsx +678 -0
- package/src/grapher/stackedCharts/StackedAreaChartState.ts +34 -0
- package/src/grapher/stackedCharts/StackedAreaChartThumbnail.tsx +215 -0
- package/src/grapher/stackedCharts/StackedAreas.tsx +223 -0
- package/src/grapher/stackedCharts/StackedBarChart.tsx +619 -0
- package/src/grapher/stackedCharts/StackedBarChartState.ts +80 -0
- package/src/grapher/stackedCharts/StackedBarChartThumbnail.tsx +220 -0
- package/src/grapher/stackedCharts/StackedBarSegment.tsx +87 -0
- package/src/grapher/stackedCharts/StackedBars.tsx +102 -0
- package/src/grapher/stackedCharts/StackedConstants.ts +109 -0
- package/src/grapher/stackedCharts/StackedDiscreteBarChart.tsx +270 -0
- package/src/grapher/stackedCharts/StackedDiscreteBarChartState.ts +296 -0
- package/src/grapher/stackedCharts/StackedDiscreteBarChartThumbnail.tsx +27 -0
- package/src/grapher/stackedCharts/StackedDiscreteBars.tsx +648 -0
- package/src/grapher/stackedCharts/StackedUtils.ts +142 -0
- package/src/grapher/tabs/Tabs.scss +169 -0
- package/src/grapher/tabs/Tabs.tsx +54 -0
- package/src/grapher/tabs/TabsWithDropdown.scss +62 -0
- package/src/grapher/tabs/TabsWithDropdown.tsx +114 -0
- package/src/grapher/testData/OwidTestData.sample.ts +273 -0
- package/src/grapher/testData/OwidTestData.ts +64 -0
- package/src/grapher/timeline/TimelineComponent.scss +139 -0
- package/src/grapher/timeline/TimelineComponent.tsx +658 -0
- package/src/grapher/timeline/TimelineController.ts +368 -0
- package/src/grapher/timeline/readme.md +7 -0
- package/src/grapher/tooltip/Tooltip.scss +510 -0
- package/src/grapher/tooltip/Tooltip.tsx +294 -0
- package/src/grapher/tooltip/TooltipContents.tsx +383 -0
- package/src/grapher/tooltip/TooltipProps.ts +123 -0
- package/src/grapher/tooltip/TooltipState.ts +81 -0
- package/src/grapher/verticalLabels/VerticalLabels.tsx +31 -0
- package/src/grapher/verticalLabels/VerticalLabelsState.ts +154 -0
- package/src/index.ts +226 -0
- package/src/styles/charts.scss +15 -0
- package/src/types/NominalType.ts +30 -0
- package/src/types/OwidOrigin.ts +18 -0
- package/src/types/OwidSource.ts +9 -0
- package/src/types/OwidVariable.ts +133 -0
- package/src/types/OwidVariableDisplayConfigInterface.ts +49 -0
- package/src/types/analyticsTypes.ts +54 -0
- package/src/types/dbTypes/Tags.ts +11 -0
- package/src/types/domainTypes/Archive.ts +139 -0
- package/src/types/domainTypes/Author.ts +28 -0
- package/src/types/domainTypes/ContentGraph.ts +76 -0
- package/src/types/domainTypes/CoreTableTypes.ts +305 -0
- package/src/types/domainTypes/DeployStatus.ts +23 -0
- package/src/types/domainTypes/Layout.ts +34 -0
- package/src/types/domainTypes/Posts.ts +34 -0
- package/src/types/domainTypes/Search.ts +299 -0
- package/src/types/domainTypes/Site.ts +8 -0
- package/src/types/domainTypes/StaticViz.ts +64 -0
- package/src/types/domainTypes/Toc.ts +11 -0
- package/src/types/domainTypes/Tombstone.ts +19 -0
- package/src/types/domainTypes/Various.ts +79 -0
- package/src/types/gdocTypes/Gdoc.ts +280 -0
- package/src/types/grapherTypes/BinningStrategyTypes.ts +46 -0
- package/src/types/grapherTypes/GrapherConstants.ts +53 -0
- package/src/types/grapherTypes/GrapherTypes.ts +743 -0
- package/src/types/index.ts +316 -0
- package/src/types/wordpressTypes/WordpressTypes.ts +9 -0
- package/src/utils/Bounds.ts +439 -0
- package/src/utils/BrowserUtils.ts +12 -0
- package/src/utils/FuzzySearch.ts +74 -0
- package/src/utils/MultiDimDataPageConfig.ts +31 -0
- package/src/utils/OwidVariable.ts +82 -0
- package/src/utils/PointVector.ts +97 -0
- package/src/utils/PromiseCache.ts +36 -0
- package/src/utils/PromiseSwitcher.ts +52 -0
- package/src/utils/TimeBounds.ts +130 -0
- package/src/utils/Tippy.tsx +57 -0
- package/src/utils/Util.ts +2369 -0
- package/src/utils/archival/archivalDate.ts +48 -0
- package/src/utils/dayjs.ts +32 -0
- package/src/utils/formatValue.ts +242 -0
- package/src/utils/grapherConfigUtils.ts +81 -0
- package/src/utils/image.ts +225 -0
- package/src/utils/index.ts +318 -0
- package/src/utils/isPresent.ts +5 -0
- package/src/utils/metadataHelpers.ts +329 -0
- package/src/utils/persistable/Persistable.ts +82 -0
- package/src/utils/persistable/readme.md +50 -0
- package/src/utils/regions.json +5635 -0
- package/src/utils/regions.ts +463 -0
- package/src/utils/serializers.ts +16 -0
- package/src/utils/string.ts +42 -0
- package/src/utils/urls/Url.ts +195 -0
- package/src/utils/urls/UrlMigration.ts +10 -0
- package/src/utils/urls/UrlUtils.ts +54 -0
- package/src/utils/urls/readme.md +90 -0
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
import * as _ from "lodash-es"
|
|
2
|
+
/* eslint-disable no-sparse-arrays */
|
|
3
|
+
import {
|
|
4
|
+
CoreMatrix,
|
|
5
|
+
ColumnTypeNames,
|
|
6
|
+
CoreTableInputOption,
|
|
7
|
+
OwidColumnDef,
|
|
8
|
+
TableSlug,
|
|
9
|
+
SubNavId,
|
|
10
|
+
FacetAxisDomain,
|
|
11
|
+
GrapherInterface,
|
|
12
|
+
AxisMinMaxValueStr,
|
|
13
|
+
GrapherChartType,
|
|
14
|
+
} from "../types/index.js"
|
|
15
|
+
import {
|
|
16
|
+
CoreTable,
|
|
17
|
+
OwidTable,
|
|
18
|
+
isNotErrorValue,
|
|
19
|
+
} from "../core-table/index.js"
|
|
20
|
+
import {
|
|
21
|
+
GitCommit,
|
|
22
|
+
PromiseCache,
|
|
23
|
+
SerializedGridProgram,
|
|
24
|
+
trimObject,
|
|
25
|
+
fetchWithRetry,
|
|
26
|
+
} from "../utils/index.js"
|
|
27
|
+
import {
|
|
28
|
+
CellDef,
|
|
29
|
+
Grammar,
|
|
30
|
+
GridBoolean,
|
|
31
|
+
GRID_CELL_DELIMITER,
|
|
32
|
+
GRID_NODE_DELIMITER,
|
|
33
|
+
RootKeywordCellDef,
|
|
34
|
+
} from "./gridLang/GridLangConstants.js"
|
|
35
|
+
import { GridProgram } from "./gridLang/GridProgram.js"
|
|
36
|
+
import { ColumnGrammar } from "./ColumnGrammar.js"
|
|
37
|
+
import {
|
|
38
|
+
DefaultNewExplorerSlug,
|
|
39
|
+
ExplorerChartCreationMode,
|
|
40
|
+
ExplorerChoiceParams,
|
|
41
|
+
EXPLORERS_ROUTE_FOLDER,
|
|
42
|
+
} from "./ExplorerConstants.js"
|
|
43
|
+
import { DecisionMatrix } from "./ExplorerDecisionMatrix.js"
|
|
44
|
+
import { ExplorerGrammar } from "./ExplorerGrammar.js"
|
|
45
|
+
import { GrapherGrammar } from "./GrapherGrammar.js"
|
|
46
|
+
import { latestGrapherConfigSchema } from "../grapher/index.js"
|
|
47
|
+
|
|
48
|
+
export const EXPLORER_FILE_SUFFIX = ".explorer.tsv"
|
|
49
|
+
|
|
50
|
+
export interface TableDef {
|
|
51
|
+
url?: string
|
|
52
|
+
columnDefinitions?: OwidColumnDef[]
|
|
53
|
+
inlineData?: string[][]
|
|
54
|
+
slug?: TableSlug
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface ExplorerGrapherInterface extends GrapherInterface {
|
|
58
|
+
grapherId?: number
|
|
59
|
+
tableSlug?: string
|
|
60
|
+
yVariableIds?: string
|
|
61
|
+
xVariableId?: string
|
|
62
|
+
colorVariableId?: string
|
|
63
|
+
sizeVariableId?: string
|
|
64
|
+
yScaleToggle?: boolean
|
|
65
|
+
yAxisMin?: number | AxisMinMaxValueStr.auto
|
|
66
|
+
facetYDomain?: FacetAxisDomain
|
|
67
|
+
relatedQuestionText?: string
|
|
68
|
+
relatedQuestionUrl?: string
|
|
69
|
+
mapTargetTime?: number
|
|
70
|
+
type?: GrapherChartType | "LineChart SlopeChart" | "None"
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const ExplorerRootDef: CellDef = {
|
|
74
|
+
...RootKeywordCellDef,
|
|
75
|
+
grammar: ExplorerGrammar,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export class ExplorerProgram extends GridProgram {
|
|
79
|
+
constructor(slug: string, tsv: string, lastCommit?: GitCommit) {
|
|
80
|
+
super(slug, tsv, lastCommit, ExplorerRootDef)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private _decisionMatrix?: DecisionMatrix
|
|
84
|
+
get decisionMatrix() {
|
|
85
|
+
if (!this._decisionMatrix) {
|
|
86
|
+
this._decisionMatrix = new DecisionMatrix(
|
|
87
|
+
this.decisionMatrixCode ?? "",
|
|
88
|
+
this.lastCommit?.hash
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
return this._decisionMatrix
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static fromJson(json: SerializedGridProgram) {
|
|
95
|
+
return new ExplorerProgram(json.slug, json.program, json.lastCommit)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get clone() {
|
|
99
|
+
return ExplorerProgram.fromJson(this.toJson())
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
get isNewFile() {
|
|
103
|
+
return this.slug === DefaultNewExplorerSlug
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
get filename() {
|
|
107
|
+
return this.slug + EXPLORER_FILE_SUFFIX
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
initDecisionMatrix(choiceParams: ExplorerChoiceParams) {
|
|
111
|
+
this.decisionMatrix.setValuesFromChoiceParams(choiceParams)
|
|
112
|
+
return this
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get fullPath() {
|
|
116
|
+
return makeFullPath(this.slug)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
get currentlySelectedGrapherRow() {
|
|
120
|
+
const row = this.getKeywordIndex(ExplorerGrammar.graphers.keyword)
|
|
121
|
+
return row === -1
|
|
122
|
+
? undefined
|
|
123
|
+
: row + this.decisionMatrix.selectedRowIndex + 2
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
static fromMatrix(slug: string, matrix: CoreMatrix) {
|
|
127
|
+
const str = matrix
|
|
128
|
+
.map((row) =>
|
|
129
|
+
row.map((cell) => cell && `${cell}`.replace(/\n/g, "\\n"))
|
|
130
|
+
)
|
|
131
|
+
.map((row) => row.join(GRID_CELL_DELIMITER))
|
|
132
|
+
.join(GRID_NODE_DELIMITER)
|
|
133
|
+
return new ExplorerProgram(slug, str)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
get explorerTitle() {
|
|
137
|
+
return this.getLineValue(ExplorerGrammar.explorerTitle.keyword)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
get title() {
|
|
141
|
+
return this.getLineValue(ExplorerGrammar.title.keyword)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
get subNavId(): SubNavId | undefined {
|
|
145
|
+
return this.getLineValue(ExplorerGrammar.subNavId.keyword) as SubNavId
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
get googleSheet() {
|
|
149
|
+
return this.getLineValue(ExplorerGrammar.googleSheet.keyword)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
get hideAlertBanner() {
|
|
153
|
+
return (
|
|
154
|
+
this.getLineValue(ExplorerGrammar.hideAlertBanner.keyword) ===
|
|
155
|
+
GridBoolean.true
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
get subNavCurrentId() {
|
|
160
|
+
return this.getLineValue(ExplorerGrammar.subNavCurrentId.keyword)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
get thumbnail() {
|
|
164
|
+
return this.getLineValue(ExplorerGrammar.thumbnail.keyword)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
get explorerSubtitle() {
|
|
168
|
+
return this.getLineValue(ExplorerGrammar.explorerSubtitle.keyword)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
get entityType() {
|
|
172
|
+
return this.getLineValue(ExplorerGrammar.entityType.keyword)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
get selection() {
|
|
176
|
+
return this.getLine(ExplorerGrammar.selection.keyword)?.slice(1)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
get pickerColumnSlugs() {
|
|
180
|
+
const slugs = this.getLineValue(
|
|
181
|
+
ExplorerGrammar.pickerColumnSlugs.keyword
|
|
182
|
+
)
|
|
183
|
+
return slugs ? slugs.split(" ") : undefined
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
get hideControls() {
|
|
187
|
+
return this.getLineValue(ExplorerGrammar.hideControls.keyword)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
get downloadDataLink() {
|
|
191
|
+
return this.getLineValue(ExplorerGrammar.downloadDataLink.keyword)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
get isPublished() {
|
|
195
|
+
return (
|
|
196
|
+
this.getLineValue(ExplorerGrammar.isPublished.keyword) ===
|
|
197
|
+
GridBoolean.true
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
setPublished(value: boolean) {
|
|
202
|
+
return this.clone.setLineValue(
|
|
203
|
+
ExplorerGrammar.isPublished.keyword,
|
|
204
|
+
value ? GridBoolean.true : GridBoolean.false
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
get wpBlockId() {
|
|
209
|
+
const blockIdString = this.getLineValue(
|
|
210
|
+
ExplorerGrammar.wpBlockId.keyword
|
|
211
|
+
)
|
|
212
|
+
return blockIdString ? parseInt(blockIdString, 10) : undefined
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
get decisionMatrixCode() {
|
|
216
|
+
const keywordIndex = this.getKeywordIndex(
|
|
217
|
+
ExplorerGrammar.graphers.keyword
|
|
218
|
+
)
|
|
219
|
+
if (keywordIndex === -1) return undefined
|
|
220
|
+
return this.getBlock(keywordIndex)
|
|
221
|
+
?.map((row) => row.join(this.cellDelimiter))
|
|
222
|
+
.join("\n")
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
get grapherCount() {
|
|
226
|
+
return this.decisionMatrix.numRows || 1
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
get tableCount() {
|
|
230
|
+
return this.getRowNumbersStartingWith(ExplorerGrammar.table.keyword)
|
|
231
|
+
.length
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
get tableSlugs(): (TableSlug | undefined)[] {
|
|
235
|
+
return this.lines
|
|
236
|
+
.filter((line) => line[0] === ExplorerGrammar.table.keyword)
|
|
237
|
+
.map((line) => line[2])
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// for backward compatibility, we currently support explorers
|
|
241
|
+
// that use Grapher IDs as well as CSV data files to create charts,
|
|
242
|
+
// but we plan to drop support for mixed-content explorers in the future
|
|
243
|
+
getChartCreationModeForExplorerGrapherConfig(
|
|
244
|
+
explorerGrapherConfig: ExplorerGrapherInterface
|
|
245
|
+
): ExplorerChartCreationMode {
|
|
246
|
+
const { decisionMatrix } = this
|
|
247
|
+
const { grapherId } = explorerGrapherConfig
|
|
248
|
+
const yVariableIdsColumn = decisionMatrix.table.get(
|
|
249
|
+
GrapherGrammar.yVariableIds.keyword
|
|
250
|
+
)
|
|
251
|
+
// referring to a variable in a single row triggers
|
|
252
|
+
// ExplorerChartCreationMode.FromVariableIds for all rows
|
|
253
|
+
if (yVariableIdsColumn.numValues)
|
|
254
|
+
return ExplorerChartCreationMode.FromVariableIds
|
|
255
|
+
if (grapherId && isNotErrorValue(grapherId))
|
|
256
|
+
return ExplorerChartCreationMode.FromGrapherId
|
|
257
|
+
return ExplorerChartCreationMode.FromExplorerTableColumnSlugs
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
get chartCreationMode(): ExplorerChartCreationMode {
|
|
261
|
+
return this.getChartCreationModeForExplorerGrapherConfig(
|
|
262
|
+
this.explorerGrapherConfig
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
get whyIsExplorerProgramInvalid(): string {
|
|
267
|
+
const {
|
|
268
|
+
chartCreationMode,
|
|
269
|
+
decisionMatrix: { table },
|
|
270
|
+
} = this
|
|
271
|
+
const { FromVariableIds, FromGrapherId, FromExplorerTableColumnSlugs } =
|
|
272
|
+
ExplorerChartCreationMode
|
|
273
|
+
|
|
274
|
+
const grapherIdColumn = table.get(GrapherGrammar.grapherId.keyword)
|
|
275
|
+
const tableSlugColumn = table.get(GrapherGrammar.tableSlug.keyword)
|
|
276
|
+
const hasGrapherId = grapherIdColumn.numValues > 0
|
|
277
|
+
const hasCsvData = tableSlugColumn.numValues > 0 || this.tableCount > 0
|
|
278
|
+
|
|
279
|
+
if (chartCreationMode === FromVariableIds && hasGrapherId)
|
|
280
|
+
return "Using variables IDs and Grapher IDs to create charts is not supported."
|
|
281
|
+
|
|
282
|
+
if (chartCreationMode === FromVariableIds && hasCsvData)
|
|
283
|
+
return "Using variable IDs and CSV data files to create charts is not supported."
|
|
284
|
+
|
|
285
|
+
if (
|
|
286
|
+
(chartCreationMode === FromGrapherId && hasCsvData) ||
|
|
287
|
+
(chartCreationMode === FromExplorerTableColumnSlugs && hasGrapherId)
|
|
288
|
+
)
|
|
289
|
+
return "Using Grapher IDs and CSV data files to create charts is deprecated."
|
|
290
|
+
|
|
291
|
+
return ""
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
get columnDefsByTableSlug(): Map<TableSlug | undefined, OwidColumnDef[]> {
|
|
295
|
+
const columnDefs = new Map<TableSlug | undefined, OwidColumnDef[]>()
|
|
296
|
+
const colDefsRows = this.getAllRowsMatchingWords(
|
|
297
|
+
ExplorerGrammar.columns.keyword
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
const matrix = this.lines
|
|
301
|
+
for (const row of colDefsRows) {
|
|
302
|
+
const tableSlugs = matrix[row].slice(1)
|
|
303
|
+
const columnDefinitions = parseColumnDefs(this.getBlock(row) ?? [])
|
|
304
|
+
if (tableSlugs.length === 0)
|
|
305
|
+
columnDefs.set(undefined, columnDefinitions)
|
|
306
|
+
else
|
|
307
|
+
tableSlugs.forEach((tableSlug) => {
|
|
308
|
+
columnDefs.set(tableSlug, columnDefinitions)
|
|
309
|
+
})
|
|
310
|
+
}
|
|
311
|
+
return columnDefs
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
get columnDefsWithoutTableSlug(): OwidColumnDef[] {
|
|
315
|
+
return this.columnDefsByTableSlug.get(undefined) ?? []
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async autofillMissingColumnDefinitionsForTableCommand(tableSlug?: string) {
|
|
319
|
+
const clone = this.clone
|
|
320
|
+
const remoteTable = await clone.constructTable(tableSlug)
|
|
321
|
+
const existingTableDef = this.getTableDef(tableSlug)
|
|
322
|
+
const table =
|
|
323
|
+
remoteTable ||
|
|
324
|
+
(existingTableDef
|
|
325
|
+
? new CoreTable(
|
|
326
|
+
existingTableDef.inlineData,
|
|
327
|
+
existingTableDef.columnDefinitions
|
|
328
|
+
)
|
|
329
|
+
: undefined)
|
|
330
|
+
const newCols = table.autodetectedColumnDefs
|
|
331
|
+
const missing = newCols
|
|
332
|
+
.appendColumns([
|
|
333
|
+
{
|
|
334
|
+
slug: ColumnGrammar.notes.keyword,
|
|
335
|
+
values: newCols.indices.map(() => `Unreviewed`),
|
|
336
|
+
},
|
|
337
|
+
])
|
|
338
|
+
.select([
|
|
339
|
+
ColumnGrammar.slug.keyword,
|
|
340
|
+
,
|
|
341
|
+
ColumnGrammar.name.keyword,
|
|
342
|
+
,
|
|
343
|
+
ColumnGrammar.type.keyword,
|
|
344
|
+
ColumnGrammar.notes.keyword,
|
|
345
|
+
] as string[])
|
|
346
|
+
|
|
347
|
+
const colDefsRow = this.getRowMatchingWords(
|
|
348
|
+
ExplorerGrammar.columns.keyword,
|
|
349
|
+
tableSlug
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
if (colDefsRow !== -1)
|
|
353
|
+
clone.updateBlock(
|
|
354
|
+
colDefsRow,
|
|
355
|
+
new CoreTable(clone.getBlock(colDefsRow))
|
|
356
|
+
.concat([missing])
|
|
357
|
+
.toMatrix()
|
|
358
|
+
)
|
|
359
|
+
else
|
|
360
|
+
clone.appendBlock(
|
|
361
|
+
`${ExplorerGrammar.columns.keyword}${
|
|
362
|
+
tableSlug ? this.cellDelimiter + tableSlug : ""
|
|
363
|
+
}`,
|
|
364
|
+
missing.toMatrix()
|
|
365
|
+
)
|
|
366
|
+
return clone
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
constructExplorerGrapherConfig(grapherRow: any): ExplorerGrapherInterface {
|
|
370
|
+
const rootObject = trimAndParseObject(this.tuplesObject, GrapherGrammar)
|
|
371
|
+
let config = { ...rootObject }
|
|
372
|
+
|
|
373
|
+
if (grapherRow && Object.keys(grapherRow).length) {
|
|
374
|
+
config = {
|
|
375
|
+
...config,
|
|
376
|
+
...trimAndParseObject(grapherRow, GrapherGrammar),
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// remove all keys that are not part of the GrapherGrammar
|
|
381
|
+
Object.keys(config).forEach((key) => {
|
|
382
|
+
if (!GrapherGrammar[key]) delete config[key]
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
return config
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
constructGrapherConfig(
|
|
389
|
+
explorerGrapherConfig: ExplorerGrapherInterface
|
|
390
|
+
): GrapherInterface {
|
|
391
|
+
const partialConfigs: GrapherInterface[] = []
|
|
392
|
+
const fields = Object.entries(explorerGrapherConfig)
|
|
393
|
+
|
|
394
|
+
for (const [field, value] of fields) {
|
|
395
|
+
const cellDef = GrapherGrammar[field]
|
|
396
|
+
partialConfigs.push(cellDef.toGrapherObject(value))
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const mergedConfig = _.merge({}, ...partialConfigs)
|
|
400
|
+
|
|
401
|
+
// assume config is valid against the latest schema
|
|
402
|
+
mergedConfig.$schema = latestGrapherConfigSchema
|
|
403
|
+
|
|
404
|
+
// TODO: can be removed once relatedQuestions is refactored
|
|
405
|
+
const { relatedQuestionUrl, relatedQuestionText } =
|
|
406
|
+
explorerGrapherConfig
|
|
407
|
+
if (relatedQuestionUrl && relatedQuestionText) {
|
|
408
|
+
mergedConfig.relatedQuestions = [
|
|
409
|
+
{ url: relatedQuestionUrl, text: relatedQuestionText },
|
|
410
|
+
]
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return mergedConfig
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Grapher config for the currently selected row including global settings.
|
|
418
|
+
* Includes all columns that are part of the GrapherGrammar.
|
|
419
|
+
*/
|
|
420
|
+
get explorerGrapherConfig(): ExplorerGrapherInterface {
|
|
421
|
+
const selectedGrapherRow = this.decisionMatrix.selectedRow
|
|
422
|
+
return this.constructExplorerGrapherConfig(selectedGrapherRow)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Grapher config for the currently selected row, with explorer-specific
|
|
427
|
+
* fields translated to valid GrapherInterface fields.
|
|
428
|
+
*
|
|
429
|
+
* For example, `yAxisMin` is translated to `{yAxis: {min: ... }}`
|
|
430
|
+
*/
|
|
431
|
+
get grapherConfig(): GrapherInterface {
|
|
432
|
+
return this.constructGrapherConfig(this.explorerGrapherConfig)
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* A static method so that all explorers on the page share requests,
|
|
437
|
+
* and no duplicate requests are sent.
|
|
438
|
+
*/
|
|
439
|
+
private static tableDataLoader = new PromiseCache(
|
|
440
|
+
async (url: string): Promise<CoreTableInputOption> => {
|
|
441
|
+
const response = await fetchWithRetry(url)
|
|
442
|
+
if (!response.ok) throw new Error(response.statusText)
|
|
443
|
+
const tableInput: CoreTableInputOption = url.endsWith(".json")
|
|
444
|
+
? await response.json()
|
|
445
|
+
: await response.text()
|
|
446
|
+
return tableInput
|
|
447
|
+
}
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
async constructTable(tableSlug?: TableSlug): Promise<OwidTable> {
|
|
451
|
+
const tableDef = this.getTableDef(tableSlug)
|
|
452
|
+
if (!tableDef) {
|
|
453
|
+
throw new Error(`Table definitions not found for '${tableSlug}'`)
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if (tableDef.inlineData) {
|
|
457
|
+
return new OwidTable(
|
|
458
|
+
tableDef.inlineData,
|
|
459
|
+
tableDef.columnDefinitions,
|
|
460
|
+
{
|
|
461
|
+
tableDescription: `Loaded '${tableSlug}' from inline data`,
|
|
462
|
+
tableSlug: tableSlug,
|
|
463
|
+
}
|
|
464
|
+
).dropEmptyRows()
|
|
465
|
+
} else if (tableDef.url) {
|
|
466
|
+
const input = await ExplorerProgram.tableDataLoader.get(
|
|
467
|
+
tableDef.url
|
|
468
|
+
)
|
|
469
|
+
return new OwidTable(input, tableDef.columnDefinitions, {
|
|
470
|
+
tableDescription: `Loaded from ${tableDef.url}`,
|
|
471
|
+
})
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
throw new Error(`No data for table '${tableSlug}'`)
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
getTableDef(tableSlug?: TableSlug): TableDef | undefined {
|
|
478
|
+
const tableDefRow = this.getRowMatchingWords(
|
|
479
|
+
ExplorerGrammar.table.keyword,
|
|
480
|
+
undefined,
|
|
481
|
+
tableSlug
|
|
482
|
+
)
|
|
483
|
+
if (tableDefRow === -1) return undefined
|
|
484
|
+
|
|
485
|
+
const inlineData = this.getBlock(tableDefRow)
|
|
486
|
+
let url = inlineData ? undefined : this.lines[tableDefRow][1]
|
|
487
|
+
|
|
488
|
+
if (url && !url.includes("://")) {
|
|
489
|
+
const owidDatasetSlug = encodeURIComponent(url)
|
|
490
|
+
url = `https://raw.githubusercontent.com/owid/owid-datasets/master/datasets/${owidDatasetSlug}/${owidDatasetSlug}.csv`
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const columnDefinitions: OwidColumnDef[] | undefined =
|
|
494
|
+
this.columnDefsByTableSlug.get(tableSlug)
|
|
495
|
+
|
|
496
|
+
return {
|
|
497
|
+
url,
|
|
498
|
+
columnDefinitions,
|
|
499
|
+
inlineData,
|
|
500
|
+
slug: tableSlug,
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
export const makeFullPath = (slug: string) =>
|
|
506
|
+
`${EXPLORERS_ROUTE_FOLDER}/${slug}${EXPLORER_FILE_SUFFIX}`
|
|
507
|
+
|
|
508
|
+
export const trimAndParseObject = (config: any, grammar: Grammar) => {
|
|
509
|
+
// Trim empty properties. Prevents things like clearing "type" which crashes Grapher. The call to grapher.reset will automatically clear things like title, subtitle, if not set.
|
|
510
|
+
const trimmedRow = trimObject(config, true) as any
|
|
511
|
+
|
|
512
|
+
// parse types
|
|
513
|
+
Object.keys(trimmedRow).forEach((key) => {
|
|
514
|
+
const def = grammar[key]
|
|
515
|
+
if (def && def.parse) trimmedRow[key] = def.parse(trimmedRow[key])
|
|
516
|
+
// If there no definition but it is a boolean, parse it (todo: always have a def)
|
|
517
|
+
else if (!def) {
|
|
518
|
+
const value = trimmedRow[key]
|
|
519
|
+
if (value === GridBoolean.true) trimmedRow[key] = true
|
|
520
|
+
else if (value === GridBoolean.false) trimmedRow[key] = false
|
|
521
|
+
}
|
|
522
|
+
})
|
|
523
|
+
return trimmedRow
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const parseColumnDefs = (block: string[][]): OwidColumnDef[] => {
|
|
527
|
+
/**
|
|
528
|
+
* A column def line can have:
|
|
529
|
+
* - a column named `variableId`, which contains a variable id
|
|
530
|
+
* - a column named `slug`, which is the referenced column in its data file
|
|
531
|
+
*
|
|
532
|
+
* We want to filter out any rows that contain neither of those, and we also
|
|
533
|
+
* want to rename `variableId` to `owidVariableId`.
|
|
534
|
+
*/
|
|
535
|
+
const columnsTable = new CoreTable(block)
|
|
536
|
+
.appendColumnsIfNew([
|
|
537
|
+
{ slug: "slug", type: ColumnTypeNames.String, name: "slug" },
|
|
538
|
+
{
|
|
539
|
+
slug: "variableId",
|
|
540
|
+
type: ColumnTypeNames.Integer,
|
|
541
|
+
name: "variableId",
|
|
542
|
+
},
|
|
543
|
+
])
|
|
544
|
+
.renameColumn("variableId", "owidVariableId")
|
|
545
|
+
// Filter out rows that neither have a slug nor an owidVariableId
|
|
546
|
+
.rowFilter(
|
|
547
|
+
(row) => !!(row.slug || typeof row.owidVariableId === "number"),
|
|
548
|
+
"Keep only column defs with a slug or variable id"
|
|
549
|
+
)
|
|
550
|
+
return columnsTable.rows.map((row) => {
|
|
551
|
+
// ignore slug if a variable id is given
|
|
552
|
+
const hasValidVariableId =
|
|
553
|
+
row.owidVariableId && isNotErrorValue(row.owidVariableId)
|
|
554
|
+
if (hasValidVariableId && row.slug) delete row.slug
|
|
555
|
+
|
|
556
|
+
for (const field in row) {
|
|
557
|
+
const cellDef = ColumnGrammar[field]
|
|
558
|
+
if (cellDef?.display) {
|
|
559
|
+
// move field into 'display' object
|
|
560
|
+
row.display = row.display || {}
|
|
561
|
+
row.display[field] = row[field]
|
|
562
|
+
delete row[field]
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return trimAndParseObject(row, ColumnGrammar)
|
|
567
|
+
})
|
|
568
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as _ from "lodash-es"
|
|
2
|
+
import { SelectionArray } from "../grapher/index.js"
|
|
3
|
+
import { Bounds, deserializeJSONFromHTML } from "../utils/index.js"
|
|
4
|
+
import {
|
|
5
|
+
EMBEDDED_EXPLORER_DELIMITER,
|
|
6
|
+
EMBEDDED_EXPLORER_GRAPHER_CONFIGS,
|
|
7
|
+
EMBEDDED_EXPLORER_PARTIAL_GRAPHER_CONFIGS,
|
|
8
|
+
EXPLORER_CONSTANTS_DELIMITER,
|
|
9
|
+
} from "./ExplorerConstants.js"
|
|
10
|
+
import { ExplorerProps } from "./Explorer.js"
|
|
11
|
+
|
|
12
|
+
export async function buildExplorerProps(
|
|
13
|
+
html: string,
|
|
14
|
+
queryStr: string,
|
|
15
|
+
selection: SelectionArray,
|
|
16
|
+
bounds?: Bounds
|
|
17
|
+
) {
|
|
18
|
+
const explorerConstants = deserializeJSONFromHTML(
|
|
19
|
+
html,
|
|
20
|
+
EXPLORER_CONSTANTS_DELIMITER
|
|
21
|
+
)
|
|
22
|
+
let grapherConfigs = deserializeJSONFromHTML(
|
|
23
|
+
html,
|
|
24
|
+
EMBEDDED_EXPLORER_GRAPHER_CONFIGS
|
|
25
|
+
)
|
|
26
|
+
let partialGrapherConfigs = deserializeJSONFromHTML(
|
|
27
|
+
html,
|
|
28
|
+
EMBEDDED_EXPLORER_PARTIAL_GRAPHER_CONFIGS
|
|
29
|
+
)
|
|
30
|
+
if (_.isArray(grapherConfigs)) {
|
|
31
|
+
grapherConfigs = grapherConfigs.map((grapherConfig) => ({
|
|
32
|
+
...grapherConfig,
|
|
33
|
+
adminBaseUrl: explorerConstants.adminBaseUrl,
|
|
34
|
+
bakedGrapherURL: explorerConstants.bakedGrapherUrl,
|
|
35
|
+
}))
|
|
36
|
+
}
|
|
37
|
+
if (_.isArray(partialGrapherConfigs)) {
|
|
38
|
+
partialGrapherConfigs = partialGrapherConfigs.map((grapherConfig) => ({
|
|
39
|
+
...grapherConfig,
|
|
40
|
+
adminBaseUrl: explorerConstants.adminBaseUrl,
|
|
41
|
+
bakedGrapherURL: explorerConstants.bakedGrapherUrl,
|
|
42
|
+
}))
|
|
43
|
+
}
|
|
44
|
+
const props: ExplorerProps = {
|
|
45
|
+
...deserializeJSONFromHTML(html, EMBEDDED_EXPLORER_DELIMITER),
|
|
46
|
+
isEmbeddedInAnOwidPage: true,
|
|
47
|
+
adminBaseUrl: explorerConstants.adminBaseUrl,
|
|
48
|
+
bakedBaseUrl: explorerConstants.bakedBaseUrl,
|
|
49
|
+
bakedGrapherUrl: explorerConstants.bakedGrapherUrl,
|
|
50
|
+
dataApiUrl: explorerConstants.dataApiUrl,
|
|
51
|
+
grapherConfigs,
|
|
52
|
+
partialGrapherConfigs,
|
|
53
|
+
queryStr,
|
|
54
|
+
selection: new SelectionArray(selection.selectedEntityNames),
|
|
55
|
+
bounds: bounds,
|
|
56
|
+
staticBounds: bounds,
|
|
57
|
+
}
|
|
58
|
+
return props
|
|
59
|
+
}
|