@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,311 @@
|
|
|
1
|
+
import { trimMatrix } from "../../core-table/index.js"
|
|
2
|
+
import {
|
|
3
|
+
isPresent,
|
|
4
|
+
GitCommit,
|
|
5
|
+
SerializedGridProgram,
|
|
6
|
+
} from "../../utils/index.js"
|
|
7
|
+
|
|
8
|
+
import { GridCell } from "./GridCell.js"
|
|
9
|
+
import {
|
|
10
|
+
CellDef,
|
|
11
|
+
CellPosition,
|
|
12
|
+
GRID_CELL_DELIMITER,
|
|
13
|
+
GRID_EDGE_DELIMITER,
|
|
14
|
+
GRID_NODE_DELIMITER,
|
|
15
|
+
Origin,
|
|
16
|
+
ParsedCell,
|
|
17
|
+
} from "./GridLangConstants.js"
|
|
18
|
+
import { tsvToMatrix } from "./GrammarUtils.js"
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Block location for the below would be like (numRows = 2)
|
|
22
|
+
* table |
|
|
23
|
+
* slug name | startRow = 1
|
|
24
|
+
* pop Population | endRow = 2
|
|
25
|
+
*/
|
|
26
|
+
interface BlockLocation {
|
|
27
|
+
startRow: number
|
|
28
|
+
endRow: number
|
|
29
|
+
numRows: number
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class GridProgram {
|
|
33
|
+
constructor(
|
|
34
|
+
slug: string,
|
|
35
|
+
tsv: string,
|
|
36
|
+
lastCommit?: GitCommit,
|
|
37
|
+
grammar?: CellDef
|
|
38
|
+
) {
|
|
39
|
+
this.lines = tsvToMatrix(tsv.replace(/\r/g, ""))
|
|
40
|
+
this.slug = slug
|
|
41
|
+
this.lastCommit = lastCommit
|
|
42
|
+
this.grammar = grammar
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private grammar?
|
|
46
|
+
|
|
47
|
+
private static guids = 0
|
|
48
|
+
guid = ++GridProgram.guids
|
|
49
|
+
|
|
50
|
+
lastCommit?: GitCommit
|
|
51
|
+
slug: string
|
|
52
|
+
|
|
53
|
+
private nodeDelimiter = GRID_NODE_DELIMITER
|
|
54
|
+
cellDelimiter = GRID_CELL_DELIMITER
|
|
55
|
+
private edgeDelimiter = GRID_EDGE_DELIMITER
|
|
56
|
+
lines: string[][]
|
|
57
|
+
|
|
58
|
+
toJson(): SerializedGridProgram {
|
|
59
|
+
return {
|
|
60
|
+
program: this.toString(),
|
|
61
|
+
slug: this.slug,
|
|
62
|
+
lastCommit: this.lastCommit,
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
findNext(position: CellPosition) {
|
|
67
|
+
const cell = this.getCell(position)
|
|
68
|
+
const { contents } = cell
|
|
69
|
+
return this.grepFirst(contents, {
|
|
70
|
+
...position,
|
|
71
|
+
column: position.column + 1,
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
findAll(position: CellPosition) {
|
|
76
|
+
const cell = this.getCell(position)
|
|
77
|
+
const { contents } = cell
|
|
78
|
+
return this.grep(contents, {
|
|
79
|
+
...position,
|
|
80
|
+
column: position.column + 1,
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private ring(position: CellPosition) {
|
|
85
|
+
const lines = this.lines
|
|
86
|
+
const numRows = lines.length
|
|
87
|
+
if (!numRows)
|
|
88
|
+
return (function* generator() {
|
|
89
|
+
// no rows to iterate over
|
|
90
|
+
})()
|
|
91
|
+
const pointer = {
|
|
92
|
+
...position,
|
|
93
|
+
started: false,
|
|
94
|
+
endRow: position.row,
|
|
95
|
+
endCol: position.column,
|
|
96
|
+
}
|
|
97
|
+
if (pointer.row >= numRows) pointer.endRow = numRows - 1
|
|
98
|
+
|
|
99
|
+
const lastLine = lines[pointer.endRow]
|
|
100
|
+
pointer.endCol =
|
|
101
|
+
lastLine[pointer.endCol] === undefined
|
|
102
|
+
? lastLine.length
|
|
103
|
+
: pointer.endCol
|
|
104
|
+
function* generator() {
|
|
105
|
+
while (true) {
|
|
106
|
+
if (
|
|
107
|
+
pointer.started &&
|
|
108
|
+
pointer.row === pointer.endRow &&
|
|
109
|
+
pointer.column === pointer.endCol
|
|
110
|
+
)
|
|
111
|
+
return
|
|
112
|
+
pointer.started = true
|
|
113
|
+
|
|
114
|
+
if (
|
|
115
|
+
lines[pointer.row] === undefined ||
|
|
116
|
+
lines[pointer.row][pointer.column] === undefined
|
|
117
|
+
) {
|
|
118
|
+
pointer.row++
|
|
119
|
+
pointer.column = 0
|
|
120
|
+
if (pointer.row >= numRows) pointer.row = 0
|
|
121
|
+
continue
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
yield {
|
|
125
|
+
row: pointer.row,
|
|
126
|
+
column: pointer.column,
|
|
127
|
+
} as CellPosition
|
|
128
|
+
pointer.column++
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return generator()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
valuesFrom(position = Origin) {
|
|
136
|
+
return Array.from(this.ring(position)).map((next) =>
|
|
137
|
+
this.getCellContents(next)
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
get numRows() {
|
|
142
|
+
return this.lines.length
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
patch(obj: any) {
|
|
146
|
+
Object.keys(obj).forEach((key) => this.setLineValue(key, obj[key]))
|
|
147
|
+
return this
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
grepFirst(key: string, position = Origin) {
|
|
151
|
+
for (const next of this.ring(position)) {
|
|
152
|
+
if (this.getCellContents(next) === key) return next
|
|
153
|
+
}
|
|
154
|
+
return undefined
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
grep(key: string, position = Origin) {
|
|
158
|
+
const hits: CellPosition[] = []
|
|
159
|
+
for (const next of this.ring(position)) {
|
|
160
|
+
if (this.getCellContents(next) === key) hits.push(next)
|
|
161
|
+
}
|
|
162
|
+
return hits
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Returns all non-blocks as an object literal
|
|
167
|
+
*/
|
|
168
|
+
get tuplesObject() {
|
|
169
|
+
const obj: { [key: string]: any } = {}
|
|
170
|
+
this.lines
|
|
171
|
+
.filter((line) => line[0] !== "")
|
|
172
|
+
.forEach((line) => {
|
|
173
|
+
const [key, ...rest] = line
|
|
174
|
+
if (key) obj[key.trim()] = rest.join(this.cellDelimiter).trim()
|
|
175
|
+
})
|
|
176
|
+
return obj
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
getLine(keyword: string) {
|
|
180
|
+
return this.lines.find((line) => line[0] === keyword)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
getLineValue(keyword: string) {
|
|
184
|
+
const line = this.getLine(keyword)
|
|
185
|
+
return line?.[1]
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
protected getBlockLocation(
|
|
189
|
+
blockRowNumber: number
|
|
190
|
+
): BlockLocation | undefined {
|
|
191
|
+
const startRow = blockRowNumber + 1
|
|
192
|
+
let numRows = this.lines
|
|
193
|
+
.slice(startRow)
|
|
194
|
+
.findIndex((line) => line.length && line[0] !== "")
|
|
195
|
+
if (numRows === 0) return undefined
|
|
196
|
+
if (numRows === -1) numRows = this.lines.slice(startRow).length
|
|
197
|
+
return { startRow, endRow: startRow + numRows, numRows }
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
protected getKeywordIndex(key: string) {
|
|
201
|
+
return this.lines.findIndex((line) => line[0] === key)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
getCell(position: CellPosition): ParsedCell {
|
|
205
|
+
return new GridCell(this.lines, position, this.grammar!)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
getCellContents(position: CellPosition) {
|
|
209
|
+
const line = this.lines[position.row]
|
|
210
|
+
return line ? line[position.column] : undefined
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
deleteBlock(row?: number) {
|
|
214
|
+
if (row === undefined) return this
|
|
215
|
+
const location = this.getBlockLocation(row)
|
|
216
|
+
if (!location) return this
|
|
217
|
+
|
|
218
|
+
this.lines.splice(location.startRow, location.numRows)
|
|
219
|
+
return this
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
deleteLine(row?: number) {
|
|
223
|
+
if (row === undefined) return this
|
|
224
|
+
this.lines.splice(row, 1)
|
|
225
|
+
return this
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
appendLine(line: string) {
|
|
229
|
+
this.lines.push(line.split(this.cellDelimiter))
|
|
230
|
+
return this
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// todo: make immutable and return a new copy
|
|
234
|
+
setCell(row: number, col: number, value: string) {
|
|
235
|
+
this.lines[row][col] = value
|
|
236
|
+
return this
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
setLineValue(key: string, value: string | undefined) {
|
|
240
|
+
const index = this.getKeywordIndex(key)
|
|
241
|
+
if (index === -1 && value !== undefined) this.lines.push([key, value])
|
|
242
|
+
else if (value === undefined) this.deleteLine(index)
|
|
243
|
+
else this.lines[index] = [key, value]
|
|
244
|
+
return this
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
getBlock(keywordIndex: number) {
|
|
248
|
+
const location = this.getBlockLocation(keywordIndex)
|
|
249
|
+
if (!location) return undefined
|
|
250
|
+
return this.lines
|
|
251
|
+
.slice(location.startRow, location.endRow)
|
|
252
|
+
.map((line) => line.slice(1))
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
updateBlock(rowNumber: number, value: string[][]) {
|
|
256
|
+
const location = this.getBlockLocation(rowNumber)
|
|
257
|
+
if (!location) throw new Error("Block not found")
|
|
258
|
+
this.lines.splice(
|
|
259
|
+
location.startRow,
|
|
260
|
+
location.numRows,
|
|
261
|
+
...value.map((line) => ["", ...line])
|
|
262
|
+
)
|
|
263
|
+
return this
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
protected appendBlock(key: string, value: string[][]) {
|
|
267
|
+
this.lines.push([key])
|
|
268
|
+
value.forEach((line) => this.lines.push(["", ...line]))
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
getRowNumbersStartingWith(startsWith: string) {
|
|
272
|
+
return this.lines
|
|
273
|
+
.map((line, index) => (line[0] === startsWith ? index : null))
|
|
274
|
+
.filter(isPresent)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private static lineMatchesWords = (
|
|
278
|
+
line: string[],
|
|
279
|
+
words: (string | undefined)[]
|
|
280
|
+
): boolean =>
|
|
281
|
+
words.every((word, index) => word === undefined || line[index] === word)
|
|
282
|
+
|
|
283
|
+
getRowMatchingWords(...words: (string | undefined)[]): number {
|
|
284
|
+
return this.lines.findIndex((line) =>
|
|
285
|
+
GridProgram.lineMatchesWords(line, words)
|
|
286
|
+
)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
getAllRowsMatchingWords(...words: (string | undefined)[]): number[] {
|
|
290
|
+
const rows: number[] = []
|
|
291
|
+
this.lines.forEach((line: string[], rowIndex: number) => {
|
|
292
|
+
if (GridProgram.lineMatchesWords(line, words)) rows.push(rowIndex)
|
|
293
|
+
})
|
|
294
|
+
return rows
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// The max number of columns in any row when you view a program as a spreadsheet
|
|
298
|
+
get width() {
|
|
299
|
+
return Math.max(...this.lines.map((arr) => arr.length))
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
toString() {
|
|
303
|
+
return this.prettify()
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
protected prettify() {
|
|
307
|
+
return trimMatrix(this.lines)
|
|
308
|
+
.map((line) => line.join(this.cellDelimiter))
|
|
309
|
+
.join(this.nodeDelimiter)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# GridLang
|
|
2
|
+
|
|
3
|
+
(Note: GridLang name is a placeholder and this readme is a stub)
|
|
4
|
+
|
|
5
|
+
GridLang is a library for building 2-dimensional domain specific languages designed to be edited in a Spreadsheet UI.
|
|
6
|
+
|
|
7
|
+
Unlike traditional computer languages that parse tokens in-order, tokens in GridLanguages are parsed in a lazy, non-linear manner, based upon there position in a 2-d matrix.
|
|
8
|
+
|
|
9
|
+
Our "Explorer"—a DSL for building OWID explorers and Graphers—is a GridLang.
|
|
10
|
+
|
|
11
|
+
GridLangs are also intrinsically "patchable"—a great way for perserving user state.
|
|
12
|
+
|
|
13
|
+
## How it works
|
|
14
|
+
|
|
15
|
+
1. Extend the base GridProgram class with a class for your new DSL.
|
|
16
|
+
2. Create a grammar for your DSL.
|
|
17
|
+
3. Load in some "programs" from TSVs.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export { Explorer, type ExplorerProps } from "./Explorer.js"
|
|
2
|
+
|
|
3
|
+
export { buildExplorerProps } from "./ExplorerUtils.js"
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
DefaultNewExplorerSlug,
|
|
7
|
+
EMBEDDED_EXPLORER_DELIMITER,
|
|
8
|
+
EMBEDDED_EXPLORER_GRAPHER_CONFIGS,
|
|
9
|
+
EMBEDDED_EXPLORER_PARTIAL_GRAPHER_CONFIGS,
|
|
10
|
+
EXPLORER_CONSTANTS_DELIMITER,
|
|
11
|
+
EXPLORER_EMBEDDED_FIGURE_SELECTOR,
|
|
12
|
+
ExplorerChartCreationMode,
|
|
13
|
+
ExplorerContainerId,
|
|
14
|
+
ExplorerControlType,
|
|
15
|
+
ExplorerControlTypeRegex,
|
|
16
|
+
EXPLORERS_GIT_CMS_FOLDER,
|
|
17
|
+
EXPLORERS_PREVIEW_ROUTE,
|
|
18
|
+
EXPLORERS_ROUTE_FOLDER,
|
|
19
|
+
GetAllExplorersRoute,
|
|
20
|
+
GetAllExplorersTagsRoute,
|
|
21
|
+
type ChoiceMap,
|
|
22
|
+
type ChoiceName,
|
|
23
|
+
type ChoiceValue,
|
|
24
|
+
type ExplorerChoice,
|
|
25
|
+
type ExplorerChoiceOption,
|
|
26
|
+
type ExplorerChoiceParams,
|
|
27
|
+
type ExplorerFullQueryParams,
|
|
28
|
+
type ExplorersRouteResponse,
|
|
29
|
+
type ExplorerStandardQueryParams,
|
|
30
|
+
UNSAVED_EXPLORER_DRAFT,
|
|
31
|
+
UNSAVED_EXPLORER_PREVIEW_QUERYPARAMS,
|
|
32
|
+
} from "./ExplorerConstants.js"
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
type TableDef,
|
|
36
|
+
ExplorerProgram,
|
|
37
|
+
EXPLORER_FILE_SUFFIX,
|
|
38
|
+
makeFullPath,
|
|
39
|
+
type ExplorerGrapherInterface,
|
|
40
|
+
} from "./ExplorerProgram.js"
|
|
41
|
+
|
|
42
|
+
export { type ExplorerPageUrlMigrationSpec } from "./urlMigrations/ExplorerPageUrlMigrationSpec.js"
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
explorerUrlMigrationsById,
|
|
46
|
+
migrateExplorerUrl,
|
|
47
|
+
} from "./urlMigrations/ExplorerUrlMigrations.js"
|
|
48
|
+
|
|
49
|
+
export { isEmpty } from "./gridLang/GrammarUtils.js"
|
|
50
|
+
|
|
51
|
+
export { ColumnGrammar } from "./ColumnGrammar.js"
|
|
52
|
+
|
|
53
|
+
export { GridCell } from "./gridLang/GridCell.js"
|
|
54
|
+
|
|
55
|
+
export { GridProgram } from "./gridLang/GridProgram.js"
|
|
56
|
+
|
|
57
|
+
export { ExplorerGrammar } from "./ExplorerGrammar.js"
|
|
58
|
+
|
|
59
|
+
export { ExplorerUrlMigrationId } from "./urlMigrations/ExplorerUrlMigrations.js"
|
|
60
|
+
|
|
61
|
+
export { DecisionMatrix } from "./ExplorerDecisionMatrix.js"
|
|
62
|
+
|
|
63
|
+
export {
|
|
64
|
+
GridBoolean,
|
|
65
|
+
type CellPosition,
|
|
66
|
+
type ParsedCell,
|
|
67
|
+
} from "./gridLang/GridLangConstants.js"
|
|
68
|
+
|
|
69
|
+
export { GrapherGrammar } from "./GrapherGrammar.js"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Explorers
|
|
2
|
+
|
|
3
|
+
The Explorer is our component that allows easy navigating through a set of authored charts or charts generated on the fly. With the Explorer a reader can quickly navigate across dozens or hundreds of different chart views without leaving the page.
|
|
4
|
+
|
|
5
|
+
The Explorer component adds a control bar above the chart with controls including radios, dropdowns and checkboxes that the reader can use to change the chart on the page. The Explorer also adds a standalone entity selection tool on the left.
|
|
6
|
+
|
|
7
|
+
The Explorer works best on desktop but is also designed to work decently on mobile devices.
|
|
8
|
+
|
|
9
|
+
## Implementation Notes
|
|
10
|
+
|
|
11
|
+
The Explorer depends on our Chart library, but the Chart library does not have a dependency on the Explorer. You should be able to delete the `explorer` folder, remove a few links, and the rest of Grapher should still work fine.
|
|
12
|
+
|
|
13
|
+
### Explorer DSL
|
|
14
|
+
|
|
15
|
+
Explorers are created in a DSL that authors can edit in a spreadsheet which is parsed to create an instance of the ExplorerProgram class.
|
|
16
|
+
|
|
17
|
+
# Explorer Grammars
|
|
18
|
+
|
|
19
|
+
This folder also contains the declarative grammars that defines all the keywords and values authors can have in their Explorer programs.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { legacyToCurrentGrapherUrl } from "../../grapher/index.js"
|
|
2
|
+
import { Url, UrlMigration } from "../../utils/index.js"
|
|
3
|
+
import {
|
|
4
|
+
decodeURIComponentOrUndefined,
|
|
5
|
+
getExplorerSlugFromUrl,
|
|
6
|
+
QueryParamTransformMap,
|
|
7
|
+
transformQueryParams,
|
|
8
|
+
} from "./ExplorerUrlMigrationUtils.js"
|
|
9
|
+
|
|
10
|
+
const EXPLORER_SLUG = "co2"
|
|
11
|
+
|
|
12
|
+
const co2QueryParamTransformMap: QueryParamTransformMap = {
|
|
13
|
+
"Gas ": {
|
|
14
|
+
newName: "Gas",
|
|
15
|
+
transformValue: decodeURIComponentOrUndefined,
|
|
16
|
+
},
|
|
17
|
+
"Accounting ": {
|
|
18
|
+
newName: "Accounting",
|
|
19
|
+
transformValue: decodeURIComponentOrUndefined,
|
|
20
|
+
},
|
|
21
|
+
"Fuel ": {
|
|
22
|
+
newName: "Fuel",
|
|
23
|
+
transformValue: decodeURIComponentOrUndefined,
|
|
24
|
+
},
|
|
25
|
+
"Count ": {
|
|
26
|
+
newName: "Count",
|
|
27
|
+
transformValue: decodeURIComponentOrUndefined,
|
|
28
|
+
},
|
|
29
|
+
"Relative to world total ": {
|
|
30
|
+
newName: "Relative to world total",
|
|
31
|
+
transformValue: (value) => (value ? "true" : "false"),
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const co2UrlMigration: UrlMigration = (url: Url) => {
|
|
36
|
+
// if it's not the /explorer/co2 path, skip it
|
|
37
|
+
const explorerSlug = getExplorerSlugFromUrl(url)
|
|
38
|
+
if (explorerSlug !== EXPLORER_SLUG) return url
|
|
39
|
+
|
|
40
|
+
url = legacyToCurrentGrapherUrl(url)
|
|
41
|
+
const queryParams = transformQueryParams(
|
|
42
|
+
url.queryParams,
|
|
43
|
+
co2QueryParamTransformMap
|
|
44
|
+
)
|
|
45
|
+
return url.setQueryParams(queryParams)
|
|
46
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Url, UrlMigration } from "../../utils/index.js"
|
|
2
|
+
import {
|
|
3
|
+
getExplorerSlugFromUrl,
|
|
4
|
+
QueryParamTransformMap,
|
|
5
|
+
transformQueryParams,
|
|
6
|
+
} from "./ExplorerUrlMigrationUtils.js"
|
|
7
|
+
|
|
8
|
+
const EXPLORER_SLUG = "coronavirus-data-explorer"
|
|
9
|
+
|
|
10
|
+
const transformMap: QueryParamTransformMap = {
|
|
11
|
+
Metric: {
|
|
12
|
+
transformValue: (value) => {
|
|
13
|
+
// Since we introduced multiple vaccinations metrics, we want to
|
|
14
|
+
// differentiate between them.
|
|
15
|
+
// And while we're there, reduce the length of "Tests per confirmed
|
|
16
|
+
// case", because it wraps to 2 lines.
|
|
17
|
+
//
|
|
18
|
+
// -@danielgavrilov, 2021-03-30
|
|
19
|
+
//
|
|
20
|
+
if (value === "Vaccinations") return "Vaccine doses"
|
|
21
|
+
if (value === "Tests per confirmed case") return "Tests per case"
|
|
22
|
+
return value
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
"Align outbreaks": {
|
|
26
|
+
newName: "Color by test positivity",
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const covidUrlMigration: UrlMigration = (url: Url) => {
|
|
31
|
+
// if it's not the /explorer/energy path, skip it
|
|
32
|
+
const explorerSlug = getExplorerSlugFromUrl(url)
|
|
33
|
+
if (explorerSlug !== EXPLORER_SLUG) return url
|
|
34
|
+
return url.setQueryParams(
|
|
35
|
+
transformQueryParams(url.queryParams, transformMap)
|
|
36
|
+
)
|
|
37
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { legacyToCurrentGrapherUrl } from "../../grapher/index.js"
|
|
2
|
+
import { Url, UrlMigration } from "../../utils/index.js"
|
|
3
|
+
import {
|
|
4
|
+
decodeURIComponentOrUndefined,
|
|
5
|
+
getExplorerSlugFromUrl,
|
|
6
|
+
QueryParamTransformMap,
|
|
7
|
+
transformQueryParams,
|
|
8
|
+
} from "./ExplorerUrlMigrationUtils.js"
|
|
9
|
+
|
|
10
|
+
const EXPLORER_SLUG = "energy"
|
|
11
|
+
|
|
12
|
+
const energyQueryParamTransformMap: QueryParamTransformMap = {
|
|
13
|
+
"Total or Breakdown ": {
|
|
14
|
+
newName: "Total or Breakdown",
|
|
15
|
+
transformValue: decodeURIComponentOrUndefined,
|
|
16
|
+
},
|
|
17
|
+
"Select a source ": {
|
|
18
|
+
newName: "Select a source",
|
|
19
|
+
transformValue: decodeURIComponentOrUndefined,
|
|
20
|
+
},
|
|
21
|
+
"Energy or Electricity ": {
|
|
22
|
+
newName: "Energy or Electricity",
|
|
23
|
+
transformValue: decodeURIComponentOrUndefined,
|
|
24
|
+
},
|
|
25
|
+
"Metric ": {
|
|
26
|
+
newName: "Metric",
|
|
27
|
+
transformValue: decodeURIComponentOrUndefined,
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const energyUrlMigration: UrlMigration = (url: Url) => {
|
|
32
|
+
// if it's not the /explorer/energy path, skip it
|
|
33
|
+
const explorerSlug = getExplorerSlugFromUrl(url)
|
|
34
|
+
if (explorerSlug !== EXPLORER_SLUG) return url
|
|
35
|
+
url = legacyToCurrentGrapherUrl(url)
|
|
36
|
+
const queryParams = transformQueryParams(
|
|
37
|
+
url.queryParams,
|
|
38
|
+
energyQueryParamTransformMap
|
|
39
|
+
)
|
|
40
|
+
return url.setQueryParams(queryParams)
|
|
41
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ExplorerUrlMigrationId } from "./ExplorerUrlMigrations.js"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* An object spec that gets encoded into pages that redirect to an explorer.
|
|
5
|
+
*
|
|
6
|
+
* It's encoded as a JSON object on the page in order to avoid storing all redirects
|
|
7
|
+
* in the client-side bundle.
|
|
8
|
+
*/
|
|
9
|
+
export interface ExplorerPageUrlMigrationSpec {
|
|
10
|
+
explorerUrlMigrationId: ExplorerUrlMigrationId
|
|
11
|
+
baseQueryStr: string
|
|
12
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as _ from "lodash-es"
|
|
2
|
+
import { Url, QueryParams } from "../../utils/index.js"
|
|
3
|
+
|
|
4
|
+
import { EXPLORERS_ROUTE_FOLDER } from "../ExplorerConstants.js"
|
|
5
|
+
|
|
6
|
+
export const decodeURIComponentOrUndefined = (value: string | undefined) =>
|
|
7
|
+
value !== undefined
|
|
8
|
+
? decodeURIComponent(value.replace(/\+/g, "%20"))
|
|
9
|
+
: undefined
|
|
10
|
+
|
|
11
|
+
export type QueryParamTransformMap = Record<
|
|
12
|
+
string,
|
|
13
|
+
{
|
|
14
|
+
newName?: string
|
|
15
|
+
transformValue?: (value: string | undefined) => string | undefined
|
|
16
|
+
}
|
|
17
|
+
>
|
|
18
|
+
|
|
19
|
+
export const transformQueryParams = (
|
|
20
|
+
oldQueryParams: Readonly<QueryParams>,
|
|
21
|
+
transformMap: QueryParamTransformMap
|
|
22
|
+
) => {
|
|
23
|
+
const newQueryParams = _.omit(
|
|
24
|
+
oldQueryParams,
|
|
25
|
+
...Object.keys(transformMap)
|
|
26
|
+
) as QueryParams
|
|
27
|
+
for (const oldParamName in transformMap) {
|
|
28
|
+
if (!(oldParamName in oldQueryParams)) continue
|
|
29
|
+
const { newName, transformValue } = transformMap[oldParamName]
|
|
30
|
+
const name = newName ?? oldParamName
|
|
31
|
+
const transform = transformValue ?? _.identity
|
|
32
|
+
newQueryParams[name] = transform(oldQueryParams[oldParamName])
|
|
33
|
+
}
|
|
34
|
+
return newQueryParams
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// todo(refactor): merge with Url's get explorerSlug()
|
|
38
|
+
export const getExplorerSlugFromUrl = (url: Url): string | undefined => {
|
|
39
|
+
if (!url.pathname) return undefined
|
|
40
|
+
const match = url.pathname.match(
|
|
41
|
+
new RegExp(`^/+${EXPLORERS_ROUTE_FOLDER}/+([^/]+)`)
|
|
42
|
+
)
|
|
43
|
+
if (match && match[1]) return match[1]
|
|
44
|
+
return undefined
|
|
45
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Url, UrlMigration, performUrlMigrations } from "../../utils/index.js"
|
|
2
|
+
|
|
3
|
+
import { legacyCovidMigrationSpec } from "./LegacyCovidUrlMigration.js"
|
|
4
|
+
import { co2UrlMigration } from "./CO2UrlMigration.js"
|
|
5
|
+
import { energyUrlMigration } from "./EnergyUrlMigration.js"
|
|
6
|
+
import { covidUrlMigration } from "./CovidUrlMigration.js"
|
|
7
|
+
|
|
8
|
+
export enum ExplorerUrlMigrationId {
|
|
9
|
+
legacyToGridCovidExplorer = "legacyToGridCovidExplorer",
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ExplorerUrlMigrationSpec {
|
|
13
|
+
explorerSlug: string
|
|
14
|
+
migrateUrl: (url: Url, baseQueryStr: string) => Url
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const explorerUrlMigrationsById: Record<
|
|
18
|
+
ExplorerUrlMigrationId,
|
|
19
|
+
ExplorerUrlMigrationSpec
|
|
20
|
+
> = {
|
|
21
|
+
legacyToGridCovidExplorer: legacyCovidMigrationSpec,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const explorerUrlMigrations: UrlMigration[] = [
|
|
25
|
+
// NOTE: The order of migrations matters!
|
|
26
|
+
co2UrlMigration,
|
|
27
|
+
energyUrlMigration,
|
|
28
|
+
covidUrlMigration,
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
export const migrateExplorerUrl: UrlMigration = (url: Url): Url => {
|
|
32
|
+
return performUrlMigrations(explorerUrlMigrations, url)
|
|
33
|
+
}
|