@carto/kepler.gl 0.0.1-alpha.map-libre
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/CHANGELOG.md +939 -0
- package/LICENSE +19 -0
- package/README.md +63 -0
- package/actions.js +21 -0
- package/cloud-providers.js +21 -0
- package/components.js +21 -0
- package/constants.js +21 -0
- package/dist/actions/action-wrapper.js +218 -0
- package/dist/actions/actions.js +198 -0
- package/dist/actions/identity-actions.js +105 -0
- package/dist/actions/index.js +161 -0
- package/dist/actions/map-state-actions.js +112 -0
- package/dist/actions/map-style-actions.js +167 -0
- package/dist/actions/provider-actions.js +129 -0
- package/dist/actions/ui-state-actions.js +316 -0
- package/dist/actions/vis-state-actions.js +1045 -0
- package/dist/cloud-providers/index.js +22 -0
- package/dist/cloud-providers/provider.js +386 -0
- package/dist/components/bottom-widget.js +215 -0
- package/dist/components/common/action-panel.js +134 -0
- package/dist/components/common/animation-control/animation-control.js +126 -0
- package/dist/components/common/animation-control/animation-controller.js +273 -0
- package/dist/components/common/animation-control/animation-speed-slider.js +101 -0
- package/dist/components/common/animation-control/floating-time-display.js +157 -0
- package/dist/components/common/animation-control/playback-controls.js +278 -0
- package/dist/components/common/animation-control/speed-control.js +68 -0
- package/dist/components/common/checkbox.js +155 -0
- package/dist/components/common/color-legend.js +249 -0
- package/dist/components/common/data-table/button.js +46 -0
- package/dist/components/common/data-table/canvas.js +32 -0
- package/dist/components/common/data-table/cell-size.js +174 -0
- package/dist/components/common/data-table/grid.js +84 -0
- package/dist/components/common/data-table/index.js +514 -0
- package/dist/components/common/data-table/option-dropdown.js +103 -0
- package/dist/components/common/dataset-label.js +36 -0
- package/dist/components/common/error-boundary.js +83 -0
- package/dist/components/common/field-selector.js +282 -0
- package/dist/components/common/field-token.js +42 -0
- package/dist/components/common/file-uploader/file-drop.js +227 -0
- package/dist/components/common/file-uploader/file-upload-progress.js +102 -0
- package/dist/components/common/file-uploader/file-upload.js +304 -0
- package/dist/components/common/file-uploader/upload-button.js +111 -0
- package/dist/components/common/histogram-plot.js +102 -0
- package/dist/components/common/icons/add.js +64 -0
- package/dist/components/common/icons/anchor_window.js +62 -0
- package/dist/components/common/icons/arrow-down-alt.js +64 -0
- package/dist/components/common/icons/arrow-down-solid .js +64 -0
- package/dist/components/common/icons/arrow-down.js +64 -0
- package/dist/components/common/icons/arrow-left.js +67 -0
- package/dist/components/common/icons/arrow-right.js +64 -0
- package/dist/components/common/icons/arrow-up-alt.js +65 -0
- package/dist/components/common/icons/arrow-up-solid.js +64 -0
- package/dist/components/common/icons/arrow-up.js +64 -0
- package/dist/components/common/icons/base.js +110 -0
- package/dist/components/common/icons/bug.js +66 -0
- package/dist/components/common/icons/cancel.js +64 -0
- package/dist/components/common/icons/checkmark.js +71 -0
- package/dist/components/common/icons/chevron-right.js +69 -0
- package/dist/components/common/icons/clipboard.js +65 -0
- package/dist/components/common/icons/clock.js +66 -0
- package/dist/components/common/icons/close.js +69 -0
- package/dist/components/common/icons/code-alt.js +68 -0
- package/dist/components/common/icons/copy.js +70 -0
- package/dist/components/common/icons/crosshairs.js +68 -0
- package/dist/components/common/icons/cube-3d.js +68 -0
- package/dist/components/common/icons/cursor-click.js +68 -0
- package/dist/components/common/icons/data-table.js +65 -0
- package/dist/components/common/icons/db.js +65 -0
- package/dist/components/common/icons/delete.js +65 -0
- package/dist/components/common/icons/docs.js +80 -0
- package/dist/components/common/icons/drag-n-drop.js +66 -0
- package/dist/components/common/icons/draw-polygon.js +87 -0
- package/dist/components/common/icons/email.js +68 -0
- package/dist/components/common/icons/expand.js +66 -0
- package/dist/components/common/icons/eye-seen.js +66 -0
- package/dist/components/common/icons/eye-unseen.js +66 -0
- package/dist/components/common/icons/file-type.js +45 -0
- package/dist/components/common/icons/file.js +64 -0
- package/dist/components/common/icons/files.js +66 -0
- package/dist/components/common/icons/filter-funnel.js +64 -0
- package/dist/components/common/icons/free-window.js +62 -0
- package/dist/components/common/icons/gear.js +66 -0
- package/dist/components/common/icons/hash.js +64 -0
- package/dist/components/common/icons/histogram.js +64 -0
- package/dist/components/common/icons/index.js +612 -0
- package/dist/components/common/icons/info.js +78 -0
- package/dist/components/common/icons/layers.js +64 -0
- package/dist/components/common/icons/left-arrow.js +68 -0
- package/dist/components/common/icons/legend.js +64 -0
- package/dist/components/common/icons/line-chart.js +63 -0
- package/dist/components/common/icons/login.js +66 -0
- package/dist/components/common/icons/logout.js +65 -0
- package/dist/components/common/icons/map-icon.js +73 -0
- package/dist/components/common/icons/map.js +73 -0
- package/dist/components/common/icons/messages.js +64 -0
- package/dist/components/common/icons/minus.js +64 -0
- package/dist/components/common/icons/pause.js +64 -0
- package/dist/components/common/icons/picture.js +66 -0
- package/dist/components/common/icons/pin.js +64 -0
- package/dist/components/common/icons/play.js +64 -0
- package/dist/components/common/icons/polygon.js +89 -0
- package/dist/components/common/icons/rectangle.js +90 -0
- package/dist/components/common/icons/reduce.js +67 -0
- package/dist/components/common/icons/reset.js +64 -0
- package/dist/components/common/icons/rocket.js +64 -0
- package/dist/components/common/icons/save.js +66 -0
- package/dist/components/common/icons/save2.js +70 -0
- package/dist/components/common/icons/search.js +66 -0
- package/dist/components/common/icons/settings.js +66 -0
- package/dist/components/common/icons/share.js +64 -0
- package/dist/components/common/icons/split.js +92 -0
- package/dist/components/common/icons/square-select.js +66 -0
- package/dist/components/common/icons/swap-horizontal.js +68 -0
- package/dist/components/common/icons/table.js +63 -0
- package/dist/components/common/icons/trash.js +66 -0
- package/dist/components/common/icons/upload.js +65 -0
- package/dist/components/common/icons/vert-dots.js +102 -0
- package/dist/components/common/icons/vert-three-dots.js +77 -0
- package/dist/components/common/icons/warning.js +79 -0
- package/dist/components/common/image-preview.js +73 -0
- package/dist/components/common/info-helper.js +84 -0
- package/dist/components/common/item-selector/accessor.js +56 -0
- package/dist/components/common/item-selector/chickleted-input.js +118 -0
- package/dist/components/common/item-selector/dropdown-list.js +316 -0
- package/dist/components/common/item-selector/item-selector-submenu.js +99 -0
- package/dist/components/common/item-selector/item-selector.js +363 -0
- package/dist/components/common/item-selector/typeahead.js +496 -0
- package/dist/components/common/line-chart.js +125 -0
- package/dist/components/common/loading-spinner.js +58 -0
- package/dist/components/common/logo.js +92 -0
- package/dist/components/common/map-layer-selector.js +50 -0
- package/dist/components/common/modal.js +204 -0
- package/dist/components/common/portaled.js +317 -0
- package/dist/components/common/progress-bar.js +56 -0
- package/dist/components/common/range-brush.js +319 -0
- package/dist/components/common/range-plot.js +148 -0
- package/dist/components/common/range-slider.js +346 -0
- package/dist/components/common/slider/mouse-event.js +136 -0
- package/dist/components/common/slider/slider-bar-handle.js +122 -0
- package/dist/components/common/slider/slider-handle.js +167 -0
- package/dist/components/common/slider/slider.js +268 -0
- package/dist/components/common/styled-components.js +395 -0
- package/dist/components/common/switch.js +47 -0
- package/dist/components/common/time-range-slider-time-title.js +74 -0
- package/dist/components/common/time-range-slider.js +131 -0
- package/dist/components/common/time-slider-marker.js +141 -0
- package/dist/components/common/toolbar-item.js +67 -0
- package/dist/components/common/toolbar.js +33 -0
- package/dist/components/common/vertical-toolbar.js +22 -0
- package/dist/components/container.js +217 -0
- package/dist/components/context.js +42 -0
- package/dist/components/editor/constants.js +47 -0
- package/dist/components/editor/editor.js +274 -0
- package/dist/components/editor/feature-action-panel.js +154 -0
- package/dist/components/editor/feature-styles.js +72 -0
- package/dist/components/editor/handle-style.js +80 -0
- package/dist/components/filters/components.js +20 -0
- package/dist/components/filters/filter-panels/filter-panel-with-field-select.js +110 -0
- package/dist/components/filters/filter-panels/multi-select-filter-panel.js +80 -0
- package/dist/components/filters/filter-panels/new-filter-panel.js +101 -0
- package/dist/components/filters/filter-panels/polygon-filter-panel.js +102 -0
- package/dist/components/filters/filter-panels/range-filter-panel.js +80 -0
- package/dist/components/filters/filter-panels/single-select-filter-panel.js +80 -0
- package/dist/components/filters/filter-panels/time-range-filter-panel.js +92 -0
- package/dist/components/filters/index.js +48 -0
- package/dist/components/filters/multi-select-filter.js +54 -0
- package/dist/components/filters/polygon-filter.js +96 -0
- package/dist/components/filters/range-filter.js +53 -0
- package/dist/components/filters/single-select-filter.js +63 -0
- package/dist/components/filters/time-range-filter.js +86 -0
- package/dist/components/filters/time-widget.js +173 -0
- package/dist/components/geocoder/geocoder.js +315 -0
- package/dist/components/geocoder-panel.js +224 -0
- package/dist/components/index.js +1485 -0
- package/dist/components/injector.js +178 -0
- package/dist/components/kepler-gl.js +563 -0
- package/dist/components/map/coordinate-info.js +68 -0
- package/dist/components/map/layer-hover-info.js +176 -0
- package/dist/components/map/layer-selector-panel.js +116 -0
- package/dist/components/map/locale-panel.js +113 -0
- package/dist/components/map/map-control-panel.js +79 -0
- package/dist/components/map/map-control-toolbar.js +25 -0
- package/dist/components/map/map-control-tooltip.js +55 -0
- package/dist/components/map/map-control.js +80 -0
- package/dist/components/map/map-draw-panel.js +142 -0
- package/dist/components/map/map-legend-panel.js +124 -0
- package/dist/components/map/map-legend.js +244 -0
- package/dist/components/map/map-popover.js +204 -0
- package/dist/components/map/split-map-button.js +98 -0
- package/dist/components/map/toggle-3d-button.js +86 -0
- package/dist/components/map-container.js +562 -0
- package/dist/components/maps-layout.js +58 -0
- package/dist/components/modal-container.js +536 -0
- package/dist/components/modals/add-map-style-modal.js +288 -0
- package/dist/components/modals/cloud-tile.js +124 -0
- package/dist/components/modals/data-table-modal.js +249 -0
- package/dist/components/modals/delete-data-modal.js +54 -0
- package/dist/components/modals/error-display.js +51 -0
- package/dist/components/modals/export-data-modal.js +227 -0
- package/dist/components/modals/export-image-modal.js +136 -0
- package/dist/components/modals/export-map-modal/components.js +51 -0
- package/dist/components/modals/export-map-modal/export-html-map.js +141 -0
- package/dist/components/modals/export-map-modal/export-json-map.js +87 -0
- package/dist/components/modals/export-map-modal/export-map-modal.js +133 -0
- package/dist/components/modals/image-modal-container.js +90 -0
- package/dist/components/modals/load-data-modal.js +97 -0
- package/dist/components/modals/load-storage-map.js +288 -0
- package/dist/components/modals/loading-dialog.js +48 -0
- package/dist/components/modals/modal-dialog.js +37 -0
- package/dist/components/modals/modal-tabs.js +99 -0
- package/dist/components/modals/overwrite-map-modal.js +80 -0
- package/dist/components/modals/provider-modal-container.js +84 -0
- package/dist/components/modals/save-map-modal.js +207 -0
- package/dist/components/modals/share-map-modal.js +202 -0
- package/dist/components/modals/status-panel.js +83 -0
- package/dist/components/modals/storage-map-viewer.js +135 -0
- package/dist/components/notification-panel/notification-item.js +164 -0
- package/dist/components/notification-panel.js +87 -0
- package/dist/components/performance.js +134 -0
- package/dist/components/plot-container.js +275 -0
- package/dist/components/side-panel/cloud-storage-dropdown.js +63 -0
- package/dist/components/side-panel/common/dataset-info.js +43 -0
- package/dist/components/side-panel/common/dataset-tag.js +42 -0
- package/dist/components/side-panel/common/dataset-title.js +170 -0
- package/dist/components/side-panel/common/source-data-catalog.js +60 -0
- package/dist/components/side-panel/common/source-data-selector.js +120 -0
- package/dist/components/side-panel/custom-panel.js +60 -0
- package/dist/components/side-panel/filter-manager.js +132 -0
- package/dist/components/side-panel/filter-panel/filter-panel-header.js +70 -0
- package/dist/components/side-panel/filter-panel/filter-panel.js +145 -0
- package/dist/components/side-panel/interaction-manager.js +58 -0
- package/dist/components/side-panel/interaction-panel/brush-config.js +54 -0
- package/dist/components/side-panel/interaction-panel/interaction-panel.js +168 -0
- package/dist/components/side-panel/interaction-panel/tooltip-config/tooltip-chicklet.js +250 -0
- package/dist/components/side-panel/interaction-panel/tooltip-config.js +163 -0
- package/dist/components/side-panel/layer-manager.js +321 -0
- package/dist/components/side-panel/layer-panel/color-dimension-scale-selector.js +45 -0
- package/dist/components/side-panel/layer-panel/color-palette.js +83 -0
- package/dist/components/side-panel/layer-panel/color-range-selector.js +370 -0
- package/dist/components/side-panel/layer-panel/color-selector.js +226 -0
- package/dist/components/side-panel/layer-panel/column-selector.js +65 -0
- package/dist/components/side-panel/layer-panel/custom-markers-config-group.js +40 -0
- package/dist/components/side-panel/layer-panel/custom-palette.js +318 -0
- package/dist/components/side-panel/layer-panel/custom-picker.js +128 -0
- package/dist/components/side-panel/layer-panel/dimension-scale-selector.js +61 -0
- package/dist/components/side-panel/layer-panel/layer-aggregation-resolution.js +26 -0
- package/dist/components/side-panel/layer-panel/layer-column-config.js +93 -0
- package/dist/components/side-panel/layer-panel/layer-config-group.js +245 -0
- package/dist/components/side-panel/layer-panel/layer-configurator.js +977 -0
- package/dist/components/side-panel/layer-panel/layer-panel-header.js +222 -0
- package/dist/components/side-panel/layer-panel/layer-panel.js +201 -0
- package/dist/components/side-panel/layer-panel/layer-type-dropdown-list.js +89 -0
- package/dist/components/side-panel/layer-panel/layer-type-list-item.js +71 -0
- package/dist/components/side-panel/layer-panel/layer-type-selector.js +96 -0
- package/dist/components/side-panel/layer-panel/layer-visibility-by-zoom.js +111 -0
- package/dist/components/side-panel/layer-panel/single-color-palette.js +109 -0
- package/dist/components/side-panel/layer-panel/text-label-panel.js +175 -0
- package/dist/components/side-panel/layer-panel/vis-config-by-field-selector.js +174 -0
- package/dist/components/side-panel/layer-panel/vis-config-slider.js +90 -0
- package/dist/components/side-panel/layer-panel/vis-config-switch.js +84 -0
- package/dist/components/side-panel/map-manager.js +155 -0
- package/dist/components/side-panel/map-style-panel/map-layer-selector.js +106 -0
- package/dist/components/side-panel/map-style-panel/map-style-selector.js +78 -0
- package/dist/components/side-panel/panel-dropdown.js +86 -0
- package/dist/components/side-panel/panel-header-action.js +121 -0
- package/dist/components/side-panel/panel-header.js +351 -0
- package/dist/components/side-panel/panel-tab.js +68 -0
- package/dist/components/side-panel/panel-title.js +28 -0
- package/dist/components/side-panel/panel-toggle.js +69 -0
- package/dist/components/side-panel/side-bar.js +164 -0
- package/dist/components/side-panel.js +242 -0
- package/dist/connect/keplergl-connect.js +68 -0
- package/dist/connect/with-local-selector.js +110 -0
- package/dist/constants/action-types.js +180 -0
- package/dist/constants/color-palette.js +547 -0
- package/dist/constants/color-ranges.js +70 -0
- package/dist/constants/custom-color-ranges.js +415 -0
- package/dist/constants/default-settings.js +902 -0
- package/dist/constants/index.js +370 -0
- package/dist/constants/keyevent.js +47 -0
- package/dist/constants/tooltip.js +205 -0
- package/dist/constants/user-feedbacks.js +33 -0
- package/dist/constants/user-guides.js +44 -0
- package/dist/deckgl-layers/3d-building-layer/3d-building-layer.js +88 -0
- package/dist/deckgl-layers/3d-building-layer/3d-building-utils.js +214 -0
- package/dist/deckgl-layers/cluster-layer/cluster-layer.js +334 -0
- package/dist/deckgl-layers/column-layer/enhanced-column-layer.js +78 -0
- package/dist/deckgl-layers/grid-layer/enhanced-cpu-grid-layer.js +96 -0
- package/dist/deckgl-layers/hexagon-layer/enhanced-hexagon-layer.js +96 -0
- package/dist/deckgl-layers/layer-utils/cluster-utils.js +119 -0
- package/dist/deckgl-layers/layer-utils/cpu-aggregator.js +643 -0
- package/dist/deckgl-layers/layer-utils/shader-utils.js +50 -0
- package/dist/deckgl-layers/line-layer/line-layer.js +111 -0
- package/dist/deckgl-layers/svg-icon-layer/scatterplot-icon-layer.js +78 -0
- package/dist/deckgl-layers/svg-icon-layer/svg-icon-layer.js +120 -0
- package/dist/index.js +155 -0
- package/dist/layers/aggregation-layer.js +416 -0
- package/dist/layers/arc-layer/arc-layer-icon.js +77 -0
- package/dist/layers/arc-layer/arc-layer.js +275 -0
- package/dist/layers/base-layer.js +1688 -0
- package/dist/layers/cluster-layer/cluster-layer-icon.js +80 -0
- package/dist/layers/cluster-layer/cluster-layer.js +151 -0
- package/dist/layers/default-layer-icon.js +87 -0
- package/dist/layers/geojson-layer/geojson-layer-icon.js +91 -0
- package/dist/layers/geojson-layer/geojson-layer.js +446 -0
- package/dist/layers/geojson-layer/geojson-utils.js +183 -0
- package/dist/layers/grid-layer/grid-layer-icon.js +136 -0
- package/dist/layers/grid-layer/grid-layer.js +115 -0
- package/dist/layers/grid-layer/grid-utils.js +62 -0
- package/dist/layers/h3-hexagon-layer/h3-hexagon-layer-icon.js +71 -0
- package/dist/layers/h3-hexagon-layer/h3-hexagon-layer.js +346 -0
- package/dist/layers/h3-hexagon-layer/h3-utils.js +97 -0
- package/dist/layers/heatmap-layer/heatmap-layer-icon.js +88 -0
- package/dist/layers/heatmap-layer/heatmap-layer.js +269 -0
- package/dist/layers/hexagon-layer/hexagon-layer-icon.js +100 -0
- package/dist/layers/hexagon-layer/hexagon-layer.js +120 -0
- package/dist/layers/hexagon-layer/hexagon-utils.js +74 -0
- package/dist/layers/icon-layer/icon-info-modal.js +117 -0
- package/dist/layers/icon-layer/icon-layer-icon.js +73 -0
- package/dist/layers/icon-layer/icon-layer.js +392 -0
- package/dist/layers/index.js +97 -0
- package/dist/layers/layer-factory.js +499 -0
- package/dist/layers/layer-text-label.js +72 -0
- package/dist/layers/layer-update.js +85 -0
- package/dist/layers/line-layer/line-layer-icon.js +79 -0
- package/dist/layers/line-layer/line-layer.js +209 -0
- package/dist/layers/mapbox-utils.js +204 -0
- package/dist/layers/mapboxgl-layer.js +210 -0
- package/dist/layers/point-layer/point-layer-icon.js +94 -0
- package/dist/layers/point-layer/point-layer.js +475 -0
- package/dist/layers/s2-geometry-layer/s2-geometry-layer.js +334 -0
- package/dist/layers/s2-geometry-layer/s2-layer-icon.js +70 -0
- package/dist/layers/s2-geometry-layer/s2-utils.js +51 -0
- package/dist/layers/scenegraph-layer/scenegraph-info-modal.js +48 -0
- package/dist/layers/scenegraph-layer/scenegraph-layer-icon.js +151 -0
- package/dist/layers/scenegraph-layer/scenegraph-layer.js +250 -0
- package/dist/layers/trip-layer/trip-info-modal.js +54 -0
- package/dist/layers/trip-layer/trip-layer-icon.js +89 -0
- package/dist/layers/trip-layer/trip-layer.js +403 -0
- package/dist/layers/trip-layer/trip-utils.js +204 -0
- package/dist/layers/types.js +47 -0
- package/dist/localization/en.js +480 -0
- package/dist/localization/formatted-message.js +45 -0
- package/dist/localization/index.js +60 -0
- package/dist/localization/locales.js +64 -0
- package/dist/middleware/index.js +47 -0
- package/dist/processors/data-processor.js +784 -0
- package/dist/processors/file-handler.js +432 -0
- package/dist/processors/index.js +106 -0
- package/dist/reducers/combined-updaters.js +195 -0
- package/dist/reducers/composer-helpers.js +110 -0
- package/dist/reducers/composers.js +27 -0
- package/dist/reducers/core.js +156 -0
- package/dist/reducers/index.js +139 -0
- package/dist/reducers/map-state-updaters.js +239 -0
- package/dist/reducers/map-state.js +47 -0
- package/dist/reducers/map-style-updaters.js +531 -0
- package/dist/reducers/map-style.js +46 -0
- package/dist/reducers/provider-state-updaters.js +541 -0
- package/dist/reducers/provider-state.js +46 -0
- package/dist/reducers/root.js +218 -0
- package/dist/reducers/ui-state-updaters.js +855 -0
- package/dist/reducers/ui-state.js +47 -0
- package/dist/reducers/vis-state-merger.js +615 -0
- package/dist/reducers/vis-state-selectors.js +52 -0
- package/dist/reducers/vis-state-updaters.js +2433 -0
- package/dist/reducers/vis-state.js +46 -0
- package/dist/schemas/dataset-schema.js +189 -0
- package/dist/schemas/index.js +132 -0
- package/dist/schemas/map-state-schema.js +49 -0
- package/dist/schemas/map-style-schema.js +122 -0
- package/dist/schemas/schema-manager.js +262 -0
- package/dist/schemas/schema-utils.js +62 -0
- package/dist/schemas/schema.js +114 -0
- package/dist/schemas/versions.js +38 -0
- package/dist/schemas/vis-state-schema.js +1071 -0
- package/dist/styles/base.js +1570 -0
- package/dist/styles/index.js +32 -0
- package/dist/styles/media-breakpoints.js +39 -0
- package/dist/tasks/tasks.js +122 -0
- package/dist/templates/export-map-html.js +45 -0
- package/dist/utils/aggregate-utils.js +75 -0
- package/dist/utils/color-utils.js +135 -0
- package/dist/utils/data-scale-utils.js +84 -0
- package/dist/utils/data-utils.js +491 -0
- package/dist/utils/dataset-utils.js +254 -0
- package/dist/utils/dom-to-image.js +557 -0
- package/dist/utils/dom-utils.js +425 -0
- package/dist/utils/export-utils.js +297 -0
- package/dist/utils/filter-utils.js +1286 -0
- package/dist/utils/gl-utils.js +35 -0
- package/dist/utils/gpu-filter-utils.js +261 -0
- package/dist/utils/index.js +226 -0
- package/dist/utils/interaction-utils.js +201 -0
- package/dist/utils/layer-utils.js +205 -0
- package/dist/utils/locale-utils.js +54 -0
- package/dist/utils/map-info-utils.js +32 -0
- package/dist/utils/map-style-utils/mapbox-gl-style-editor.js +212 -0
- package/dist/utils/map-style-utils/mapbox-utils.js +35 -0
- package/dist/utils/mapbox-utils.js +39 -0
- package/dist/utils/notifications-utils.js +89 -0
- package/dist/utils/observe-dimensions.js +147 -0
- package/dist/utils/projection-utils.js +83 -0
- package/dist/utils/searcher-utils.js +45 -0
- package/dist/utils/split-map-utils.js +108 -0
- package/dist/utils/table-utils/data-container-utils.js +69 -0
- package/dist/utils/table-utils/data-row.js +82 -0
- package/dist/utils/table-utils/index.js +20 -0
- package/dist/utils/table-utils/indexed-data-container.js +241 -0
- package/dist/utils/table-utils/kepler-table.js +544 -0
- package/dist/utils/table-utils/row-data-container.js +242 -0
- package/dist/utils/utils.js +234 -0
- package/layers.js +21 -0
- package/localization.js +21 -0
- package/middleware.js +21 -0
- package/package.json +281 -0
- package/processors.js +21 -0
- package/reducers.js +21 -0
- package/schemas.js +21 -0
- package/src/actions/action-wrapper.js +183 -0
- package/src/actions/actions.d.ts +104 -0
- package/src/actions/actions.js +178 -0
- package/src/actions/identity-actions.d.ts +53 -0
- package/src/actions/identity-actions.js +83 -0
- package/src/actions/index.d.ts +23 -0
- package/src/actions/index.js +42 -0
- package/src/actions/map-state-actions.d.ts +46 -0
- package/src/actions/map-state-actions.js +90 -0
- package/src/actions/map-style-actions.d.ts +116 -0
- package/src/actions/map-style-actions.js +135 -0
- package/src/actions/provider-actions.d.ts +203 -0
- package/src/actions/provider-actions.js +94 -0
- package/src/actions/ui-state-actions.d.ts +200 -0
- package/src/actions/ui-state-actions.js +272 -0
- package/src/actions/vis-state-actions.d.ts +502 -0
- package/src/actions/vis-state-actions.js +919 -0
- package/src/cloud-providers/index.d.ts +53 -0
- package/src/cloud-providers/index.js +21 -0
- package/src/cloud-providers/provider.js +233 -0
- package/src/components/bottom-widget.d.ts +33 -0
- package/src/components/bottom-widget.js +235 -0
- package/src/components/common/action-panel.d.ts +24 -0
- package/src/components/common/action-panel.js +177 -0
- package/src/components/common/animation-control/animation-control.js +155 -0
- package/src/components/common/animation-control/animation-controller.js +224 -0
- package/src/components/common/animation-control/animation-speed-slider.js +79 -0
- package/src/components/common/animation-control/floating-time-display.js +192 -0
- package/src/components/common/animation-control/playback-controls.js +278 -0
- package/src/components/common/animation-control/speed-control.js +71 -0
- package/src/components/common/checkbox.js +128 -0
- package/src/components/common/color-legend.js +198 -0
- package/src/components/common/data-table/button.js +47 -0
- package/src/components/common/data-table/canvas.js +43 -0
- package/src/components/common/data-table/cell-size.js +180 -0
- package/src/components/common/data-table/grid.js +55 -0
- package/src/components/common/data-table/index.js +620 -0
- package/src/components/common/data-table/option-dropdown.js +110 -0
- package/src/components/common/dataset-label.js +40 -0
- package/src/components/common/error-boundary.js +43 -0
- package/src/components/common/field-selector.js +233 -0
- package/src/components/common/field-token.js +56 -0
- package/src/components/common/file-uploader/file-drop.d.ts +19 -0
- package/src/components/common/file-uploader/file-drop.js +196 -0
- package/src/components/common/file-uploader/file-upload-progress.d.ts +11 -0
- package/src/components/common/file-uploader/file-upload-progress.js +110 -0
- package/src/components/common/file-uploader/file-upload.d.ts +22 -0
- package/src/components/common/file-uploader/file-upload.js +301 -0
- package/src/components/common/file-uploader/upload-button.d.ts.wip +11 -0
- package/src/components/common/file-uploader/upload-button.js +83 -0
- package/src/components/common/histogram-plot.js +102 -0
- package/src/components/common/icons/add.js +43 -0
- package/src/components/common/icons/anchor_window.js +53 -0
- package/src/components/common/icons/arrow-down-alt.js +43 -0
- package/src/components/common/icons/arrow-down-solid .js +43 -0
- package/src/components/common/icons/arrow-down.js +46 -0
- package/src/components/common/icons/arrow-left.js +48 -0
- package/src/components/common/icons/arrow-right.js +46 -0
- package/src/components/common/icons/arrow-up-alt.js +46 -0
- package/src/components/common/icons/arrow-up-solid.js +43 -0
- package/src/components/common/icons/arrow-up.js +46 -0
- package/src/components/common/icons/base.js +90 -0
- package/src/components/common/icons/bug.js +46 -0
- package/src/components/common/icons/cancel.js +43 -0
- package/src/components/common/icons/checkmark.js +45 -0
- package/src/components/common/icons/chevron-right.js +47 -0
- package/src/components/common/icons/clipboard.js +46 -0
- package/src/components/common/icons/clock.js +44 -0
- package/src/components/common/icons/close.js +49 -0
- package/src/components/common/icons/code-alt.js +43 -0
- package/src/components/common/icons/copy.js +44 -0
- package/src/components/common/icons/crosshairs.js +43 -0
- package/src/components/common/icons/cube-3d.js +45 -0
- package/src/components/common/icons/cursor-click.js +49 -0
- package/src/components/common/icons/data-table.js +45 -0
- package/src/components/common/icons/db.js +45 -0
- package/src/components/common/icons/delete.js +44 -0
- package/src/components/common/icons/docs.js +46 -0
- package/src/components/common/icons/drag-n-drop.js +44 -0
- package/src/components/common/icons/draw-polygon.js +60 -0
- package/src/components/common/icons/email.js +45 -0
- package/src/components/common/icons/expand.js +45 -0
- package/src/components/common/icons/eye-seen.js +44 -0
- package/src/components/common/icons/eye-unseen.js +44 -0
- package/src/components/common/icons/file-type.js +57 -0
- package/src/components/common/icons/file.js +43 -0
- package/src/components/common/icons/files.js +42 -0
- package/src/components/common/icons/filter-funnel.js +43 -0
- package/src/components/common/icons/free-window.js +53 -0
- package/src/components/common/icons/gear.js +45 -0
- package/src/components/common/icons/hash.js +43 -0
- package/src/components/common/icons/histogram.js +47 -0
- package/src/components/common/icons/index.js +96 -0
- package/src/components/common/icons/info.js +54 -0
- package/src/components/common/icons/layers.js +43 -0
- package/src/components/common/icons/left-arrow.js +43 -0
- package/src/components/common/icons/legend.js +43 -0
- package/src/components/common/icons/line-chart.js +45 -0
- package/src/components/common/icons/login.js +46 -0
- package/src/components/common/icons/logout.js +43 -0
- package/src/components/common/icons/map-icon.js +69 -0
- package/src/components/common/icons/map.js +69 -0
- package/src/components/common/icons/messages.js +43 -0
- package/src/components/common/icons/minus.js +45 -0
- package/src/components/common/icons/pause.js +43 -0
- package/src/components/common/icons/picture.js +43 -0
- package/src/components/common/icons/pin.js +43 -0
- package/src/components/common/icons/play.js +43 -0
- package/src/components/common/icons/polygon.js +74 -0
- package/src/components/common/icons/rectangle.js +75 -0
- package/src/components/common/icons/reduce.js +48 -0
- package/src/components/common/icons/reset.js +43 -0
- package/src/components/common/icons/rocket.js +43 -0
- package/src/components/common/icons/save.js +44 -0
- package/src/components/common/icons/save2.js +47 -0
- package/src/components/common/icons/search.js +44 -0
- package/src/components/common/icons/settings.js +45 -0
- package/src/components/common/icons/share.js +43 -0
- package/src/components/common/icons/split.js +63 -0
- package/src/components/common/icons/square-select.js +44 -0
- package/src/components/common/icons/swap-horizontal.js +43 -0
- package/src/components/common/icons/table.js +46 -0
- package/src/components/common/icons/trash.js +51 -0
- package/src/components/common/icons/upload.js +44 -0
- package/src/components/common/icons/vert-dots.js +50 -0
- package/src/components/common/icons/vert-three-dots.js +45 -0
- package/src/components/common/icons/warning.js +46 -0
- package/src/components/common/image-preview.js +111 -0
- package/src/components/common/info-helper.js +84 -0
- package/src/components/common/item-selector/accessor.js +45 -0
- package/src/components/common/item-selector/chickleted-input.js +143 -0
- package/src/components/common/item-selector/dropdown-list.js +250 -0
- package/src/components/common/item-selector/item-selector-submenu.js +68 -0
- package/src/components/common/item-selector/item-selector.d.ts +34 -0
- package/src/components/common/item-selector/item-selector.js +360 -0
- package/src/components/common/item-selector/typeahead.js +507 -0
- package/src/components/common/line-chart.js +134 -0
- package/src/components/common/loading-spinner.js +64 -0
- package/src/components/common/logo.js +92 -0
- package/src/components/common/map-layer-selector.d.ts +10 -0
- package/src/components/common/map-layer-selector.js +54 -0
- package/src/components/common/modal.js +233 -0
- package/src/components/common/portaled.js +264 -0
- package/src/components/common/progress-bar.d.ts +13 -0
- package/src/components/common/progress-bar.js +49 -0
- package/src/components/common/range-brush.js +256 -0
- package/src/components/common/range-plot.js +139 -0
- package/src/components/common/range-slider.js +299 -0
- package/src/components/common/slider/mouse-event.js +97 -0
- package/src/components/common/slider/slider-bar-handle.js +97 -0
- package/src/components/common/slider/slider-handle.js +181 -0
- package/src/components/common/slider/slider.js +213 -0
- package/src/components/common/styled-components.js +657 -0
- package/src/components/common/switch.js +50 -0
- package/src/components/common/time-range-slider-time-title.js +76 -0
- package/src/components/common/time-range-slider.js +163 -0
- package/src/components/common/time-slider-marker.js +168 -0
- package/src/components/common/toolbar-item.d.ts +14 -0
- package/src/components/common/toolbar-item.js +83 -0
- package/src/components/common/toolbar.js +45 -0
- package/src/components/common/vertical-toolbar.js +35 -0
- package/src/components/container.js +173 -0
- package/src/components/context.d.ts +10 -0
- package/src/components/context.js +32 -0
- package/src/components/editor/constants.js +39 -0
- package/src/components/editor/editor.js +218 -0
- package/src/components/editor/feature-action-panel.js +143 -0
- package/src/components/editor/feature-styles.js +75 -0
- package/src/components/editor/handle-style.js +89 -0
- package/src/components/filters/components.js +28 -0
- package/src/components/filters/filter-panels/filter-panel-types.d.ts +28 -0
- package/src/components/filters/filter-panels/filter-panel-with-field-select.js +124 -0
- package/src/components/filters/filter-panels/multi-select-filter-panel.js +75 -0
- package/src/components/filters/filter-panels/new-filter-panel.js +99 -0
- package/src/components/filters/filter-panels/polygon-filter-panel.js +96 -0
- package/src/components/filters/filter-panels/range-filter-panel.js +75 -0
- package/src/components/filters/filter-panels/single-select-filter-panel.js +75 -0
- package/src/components/filters/filter-panels/time-range-filter-panel.js +95 -0
- package/src/components/filters/index.js +25 -0
- package/src/components/filters/multi-select-filter.js +36 -0
- package/src/components/filters/polygon-filter.d.ts +13 -0
- package/src/components/filters/polygon-filter.js +73 -0
- package/src/components/filters/range-filter.js +43 -0
- package/src/components/filters/single-select-filter.js +49 -0
- package/src/components/filters/time-range-filter.js +68 -0
- package/src/components/filters/time-widget.js +228 -0
- package/src/components/geocoder/geocoder.d.ts +33 -0
- package/src/components/geocoder/geocoder.js +272 -0
- package/src/components/geocoder-panel.js +191 -0
- package/src/components/index.js +247 -0
- package/src/components/injector.js +161 -0
- package/src/components/kepler-gl.d.ts +60 -0
- package/src/components/kepler-gl.js +525 -0
- package/src/components/map/coordinate-info.js +53 -0
- package/src/components/map/layer-hover-info.d.ts +12 -0
- package/src/components/map/layer-hover-info.js +185 -0
- package/src/components/map/layer-selector-panel.d.ts +16 -0
- package/src/components/map/layer-selector-panel.js +106 -0
- package/src/components/map/locale-panel.d.ts +12 -0
- package/src/components/map/locale-panel.js +91 -0
- package/src/components/map/map-control-panel.d.ts +11 -0
- package/src/components/map/map-control-panel.js +98 -0
- package/src/components/map/map-control-toolbar.js +33 -0
- package/src/components/map/map-control-tooltip.d.ts +8 -0
- package/src/components/map/map-control-tooltip.js +40 -0
- package/src/components/map/map-control.d.ts +37 -0
- package/src/components/map/map-control.js +100 -0
- package/src/components/map/map-draw-panel.d.ts +16 -0
- package/src/components/map/map-draw-panel.js +125 -0
- package/src/components/map/map-legend-panel.d.ts +20 -0
- package/src/components/map/map-legend-panel.js +100 -0
- package/src/components/map/map-legend.d.ts +58 -0
- package/src/components/map/map-legend.js +228 -0
- package/src/components/map/map-popover.d.ts +28 -0
- package/src/components/map/map-popover.js +250 -0
- package/src/components/map/split-map-button.d.ts +19 -0
- package/src/components/map/split-map-button.js +82 -0
- package/src/components/map/toggle-3d-button.d.ts +16 -0
- package/src/components/map/toggle-3d-button.js +75 -0
- package/src/components/map-container.d.ts +18 -0
- package/src/components/map-container.js +502 -0
- package/src/components/maps-layout.d.ts +5 -0
- package/src/components/maps-layout.js +40 -0
- package/src/components/modal-container.d.ts +38 -0
- package/src/components/modal-container.js +545 -0
- package/src/components/modals/add-map-style-modal.js +301 -0
- package/src/components/modals/cloud-tile.js +147 -0
- package/src/components/modals/data-table-modal.js +217 -0
- package/src/components/modals/delete-data-modal.js +48 -0
- package/src/components/modals/error-display.js +39 -0
- package/src/components/modals/export-data-modal.js +193 -0
- package/src/components/modals/export-image-modal.d.ts +21 -0
- package/src/components/modals/export-image-modal.js +144 -0
- package/src/components/modals/export-map-modal/components.js +42 -0
- package/src/components/modals/export-map-modal/export-html-map.d.ts +21 -0
- package/src/components/modals/export-map-modal/export-html-map.js +145 -0
- package/src/components/modals/export-map-modal/export-json-map.js +100 -0
- package/src/components/modals/export-map-modal/export-map-modal.js +114 -0
- package/src/components/modals/image-modal-container.d.ts +13 -0
- package/src/components/modals/image-modal-container.js +76 -0
- package/src/components/modals/load-data-modal.d.ts +30 -0
- package/src/components/modals/load-data-modal.js +94 -0
- package/src/components/modals/load-storage-map.js +381 -0
- package/src/components/modals/loading-dialog.js +69 -0
- package/src/components/modals/modal-dialog.js +25 -0
- package/src/components/modals/modal-tabs.js +126 -0
- package/src/components/modals/overwrite-map-modal.d.ts +18 -0
- package/src/components/modals/overwrite-map-modal.js +97 -0
- package/src/components/modals/provider-modal-container.d.ts +12 -0
- package/src/components/modals/provider-modal-container.js +60 -0
- package/src/components/modals/save-map-modal.d.ts +32 -0
- package/src/components/modals/save-map-modal.js +244 -0
- package/src/components/modals/share-map-modal.js +208 -0
- package/src/components/modals/status-panel.js +95 -0
- package/src/components/modals/storage-map-viewer.js +177 -0
- package/src/components/notification-panel/notification-item.js +132 -0
- package/src/components/notification-panel.js +72 -0
- package/src/components/performance.js +103 -0
- package/src/components/plot-container.js +228 -0
- package/src/components/side-panel/cloud-storage-dropdown.js +52 -0
- package/src/components/side-panel/common/dataset-info.js +45 -0
- package/src/components/side-panel/common/dataset-tag.js +55 -0
- package/src/components/side-panel/common/dataset-title.js +146 -0
- package/src/components/side-panel/common/source-data-catalog.js +61 -0
- package/src/components/side-panel/common/source-data-selector.js +79 -0
- package/src/components/side-panel/custom-panel.js +50 -0
- package/src/components/side-panel/filter-manager.js +105 -0
- package/src/components/side-panel/filter-panel/filter-panel-header.js +83 -0
- package/src/components/side-panel/filter-panel/filter-panel.js +126 -0
- package/src/components/side-panel/interaction-manager.js +46 -0
- package/src/components/side-panel/interaction-panel/brush-config.js +51 -0
- package/src/components/side-panel/interaction-panel/interaction-panel.js +115 -0
- package/src/components/side-panel/interaction-panel/tooltip-config/tooltip-chicklet.js +199 -0
- package/src/components/side-panel/interaction-panel/tooltip-config.js +190 -0
- package/src/components/side-panel/layer-manager.js +290 -0
- package/src/components/side-panel/layer-panel/color-dimension-scale-selector.js +33 -0
- package/src/components/side-panel/layer-panel/color-palette.js +90 -0
- package/src/components/side-panel/layer-panel/color-range-selector.js +322 -0
- package/src/components/side-panel/layer-panel/color-selector.js +193 -0
- package/src/components/side-panel/layer-panel/column-selector.js +70 -0
- package/src/components/side-panel/layer-panel/custom-markers-config-group.js +30 -0
- package/src/components/side-panel/layer-panel/custom-palette.js +296 -0
- package/src/components/side-panel/layer-panel/custom-picker.js +88 -0
- package/src/components/side-panel/layer-panel/dimension-scale-selector.js +48 -0
- package/src/components/side-panel/layer-panel/layer-aggregation-resolution.js +13 -0
- package/src/components/side-panel/layer-panel/layer-column-config.js +113 -0
- package/src/components/side-panel/layer-panel/layer-config-group.js +237 -0
- package/src/components/side-panel/layer-panel/layer-configurator.js +1317 -0
- package/src/components/side-panel/layer-panel/layer-panel-header.js +236 -0
- package/src/components/side-panel/layer-panel/layer-panel.js +171 -0
- package/src/components/side-panel/layer-panel/layer-type-dropdown-list.js +105 -0
- package/src/components/side-panel/layer-panel/layer-type-list-item.js +83 -0
- package/src/components/side-panel/layer-panel/layer-type-selector.js +89 -0
- package/src/components/side-panel/layer-panel/layer-visibility-by-zoom.js +123 -0
- package/src/components/side-panel/layer-panel/single-color-palette.js +98 -0
- package/src/components/side-panel/layer-panel/text-label-panel.js +179 -0
- package/src/components/side-panel/layer-panel/vis-config-by-field-selector.js +163 -0
- package/src/components/side-panel/layer-panel/vis-config-slider.js +82 -0
- package/src/components/side-panel/layer-panel/vis-config-switch.js +87 -0
- package/src/components/side-panel/map-manager.js +114 -0
- package/src/components/side-panel/map-style-panel/map-layer-selector.js +128 -0
- package/src/components/side-panel/map-style-panel/map-style-selector.js +111 -0
- package/src/components/side-panel/panel-dropdown.js +53 -0
- package/src/components/side-panel/panel-header-action.js +106 -0
- package/src/components/side-panel/panel-header.js +321 -0
- package/src/components/side-panel/panel-tab.js +62 -0
- package/src/components/side-panel/panel-title.js +32 -0
- package/src/components/side-panel/panel-toggle.js +70 -0
- package/src/components/side-panel/side-bar.js +136 -0
- package/src/components/side-panel.d.ts +33 -0
- package/src/components/side-panel.js +253 -0
- package/src/connect/keplergl-connect.js +47 -0
- package/src/connect/with-local-selector.d.ts +11 -0
- package/src/connect/with-local-selector.js +67 -0
- package/src/constants/action-types.d.ts +135 -0
- package/src/constants/action-types.js +184 -0
- package/src/constants/color-palette.js +553 -0
- package/src/constants/color-ranges.js +63 -0
- package/src/constants/custom-color-ranges.js +551 -0
- package/src/constants/default-settings.js +991 -0
- package/src/constants/index.js +80 -0
- package/src/constants/keyevent.js +36 -0
- package/src/constants/tooltip.js +198 -0
- package/src/constants/user-feedbacks.js +32 -0
- package/src/constants/user-guides.js +32 -0
- package/src/deckgl-layers/3d-building-layer/3d-building-layer.js +56 -0
- package/src/deckgl-layers/3d-building-layer/3d-building-utils.js +192 -0
- package/src/deckgl-layers/cluster-layer/cluster-layer.js +255 -0
- package/src/deckgl-layers/column-layer/enhanced-column-layer.js +63 -0
- package/src/deckgl-layers/grid-layer/enhanced-cpu-grid-layer.js +70 -0
- package/src/deckgl-layers/hexagon-layer/enhanced-hexagon-layer.js +70 -0
- package/src/deckgl-layers/layer-utils/cluster-utils.js +76 -0
- package/src/deckgl-layers/layer-utils/cpu-aggregator.js +583 -0
- package/src/deckgl-layers/layer-utils/shader-utils.js +41 -0
- package/src/deckgl-layers/line-layer/line-layer.js +122 -0
- package/src/deckgl-layers/svg-icon-layer/scatterplot-icon-layer.js +57 -0
- package/src/deckgl-layers/svg-icon-layer/svg-icon-layer.js +85 -0
- package/src/index.js +52 -0
- package/src/layers/aggregation-layer.js +356 -0
- package/src/layers/arc-layer/arc-layer-icon.js +67 -0
- package/src/layers/arc-layer/arc-layer.js +221 -0
- package/src/layers/base-layer.js +1439 -0
- package/src/layers/cluster-layer/cluster-layer-icon.js +71 -0
- package/src/layers/cluster-layer/cluster-layer.js +125 -0
- package/src/layers/default-layer-icon.js +50 -0
- package/src/layers/geojson-layer/geojson-layer-icon.js +68 -0
- package/src/layers/geojson-layer/geojson-layer.js +344 -0
- package/src/layers/geojson-layer/geojson-utils.js +179 -0
- package/src/layers/grid-layer/grid-layer-icon.js +53 -0
- package/src/layers/grid-layer/grid-layer.js +95 -0
- package/src/layers/grid-layer/grid-utils.js +71 -0
- package/src/layers/h3-hexagon-layer/h3-hexagon-layer-icon.js +48 -0
- package/src/layers/h3-hexagon-layer/h3-hexagon-layer.js +264 -0
- package/src/layers/h3-hexagon-layer/h3-utils.js +65 -0
- package/src/layers/heatmap-layer/heatmap-layer-icon.js +64 -0
- package/src/layers/heatmap-layer/heatmap-layer.js +226 -0
- package/src/layers/hexagon-layer/hexagon-layer-icon.js +74 -0
- package/src/layers/hexagon-layer/hexagon-layer.js +95 -0
- package/src/layers/hexagon-layer/hexagon-utils.js +63 -0
- package/src/layers/icon-layer/icon-info-modal.js +155 -0
- package/src/layers/icon-layer/icon-layer-icon.js +56 -0
- package/src/layers/icon-layer/icon-layer.js +324 -0
- package/src/layers/index.d.ts +126 -0
- package/src/layers/index.js +72 -0
- package/src/layers/layer-factory.d.ts +148 -0
- package/src/layers/layer-factory.js +480 -0
- package/src/layers/layer-text-label.js +62 -0
- package/src/layers/layer-update.js +71 -0
- package/src/layers/line-layer/line-layer-icon.js +69 -0
- package/src/layers/line-layer/line-layer.js +161 -0
- package/src/layers/mapbox-utils.js +195 -0
- package/src/layers/mapboxgl-layer.js +154 -0
- package/src/layers/point-layer/point-layer-icon.js +51 -0
- package/src/layers/point-layer/point-layer.js +414 -0
- package/src/layers/s2-geometry-layer/s2-geometry-layer.js +265 -0
- package/src/layers/s2-geometry-layer/s2-layer-icon.js +47 -0
- package/src/layers/s2-geometry-layer/s2-utils.js +36 -0
- package/src/layers/scenegraph-layer/scenegraph-info-modal.js +97 -0
- package/src/layers/scenegraph-layer/scenegraph-layer-icon.js +144 -0
- package/src/layers/scenegraph-layer/scenegraph-layer.js +182 -0
- package/src/layers/trip-layer/trip-info-modal.js +82 -0
- package/src/layers/trip-layer/trip-layer-icon.js +62 -0
- package/src/layers/trip-layer/trip-layer.js +295 -0
- package/src/layers/trip-layer/trip-utils.js +169 -0
- package/src/layers/types.js +37 -0
- package/src/localization/en.js +501 -0
- package/src/localization/formatted-message.js +33 -0
- package/src/localization/index.js +32 -0
- package/src/localization/locales.js +46 -0
- package/src/middleware/index.js +34 -0
- package/src/processors/data-processor.d.ts +57 -0
- package/src/processors/data-processor.js +684 -0
- package/src/processors/file-handler.d.ts +46 -0
- package/src/processors/file-handler.js +220 -0
- package/src/processors/index.js +44 -0
- package/src/reducers/combined-updaters.d.ts +26 -0
- package/src/reducers/combined-updaters.js +198 -0
- package/src/reducers/composer-helpers.d.ts +32 -0
- package/src/reducers/composer-helpers.js +70 -0
- package/src/reducers/composers.js +33 -0
- package/src/reducers/core.d.ts +25 -0
- package/src/reducers/core.js +97 -0
- package/src/reducers/index.d.ts +118 -0
- package/src/reducers/index.js +53 -0
- package/src/reducers/map-state-updaters.d.ts +64 -0
- package/src/reducers/map-state-updaters.js +224 -0
- package/src/reducers/map-state.js +47 -0
- package/src/reducers/map-style-updaters.d.ts +76 -0
- package/src/reducers/map-style-updaters.js +541 -0
- package/src/reducers/map-style.js +53 -0
- package/src/reducers/provider-state-updaters.d.ts +88 -0
- package/src/reducers/provider-state-updaters.js +428 -0
- package/src/reducers/provider-state.js +53 -0
- package/src/reducers/root.js +230 -0
- package/src/reducers/types.d.ts +10 -0
- package/src/reducers/ui-state-updaters.d.ts +198 -0
- package/src/reducers/ui-state-updaters.js +766 -0
- package/src/reducers/ui-state.js +73 -0
- package/src/reducers/vis-state-merger.d.ts +78 -0
- package/src/reducers/vis-state-merger.js +545 -0
- package/src/reducers/vis-state-selectors.js +35 -0
- package/src/reducers/vis-state-updaters.d.ts +534 -0
- package/src/reducers/vis-state-updaters.js +2137 -0
- package/src/reducers/vis-state.js +155 -0
- package/src/schemas/dataset-schema.js +141 -0
- package/src/schemas/index.d.ts +24 -0
- package/src/schemas/index.js +42 -0
- package/src/schemas/map-state-schema.js +52 -0
- package/src/schemas/map-style-schema.js +95 -0
- package/src/schemas/schema-manager.d.ts +229 -0
- package/src/schemas/schema-manager.js +228 -0
- package/src/schemas/schema-utils.js +54 -0
- package/src/schemas/schema.d.ts +47 -0
- package/src/schemas/schema.js +90 -0
- package/src/schemas/versions.d.ts +23 -0
- package/src/schemas/versions.js +28 -0
- package/src/schemas/vis-state-schema.js +731 -0
- package/src/styles/base.js +1620 -0
- package/src/styles/index.js +22 -0
- package/src/styles/media-breakpoints.js +47 -0
- package/src/tasks/tasks.js +92 -0
- package/src/templates/export-map-html.js +262 -0
- package/src/typedefs/README.md +3 -0
- package/src/typedefs/deck.gl__core.d.ts +64 -0
- package/src/typedefs/deck.gl__mesh-layers.d.ts +33 -0
- package/src/utils/aggregate-utils.js +71 -0
- package/src/utils/color-utils.js +106 -0
- package/src/utils/data-scale-utils.d.ts +26 -0
- package/src/utils/data-scale-utils.js +61 -0
- package/src/utils/data-utils.d.ts +45 -0
- package/src/utils/data-utils.js +428 -0
- package/src/utils/dataset-utils.d.ts +10 -0
- package/src/utils/dataset-utils.js +255 -0
- package/src/utils/dom-to-image.js +533 -0
- package/src/utils/dom-utils.js +354 -0
- package/src/utils/export-utils.js +247 -0
- package/src/utils/filter-utils.d.ts +192 -0
- package/src/utils/filter-utils.js +1114 -0
- package/src/utils/gl-utils.js +42 -0
- package/src/utils/gpu-filter-utils.d.ts +28 -0
- package/src/utils/gpu-filter-utils.js +253 -0
- package/src/utils/index.d.ts +5 -0
- package/src/utils/index.js +55 -0
- package/src/utils/interaction-utils.d.ts +36 -0
- package/src/utils/interaction-utils.js +185 -0
- package/src/utils/layer-utils.d.ts +78 -0
- package/src/utils/layer-utils.js +205 -0
- package/src/utils/locale-utils.js +59 -0
- package/src/utils/map-info-utils.js +29 -0
- package/src/utils/map-style-utils/mapbox-gl-style-editor.js +201 -0
- package/src/utils/map-style-utils/mapbox-utils.js +28 -0
- package/src/utils/mapbox-utils.js +27 -0
- package/src/utils/notifications-utils.js +83 -0
- package/src/utils/observe-dimensions.d.ts +18 -0
- package/src/utils/observe-dimensions.js +115 -0
- package/src/utils/projection-utils.js +72 -0
- package/src/utils/searcher-utils.js +37 -0
- package/src/utils/split-map-utils.js +104 -0
- package/src/utils/table-utils/UPGRADE-data-container.md +38 -0
- package/src/utils/table-utils/data-container-interface.d.ts +140 -0
- package/src/utils/table-utils/data-container-utils.d.ts +43 -0
- package/src/utils/table-utils/data-container-utils.js +61 -0
- package/src/utils/table-utils/data-row.d.ts +65 -0
- package/src/utils/table-utils/data-row.js +54 -0
- package/src/utils/table-utils/index.d.ts +1 -0
- package/src/utils/table-utils/index.js +21 -0
- package/src/utils/table-utils/indexed-data-container.d.ts +26 -0
- package/src/utils/table-utils/indexed-data-container.js +152 -0
- package/src/utils/table-utils/kepler-table.d.ts +114 -0
- package/src/utils/table-utils/kepler-table.js +486 -0
- package/src/utils/table-utils/row-data-container.d.ts +30 -0
- package/src/utils/table-utils/row-data-container.js +151 -0
- package/src/utils/utils.js +202 -0
- package/styles.js +21 -0
|
@@ -0,0 +1,2137 @@
|
|
|
1
|
+
// Copyright (c) 2022 Uber Technologies, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
// in the Software without restriction, including without limitation the rights
|
|
6
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
// furnished to do so, subject to the following conditions:
|
|
9
|
+
//
|
|
10
|
+
// The above copyright notice and this permission notice shall be included in
|
|
11
|
+
// all copies or substantial portions of the Software.
|
|
12
|
+
//
|
|
13
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
// THE SOFTWARE.
|
|
20
|
+
|
|
21
|
+
import {console as Console} from 'global/window';
|
|
22
|
+
import {disableStackCapturing, withTask} from 'react-palm/tasks';
|
|
23
|
+
import cloneDeep from 'lodash.clonedeep';
|
|
24
|
+
import uniq from 'lodash.uniq';
|
|
25
|
+
import get from 'lodash.get';
|
|
26
|
+
import xor from 'lodash.xor';
|
|
27
|
+
import copy from 'copy-to-clipboard';
|
|
28
|
+
import {parseFieldValue} from 'utils/data-utils';
|
|
29
|
+
// Tasks
|
|
30
|
+
import {LOAD_FILE_TASK, UNWRAP_TASK, PROCESS_FILE_DATA, DELAY_TASK} from 'tasks/tasks';
|
|
31
|
+
// Actions
|
|
32
|
+
import {
|
|
33
|
+
loadFilesErr,
|
|
34
|
+
loadFilesSuccess,
|
|
35
|
+
loadFileStepSuccess,
|
|
36
|
+
loadNextFile,
|
|
37
|
+
nextFileBatch
|
|
38
|
+
} from 'actions/vis-state-actions';
|
|
39
|
+
// Utils
|
|
40
|
+
import {findFieldsToShow, getDefaultInteraction} from 'utils/interaction-utils';
|
|
41
|
+
import {
|
|
42
|
+
applyFilterFieldName,
|
|
43
|
+
applyFiltersToDatasets,
|
|
44
|
+
featureToFilterValue,
|
|
45
|
+
FILTER_UPDATER_PROPS,
|
|
46
|
+
filterDatasetCPU,
|
|
47
|
+
generatePolygonFilter,
|
|
48
|
+
getDefaultFilter,
|
|
49
|
+
getDefaultFilterPlotType,
|
|
50
|
+
getFilterIdInFeature,
|
|
51
|
+
getFilterPlot,
|
|
52
|
+
getTimeWidgetTitleFormatter,
|
|
53
|
+
isInRange,
|
|
54
|
+
LIMITED_FILTER_EFFECT_PROPS,
|
|
55
|
+
updateFilterDataId
|
|
56
|
+
} from 'utils/filter-utils';
|
|
57
|
+
import {assignGpuChannel, setFilterGpuMode} from 'utils/gpu-filter-utils';
|
|
58
|
+
import {createNewDataEntry} from 'utils/dataset-utils';
|
|
59
|
+
import {sortDatasetByColumn} from 'utils/table-utils/kepler-table';
|
|
60
|
+
import {set, toArray, arrayInsert, generateHashId} from 'utils/utils';
|
|
61
|
+
|
|
62
|
+
import {calculateLayerData, findDefaultLayer} from 'utils/layer-utils';
|
|
63
|
+
|
|
64
|
+
import {
|
|
65
|
+
isValidMerger,
|
|
66
|
+
VIS_STATE_MERGERS,
|
|
67
|
+
validateLayerWithData,
|
|
68
|
+
createLayerFromConfig,
|
|
69
|
+
serializeLayer
|
|
70
|
+
} from './vis-state-merger';
|
|
71
|
+
|
|
72
|
+
import {
|
|
73
|
+
addNewLayersToSplitMap,
|
|
74
|
+
computeSplitMapLayers,
|
|
75
|
+
removeLayerFromSplitMaps
|
|
76
|
+
} from 'utils/split-map-utils';
|
|
77
|
+
|
|
78
|
+
import {Layer, LayerClasses, LAYER_ID_LENGTH} from 'layers';
|
|
79
|
+
import {DEFAULT_TEXT_LABEL, DEFAULT_SECONDARY_TEXT_LABEL} from 'layers/layer-factory';
|
|
80
|
+
import {EDITOR_MODES, SORT_ORDER, FILTER_TYPES} from 'constants/default-settings';
|
|
81
|
+
import {pick_, merge_, swap_} from './composer-helpers';
|
|
82
|
+
import {processFileContent} from 'actions/vis-state-actions';
|
|
83
|
+
|
|
84
|
+
import KeplerGLSchema from 'schemas';
|
|
85
|
+
|
|
86
|
+
// type imports
|
|
87
|
+
/** @typedef {import('./vis-state-updaters').Field} Field */
|
|
88
|
+
/** @typedef {import('./vis-state-updaters').Filter} Filter */
|
|
89
|
+
/** @typedef {import('./vis-state-updaters').KeplerTable} KeplerTable */
|
|
90
|
+
/** @typedef {import('./vis-state-updaters').VisState} VisState */
|
|
91
|
+
/** @typedef {import('./vis-state-updaters').Datasets} Datasets */
|
|
92
|
+
/** @typedef {import('./vis-state-updaters').AnimationConfig} AnimationConfig */
|
|
93
|
+
/** @typedef {import('./vis-state-updaters').Editor} Editor */
|
|
94
|
+
|
|
95
|
+
// react-palm
|
|
96
|
+
// disable capture exception for react-palm call to withTask
|
|
97
|
+
disableStackCapturing();
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Updaters for `visState` reducer. Can be used in your root reducer to directly modify kepler.gl's state.
|
|
101
|
+
* Read more about [Using updaters](../advanced-usage/using-updaters.md)
|
|
102
|
+
*
|
|
103
|
+
* @public
|
|
104
|
+
* @example
|
|
105
|
+
*
|
|
106
|
+
* import keplerGlReducer, {visStateUpdaters} from 'kepler.gl/reducers';
|
|
107
|
+
* // Root Reducer
|
|
108
|
+
* const reducers = combineReducers({
|
|
109
|
+
* keplerGl: keplerGlReducer,
|
|
110
|
+
* app: appReducer
|
|
111
|
+
* });
|
|
112
|
+
*
|
|
113
|
+
* const composedReducer = (state, action) => {
|
|
114
|
+
* switch (action.type) {
|
|
115
|
+
* case 'CLICK_BUTTON':
|
|
116
|
+
* return {
|
|
117
|
+
* ...state,
|
|
118
|
+
* keplerGl: {
|
|
119
|
+
* ...state.keplerGl,
|
|
120
|
+
* foo: {
|
|
121
|
+
* ...state.keplerGl.foo,
|
|
122
|
+
* visState: visStateUpdaters.enlargeFilterUpdater(
|
|
123
|
+
* state.keplerGl.foo.visState,
|
|
124
|
+
* {idx: 0}
|
|
125
|
+
* )
|
|
126
|
+
* }
|
|
127
|
+
* }
|
|
128
|
+
* };
|
|
129
|
+
* }
|
|
130
|
+
* return reducers(state, action);
|
|
131
|
+
* };
|
|
132
|
+
*
|
|
133
|
+
* export default composedReducer;
|
|
134
|
+
*/
|
|
135
|
+
/* eslint-disable no-unused-vars */
|
|
136
|
+
// @ts-ignore
|
|
137
|
+
const visStateUpdaters = null;
|
|
138
|
+
/* eslint-enable no-unused-vars */
|
|
139
|
+
|
|
140
|
+
/** @type {AnimationConfig} */
|
|
141
|
+
export const DEFAULT_ANIMATION_CONFIG = {
|
|
142
|
+
domain: null,
|
|
143
|
+
currentTime: null,
|
|
144
|
+
speed: 1,
|
|
145
|
+
isAnimating: false,
|
|
146
|
+
timeFormat: null,
|
|
147
|
+
timezone: null,
|
|
148
|
+
defaultTimeFormat: null
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/** @type {Editor} */
|
|
152
|
+
export const DEFAULT_EDITOR = {
|
|
153
|
+
mode: EDITOR_MODES.DRAW_POLYGON,
|
|
154
|
+
features: [],
|
|
155
|
+
selectedFeature: null,
|
|
156
|
+
visible: true
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Default initial `visState`
|
|
161
|
+
* @memberof visStateUpdaters
|
|
162
|
+
* @constant
|
|
163
|
+
* @type {VisState}
|
|
164
|
+
* @public
|
|
165
|
+
*/
|
|
166
|
+
export const INITIAL_VIS_STATE = {
|
|
167
|
+
// map info
|
|
168
|
+
mapInfo: {
|
|
169
|
+
title: '',
|
|
170
|
+
description: ''
|
|
171
|
+
},
|
|
172
|
+
// layers
|
|
173
|
+
layers: [],
|
|
174
|
+
layerData: [],
|
|
175
|
+
layerToBeMerged: [],
|
|
176
|
+
layerOrder: [],
|
|
177
|
+
|
|
178
|
+
// filters
|
|
179
|
+
filters: [],
|
|
180
|
+
filterToBeMerged: [],
|
|
181
|
+
|
|
182
|
+
// a collection of multiple dataset
|
|
183
|
+
datasets: {},
|
|
184
|
+
editingDataset: undefined,
|
|
185
|
+
|
|
186
|
+
interactionConfig: getDefaultInteraction(),
|
|
187
|
+
interactionToBeMerged: undefined,
|
|
188
|
+
|
|
189
|
+
layerBlending: 'normal',
|
|
190
|
+
hoverInfo: undefined,
|
|
191
|
+
clicked: undefined,
|
|
192
|
+
mousePos: {},
|
|
193
|
+
|
|
194
|
+
// this is used when user split maps
|
|
195
|
+
splitMaps: [
|
|
196
|
+
// this will contain a list of objects to
|
|
197
|
+
// describe the state of layer availability and visibility for each map
|
|
198
|
+
// [
|
|
199
|
+
// {
|
|
200
|
+
// layers: {layer_id: true | false}
|
|
201
|
+
// }
|
|
202
|
+
// ]
|
|
203
|
+
],
|
|
204
|
+
splitMapsToBeMerged: [],
|
|
205
|
+
|
|
206
|
+
// defaults layer classes
|
|
207
|
+
layerClasses: LayerClasses,
|
|
208
|
+
|
|
209
|
+
// default animation
|
|
210
|
+
// time in unix timestamp (milliseconds) (the number of seconds since the Unix Epoch)
|
|
211
|
+
animationConfig: DEFAULT_ANIMATION_CONFIG,
|
|
212
|
+
|
|
213
|
+
editor: DEFAULT_EDITOR,
|
|
214
|
+
|
|
215
|
+
fileLoading: false,
|
|
216
|
+
fileLoadingProgress: {},
|
|
217
|
+
|
|
218
|
+
loaders: [],
|
|
219
|
+
loadOptions: {},
|
|
220
|
+
|
|
221
|
+
// visStateMergers
|
|
222
|
+
mergers: VIS_STATE_MERGERS,
|
|
223
|
+
|
|
224
|
+
// kepler schemas
|
|
225
|
+
schema: KeplerGLSchema
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Update state with updated layer and layerData
|
|
230
|
+
* @type {typeof import('./vis-state-updaters').updateStateWithLayerAndData}
|
|
231
|
+
*
|
|
232
|
+
*/
|
|
233
|
+
export function updateStateWithLayerAndData(state, {layerData, layer, idx}) {
|
|
234
|
+
return {
|
|
235
|
+
...state,
|
|
236
|
+
layers: state.layers.map((lyr, i) => (i === idx ? layer : lyr)),
|
|
237
|
+
layerData: layerData
|
|
238
|
+
? state.layerData.map((d, i) => (i === idx ? layerData : d))
|
|
239
|
+
: state.layerData
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function updateStateOnLayerVisibilityChange(state, layer) {
|
|
244
|
+
let newState = state;
|
|
245
|
+
if (state.splitMaps.length) {
|
|
246
|
+
newState = {
|
|
247
|
+
...state,
|
|
248
|
+
splitMaps: layer.config.isVisible
|
|
249
|
+
? addNewLayersToSplitMap(state.splitMaps, layer)
|
|
250
|
+
: removeLayerFromSplitMaps(state.splitMaps, layer)
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (layer.config.animation.enabled) {
|
|
255
|
+
newState = updateAnimationDomain(state);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return newState;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Update layer base config: dataId, label, column, isVisible
|
|
263
|
+
* @memberof visStateUpdaters
|
|
264
|
+
* @type {typeof import('./vis-state-updaters').layerConfigChangeUpdater}
|
|
265
|
+
* @returns nextState
|
|
266
|
+
*/
|
|
267
|
+
export function layerConfigChangeUpdater(state, action) {
|
|
268
|
+
const {oldLayer} = action;
|
|
269
|
+
const idx = state.layers.findIndex(l => l.id === oldLayer.id);
|
|
270
|
+
const props = Object.keys(action.newConfig);
|
|
271
|
+
if (typeof action.newConfig.dataId === 'string') {
|
|
272
|
+
const {dataId, ...restConfig} = action.newConfig;
|
|
273
|
+
const stateWithDataId = layerDataIdChangeUpdater(state, {
|
|
274
|
+
oldLayer,
|
|
275
|
+
newConfig: {dataId}
|
|
276
|
+
});
|
|
277
|
+
const nextLayer = stateWithDataId.layers.find(l => l.id === oldLayer.id);
|
|
278
|
+
return nextLayer && Object.keys(restConfig).length
|
|
279
|
+
? layerConfigChangeUpdater(stateWithDataId, {oldLayer: nextLayer, newConfig: restConfig})
|
|
280
|
+
: stateWithDataId;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
let newLayer = oldLayer.updateLayerConfig(action.newConfig);
|
|
284
|
+
|
|
285
|
+
let layerData;
|
|
286
|
+
|
|
287
|
+
// let newLayer;
|
|
288
|
+
if (newLayer.shouldCalculateLayerData(props)) {
|
|
289
|
+
const oldLayerData = state.layerData[idx];
|
|
290
|
+
const updateLayerDataResult = calculateLayerData(newLayer, state, oldLayerData);
|
|
291
|
+
|
|
292
|
+
layerData = updateLayerDataResult.layerData;
|
|
293
|
+
newLayer = updateLayerDataResult.layer;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
let newState = state;
|
|
297
|
+
if ('isVisible' in action.newConfig) {
|
|
298
|
+
newState = updateStateOnLayerVisibilityChange(state, newLayer);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return updateStateWithLayerAndData(newState, {
|
|
302
|
+
layer: newLayer,
|
|
303
|
+
layerData,
|
|
304
|
+
idx
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function addOrRemoveTextLabels(newFields, textLabel) {
|
|
309
|
+
let newTextLabel = textLabel.slice();
|
|
310
|
+
|
|
311
|
+
const currentFields = textLabel.map(tl => tl.field && tl.field.name).filter(d => d);
|
|
312
|
+
|
|
313
|
+
const addFields = newFields.filter(f => !currentFields.includes(f.name));
|
|
314
|
+
const deleteFields = currentFields.filter(f => !newFields.find(fd => fd.name === f));
|
|
315
|
+
|
|
316
|
+
// delete
|
|
317
|
+
newTextLabel = newTextLabel.filter(tl => tl.field && !deleteFields.includes(tl.field.name));
|
|
318
|
+
|
|
319
|
+
// add
|
|
320
|
+
newTextLabel = newTextLabel.filter(tl => tl.field);
|
|
321
|
+
const defaultLabel = newTextLabel.length ? DEFAULT_SECONDARY_TEXT_LABEL : DEFAULT_TEXT_LABEL;
|
|
322
|
+
newTextLabel = [...newTextLabel, ...addFields.map(af => ({...defaultLabel, field: af}))];
|
|
323
|
+
|
|
324
|
+
// limit to 2 labels (overwrite 2nd label with 3rd)
|
|
325
|
+
if (newTextLabel.length > 2) {
|
|
326
|
+
newTextLabel = [newTextLabel[0], newTextLabel[2]];
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// default
|
|
330
|
+
newTextLabel = !newTextLabel.length ? [DEFAULT_TEXT_LABEL] : newTextLabel;
|
|
331
|
+
|
|
332
|
+
return newTextLabel;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function updateTextLabelPropAndValue(idx, prop, value, textLabel) {
|
|
336
|
+
if (!textLabel[idx].hasOwnProperty(prop)) {
|
|
337
|
+
return textLabel;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
let newTextLabel = textLabel.slice();
|
|
341
|
+
|
|
342
|
+
if (prop && (value || textLabel.length === 1)) {
|
|
343
|
+
newTextLabel = textLabel.map((tl, i) => (i === idx ? {...tl, [prop]: value} : tl));
|
|
344
|
+
} else if (prop === 'field' && value === null && textLabel.length > 1) {
|
|
345
|
+
// remove label when field value is set to null
|
|
346
|
+
newTextLabel.splice(idx, 1);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return newTextLabel;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Update layer base config: dataId, label, column, isVisible
|
|
354
|
+
* @memberof visStateUpdaters
|
|
355
|
+
* @type {typeof import('./vis-state-updaters').layerTextLabelChangeUpdater}
|
|
356
|
+
* @returns nextState
|
|
357
|
+
*/
|
|
358
|
+
export function layerTextLabelChangeUpdater(state, action) {
|
|
359
|
+
const {oldLayer, idx, prop, value} = action;
|
|
360
|
+
const {textLabel} = oldLayer.config;
|
|
361
|
+
|
|
362
|
+
let newTextLabel = textLabel.slice();
|
|
363
|
+
if (!textLabel[idx] && idx === textLabel.length) {
|
|
364
|
+
// if idx is set to length, add empty text label
|
|
365
|
+
newTextLabel = [...textLabel, idx === 0 ? DEFAULT_TEXT_LABEL : DEFAULT_SECONDARY_TEXT_LABEL];
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (idx === 'all' && prop === 'fields') {
|
|
369
|
+
newTextLabel = addOrRemoveTextLabels(value, textLabel);
|
|
370
|
+
} else {
|
|
371
|
+
newTextLabel = updateTextLabelPropAndValue(idx, prop, value, newTextLabel);
|
|
372
|
+
}
|
|
373
|
+
// update text label prop and value
|
|
374
|
+
return layerConfigChangeUpdater(state, {
|
|
375
|
+
oldLayer,
|
|
376
|
+
newConfig: {textLabel: newTextLabel}
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function validateExistingLayerWithData(dataset, layerClasses, layer) {
|
|
381
|
+
const loadedLayer = serializeLayer(layer);
|
|
382
|
+
return validateLayerWithData(dataset, loadedLayer, layerClasses, {
|
|
383
|
+
allowEmptyColumn: true
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Update layer config dataId
|
|
389
|
+
* @memberof visStateUpdaters
|
|
390
|
+
* @type {typeof import('./vis-state-updaters').layerDataIdChangeUpdater}
|
|
391
|
+
* @returns nextState
|
|
392
|
+
*/
|
|
393
|
+
export function layerDataIdChangeUpdater(state, action) {
|
|
394
|
+
const {oldLayer, newConfig} = action;
|
|
395
|
+
const {dataId} = newConfig;
|
|
396
|
+
|
|
397
|
+
if (!oldLayer || !state.datasets[dataId]) {
|
|
398
|
+
return state;
|
|
399
|
+
}
|
|
400
|
+
const idx = state.layers.findIndex(l => l.id === oldLayer.id);
|
|
401
|
+
|
|
402
|
+
let newLayer = oldLayer.updateLayerConfig({dataId});
|
|
403
|
+
// this may happen when a layer is new (type: null and no columns) but it's not ready to be saved
|
|
404
|
+
if (newLayer.isValidToSave()) {
|
|
405
|
+
const validated = validateExistingLayerWithData(
|
|
406
|
+
state.datasets[dataId],
|
|
407
|
+
state.layerClasses,
|
|
408
|
+
newLayer
|
|
409
|
+
);
|
|
410
|
+
// if cant validate it with data create a new one
|
|
411
|
+
if (!validated) {
|
|
412
|
+
newLayer = new state.layerClasses[oldLayer.type]({dataId, id: oldLayer.id});
|
|
413
|
+
} else {
|
|
414
|
+
newLayer = validated;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
newLayer = newLayer.updateLayerConfig({
|
|
419
|
+
isVisible: oldLayer.config.isVisible,
|
|
420
|
+
isConfigActive: true
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
newLayer.updateLayerDomain(state.datasets);
|
|
424
|
+
const {layerData, layer} = calculateLayerData(newLayer, state, undefined);
|
|
425
|
+
|
|
426
|
+
return updateStateWithLayerAndData(state, {layerData, layer, idx});
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Update layer type. Previews layer config will be copied if applicable.
|
|
431
|
+
* @memberof visStateUpdaters
|
|
432
|
+
* @type {typeof import('./vis-state-updaters').layerTypeChangeUpdater}
|
|
433
|
+
* @public
|
|
434
|
+
*/
|
|
435
|
+
export function layerTypeChangeUpdater(state, action) {
|
|
436
|
+
const {oldLayer, newType} = action;
|
|
437
|
+
if (!oldLayer) {
|
|
438
|
+
return state;
|
|
439
|
+
}
|
|
440
|
+
const oldId = oldLayer.id;
|
|
441
|
+
const idx = state.layers.findIndex(l => l.id === oldId);
|
|
442
|
+
|
|
443
|
+
if (!state.layerClasses[newType]) {
|
|
444
|
+
Console.error(`${newType} is not a valid layer type`);
|
|
445
|
+
return state;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// get a mint layer, with new id and type
|
|
449
|
+
// because deck.gl uses id to match between new and old layer.
|
|
450
|
+
// If type has changed but id is the same, it will break
|
|
451
|
+
const newLayer = new state.layerClasses[newType]();
|
|
452
|
+
|
|
453
|
+
newLayer.assignConfigToLayer(oldLayer.config, oldLayer.visConfigSettings);
|
|
454
|
+
|
|
455
|
+
newLayer.updateLayerDomain(state.datasets);
|
|
456
|
+
const {layerData, layer} = calculateLayerData(newLayer, state);
|
|
457
|
+
let newState = updateStateWithLayerAndData(state, {layerData, layer, idx});
|
|
458
|
+
|
|
459
|
+
if (layer.config.animation.enabled || oldLayer.config.animation.enabled) {
|
|
460
|
+
newState = updateAnimationDomain(newState);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// update splitMap layer id
|
|
464
|
+
if (state.splitMaps.length) {
|
|
465
|
+
newState = {
|
|
466
|
+
...newState,
|
|
467
|
+
splitMaps: newState.splitMaps.map(settings => {
|
|
468
|
+
const {[oldId]: oldLayerMap, ...otherLayers} = settings.layers;
|
|
469
|
+
return oldId in settings.layers
|
|
470
|
+
? {
|
|
471
|
+
...settings,
|
|
472
|
+
layers: {
|
|
473
|
+
...otherLayers,
|
|
474
|
+
[layer.id]: oldLayerMap
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
: settings;
|
|
478
|
+
})
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
return newState;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Update layer visual channel
|
|
487
|
+
* @memberof visStateUpdaters
|
|
488
|
+
* @type {typeof import('./vis-state-updaters').layerVisualChannelChangeUpdater}
|
|
489
|
+
* @returns {Object} nextState
|
|
490
|
+
* @public
|
|
491
|
+
*/
|
|
492
|
+
export function layerVisualChannelChangeUpdater(state, action) {
|
|
493
|
+
const {oldLayer, newConfig, channel} = action;
|
|
494
|
+
if (!oldLayer.config.dataId) {
|
|
495
|
+
return state;
|
|
496
|
+
}
|
|
497
|
+
const dataset = state.datasets[oldLayer.config.dataId];
|
|
498
|
+
|
|
499
|
+
const idx = state.layers.findIndex(l => l.id === oldLayer.id);
|
|
500
|
+
const newLayer = oldLayer.updateLayerConfig(newConfig);
|
|
501
|
+
|
|
502
|
+
newLayer.updateLayerVisualChannel(dataset, channel);
|
|
503
|
+
|
|
504
|
+
const oldLayerData = state.layerData[idx];
|
|
505
|
+
const {layerData, layer} = calculateLayerData(newLayer, state, oldLayerData);
|
|
506
|
+
|
|
507
|
+
return updateStateWithLayerAndData(state, {layerData, layer, idx});
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Update layer `visConfig`
|
|
512
|
+
* @memberof visStateUpdaters
|
|
513
|
+
* @type {typeof import('./vis-state-updaters').layerVisConfigChangeUpdater}
|
|
514
|
+
* @public
|
|
515
|
+
*/
|
|
516
|
+
export function layerVisConfigChangeUpdater(state, action) {
|
|
517
|
+
const {oldLayer} = action;
|
|
518
|
+
const idx = state.layers.findIndex(l => l.id === oldLayer.id);
|
|
519
|
+
const props = Object.keys(action.newVisConfig);
|
|
520
|
+
const newVisConfig = {
|
|
521
|
+
...oldLayer.config.visConfig,
|
|
522
|
+
...action.newVisConfig
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
const newLayer = oldLayer.updateLayerConfig({visConfig: newVisConfig});
|
|
526
|
+
|
|
527
|
+
if (newLayer.shouldCalculateLayerData(props)) {
|
|
528
|
+
const oldLayerData = state.layerData[idx];
|
|
529
|
+
const {layerData, layer} = calculateLayerData(newLayer, state, oldLayerData);
|
|
530
|
+
return updateStateWithLayerAndData(state, {layerData, layer, idx});
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return updateStateWithLayerAndData(state, {layer: newLayer, idx});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Update filter property
|
|
538
|
+
* @memberof visStateUpdaters
|
|
539
|
+
* @type {typeof import('./vis-state-updaters').setFilterAnimationTimeUpdater}
|
|
540
|
+
* @public
|
|
541
|
+
*/
|
|
542
|
+
export function setFilterAnimationTimeUpdater(state, action) {
|
|
543
|
+
return setFilterUpdater(state, action);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Update filter animation window
|
|
548
|
+
* @memberof visStateUpdaters
|
|
549
|
+
* @type {typeof import('./vis-state-updaters').setFilterAnimationWindowUpdater}
|
|
550
|
+
* @public
|
|
551
|
+
*/
|
|
552
|
+
export function setFilterAnimationWindowUpdater(state, {id, animationWindow}) {
|
|
553
|
+
return {
|
|
554
|
+
...state,
|
|
555
|
+
filters: state.filters.map(f =>
|
|
556
|
+
f.id === id
|
|
557
|
+
? {
|
|
558
|
+
...f,
|
|
559
|
+
animationWindow
|
|
560
|
+
}
|
|
561
|
+
: f
|
|
562
|
+
)
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Update filter property
|
|
567
|
+
* @memberof visStateUpdaters
|
|
568
|
+
* @type {typeof import('./vis-state-updaters').setFilterUpdater}
|
|
569
|
+
* @public
|
|
570
|
+
*/
|
|
571
|
+
export function setFilterUpdater(state, action) {
|
|
572
|
+
const {idx, prop, value, valueIndex = 0} = action;
|
|
573
|
+
const oldFilter = state.filters[idx];
|
|
574
|
+
|
|
575
|
+
if (!oldFilter) {
|
|
576
|
+
Console.error(`filters.${idx} is undefined`);
|
|
577
|
+
return state;
|
|
578
|
+
}
|
|
579
|
+
let newFilter = set([prop], value, oldFilter);
|
|
580
|
+
let newState = state;
|
|
581
|
+
|
|
582
|
+
const {dataId} = newFilter;
|
|
583
|
+
|
|
584
|
+
// Ensuring backward compatibility
|
|
585
|
+
let datasetIds = toArray(dataId);
|
|
586
|
+
|
|
587
|
+
switch (prop) {
|
|
588
|
+
// TODO: Next PR for UI if we update dataId, we need to consider two cases:
|
|
589
|
+
// 1. dataId is empty: create a default filter
|
|
590
|
+
// 2. Add a new dataset id
|
|
591
|
+
case FILTER_UPDATER_PROPS.dataId:
|
|
592
|
+
// if trying to update filter dataId. create an empty new filter
|
|
593
|
+
newFilter = updateFilterDataId(dataId);
|
|
594
|
+
break;
|
|
595
|
+
|
|
596
|
+
case FILTER_UPDATER_PROPS.name:
|
|
597
|
+
// we are supporting the current functionality
|
|
598
|
+
// TODO: Next PR for UI filter name will only update filter name but it won't have side effects
|
|
599
|
+
// we are gonna use pair of datasets and fieldIdx to update the filter
|
|
600
|
+
const datasetId = newFilter.dataId[valueIndex];
|
|
601
|
+
const {filter: updatedFilter, dataset: newDataset} = applyFilterFieldName(
|
|
602
|
+
newFilter,
|
|
603
|
+
state.datasets[datasetId],
|
|
604
|
+
value,
|
|
605
|
+
valueIndex,
|
|
606
|
+
{mergeDomain: false}
|
|
607
|
+
);
|
|
608
|
+
if (!updatedFilter) {
|
|
609
|
+
return state;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
newFilter = updatedFilter;
|
|
613
|
+
|
|
614
|
+
if (newFilter.gpu) {
|
|
615
|
+
newFilter = setFilterGpuMode(newFilter, state.filters);
|
|
616
|
+
newFilter = assignGpuChannel(newFilter, state.filters);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
newState = set(['datasets', datasetId], newDataset, state);
|
|
620
|
+
|
|
621
|
+
// only filter the current dataset
|
|
622
|
+
break;
|
|
623
|
+
case FILTER_UPDATER_PROPS.layerId:
|
|
624
|
+
// We need to update only datasetId/s if we have added/removed layers
|
|
625
|
+
// - check for layerId changes (XOR works because of string values)
|
|
626
|
+
// if no differences between layerIds, don't do any filtering
|
|
627
|
+
// @ts-ignore
|
|
628
|
+
const layerIdDifference = xor(newFilter.layerId, oldFilter.layerId);
|
|
629
|
+
|
|
630
|
+
const layerDataIds = uniq(
|
|
631
|
+
layerIdDifference
|
|
632
|
+
.map(lid =>
|
|
633
|
+
get(
|
|
634
|
+
state.layers.find(l => l.id === lid),
|
|
635
|
+
['config', 'dataId']
|
|
636
|
+
)
|
|
637
|
+
)
|
|
638
|
+
.filter(d => d)
|
|
639
|
+
);
|
|
640
|
+
|
|
641
|
+
// only filter datasetsIds
|
|
642
|
+
datasetIds = layerDataIds;
|
|
643
|
+
|
|
644
|
+
// Update newFilter dataIds
|
|
645
|
+
const newDataIds = uniq(
|
|
646
|
+
newFilter.layerId
|
|
647
|
+
.map(lid =>
|
|
648
|
+
get(
|
|
649
|
+
state.layers.find(l => l.id === lid),
|
|
650
|
+
['config', 'dataId']
|
|
651
|
+
)
|
|
652
|
+
)
|
|
653
|
+
.filter(d => d)
|
|
654
|
+
);
|
|
655
|
+
|
|
656
|
+
newFilter = {
|
|
657
|
+
...newFilter,
|
|
658
|
+
dataId: newDataIds
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
break;
|
|
662
|
+
default:
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
const enlargedFilter = state.filters.find(f => f.enlarged);
|
|
667
|
+
|
|
668
|
+
if (enlargedFilter && enlargedFilter.id !== newFilter.id) {
|
|
669
|
+
// there should be only one enlarged filter
|
|
670
|
+
newFilter.enlarged = false;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// save new filters to newState
|
|
674
|
+
newState = set(['filters', idx], newFilter, newState);
|
|
675
|
+
|
|
676
|
+
// if we are currently setting a prop that only requires to filter the current
|
|
677
|
+
// dataset we will pass only the current dataset to applyFiltersToDatasets and
|
|
678
|
+
// updateAllLayerDomainData otherwise we pass the all list of datasets as defined in dataId
|
|
679
|
+
const datasetIdsToFilter = LIMITED_FILTER_EFFECT_PROPS[prop]
|
|
680
|
+
? [datasetIds[valueIndex]]
|
|
681
|
+
: datasetIds;
|
|
682
|
+
|
|
683
|
+
// filter data
|
|
684
|
+
const filteredDatasets = applyFiltersToDatasets(
|
|
685
|
+
datasetIdsToFilter,
|
|
686
|
+
newState.datasets,
|
|
687
|
+
newState.filters,
|
|
688
|
+
newState.layers
|
|
689
|
+
);
|
|
690
|
+
|
|
691
|
+
newState = set(['datasets'], filteredDatasets, newState);
|
|
692
|
+
// dataId is an array
|
|
693
|
+
// pass only the dataset we need to update
|
|
694
|
+
newState = updateAllLayerDomainData(newState, datasetIdsToFilter, newFilter);
|
|
695
|
+
|
|
696
|
+
return newState;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Set the property of a filter plot
|
|
701
|
+
* @memberof visStateUpdaters
|
|
702
|
+
* @type {typeof import('./vis-state-updaters').setFilterPlotUpdater}
|
|
703
|
+
* @public
|
|
704
|
+
*/
|
|
705
|
+
export const setFilterPlotUpdater = (state, {idx, newProp, valueIndex = 0}) => {
|
|
706
|
+
let newFilter = {...state.filters[idx], ...newProp};
|
|
707
|
+
const prop = Object.keys(newProp)[0];
|
|
708
|
+
if (prop === 'yAxis') {
|
|
709
|
+
const plotType = getDefaultFilterPlotType(newFilter);
|
|
710
|
+
// TODO: plot is not supported in multi dataset filter for now
|
|
711
|
+
if (plotType) {
|
|
712
|
+
newFilter = {
|
|
713
|
+
...newFilter,
|
|
714
|
+
...getFilterPlot({...newFilter, plotType}, state.datasets[newFilter.dataId[valueIndex]]),
|
|
715
|
+
plotType
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
return {
|
|
721
|
+
...state,
|
|
722
|
+
filters: state.filters.map((f, i) => (i === idx ? newFilter : f))
|
|
723
|
+
};
|
|
724
|
+
};
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Add a new filter
|
|
728
|
+
* @memberof visStateUpdaters
|
|
729
|
+
* @type {typeof import('./vis-state-updaters').addFilterUpdater}
|
|
730
|
+
* @public
|
|
731
|
+
*/
|
|
732
|
+
export const addFilterUpdater = (state, action) =>
|
|
733
|
+
!action.dataId
|
|
734
|
+
? state
|
|
735
|
+
: {
|
|
736
|
+
...state,
|
|
737
|
+
filters: [...state.filters, getDefaultFilter(action.dataId)]
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* Set layer color palette ui state
|
|
742
|
+
* @memberof visStateUpdaters
|
|
743
|
+
* @type {typeof import('./vis-state-updaters').layerColorUIChangeUpdater}
|
|
744
|
+
*/
|
|
745
|
+
export const layerColorUIChangeUpdater = (state, {oldLayer, prop, newConfig}) => {
|
|
746
|
+
const oldVixConfig = oldLayer.config.visConfig[prop];
|
|
747
|
+
const newLayer = oldLayer.updateLayerColorUI(prop, newConfig);
|
|
748
|
+
const newVisConfig = newLayer.config.visConfig[prop];
|
|
749
|
+
if (oldVixConfig !== newVisConfig) {
|
|
750
|
+
return layerVisConfigChangeUpdater(state, {
|
|
751
|
+
oldLayer,
|
|
752
|
+
newVisConfig: {
|
|
753
|
+
[prop]: newVisConfig
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
return {
|
|
758
|
+
...state,
|
|
759
|
+
layers: state.layers.map(l => (l.id === oldLayer.id ? newLayer : l))
|
|
760
|
+
};
|
|
761
|
+
};
|
|
762
|
+
|
|
763
|
+
/**
|
|
764
|
+
* Start and end filter animation
|
|
765
|
+
* @memberof visStateUpdaters
|
|
766
|
+
* @type {typeof import('./vis-state-updaters').toggleFilterAnimationUpdater}
|
|
767
|
+
* @public
|
|
768
|
+
*/
|
|
769
|
+
export const toggleFilterAnimationUpdater = (state, action) => ({
|
|
770
|
+
...state,
|
|
771
|
+
filters: state.filters.map((f, i) => (i === action.idx ? {...f, isAnimating: !f.isAnimating} : f))
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* @memberof visStateUpdaters
|
|
776
|
+
* @type {typeof import('./vis-state-updaters').toggleLayerAnimationUpdater}
|
|
777
|
+
* @public
|
|
778
|
+
*/
|
|
779
|
+
export const toggleLayerAnimationUpdater = state => ({
|
|
780
|
+
...state,
|
|
781
|
+
animationConfig: {
|
|
782
|
+
...state.animationConfig,
|
|
783
|
+
isAnimating: !state.animationConfig.isAnimating
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Hide and show layer animation control
|
|
789
|
+
* @memberof visStateUpdaters
|
|
790
|
+
* @type {typeof import('./vis-state-updaters').toggleLayerAnimationControlUpdater}
|
|
791
|
+
* @public
|
|
792
|
+
*/
|
|
793
|
+
export const toggleLayerAnimationControlUpdater = state => ({
|
|
794
|
+
...state,
|
|
795
|
+
animationConfig: {
|
|
796
|
+
...state.animationConfig,
|
|
797
|
+
hideControl: !state.animationConfig.hideControl
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Change filter animation speed
|
|
803
|
+
* @memberof visStateUpdaters
|
|
804
|
+
* @type {typeof import('./vis-state-updaters').updateFilterAnimationSpeedUpdater}
|
|
805
|
+
* @public
|
|
806
|
+
*/
|
|
807
|
+
export const updateFilterAnimationSpeedUpdater = (state, action) => ({
|
|
808
|
+
...state,
|
|
809
|
+
filters: state.filters.map((f, i) => (i === action.idx ? {...f, speed: action.speed} : f))
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Reset animation config current time to a specified value
|
|
814
|
+
* @memberof visStateUpdaters
|
|
815
|
+
* @type {typeof import('./vis-state-updaters').setLayerAnimationTimeUpdater}
|
|
816
|
+
* @public
|
|
817
|
+
*
|
|
818
|
+
*/
|
|
819
|
+
export const setLayerAnimationTimeUpdater = (state, {value}) => ({
|
|
820
|
+
...state,
|
|
821
|
+
animationConfig: {
|
|
822
|
+
...state.animationConfig,
|
|
823
|
+
currentTime: value
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* Update animation speed with the vertical speed slider
|
|
829
|
+
* @memberof visStateUpdaters
|
|
830
|
+
* @type {typeof import('./vis-state-updaters').updateLayerAnimationSpeedUpdater}
|
|
831
|
+
* @public
|
|
832
|
+
*
|
|
833
|
+
*/
|
|
834
|
+
export const updateLayerAnimationSpeedUpdater = (state, {speed}) => {
|
|
835
|
+
return {
|
|
836
|
+
...state,
|
|
837
|
+
animationConfig: {
|
|
838
|
+
...state.animationConfig,
|
|
839
|
+
speed
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
};
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Show larger time filter at bottom for time playback (apply to time filter only)
|
|
846
|
+
* @memberof visStateUpdaters
|
|
847
|
+
* @type {typeof import('./vis-state-updaters').enlargeFilterUpdater}
|
|
848
|
+
* @public
|
|
849
|
+
*/
|
|
850
|
+
export const enlargeFilterUpdater = (state, action) => {
|
|
851
|
+
return {
|
|
852
|
+
...state,
|
|
853
|
+
filters: state.filters.map((f, i) =>
|
|
854
|
+
i === action.idx
|
|
855
|
+
? {
|
|
856
|
+
...f,
|
|
857
|
+
enlarged: !f.enlarged
|
|
858
|
+
}
|
|
859
|
+
: f
|
|
860
|
+
)
|
|
861
|
+
};
|
|
862
|
+
};
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* Toggles filter feature visibility
|
|
866
|
+
* @memberof visStateUpdaters
|
|
867
|
+
* @type {typeof import('./vis-state-updaters').toggleFilterFeatureUpdater}
|
|
868
|
+
*/
|
|
869
|
+
export const toggleFilterFeatureUpdater = (state, action) => {
|
|
870
|
+
const filter = state.filters[action.idx];
|
|
871
|
+
const isVisible = get(filter, ['value', 'properties', 'isVisible']);
|
|
872
|
+
const newFilter = {
|
|
873
|
+
...filter,
|
|
874
|
+
value: featureToFilterValue(filter.value, filter.id, {
|
|
875
|
+
isVisible: !isVisible
|
|
876
|
+
})
|
|
877
|
+
};
|
|
878
|
+
|
|
879
|
+
return {
|
|
880
|
+
...state,
|
|
881
|
+
filters: Object.assign([...state.filters], {[action.idx]: newFilter})
|
|
882
|
+
};
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Remove a filter
|
|
887
|
+
* @memberof visStateUpdaters
|
|
888
|
+
* @type {typeof import('./vis-state-updaters').removeFilterUpdater}
|
|
889
|
+
* @public
|
|
890
|
+
*/
|
|
891
|
+
export const removeFilterUpdater = (state, action) => {
|
|
892
|
+
const {idx} = action;
|
|
893
|
+
const {dataId, id} = state.filters[idx];
|
|
894
|
+
|
|
895
|
+
const newFilters = [
|
|
896
|
+
...state.filters.slice(0, idx),
|
|
897
|
+
...state.filters.slice(idx + 1, state.filters.length)
|
|
898
|
+
];
|
|
899
|
+
|
|
900
|
+
const filteredDatasets = applyFiltersToDatasets(dataId, state.datasets, newFilters, state.layers);
|
|
901
|
+
const newEditor =
|
|
902
|
+
getFilterIdInFeature(state.editor.selectedFeature) === id
|
|
903
|
+
? {
|
|
904
|
+
...state.editor,
|
|
905
|
+
selectedFeature: null
|
|
906
|
+
}
|
|
907
|
+
: state.editor;
|
|
908
|
+
|
|
909
|
+
let newState = set(['filters'], newFilters, state);
|
|
910
|
+
newState = set(['datasets'], filteredDatasets, newState);
|
|
911
|
+
newState = set(['editor'], newEditor, newState);
|
|
912
|
+
|
|
913
|
+
return updateAllLayerDomainData(newState, dataId, undefined);
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* Add a new layer
|
|
918
|
+
* @memberof visStateUpdaters
|
|
919
|
+
* @type {typeof import('./vis-state-updaters').addLayerUpdater}
|
|
920
|
+
* @public
|
|
921
|
+
*/
|
|
922
|
+
export const addLayerUpdater = (state, action) => {
|
|
923
|
+
let newLayer;
|
|
924
|
+
let newLayerData;
|
|
925
|
+
if (action.config) {
|
|
926
|
+
newLayer = createLayerFromConfig(state, action.config);
|
|
927
|
+
if (!newLayer) {
|
|
928
|
+
Console.warn(
|
|
929
|
+
'Failed to create layer from config, it usually means the config is not be in correct format',
|
|
930
|
+
action.config
|
|
931
|
+
);
|
|
932
|
+
return state;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
const result = calculateLayerData(newLayer, state);
|
|
936
|
+
newLayer = result.layer;
|
|
937
|
+
newLayerData = result.layerData;
|
|
938
|
+
} else {
|
|
939
|
+
// create an empty layer with the first available dataset
|
|
940
|
+
const defaultDataset = Object.keys(state.datasets)[0];
|
|
941
|
+
newLayer = new Layer({
|
|
942
|
+
isVisible: true,
|
|
943
|
+
isConfigActive: true,
|
|
944
|
+
dataId: defaultDataset
|
|
945
|
+
});
|
|
946
|
+
newLayerData = {};
|
|
947
|
+
}
|
|
948
|
+
return {
|
|
949
|
+
...state,
|
|
950
|
+
layers: [...state.layers, newLayer],
|
|
951
|
+
layerData: [...state.layerData, newLayerData],
|
|
952
|
+
layerOrder: [...state.layerOrder, state.layerOrder.length],
|
|
953
|
+
splitMaps: addNewLayersToSplitMap(state.splitMaps, newLayer)
|
|
954
|
+
};
|
|
955
|
+
};
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* remove layer
|
|
959
|
+
* @memberof visStateUpdaters
|
|
960
|
+
* @type {typeof import('./vis-state-updaters').removeLayerUpdater}
|
|
961
|
+
* @public
|
|
962
|
+
*/
|
|
963
|
+
export const removeLayerUpdater = (state, {idx}) => {
|
|
964
|
+
const {layers, layerData, clicked, hoverInfo} = state;
|
|
965
|
+
const layerToRemove = state.layers[idx];
|
|
966
|
+
const newMaps = removeLayerFromSplitMaps(state.splitMaps, layerToRemove);
|
|
967
|
+
|
|
968
|
+
const newState = {
|
|
969
|
+
...state,
|
|
970
|
+
layers: [...layers.slice(0, idx), ...layers.slice(idx + 1, layers.length)],
|
|
971
|
+
layerData: [...layerData.slice(0, idx), ...layerData.slice(idx + 1, layerData.length)],
|
|
972
|
+
layerOrder: state.layerOrder.filter(i => i !== idx).map(pid => (pid > idx ? pid - 1 : pid)),
|
|
973
|
+
clicked: layerToRemove.isLayerHovered(clicked) ? undefined : clicked,
|
|
974
|
+
hoverInfo: layerToRemove.isLayerHovered(hoverInfo) ? undefined : hoverInfo,
|
|
975
|
+
splitMaps: newMaps
|
|
976
|
+
// TODO: update filters, create helper to remove layer form filter (remove layerid and dataid) if mapped
|
|
977
|
+
};
|
|
978
|
+
|
|
979
|
+
return updateAnimationDomain(newState);
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
* duplicate layer
|
|
984
|
+
* @memberof visStateUpdaters
|
|
985
|
+
* @type {typeof import('./vis-state-updaters').duplicateLayerUpdater}
|
|
986
|
+
* @public
|
|
987
|
+
*/
|
|
988
|
+
export const duplicateLayerUpdater = (state, {idx}) => {
|
|
989
|
+
const {layers} = state;
|
|
990
|
+
const original = state.layers[idx];
|
|
991
|
+
const originalLayerOrderIdx = state.layerOrder.findIndex(i => i === idx);
|
|
992
|
+
|
|
993
|
+
if (!original) {
|
|
994
|
+
Console.warn(`layer.${idx} is undefined`);
|
|
995
|
+
return state;
|
|
996
|
+
}
|
|
997
|
+
let newLabel = `Copy of ${original.config.label}`;
|
|
998
|
+
let postfix = 0;
|
|
999
|
+
// eslint-disable-next-line no-loop-func
|
|
1000
|
+
while (layers.find(l => l.config.label === newLabel)) {
|
|
1001
|
+
newLabel = `Copy of ${original.config.label} ${++postfix}`;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
// collect layer config from original
|
|
1005
|
+
const loadedLayer = serializeLayer(original);
|
|
1006
|
+
|
|
1007
|
+
// assign new id and label to copied layer
|
|
1008
|
+
if (!loadedLayer.config) {
|
|
1009
|
+
return state;
|
|
1010
|
+
}
|
|
1011
|
+
loadedLayer.config.label = newLabel;
|
|
1012
|
+
loadedLayer.id = generateHashId(LAYER_ID_LENGTH);
|
|
1013
|
+
|
|
1014
|
+
// add layer to state
|
|
1015
|
+
let nextState = addLayerUpdater(state, {config: loadedLayer});
|
|
1016
|
+
|
|
1017
|
+
// new added layer are at the end, move it to be on top of original layer
|
|
1018
|
+
const newLayerOrderIdx = nextState.layerOrder.length - 1;
|
|
1019
|
+
const newLayerOrder = arrayInsert(
|
|
1020
|
+
nextState.layerOrder.slice(0, newLayerOrderIdx),
|
|
1021
|
+
originalLayerOrderIdx,
|
|
1022
|
+
newLayerOrderIdx
|
|
1023
|
+
);
|
|
1024
|
+
|
|
1025
|
+
nextState = {
|
|
1026
|
+
...nextState,
|
|
1027
|
+
layerOrder: newLayerOrder
|
|
1028
|
+
};
|
|
1029
|
+
|
|
1030
|
+
return updateAnimationDomain(nextState);
|
|
1031
|
+
};
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* Reorder layer
|
|
1035
|
+
* @memberof visStateUpdaters
|
|
1036
|
+
* @type {typeof import('./vis-state-updaters').reorderLayerUpdater}
|
|
1037
|
+
* @public
|
|
1038
|
+
*/
|
|
1039
|
+
export const reorderLayerUpdater = (state, {order}) => ({
|
|
1040
|
+
...state,
|
|
1041
|
+
layerOrder: order
|
|
1042
|
+
});
|
|
1043
|
+
|
|
1044
|
+
/**
|
|
1045
|
+
* Remove a dataset and all layers, filters, tooltip configs that based on it
|
|
1046
|
+
* @memberof visStateUpdaters
|
|
1047
|
+
* @type {typeof import('./vis-state-updaters').removeDatasetUpdater}
|
|
1048
|
+
* @public
|
|
1049
|
+
*/
|
|
1050
|
+
export const removeDatasetUpdater = (state, action) => {
|
|
1051
|
+
// extract dataset key
|
|
1052
|
+
const {dataId: datasetKey} = action;
|
|
1053
|
+
const {datasets} = state;
|
|
1054
|
+
|
|
1055
|
+
// check if dataset is present
|
|
1056
|
+
if (!datasets[datasetKey]) {
|
|
1057
|
+
return state;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
/* eslint-disable no-unused-vars */
|
|
1061
|
+
const {
|
|
1062
|
+
layers,
|
|
1063
|
+
datasets: {[datasetKey]: dataset, ...newDatasets}
|
|
1064
|
+
} = state;
|
|
1065
|
+
/* eslint-enable no-unused-vars */
|
|
1066
|
+
|
|
1067
|
+
const indexes = layers.reduce((listOfIndexes, layer, index) => {
|
|
1068
|
+
if (layer.config.dataId === datasetKey) {
|
|
1069
|
+
// @ts-ignore
|
|
1070
|
+
listOfIndexes.push(index);
|
|
1071
|
+
}
|
|
1072
|
+
return listOfIndexes;
|
|
1073
|
+
}, []);
|
|
1074
|
+
|
|
1075
|
+
// remove layers and datasets
|
|
1076
|
+
const {newState} = indexes.reduce(
|
|
1077
|
+
({newState: currentState, indexCounter}, idx) => {
|
|
1078
|
+
const currentIndex = idx - indexCounter;
|
|
1079
|
+
currentState = removeLayerUpdater(currentState, {idx: currentIndex});
|
|
1080
|
+
indexCounter++;
|
|
1081
|
+
return {newState: currentState, indexCounter};
|
|
1082
|
+
},
|
|
1083
|
+
{newState: {...state, datasets: newDatasets}, indexCounter: 0}
|
|
1084
|
+
);
|
|
1085
|
+
|
|
1086
|
+
// remove filters
|
|
1087
|
+
const filters = state.filters.filter(filter => !filter.dataId.includes(datasetKey));
|
|
1088
|
+
|
|
1089
|
+
// update interactionConfig
|
|
1090
|
+
let {interactionConfig} = state;
|
|
1091
|
+
const {tooltip} = interactionConfig;
|
|
1092
|
+
if (tooltip) {
|
|
1093
|
+
const {config} = tooltip;
|
|
1094
|
+
/* eslint-disable no-unused-vars */
|
|
1095
|
+
const {[datasetKey]: fields, ...fieldsToShow} = config.fieldsToShow;
|
|
1096
|
+
/* eslint-enable no-unused-vars */
|
|
1097
|
+
interactionConfig = {
|
|
1098
|
+
...interactionConfig,
|
|
1099
|
+
tooltip: {...tooltip, config: {...config, fieldsToShow}}
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
return {...newState, filters, interactionConfig};
|
|
1104
|
+
};
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* update layer blending mode
|
|
1108
|
+
* @memberof visStateUpdaters
|
|
1109
|
+
* @type {typeof import('./vis-state-updaters').updateLayerBlendingUpdater}
|
|
1110
|
+
* @public
|
|
1111
|
+
*/
|
|
1112
|
+
export const updateLayerBlendingUpdater = (state, action) => ({
|
|
1113
|
+
...state,
|
|
1114
|
+
layerBlending: action.mode
|
|
1115
|
+
});
|
|
1116
|
+
|
|
1117
|
+
/**
|
|
1118
|
+
* Display dataset table in a modal
|
|
1119
|
+
* @memberof visStateUpdaters
|
|
1120
|
+
* @type {typeof import('./vis-state-updaters').showDatasetTableUpdater}
|
|
1121
|
+
* @public
|
|
1122
|
+
*/
|
|
1123
|
+
export const showDatasetTableUpdater = (state, action) => {
|
|
1124
|
+
return {
|
|
1125
|
+
...state,
|
|
1126
|
+
editingDataset: action.dataId
|
|
1127
|
+
};
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* reset visState to initial State
|
|
1132
|
+
* @memberof visStateUpdaters
|
|
1133
|
+
* @type {typeof import('./vis-state-updaters').resetMapConfigUpdater}
|
|
1134
|
+
* @public
|
|
1135
|
+
*/
|
|
1136
|
+
export const resetMapConfigUpdater = state => ({
|
|
1137
|
+
...INITIAL_VIS_STATE,
|
|
1138
|
+
...state.initialState,
|
|
1139
|
+
initialState: state.initialState
|
|
1140
|
+
});
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* Propagate `visState` reducer with a new configuration. Current config will be override.
|
|
1144
|
+
* @memberof visStateUpdaters
|
|
1145
|
+
* @type {typeof import('./vis-state-updaters').receiveMapConfigUpdater}
|
|
1146
|
+
* @public
|
|
1147
|
+
*/
|
|
1148
|
+
export const receiveMapConfigUpdater = (state, {payload: {config = {}, options = {}}}) => {
|
|
1149
|
+
if (!config.visState) {
|
|
1150
|
+
return state;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
const {keepExistingConfig} = options;
|
|
1154
|
+
|
|
1155
|
+
// reset config if keepExistingConfig is falsy
|
|
1156
|
+
let mergedState = !keepExistingConfig ? resetMapConfigUpdater(state) : state;
|
|
1157
|
+
for (const merger of state.mergers) {
|
|
1158
|
+
if (isValidMerger(merger) && config.visState[merger.prop]) {
|
|
1159
|
+
mergedState = merger.merge(mergedState, config.visState[merger.prop], true);
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
return mergedState;
|
|
1164
|
+
};
|
|
1165
|
+
|
|
1166
|
+
/**
|
|
1167
|
+
* Trigger layer hover event with hovered object
|
|
1168
|
+
* @memberof visStateUpdaters
|
|
1169
|
+
* @type {typeof import('./vis-state-updaters').layerHoverUpdater}
|
|
1170
|
+
* @public
|
|
1171
|
+
*/
|
|
1172
|
+
export const layerHoverUpdater = (state, action) => ({
|
|
1173
|
+
...state,
|
|
1174
|
+
hoverInfo: action.info
|
|
1175
|
+
});
|
|
1176
|
+
|
|
1177
|
+
/* eslint-enable max-statements */
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* Update `interactionConfig`
|
|
1181
|
+
* @memberof visStateUpdaters
|
|
1182
|
+
* @type {typeof import('./vis-state-updaters').interactionConfigChangeUpdater}
|
|
1183
|
+
* @public
|
|
1184
|
+
*/
|
|
1185
|
+
export function interactionConfigChangeUpdater(state, action) {
|
|
1186
|
+
const {config} = action;
|
|
1187
|
+
|
|
1188
|
+
const interactionConfig = {
|
|
1189
|
+
...state.interactionConfig,
|
|
1190
|
+
...{[config.id]: config}
|
|
1191
|
+
};
|
|
1192
|
+
|
|
1193
|
+
// Don't enable tooltip and brush at the same time
|
|
1194
|
+
// but coordinates can be shown at all time
|
|
1195
|
+
const contradict = ['brush', 'tooltip'];
|
|
1196
|
+
|
|
1197
|
+
if (
|
|
1198
|
+
contradict.includes(config.id) &&
|
|
1199
|
+
config.enabled &&
|
|
1200
|
+
!state.interactionConfig[config.id].enabled
|
|
1201
|
+
) {
|
|
1202
|
+
// only enable one interaction at a time
|
|
1203
|
+
contradict.forEach(k => {
|
|
1204
|
+
if (k !== config.id) {
|
|
1205
|
+
interactionConfig[k] = {...interactionConfig[k], enabled: false};
|
|
1206
|
+
}
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
const newState = {
|
|
1211
|
+
...state,
|
|
1212
|
+
interactionConfig
|
|
1213
|
+
};
|
|
1214
|
+
|
|
1215
|
+
if (config.id === 'geocoder' && !config.enabled) {
|
|
1216
|
+
return removeDatasetUpdater(newState, {dataId: 'geocoder_dataset'});
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
return newState;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
/**
|
|
1223
|
+
* Trigger layer click event with clicked object
|
|
1224
|
+
* @memberof visStateUpdaters
|
|
1225
|
+
* @type {typeof import('./vis-state-updaters').layerClickUpdater}
|
|
1226
|
+
* @public
|
|
1227
|
+
*/
|
|
1228
|
+
export const layerClickUpdater = (state, action) => ({
|
|
1229
|
+
...state,
|
|
1230
|
+
mousePos: state.interactionConfig.coordinate.enabled
|
|
1231
|
+
? {
|
|
1232
|
+
...state.mousePos,
|
|
1233
|
+
pinned: state.mousePos.pinned ? null : cloneDeep(state.mousePos)
|
|
1234
|
+
}
|
|
1235
|
+
: state.mousePos,
|
|
1236
|
+
clicked: action.info && action.info.picked ? action.info : null
|
|
1237
|
+
});
|
|
1238
|
+
|
|
1239
|
+
/**
|
|
1240
|
+
* Trigger map click event, unselect clicked object
|
|
1241
|
+
* @memberof visStateUpdaters
|
|
1242
|
+
* @type {typeof import('./vis-state-updaters').mapClickUpdater}
|
|
1243
|
+
* @public
|
|
1244
|
+
*/
|
|
1245
|
+
export const mapClickUpdater = state => {
|
|
1246
|
+
return {
|
|
1247
|
+
...state,
|
|
1248
|
+
clicked: null
|
|
1249
|
+
};
|
|
1250
|
+
};
|
|
1251
|
+
|
|
1252
|
+
/**
|
|
1253
|
+
* Trigger map move event
|
|
1254
|
+
* @memberof visStateUpdaters
|
|
1255
|
+
* @type {typeof import('./vis-state-updaters').mouseMoveUpdater}
|
|
1256
|
+
* @public
|
|
1257
|
+
*/
|
|
1258
|
+
export const mouseMoveUpdater = (state, {evt}) => {
|
|
1259
|
+
if (Object.values(state.interactionConfig).some(config => config.enabled)) {
|
|
1260
|
+
return {
|
|
1261
|
+
...state,
|
|
1262
|
+
mousePos: {
|
|
1263
|
+
...state.mousePos,
|
|
1264
|
+
mousePosition: [...evt.point],
|
|
1265
|
+
coordinate: [...evt.lngLat]
|
|
1266
|
+
}
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
return state;
|
|
1271
|
+
};
|
|
1272
|
+
/**
|
|
1273
|
+
* Toggle visibility of a layer for a split map
|
|
1274
|
+
* @memberof visStateUpdaters
|
|
1275
|
+
* @type {typeof import('./vis-state-updaters').toggleSplitMapUpdater}
|
|
1276
|
+
* @public
|
|
1277
|
+
*/
|
|
1278
|
+
export const toggleSplitMapUpdater = (state, action) =>
|
|
1279
|
+
state.splitMaps && state.splitMaps.length === 0
|
|
1280
|
+
? {
|
|
1281
|
+
...state,
|
|
1282
|
+
// maybe we should use an array to store state for a single map as well
|
|
1283
|
+
// if current maps length is equal to 0 it means that we are about to split the view
|
|
1284
|
+
splitMaps: computeSplitMapLayers(state.layers)
|
|
1285
|
+
}
|
|
1286
|
+
: closeSpecificMapAtIndex(state, action);
|
|
1287
|
+
|
|
1288
|
+
/**
|
|
1289
|
+
* Toggle visibility of a layer in a split map
|
|
1290
|
+
* @memberof visStateUpdaters
|
|
1291
|
+
* @type {typeof import('./vis-state-updaters').toggleLayerForMapUpdater}
|
|
1292
|
+
* @public
|
|
1293
|
+
*/
|
|
1294
|
+
export const toggleLayerForMapUpdater = (state, {mapIndex, layerId}) => {
|
|
1295
|
+
const {splitMaps} = state;
|
|
1296
|
+
|
|
1297
|
+
return {
|
|
1298
|
+
...state,
|
|
1299
|
+
splitMaps: splitMaps.map((sm, i) =>
|
|
1300
|
+
i === mapIndex
|
|
1301
|
+
? {
|
|
1302
|
+
...splitMaps[i],
|
|
1303
|
+
layers: {
|
|
1304
|
+
...splitMaps[i].layers,
|
|
1305
|
+
// if layerId not in layers, set it to visible
|
|
1306
|
+
[layerId]: !splitMaps[i].layers[layerId]
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
: sm
|
|
1310
|
+
)
|
|
1311
|
+
};
|
|
1312
|
+
};
|
|
1313
|
+
|
|
1314
|
+
/**
|
|
1315
|
+
* Add new dataset to `visState`, with option to load a map config along with the datasets
|
|
1316
|
+
* @memberof visStateUpdaters
|
|
1317
|
+
* @type {typeof import('./vis-state-updaters').updateVisDataUpdater}
|
|
1318
|
+
* @public
|
|
1319
|
+
*/
|
|
1320
|
+
/* eslint-disable max-statements */
|
|
1321
|
+
// eslint-disable-next-line complexity
|
|
1322
|
+
export const updateVisDataUpdater = (state, action) => {
|
|
1323
|
+
// datasets can be a single data entries or an array of multiple data entries
|
|
1324
|
+
const {config, options} = action;
|
|
1325
|
+
const datasets = toArray(action.datasets);
|
|
1326
|
+
|
|
1327
|
+
const newDataEntries = datasets.reduce(
|
|
1328
|
+
(accu, {info = {}, ...rest} = {}) => ({
|
|
1329
|
+
...accu,
|
|
1330
|
+
...(createNewDataEntry({info, ...rest}, state.datasets) || {})
|
|
1331
|
+
}),
|
|
1332
|
+
{}
|
|
1333
|
+
);
|
|
1334
|
+
|
|
1335
|
+
const dataEmpty = Object.keys(newDataEntries).length < 1;
|
|
1336
|
+
|
|
1337
|
+
// apply config if passed from action
|
|
1338
|
+
const previousState = config
|
|
1339
|
+
? receiveMapConfigUpdater(state, {
|
|
1340
|
+
payload: {config, options}
|
|
1341
|
+
})
|
|
1342
|
+
: state;
|
|
1343
|
+
|
|
1344
|
+
let mergedState = {
|
|
1345
|
+
...previousState,
|
|
1346
|
+
datasets: {
|
|
1347
|
+
...previousState.datasets,
|
|
1348
|
+
...newDataEntries
|
|
1349
|
+
}
|
|
1350
|
+
};
|
|
1351
|
+
|
|
1352
|
+
// merge state with config to be merged
|
|
1353
|
+
for (const merger of mergedState.mergers) {
|
|
1354
|
+
if (isValidMerger(merger) && merger.toMergeProp && mergedState[merger.toMergeProp]) {
|
|
1355
|
+
const toMerge = mergedState[merger.toMergeProp];
|
|
1356
|
+
mergedState[merger.toMergeProp] = INITIAL_VIS_STATE[merger.toMergeProp];
|
|
1357
|
+
mergedState = merger.merge(mergedState, toMerge);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
let newLayers = !dataEmpty
|
|
1362
|
+
? mergedState.layers.filter(l => l.config.dataId && l.config.dataId in newDataEntries)
|
|
1363
|
+
: [];
|
|
1364
|
+
|
|
1365
|
+
if (!newLayers.length && (options || {}).autoCreateLayers !== false) {
|
|
1366
|
+
// no layer merged, find defaults
|
|
1367
|
+
const result = addDefaultLayers(mergedState, newDataEntries);
|
|
1368
|
+
mergedState = result.state;
|
|
1369
|
+
newLayers = result.newLayers;
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
if (mergedState.splitMaps.length) {
|
|
1373
|
+
// if map is split, add new layers to splitMaps
|
|
1374
|
+
newLayers = mergedState.layers.filter(
|
|
1375
|
+
l => l.config.dataId && l.config.dataId in newDataEntries
|
|
1376
|
+
);
|
|
1377
|
+
mergedState = {
|
|
1378
|
+
...mergedState,
|
|
1379
|
+
splitMaps: addNewLayersToSplitMap(mergedState.splitMaps, newLayers)
|
|
1380
|
+
};
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
// if no tooltips merged add default tooltips
|
|
1384
|
+
Object.keys(newDataEntries).forEach(dataId => {
|
|
1385
|
+
const tooltipFields = mergedState.interactionConfig.tooltip.config.fieldsToShow[dataId];
|
|
1386
|
+
if (!Array.isArray(tooltipFields) || !tooltipFields.length) {
|
|
1387
|
+
mergedState = addDefaultTooltips(mergedState, newDataEntries[dataId]);
|
|
1388
|
+
}
|
|
1389
|
+
});
|
|
1390
|
+
|
|
1391
|
+
let updatedState = updateAllLayerDomainData(
|
|
1392
|
+
mergedState,
|
|
1393
|
+
dataEmpty ? Object.keys(mergedState.datasets) : Object.keys(newDataEntries),
|
|
1394
|
+
undefined
|
|
1395
|
+
);
|
|
1396
|
+
|
|
1397
|
+
// register layer animation domain,
|
|
1398
|
+
// need to be called after layer data is calculated
|
|
1399
|
+
updatedState = updateAnimationDomain(updatedState);
|
|
1400
|
+
|
|
1401
|
+
return updatedState;
|
|
1402
|
+
};
|
|
1403
|
+
/* eslint-enable max-statements */
|
|
1404
|
+
|
|
1405
|
+
/**
|
|
1406
|
+
* Rename an existing dataset in `visState`
|
|
1407
|
+
* @memberof visStateUpdaters
|
|
1408
|
+
* @type {typeof import('./vis-state-updaters').renameDatasetUpdater}
|
|
1409
|
+
* @public
|
|
1410
|
+
*/
|
|
1411
|
+
export function renameDatasetUpdater(state, action) {
|
|
1412
|
+
const {dataId, label} = action;
|
|
1413
|
+
const {datasets} = state;
|
|
1414
|
+
const existing = datasets[dataId];
|
|
1415
|
+
// @ts-ignore
|
|
1416
|
+
return existing
|
|
1417
|
+
? {
|
|
1418
|
+
...state,
|
|
1419
|
+
datasets: {
|
|
1420
|
+
...datasets,
|
|
1421
|
+
[dataId]: {
|
|
1422
|
+
...existing,
|
|
1423
|
+
label
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
: // No-op if the dataset doesn't exist
|
|
1428
|
+
state;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
/**
|
|
1432
|
+
* When a user clicks on the specific map closing icon
|
|
1433
|
+
* the application will close the selected map
|
|
1434
|
+
* and will merge the remaining one with the global state
|
|
1435
|
+
* TODO: i think in the future this action should be called merge map layers with global settings
|
|
1436
|
+
* @param {Object} state `visState`
|
|
1437
|
+
* @param {Object} action action
|
|
1438
|
+
* @returns {Object} nextState
|
|
1439
|
+
*/
|
|
1440
|
+
export function closeSpecificMapAtIndex(state, action) {
|
|
1441
|
+
// retrieve layers meta data from the remaining map that we need to keep
|
|
1442
|
+
const indexToRetrieve = 1 - action.payload;
|
|
1443
|
+
const mapLayers = state.splitMaps[indexToRetrieve].layers;
|
|
1444
|
+
const {layers} = state;
|
|
1445
|
+
|
|
1446
|
+
// update layer visibility
|
|
1447
|
+
const newLayers = layers.map(layer =>
|
|
1448
|
+
!mapLayers[layer.id] && layer.config.isVisible
|
|
1449
|
+
? layer.updateLayerConfig({
|
|
1450
|
+
// if layer.id is not in mapLayers, it should be inVisible
|
|
1451
|
+
isVisible: false
|
|
1452
|
+
})
|
|
1453
|
+
: layer
|
|
1454
|
+
);
|
|
1455
|
+
|
|
1456
|
+
// delete map
|
|
1457
|
+
return {
|
|
1458
|
+
...state,
|
|
1459
|
+
layers: newLayers,
|
|
1460
|
+
splitMaps: []
|
|
1461
|
+
};
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
/**
|
|
1465
|
+
* Trigger file loading dispatch `addDataToMap` if succeed, or `loadFilesErr` if failed
|
|
1466
|
+
* @memberof visStateUpdaters
|
|
1467
|
+
* @type {typeof import('./vis-state-updaters').loadFilesUpdater}
|
|
1468
|
+
* @public
|
|
1469
|
+
*/
|
|
1470
|
+
export const loadFilesUpdater = (state, action) => {
|
|
1471
|
+
const {files, onFinish = loadFilesSuccess} = action;
|
|
1472
|
+
if (!files.length) {
|
|
1473
|
+
return state;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
const fileLoadingProgress = Array.from(files).reduce(
|
|
1477
|
+
(accu, f, i) => merge_(initialFileLoadingProgress(f, i))(accu),
|
|
1478
|
+
{}
|
|
1479
|
+
);
|
|
1480
|
+
|
|
1481
|
+
const fileLoading = {
|
|
1482
|
+
fileCache: [],
|
|
1483
|
+
filesToLoad: files,
|
|
1484
|
+
onFinish
|
|
1485
|
+
};
|
|
1486
|
+
|
|
1487
|
+
const nextState = merge_({fileLoadingProgress, fileLoading})(state);
|
|
1488
|
+
|
|
1489
|
+
return loadNextFileUpdater(nextState);
|
|
1490
|
+
};
|
|
1491
|
+
|
|
1492
|
+
/**
|
|
1493
|
+
* Sucessfully loaded one file, move on to the next one
|
|
1494
|
+
* @memberof visStateUpdaters
|
|
1495
|
+
* @type {typeof import('./vis-state-updaters').loadFileStepSuccessUpdater}
|
|
1496
|
+
* @public
|
|
1497
|
+
*/
|
|
1498
|
+
export function loadFileStepSuccessUpdater(state, action) {
|
|
1499
|
+
if (!state.fileLoading) {
|
|
1500
|
+
return state;
|
|
1501
|
+
}
|
|
1502
|
+
const {fileName, fileCache} = action;
|
|
1503
|
+
const {filesToLoad, onFinish} = state.fileLoading;
|
|
1504
|
+
const stateWithProgress = updateFileLoadingProgressUpdater(state, {
|
|
1505
|
+
fileName,
|
|
1506
|
+
progress: {percent: 1, message: 'Done'}
|
|
1507
|
+
});
|
|
1508
|
+
|
|
1509
|
+
// save processed file to fileCache
|
|
1510
|
+
const stateWithCache = pick_('fileLoading')(merge_({fileCache}))(stateWithProgress);
|
|
1511
|
+
|
|
1512
|
+
return withTask(
|
|
1513
|
+
stateWithCache,
|
|
1514
|
+
DELAY_TASK(200).map(filesToLoad.length ? loadNextFile : () => onFinish(fileCache))
|
|
1515
|
+
);
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
// withTask<T>(state: T, task: any): T
|
|
1519
|
+
|
|
1520
|
+
/**
|
|
1521
|
+
*
|
|
1522
|
+
* @memberof visStateUpdaters
|
|
1523
|
+
* @type {typeof import('./vis-state-updaters').loadNextFileUpdater}
|
|
1524
|
+
* @public
|
|
1525
|
+
*/
|
|
1526
|
+
export function loadNextFileUpdater(state) {
|
|
1527
|
+
if (!state.fileLoading) {
|
|
1528
|
+
return state;
|
|
1529
|
+
}
|
|
1530
|
+
const {filesToLoad} = state.fileLoading;
|
|
1531
|
+
const [file, ...remainingFilesToLoad] = filesToLoad;
|
|
1532
|
+
|
|
1533
|
+
// save filesToLoad to state
|
|
1534
|
+
const nextState = pick_('fileLoading')(merge_({filesToLoad: remainingFilesToLoad}))(state);
|
|
1535
|
+
|
|
1536
|
+
const stateWithProgress = updateFileLoadingProgressUpdater(nextState, {
|
|
1537
|
+
fileName: file.name,
|
|
1538
|
+
progress: {percent: 0, message: 'loading...'}
|
|
1539
|
+
});
|
|
1540
|
+
|
|
1541
|
+
const {loaders, loadOptions} = state;
|
|
1542
|
+
return withTask(
|
|
1543
|
+
stateWithProgress,
|
|
1544
|
+
makeLoadFileTask(file, nextState.fileLoading.fileCache, loaders, loadOptions)
|
|
1545
|
+
);
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
export function makeLoadFileTask(file, fileCache, loaders = [], loadOptions = {}) {
|
|
1549
|
+
return LOAD_FILE_TASK({file, fileCache, loaders, loadOptions}).bimap(
|
|
1550
|
+
// prettier ignore
|
|
1551
|
+
// success
|
|
1552
|
+
gen =>
|
|
1553
|
+
nextFileBatch({
|
|
1554
|
+
gen,
|
|
1555
|
+
fileName: file.name,
|
|
1556
|
+
onFinish: result =>
|
|
1557
|
+
processFileContent({
|
|
1558
|
+
content: result,
|
|
1559
|
+
fileCache
|
|
1560
|
+
})
|
|
1561
|
+
}),
|
|
1562
|
+
|
|
1563
|
+
// error
|
|
1564
|
+
err => loadFilesErr(file.name, err)
|
|
1565
|
+
);
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
/**
|
|
1569
|
+
*
|
|
1570
|
+
* @memberof visStateUpdaters
|
|
1571
|
+
* @type {typeof import('./vis-state-updaters').processFileContentUpdater}
|
|
1572
|
+
* @public
|
|
1573
|
+
*/
|
|
1574
|
+
export function processFileContentUpdater(state, action) {
|
|
1575
|
+
const {content, fileCache} = action.payload;
|
|
1576
|
+
|
|
1577
|
+
const stateWithProgress = updateFileLoadingProgressUpdater(state, {
|
|
1578
|
+
fileName: content.fileName,
|
|
1579
|
+
progress: {percent: 1, message: 'processing...'}
|
|
1580
|
+
});
|
|
1581
|
+
|
|
1582
|
+
return withTask(
|
|
1583
|
+
stateWithProgress,
|
|
1584
|
+
PROCESS_FILE_DATA({content, fileCache}).bimap(
|
|
1585
|
+
result => loadFileStepSuccess({fileName: content.fileName, fileCache: result}),
|
|
1586
|
+
err => loadFilesErr(content.fileName, err)
|
|
1587
|
+
)
|
|
1588
|
+
);
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
export function parseProgress(prevProgress = {}, progress) {
|
|
1592
|
+
// This happens when receiving query metadata or other cases we don't
|
|
1593
|
+
// have an update for the user.
|
|
1594
|
+
if (!progress || !progress.percent) {
|
|
1595
|
+
return {};
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
return {
|
|
1599
|
+
percent: progress.percent
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
/**
|
|
1604
|
+
* gets called with payload = AsyncGenerator<???>
|
|
1605
|
+
* @memberof visStateUpdaters
|
|
1606
|
+
* @type {typeof import('./vis-state-updaters').nextFileBatchUpdater}
|
|
1607
|
+
* @public
|
|
1608
|
+
*/
|
|
1609
|
+
export const nextFileBatchUpdater = (
|
|
1610
|
+
state,
|
|
1611
|
+
{payload: {gen, fileName, progress, accumulated, onFinish}}
|
|
1612
|
+
) => {
|
|
1613
|
+
const stateWithProgress = updateFileLoadingProgressUpdater(state, {
|
|
1614
|
+
fileName,
|
|
1615
|
+
progress: parseProgress(state.fileLoadingProgress[fileName], progress)
|
|
1616
|
+
});
|
|
1617
|
+
return withTask(
|
|
1618
|
+
stateWithProgress,
|
|
1619
|
+
UNWRAP_TASK(gen.next()).bimap(
|
|
1620
|
+
({value, done}) => {
|
|
1621
|
+
return done
|
|
1622
|
+
? onFinish(accumulated)
|
|
1623
|
+
: nextFileBatch({
|
|
1624
|
+
gen,
|
|
1625
|
+
fileName,
|
|
1626
|
+
progress: value.progress,
|
|
1627
|
+
accumulated: value,
|
|
1628
|
+
onFinish
|
|
1629
|
+
});
|
|
1630
|
+
},
|
|
1631
|
+
err => loadFilesErr(fileName, err)
|
|
1632
|
+
)
|
|
1633
|
+
);
|
|
1634
|
+
};
|
|
1635
|
+
|
|
1636
|
+
/**
|
|
1637
|
+
* Trigger loading file error
|
|
1638
|
+
* @memberof visStateUpdaters
|
|
1639
|
+
* @type {typeof import('./vis-state-updaters').loadFilesErrUpdater}
|
|
1640
|
+
* @public
|
|
1641
|
+
*/
|
|
1642
|
+
export const loadFilesErrUpdater = (state, {error, fileName}) => {
|
|
1643
|
+
// update ui with error message
|
|
1644
|
+
Console.warn(error);
|
|
1645
|
+
if (!state.fileLoading) {
|
|
1646
|
+
return state;
|
|
1647
|
+
}
|
|
1648
|
+
const {filesToLoad, onFinish, fileCache} = state.fileLoading;
|
|
1649
|
+
|
|
1650
|
+
const nextState = updateFileLoadingProgressUpdater(state, {
|
|
1651
|
+
fileName,
|
|
1652
|
+
progress: {error}
|
|
1653
|
+
});
|
|
1654
|
+
|
|
1655
|
+
// kick off next file or finish
|
|
1656
|
+
return withTask(
|
|
1657
|
+
nextState,
|
|
1658
|
+
DELAY_TASK(200).map(filesToLoad.length ? loadNextFile : () => onFinish(fileCache))
|
|
1659
|
+
);
|
|
1660
|
+
};
|
|
1661
|
+
|
|
1662
|
+
/**
|
|
1663
|
+
* When select dataset for export, apply cpu filter to selected dataset
|
|
1664
|
+
* @memberof visStateUpdaters
|
|
1665
|
+
* @type {typeof import('./vis-state-updaters').applyCPUFilterUpdater}
|
|
1666
|
+
* @public
|
|
1667
|
+
*/
|
|
1668
|
+
export const applyCPUFilterUpdater = (state, {dataId}) => {
|
|
1669
|
+
// apply cpuFilter
|
|
1670
|
+
const dataIds = toArray(dataId);
|
|
1671
|
+
|
|
1672
|
+
return dataIds.reduce((accu, id) => filterDatasetCPU(accu, id), state);
|
|
1673
|
+
};
|
|
1674
|
+
|
|
1675
|
+
/**
|
|
1676
|
+
* User input to update the info of the map
|
|
1677
|
+
* @memberof visStateUpdaters
|
|
1678
|
+
* @type {typeof import('./vis-state-updaters').setMapInfoUpdater}
|
|
1679
|
+
* @public
|
|
1680
|
+
*/
|
|
1681
|
+
export const setMapInfoUpdater = (state, action) => ({
|
|
1682
|
+
...state,
|
|
1683
|
+
mapInfo: {
|
|
1684
|
+
...state.mapInfo,
|
|
1685
|
+
...action.info
|
|
1686
|
+
}
|
|
1687
|
+
});
|
|
1688
|
+
/**
|
|
1689
|
+
* Helper function to update All layer domain and layer data of state
|
|
1690
|
+
* @type {typeof import('./vis-state-updaters').addDefaultLayers}
|
|
1691
|
+
*/
|
|
1692
|
+
export function addDefaultLayers(state, datasets) {
|
|
1693
|
+
/** @type {Layer[]} */
|
|
1694
|
+
const empty = [];
|
|
1695
|
+
const defaultLayers = Object.values(datasets).reduce((accu, dataset) => {
|
|
1696
|
+
const foundLayers = findDefaultLayer(dataset, state.layerClasses);
|
|
1697
|
+
return foundLayers && foundLayers.length ? accu.concat(foundLayers) : accu;
|
|
1698
|
+
}, empty);
|
|
1699
|
+
|
|
1700
|
+
return {
|
|
1701
|
+
state: {
|
|
1702
|
+
...state,
|
|
1703
|
+
layers: [...state.layers, ...defaultLayers],
|
|
1704
|
+
layerOrder: [
|
|
1705
|
+
// put new layers on top of old ones
|
|
1706
|
+
...defaultLayers.map((_, i) => state.layers.length + i),
|
|
1707
|
+
...state.layerOrder
|
|
1708
|
+
]
|
|
1709
|
+
},
|
|
1710
|
+
newLayers: defaultLayers
|
|
1711
|
+
};
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
/**
|
|
1715
|
+
* helper function to find default tooltips
|
|
1716
|
+
* @param {Object} state
|
|
1717
|
+
* @param {Object} dataset
|
|
1718
|
+
* @returns {Object} nextState
|
|
1719
|
+
*/
|
|
1720
|
+
export function addDefaultTooltips(state, dataset) {
|
|
1721
|
+
const tooltipFields = dataset.metadata.isDynamicSpatialIndex
|
|
1722
|
+
? {[dataset.id]: []}
|
|
1723
|
+
: findFieldsToShow(dataset);
|
|
1724
|
+
const merged = {
|
|
1725
|
+
...state.interactionConfig.tooltip.config.fieldsToShow,
|
|
1726
|
+
...tooltipFields
|
|
1727
|
+
};
|
|
1728
|
+
|
|
1729
|
+
return set(['interactionConfig', 'tooltip', 'config', 'fieldsToShow'], merged, state);
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
export function initialFileLoadingProgress(file, index) {
|
|
1733
|
+
const fileName = file.name || `Untitled File ${index}`;
|
|
1734
|
+
return {
|
|
1735
|
+
[fileName]: {
|
|
1736
|
+
// percent of current file
|
|
1737
|
+
percent: 0,
|
|
1738
|
+
message: '',
|
|
1739
|
+
fileName,
|
|
1740
|
+
error: null
|
|
1741
|
+
}
|
|
1742
|
+
};
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
export function updateFileLoadingProgressUpdater(state, {fileName, progress}) {
|
|
1746
|
+
return pick_('fileLoadingProgress')(pick_(fileName)(merge_(progress)))(state);
|
|
1747
|
+
}
|
|
1748
|
+
/**
|
|
1749
|
+
* Helper function to update layer domains for an array of datasets
|
|
1750
|
+
* @type {typeof import('./vis-state-updaters').updateAllLayerDomainData}
|
|
1751
|
+
*/
|
|
1752
|
+
export function updateAllLayerDomainData(state, dataId, updatedFilter) {
|
|
1753
|
+
const dataIds = typeof dataId === 'string' ? [dataId] : dataId;
|
|
1754
|
+
const newLayers = [];
|
|
1755
|
+
const newLayerData = [];
|
|
1756
|
+
|
|
1757
|
+
state.layers.forEach((oldLayer, i) => {
|
|
1758
|
+
if (oldLayer.config.dataId && dataIds.includes(oldLayer.config.dataId)) {
|
|
1759
|
+
// No need to recalculate layer domain if filter has fixed domain
|
|
1760
|
+
const newLayer =
|
|
1761
|
+
updatedFilter && updatedFilter.fixedDomain
|
|
1762
|
+
? oldLayer
|
|
1763
|
+
: oldLayer.updateLayerDomain(state.datasets, updatedFilter);
|
|
1764
|
+
|
|
1765
|
+
const {layerData, layer} = calculateLayerData(newLayer, state, state.layerData[i]);
|
|
1766
|
+
|
|
1767
|
+
newLayers.push(layer);
|
|
1768
|
+
newLayerData.push(layerData);
|
|
1769
|
+
} else {
|
|
1770
|
+
newLayers.push(oldLayer);
|
|
1771
|
+
newLayerData.push(state.layerData[i]);
|
|
1772
|
+
}
|
|
1773
|
+
});
|
|
1774
|
+
|
|
1775
|
+
const newState = {
|
|
1776
|
+
...state,
|
|
1777
|
+
layers: newLayers,
|
|
1778
|
+
layerData: newLayerData
|
|
1779
|
+
};
|
|
1780
|
+
|
|
1781
|
+
return newState;
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
export function updateAnimationDomain(state) {
|
|
1785
|
+
// merge all animatable layer domain and update global config
|
|
1786
|
+
const animatableLayers = state.layers.filter(
|
|
1787
|
+
l =>
|
|
1788
|
+
l.config.isVisible &&
|
|
1789
|
+
l.config.animation &&
|
|
1790
|
+
l.config.animation.enabled &&
|
|
1791
|
+
Array.isArray(l.animationDomain)
|
|
1792
|
+
);
|
|
1793
|
+
|
|
1794
|
+
if (!animatableLayers.length) {
|
|
1795
|
+
return {
|
|
1796
|
+
...state,
|
|
1797
|
+
animationConfig: {
|
|
1798
|
+
...state.animationConfig,
|
|
1799
|
+
domain: null,
|
|
1800
|
+
defaultTimeFormat: null
|
|
1801
|
+
}
|
|
1802
|
+
};
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
const mergedDomain = animatableLayers.reduce(
|
|
1806
|
+
(accu, layer) => [
|
|
1807
|
+
Math.min(accu[0], layer.animationDomain[0]),
|
|
1808
|
+
Math.max(accu[1], layer.animationDomain[1])
|
|
1809
|
+
],
|
|
1810
|
+
[Number(Infinity), -Infinity]
|
|
1811
|
+
);
|
|
1812
|
+
const defaultTimeFormat = getTimeWidgetTitleFormatter(mergedDomain);
|
|
1813
|
+
|
|
1814
|
+
return {
|
|
1815
|
+
...state,
|
|
1816
|
+
animationConfig: {
|
|
1817
|
+
...state.animationConfig,
|
|
1818
|
+
currentTime: isInRange(state.animationConfig.currentTime, mergedDomain)
|
|
1819
|
+
? state.animationConfig.currentTime
|
|
1820
|
+
: mergedDomain[0],
|
|
1821
|
+
domain: mergedDomain,
|
|
1822
|
+
defaultTimeFormat
|
|
1823
|
+
}
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
/**
|
|
1828
|
+
* Update the status of the editor
|
|
1829
|
+
* @memberof visStateUpdaters
|
|
1830
|
+
* @type {typeof import('./vis-state-updaters').setEditorModeUpdater}
|
|
1831
|
+
*/
|
|
1832
|
+
export const setEditorModeUpdater = (state, {mode}) => ({
|
|
1833
|
+
...state,
|
|
1834
|
+
editor: {
|
|
1835
|
+
...state.editor,
|
|
1836
|
+
mode,
|
|
1837
|
+
selectedFeature: null
|
|
1838
|
+
}
|
|
1839
|
+
});
|
|
1840
|
+
|
|
1841
|
+
// const featureToFilterValue = (feature) => ({...feature, id: feature.id});
|
|
1842
|
+
/**
|
|
1843
|
+
* Update editor features
|
|
1844
|
+
* @memberof visStateUpdaters
|
|
1845
|
+
* @type {typeof import('./vis-state-updaters').setFeaturesUpdater}
|
|
1846
|
+
*/
|
|
1847
|
+
export function setFeaturesUpdater(state, {features = []}) {
|
|
1848
|
+
const lastFeature = features.length && features[features.length - 1];
|
|
1849
|
+
|
|
1850
|
+
const newState = {
|
|
1851
|
+
...state,
|
|
1852
|
+
editor: {
|
|
1853
|
+
...state.editor,
|
|
1854
|
+
// only save none filter features to editor
|
|
1855
|
+
features: features.filter(f => !getFilterIdInFeature(f)),
|
|
1856
|
+
mode: lastFeature && lastFeature.properties.isClosed ? EDITOR_MODES.EDIT : state.editor.mode
|
|
1857
|
+
}
|
|
1858
|
+
};
|
|
1859
|
+
|
|
1860
|
+
// Retrieve existing feature
|
|
1861
|
+
const {selectedFeature} = state.editor;
|
|
1862
|
+
|
|
1863
|
+
// If no feature is selected we can simply return since no operations
|
|
1864
|
+
if (!selectedFeature) {
|
|
1865
|
+
return newState;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
// TODO: check if the feature has changed
|
|
1869
|
+
const feature = features.find(f => f.id === selectedFeature.id);
|
|
1870
|
+
|
|
1871
|
+
// if feature is part of a filter
|
|
1872
|
+
const filterId = feature && getFilterIdInFeature(feature);
|
|
1873
|
+
if (filterId && feature) {
|
|
1874
|
+
const featureValue = featureToFilterValue(feature, filterId);
|
|
1875
|
+
const filterIdx = state.filters.findIndex(fil => fil.id === filterId);
|
|
1876
|
+
return setFilterUpdater(newState, {
|
|
1877
|
+
idx: filterIdx,
|
|
1878
|
+
prop: 'value',
|
|
1879
|
+
value: featureValue
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
return newState;
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
/**
|
|
1887
|
+
* Set the current selected feature
|
|
1888
|
+
* @memberof uiStateUpdaters
|
|
1889
|
+
* @type {typeof import('./vis-state-updaters').setSelectedFeatureUpdater}
|
|
1890
|
+
*/
|
|
1891
|
+
export const setSelectedFeatureUpdater = (state, {feature}) => ({
|
|
1892
|
+
...state,
|
|
1893
|
+
editor: {
|
|
1894
|
+
...state.editor,
|
|
1895
|
+
selectedFeature: feature
|
|
1896
|
+
}
|
|
1897
|
+
});
|
|
1898
|
+
|
|
1899
|
+
/**
|
|
1900
|
+
* Delete existing feature from filters
|
|
1901
|
+
* @memberof visStateUpdaters
|
|
1902
|
+
* @type {typeof import('./vis-state-updaters').deleteFeatureUpdater}
|
|
1903
|
+
*/
|
|
1904
|
+
export function deleteFeatureUpdater(state, {feature}) {
|
|
1905
|
+
if (!feature) {
|
|
1906
|
+
return state;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
const newState = {
|
|
1910
|
+
...state,
|
|
1911
|
+
editor: {
|
|
1912
|
+
...state.editor,
|
|
1913
|
+
selectedFeature: null
|
|
1914
|
+
}
|
|
1915
|
+
};
|
|
1916
|
+
|
|
1917
|
+
if (getFilterIdInFeature(feature)) {
|
|
1918
|
+
const filterIdx = newState.filters.findIndex(f => f.id === getFilterIdInFeature(feature));
|
|
1919
|
+
|
|
1920
|
+
return filterIdx > -1 ? removeFilterUpdater(newState, {idx: filterIdx}) : newState;
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
// modify editor object
|
|
1924
|
+
const newEditor = {
|
|
1925
|
+
...state.editor,
|
|
1926
|
+
features: state.editor.features.filter(f => f.id !== feature.id),
|
|
1927
|
+
selectedFeature: null
|
|
1928
|
+
};
|
|
1929
|
+
|
|
1930
|
+
return {
|
|
1931
|
+
...state,
|
|
1932
|
+
editor: newEditor
|
|
1933
|
+
};
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
/**
|
|
1937
|
+
* Toggle feature as layer filter
|
|
1938
|
+
* @memberof visStateUpdaters
|
|
1939
|
+
* @type {typeof import('./vis-state-updaters').setPolygonFilterLayerUpdater}
|
|
1940
|
+
*/
|
|
1941
|
+
export function setPolygonFilterLayerUpdater(state, payload) {
|
|
1942
|
+
const {layer, feature} = payload;
|
|
1943
|
+
const filterId = getFilterIdInFeature(feature);
|
|
1944
|
+
|
|
1945
|
+
// let newFilter = null;
|
|
1946
|
+
let filterIdx;
|
|
1947
|
+
let newLayerId = [layer.id];
|
|
1948
|
+
let newState = state;
|
|
1949
|
+
// If polygon filter already exists, we need to find out if the current layer is already included
|
|
1950
|
+
if (filterId) {
|
|
1951
|
+
filterIdx = state.filters.findIndex(f => f.id === filterId);
|
|
1952
|
+
|
|
1953
|
+
if (!state.filters[filterIdx]) {
|
|
1954
|
+
// what if filter doesn't exist?... not possible.
|
|
1955
|
+
// because features in the editor is passed in from filters and editors.
|
|
1956
|
+
// but we will move this feature back to editor just in case
|
|
1957
|
+
const noneFilterFeature = {
|
|
1958
|
+
...feature,
|
|
1959
|
+
properties: {
|
|
1960
|
+
...feature.properties,
|
|
1961
|
+
filterId: null
|
|
1962
|
+
}
|
|
1963
|
+
};
|
|
1964
|
+
|
|
1965
|
+
return {
|
|
1966
|
+
...state,
|
|
1967
|
+
editor: {
|
|
1968
|
+
...state.editor,
|
|
1969
|
+
features: [...state.editor.features, noneFilterFeature],
|
|
1970
|
+
selectedFeature: noneFilterFeature
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1973
|
+
}
|
|
1974
|
+
const filter = state.filters[filterIdx];
|
|
1975
|
+
const {layerId = []} = filter;
|
|
1976
|
+
const isLayerIncluded = layerId.includes(layer.id);
|
|
1977
|
+
|
|
1978
|
+
newLayerId = isLayerIncluded
|
|
1979
|
+
? // if layer is included, remove it
|
|
1980
|
+
layerId.filter(l => l !== layer.id)
|
|
1981
|
+
: [...layerId, layer.id];
|
|
1982
|
+
} else {
|
|
1983
|
+
// if we haven't create the polygon filter, create it
|
|
1984
|
+
const newFilter = generatePolygonFilter([], feature);
|
|
1985
|
+
filterIdx = state.filters.length;
|
|
1986
|
+
|
|
1987
|
+
// add feature, remove feature from eidtor
|
|
1988
|
+
newState = {
|
|
1989
|
+
...state,
|
|
1990
|
+
filters: [...state.filters, newFilter],
|
|
1991
|
+
editor: {
|
|
1992
|
+
...state.editor,
|
|
1993
|
+
features: state.editor.features.filter(f => f.id !== feature.id),
|
|
1994
|
+
selectedFeature: newFilter.value
|
|
1995
|
+
}
|
|
1996
|
+
};
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
return setFilterUpdater(newState, {
|
|
2000
|
+
idx: filterIdx,
|
|
2001
|
+
prop: 'layerId',
|
|
2002
|
+
value: newLayerId
|
|
2003
|
+
});
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
/**
|
|
2007
|
+
* @memberof visStateUpdaters
|
|
2008
|
+
* @type {typeof import('./vis-state-updaters').sortTableColumnUpdater}
|
|
2009
|
+
* @public
|
|
2010
|
+
*/
|
|
2011
|
+
export function sortTableColumnUpdater(state, {dataId, column, mode}) {
|
|
2012
|
+
const dataset = state.datasets[dataId];
|
|
2013
|
+
if (!dataset) {
|
|
2014
|
+
return state;
|
|
2015
|
+
}
|
|
2016
|
+
let sortMode = mode;
|
|
2017
|
+
if (!sortMode) {
|
|
2018
|
+
const currentMode = get(dataset, ['sortColumn', column]);
|
|
2019
|
+
// @ts-ignore - should be fixable in a TS file
|
|
2020
|
+
sortMode = currentMode
|
|
2021
|
+
? Object.keys(SORT_ORDER).find(m => m !== currentMode)
|
|
2022
|
+
: SORT_ORDER.ASCENDING;
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
const sorted = sortDatasetByColumn(dataset, column, sortMode);
|
|
2026
|
+
return set(['datasets', dataId], sorted, state);
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
/**
|
|
2030
|
+
* @memberof visStateUpdaters
|
|
2031
|
+
* @type {typeof import('./vis-state-updaters').pinTableColumnUpdater}
|
|
2032
|
+
* @public
|
|
2033
|
+
*/
|
|
2034
|
+
export function pinTableColumnUpdater(state, {dataId, column}) {
|
|
2035
|
+
const dataset = state.datasets[dataId];
|
|
2036
|
+
if (!dataset) {
|
|
2037
|
+
return state;
|
|
2038
|
+
}
|
|
2039
|
+
const field = dataset.fields.find(f => f.name === column);
|
|
2040
|
+
if (!field) {
|
|
2041
|
+
return state;
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
let pinnedColumns;
|
|
2045
|
+
if (Array.isArray(dataset.pinnedColumns) && dataset.pinnedColumns.includes(field.name)) {
|
|
2046
|
+
// unpin it
|
|
2047
|
+
pinnedColumns = dataset.pinnedColumns.filter(co => co !== field.name);
|
|
2048
|
+
} else {
|
|
2049
|
+
pinnedColumns = (dataset.pinnedColumns || []).concat(field.name);
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
return set(['datasets', dataId, 'pinnedColumns'], pinnedColumns, state);
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
/**
|
|
2056
|
+
* Copy column content as strings
|
|
2057
|
+
* @memberof visStateUpdaters
|
|
2058
|
+
* @type {typeof import('./vis-state-updaters').copyTableColumnUpdater}
|
|
2059
|
+
* @public
|
|
2060
|
+
*/
|
|
2061
|
+
export function copyTableColumnUpdater(state, {dataId, column}) {
|
|
2062
|
+
const dataset = state.datasets[dataId];
|
|
2063
|
+
if (!dataset) {
|
|
2064
|
+
return state;
|
|
2065
|
+
}
|
|
2066
|
+
const fieldIdx = dataset.fields.findIndex(f => f.name === column);
|
|
2067
|
+
if (fieldIdx < 0) {
|
|
2068
|
+
return state;
|
|
2069
|
+
}
|
|
2070
|
+
const {type} = dataset.fields[fieldIdx];
|
|
2071
|
+
const text = dataset.dataContainer
|
|
2072
|
+
.map(row => parseFieldValue(row.valueAt(fieldIdx), type), true)
|
|
2073
|
+
.join('\n');
|
|
2074
|
+
|
|
2075
|
+
copy(text);
|
|
2076
|
+
|
|
2077
|
+
return state;
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
/**
|
|
2081
|
+
* Update editor
|
|
2082
|
+
* @type {typeof import('./vis-state-updaters').toggleEditorVisibilityUpdater}
|
|
2083
|
+
*/
|
|
2084
|
+
export function toggleEditorVisibilityUpdater(state) {
|
|
2085
|
+
return {
|
|
2086
|
+
...state,
|
|
2087
|
+
editor: {
|
|
2088
|
+
...state.editor,
|
|
2089
|
+
visible: !state.editor.visible
|
|
2090
|
+
}
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
export function setFilterAnimationTimeConfigUpdater(state, {idx, config}) {
|
|
2095
|
+
const oldFilter = state.filters[idx];
|
|
2096
|
+
if (!oldFilter) {
|
|
2097
|
+
Console.error(`filters.${idx} is undefined`);
|
|
2098
|
+
return state;
|
|
2099
|
+
}
|
|
2100
|
+
if (oldFilter.type !== FILTER_TYPES.timeRange) {
|
|
2101
|
+
Console.error(
|
|
2102
|
+
`setFilterAnimationTimeConfig can only be called to update a time filter. check filter.type === 'timeRange'`
|
|
2103
|
+
);
|
|
2104
|
+
return state;
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
const updates = checkTimeConfigArgs(config);
|
|
2108
|
+
|
|
2109
|
+
return pick_('filters')(swap_(merge_(updates)(oldFilter)))(state);
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
function checkTimeConfigArgs(config) {
|
|
2113
|
+
const allowed = ['timeFormat', 'timezone'];
|
|
2114
|
+
return Object.keys(config).reduce((accu, prop) => {
|
|
2115
|
+
if (!allowed.includes(prop)) {
|
|
2116
|
+
Console.error(
|
|
2117
|
+
`setLayerAnimationTimeConfig takes timeFormat and/or timezone as options, found ${prop}`
|
|
2118
|
+
);
|
|
2119
|
+
return accu;
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
// here we are NOT checking if timezone or timeFormat input is valid
|
|
2123
|
+
accu[prop] = config[prop];
|
|
2124
|
+
return accu;
|
|
2125
|
+
}, {});
|
|
2126
|
+
}
|
|
2127
|
+
/**
|
|
2128
|
+
* Update editor
|
|
2129
|
+
* @type {typeof import('./vis-state-updaters').setLayerAnimationTimeConfigUpdater}
|
|
2130
|
+
*/
|
|
2131
|
+
export function setLayerAnimationTimeConfigUpdater(state, {config}) {
|
|
2132
|
+
if (!config) {
|
|
2133
|
+
return state;
|
|
2134
|
+
}
|
|
2135
|
+
const updates = checkTimeConfigArgs(config);
|
|
2136
|
+
return pick_('animationConfig')(merge_(updates))(state);
|
|
2137
|
+
}
|