UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

708 lines (659 loc) 18.8 kB
// Copyright (c) 2020 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // vis-state-reducer import ActionTypes from 'constants/action-types'; /** * Update layer base config: dataId, label, column, isVisible * @memberof visStateActions * @param {Object} oldLayer - layer to be updated * @param {Object} newConfig - new config * @returns {{type: ActionTypes.LAYER_CONFIG_CHANGE, oldLayer: oldLayer, newConfig: newConfig}} * @public */ export function layerConfigChange(oldLayer, newConfig) { return { type: ActionTypes.LAYER_CONFIG_CHANGE, oldLayer, newConfig }; } /** * Update layer text label * @memberof visStateActions * @param {Object} oldLayer - layer to be updated * @param {Number} idx -`idx` of text label to be updated * @param {string} prop - `prop` of text label, e,g, `anchor`, `alignment`, `color`, `size`, `field` * @param {*} value - new value * @returns {{type: ActionTypes.LAYER_TEXT_LABEL_CHANGE, oldLayer: oldLayer, idx: idx, prop: prop, value:}} * @public */ export function layerTextLabelChange(oldLayer, idx, prop, value) { return { type: ActionTypes.LAYER_TEXT_LABEL_CHANGE, oldLayer, idx, prop, value }; } /** * Update layer type. Previews layer config will be copied if applicable. * @memberof visStateActions * @param {Object} oldLayer - layer to be updated * @param {string} newType - new type * @returns {{type: ActionTypes.LAYER_TYPE_CHANGE, oldLayer: oldLayer, newType: newType}} * @public */ export function layerTypeChange(oldLayer, newType) { return { type: ActionTypes.LAYER_TYPE_CHANGE, oldLayer, newType }; } /** * Update layer visual channel * @memberof visStateActions * @param {Object} oldLayer - layer to be updated * @param {Object} newConfig - new visual channel config * @param {string} channel - channel to be updated * @returns {{type: ActionTypes.LAYER_VISUAL_CHANNEL_CHANGE, oldLayer: oldLayer, newConfig: newConfig, channel: channel}} * @public */ export function layerVisualChannelConfigChange(oldLayer, newConfig, channel) { return { type: ActionTypes.LAYER_VISUAL_CHANNEL_CHANGE, oldLayer, newConfig, channel }; } /** * Update layer `visConfig` * @memberof visStateActions * @param {Object} oldLayer - layer to be updated * @param {Object} newVisConfig - new visConfig as a key value map: e.g. `{opacity: 0.8}` * @returns {{type: ActionTypes.LAYER_VIS_CONFIG_CHANGE, oldLayer: oldLayer, newVisConfig: newVisConfig}} * @public */ export function layerVisConfigChange(oldLayer, newVisConfig) { return { type: ActionTypes.LAYER_VIS_CONFIG_CHANGE, oldLayer, newVisConfig }; } /** * Set the color palette ui for layer color * @memberOf visStateActions * @param {Object} oldLayer - layer to be updated * @param {String} prop - which color prop * @param {object} newConfig - to be merged * @public */ export function layerColorUIChange(oldLayer, prop, newConfig) { return { type: ActionTypes.LAYER_COLOR_UI_CHANGE, oldLayer, prop, newConfig }; } /** * Update layer blending mode * @memberof visStateActions * @param {string} mode one of `additive`, `normal` and `subtractive` * @returns {{type: ActionTypes.UPDATE_LAYER_BLENDING, mode: mode}} * @public */ export function updateLayerBlending(mode) { return { type: ActionTypes.UPDATE_LAYER_BLENDING, mode }; } /** * Update `interactionConfig` * @memberof visStateActions * @param {Object} config - new config as key value map: `{tooltip: {enabled: true}}` * @returns {{type: ActionTypes.INTERACTION_CONFIG_CHANGE, config: config}} * @public */ export function interactionConfigChange(config) { return { type: ActionTypes.INTERACTION_CONFIG_CHANGE, config }; } /** * Update filter property * @memberof visStateActions * @param {Number} idx -`idx` of filter to be updated * @param {string} prop - `prop` of filter, e,g, `dataId`, `name`, `value` * @param {*} value - new value * @param {Number} valueIndex - array properties like dataset require index in order to improve performance * @returns {{type: ActionTypes.SET_FILTER, idx: idx, prop: prop, value: value}} * @public */ export function setFilter(idx, prop, value, valueIndex) { return { type: ActionTypes.SET_FILTER, idx, prop, value, valueIndex }; } /** * Add a new filter * @memberof visStateActions * @param {string} dataId - dataset `id` this new filter is associated with * @returns {{type: ActionTypes.ADD_FILTER, dataId: dataId}} * @public */ export function addFilter(dataId) { return { type: ActionTypes.ADD_FILTER, dataId }; } /** * Add a new layer * @memberof visStateActions * @param {Object} props - new layer props * @returns {{type: ActionTypes.ADD_LAYER, props: props}} * @public */ export function addLayer(props) { return { type: ActionTypes.ADD_LAYER, props }; } /** * Reorder layer, order is an array of layer indexes, index 0 will be the one at the bottom * @memberof visStateActions * @param {Array<Number>} order an array of layer indexes * @returns {{type: ActionTypes.REORDER_LAYER, order: order}} * @public * @example * * // bring `layers[1]` below `layers[0]`, the sequence layers will be rendered is `1`, `0`, `2`, `3`. * // `1` will be at the bottom, `3` will be at the top. * this.props.dispatch(reorderLayer([1, 0, 2, 3])); */ export function reorderLayer(order) { return { type: ActionTypes.REORDER_LAYER, order }; } /** * Remove a filter from `visState.filters`, once a filter is removed, data will be re-filtered and layer will be updated * @memberof visStateActions * @param {Number} idx idx of filter to be removed * @returns {{type: ActionTypes.REMOVE_FILTER, idx: idx}} * @public */ export function removeFilter(idx) { return { type: ActionTypes.REMOVE_FILTER, idx }; } /** * Remove a layer * @memberof visStateActions * @param {Number} idx idx of layer to be removed * @returns {{type: ActionTypes.REMOVE_LAYER, idx: idx}} * @public */ export function removeLayer(idx) { return { type: ActionTypes.REMOVE_LAYER, idx }; } /** * Remove a dataset and all layers, filters, tooltip configs that based on it * @memberof visStateActions * @param {string} key dataset id * @returns {{type: ActionTypes.REMOVE_DATASET, key: key}} * @public */ export function removeDataset(key) { return { type: ActionTypes.REMOVE_DATASET, key }; } /** * Display dataset table in a modal * @memberof visStateActions * @param {string} dataId dataset id to show in table * @returns {{type: ActionTypes.SHOW_DATASET_TABLE, dataId: dataId}} * @public */ export function showDatasetTable(dataId) { return { type: ActionTypes.SHOW_DATASET_TABLE, dataId }; } /** * Sort dataset column, for table display * @param {string} dataId * @param {string} column * @param {string} mode */ export function sortTableColumn(dataId, column, mode) { return { type: ActionTypes.SORT_TABLE_COLUMN, dataId, column, mode }; } /** * Pin dataset column, for table display * @param {string} dataId * @param {string} column */ export function pinTableColumn(dataId, column) { return { type: ActionTypes.PIN_TABLE_COLUMN, dataId, column }; } /** * Copy column, for table display * @param {string} dataId * @param {string} column */ export function copyTableColumn(dataId, column) { return { type: ActionTypes.COPY_TABLE_COLUMN, dataId, column }; } /** * Add new dataset to `visState`, with option to load a map config along with the datasets * @memberof visStateActions * @param {Array<Object>|Object} datasets - ***required** datasets can be a dataset or an array of datasets * Each dataset object needs to have `info` and `data` property. * @param {Object} datasets.info -info of a dataset * @param {string} datasets.info.id - id of this dataset. If config is defined, `id` should matches the `dataId` in config. * @param {string} datasets.info.label - A display name of this dataset * @param {Object} datasets.data - ***required** The data object, in a tabular format with 2 properties `fields` and `rows` * @param {Array<Object>} datasets.data.fields - ***required** Array of fields, * @param {string} datasets.data.fields.name - ***required** Name of the field, * @param {Array<Array>} datasets.data.rows - ***required** Array of rows, in a tabular format with `fields` and `rows` * @param {Object} options * @param {boolean} options.centerMap `default: true` if `centerMap` is set to `true` kepler.gl will * place the map view within the data points boundaries * @param {boolean} options.readOnly `default: false` if `readOnly` is set to `true` * the left setting panel will be hidden * @param {Object} config this object will contain the full kepler.gl instance configuration {mapState, mapStyle, visState} * @returns {{type: ActionTypes.UPDATE_VIS_DATA, datasets: datasets, options: options, config: config}} * @public */ export function updateVisData(datasets, options, config) { return { type: ActionTypes.UPDATE_VIS_DATA, datasets, options, config }; } /** * Start and end filter animation * @memberof visStateActions * @param {Number} idx - idx of filter * @returns {{type: ActionTypes.TOGGLE_FILTER_ANIMATION, idx: idx}} * @public */ export function toggleFilterAnimation(idx) { return { type: ActionTypes.TOGGLE_FILTER_ANIMATION, idx }; } /** * Change filter animation speed * @memberof visStateActions * @param {Number} idx - `idx` of filter * @param {Number} speed - `speed` to change it to. `speed` is a multiplier * @returns {{type: ActionTypes.UPDATE_FILTER_ANIMATION_SPEED, idx: idx, speed: speed}} * @public */ export function updateFilterAnimationSpeed(idx, speed) { return { type: ActionTypes.UPDATE_FILTER_ANIMATION_SPEED, idx, speed }; } /** * Reset animation * @memberof visStateActions * @param {Number} value - Current value of the slider * @returns {{type: ActionTypes.UPDATE_ANIMATION_TIME, value: value}} * @public */ export function updateAnimationTime(value) { return { type: ActionTypes.UPDATE_ANIMATION_TIME, value }; } /** * update trip layer animation speed * @memberof visStateActions * @param {Number} speed - `speed` to change it to. `speed` is a multiplier * @returns {{type: ActionTypes.UPDATE_LAYER_ANIMATION_SPEED, speed: speed}} * @public */ export function updateLayerAnimationSpeed(speed) { return { type: ActionTypes.UPDATE_LAYER_ANIMATION_SPEED, speed }; } /** * Show larger time filter at bottom for time playback (apply to time filter only) * @memberof visStateActions * @param {Number} idx - index of filter to enlarge * @returns {{type: ActionTypes.ENLARGE_FILTER, idx: idx}} * @public */ export function enlargeFilter(idx) { return { type: ActionTypes.ENLARGE_FILTER, idx }; } /** * Show/hide filter feature on map * @memberof visStateActions * @param {Number} idx - index of filter feature to show/hide * @return {{type: ActionTypes.TOGGLE_FILTER_FEATURE, idx: idx}} */ export function toggleFilterFeature(idx) { return { type: ActionTypes.TOGGLE_FILTER_FEATURE, idx }; } /** * Trigger layer hover event with hovered object * @memberof visStateActions * @param {Object} info - Object hovered, returned by deck.gl * @returns {{type: ActionTypes.LAYER_HOVER, info: info}} * @public */ export function onLayerHover(info) { return { type: ActionTypes.LAYER_HOVER, info }; } /** * Trigger layer click event with clicked object * @memberof visStateActions * @param {Object} info - Object clicked, returned by deck.gl * @returns {{type: ActionTypes.LAYER_CLICK, info: info}} * @public */ export function onLayerClick(info) { return { type: ActionTypes.LAYER_CLICK, info }; } /** * Trigger map click event, unselect clicked object * @memberof visStateActions * @returns {{type: ActionTypes.MAP_CLICK}} * @public */ export function onMapClick() { return { type: ActionTypes.MAP_CLICK }; } /** * Trigger map mouse moveevent, payload would be * React-map-gl PointerEvent * https://uber.github.io/react-map-gl/#/documentation/api-reference/pointer-event * * @memberof visStateActions * @param {Object} evt - PointerEvent * @returns {{type: ActionTypes.MAP_CLICK}} * @public */ export function onMouseMove(evt) { return { type: ActionTypes.MOUSE_MOVE, evt }; } /** * Toggle visibility of a layer in a split map * @memberof visStateActions * @param {Number} mapIndex - index of the split map * @param {string} layerId - id of the layer * @returns {{type: ActionTypes.TOGGLE_LAYER_FOR_MAP, mapIndex: *, layerId: *}} * @public */ export function toggleLayerForMap(mapIndex, layerId) { return { type: ActionTypes.TOGGLE_LAYER_FOR_MAP, mapIndex, layerId }; } /** * Set the property of a filter plot * @memberof visStateActions * @param {Number} idx * @param {Object} newProp key value mapping of new prop `{yAxis: 'histogram'}` * @returns {{type: ActionTypes.SET_FILTER_PLOT, idx: *, newProp: *}} * @public */ export function setFilterPlot(idx, newProp) { return { type: ActionTypes.SET_FILTER_PLOT, idx, newProp }; } /** * Set the property of a filter plot * @memberof visStateActions * @param {Number} idx * @param {Object} newProp key value mapping of new prop `{yAxis: 'histogram'}` * @returns {{type: ActionTypes.SET_FILTER_PLOT, idx: *, newProp: *}} * @public */ export function setMapInfo(info) { return { type: ActionTypes.SET_MAP_INFO, info }; } /** * Trigger file loading dispatch `addDataToMap` if succeed, or `loadFilesErr` if failed * @memberof visStateActions * @param {Array<Object>} files array of fileblob * @returns {{type: ActionTypes.LOAD_FILES, files: *}} * @public */ export function loadFiles(files) { return { type: ActionTypes.LOAD_FILES, files }; } /** * called with next file to load * @param {object} payload * @param {Array<object>} payload.fileCache * @param {Array<object>} payload.filesToLoad * @param {number} payload.totalCount * @param {Function} payload.onFinish - action creator to execute when all files are loaded */ export function loadNextFile({fileCache, filesToLoad, totalCount, onFinish}) { return { type: ActionTypes.LOAD_NEXT_FILE, fileCache, filesToLoad, totalCount, onFinish }; } /** * called when all files are processed and loaded * @param {Array<object>} result */ export function loadFileSuccess(result) { return { type: ActionTypes.LOAD_FILES_SUCCESS, result }; } /** * Trigger loading file error * @memberof visStateActions * @param {*} error * @returns {{type: ActionTypes.LOAD_FILES_ERR, error: Object}} * @public */ export function loadFilesErr(error) { return { type: ActionTypes.LOAD_FILES_ERR, error }; } /** * Store features to state * @memberof visStateActions * @param {Array<Object>} features * @returns {{type: ActionTypes.SET_FEATURES, features: Object}} */ export function setFeatures(features) { return { type: ActionTypes.SET_FEATURES, features }; } /** * It will apply the provide feature as filter to the given layer. * If the given feature is already applied as filter to the layer, it will remove the layer from the filter * @memberof visStateActions * @param {Object} layer * @param {Object} feature * @return {{feature: *, type: ActionTypes.SET_POLYGON_FILTER_LAYER, layer: *}} */ export function setPolygonFilterLayer(layer, feature) { return { type: ActionTypes.SET_POLYGON_FILTER_LAYER, layer, feature }; } /** * Set the current feature to be edited/deleted * @memberof visStateActions * @param {Object} feature * @return {{feature: feature, type: ActionTypes.SET_SELECTED_FEATURE}} */ export function setSelectedFeature(feature) { return { type: ActionTypes.SET_SELECTED_FEATURE, feature }; } /** * Delete the given feature * @memberof visStateActions * @param {Object} feature * @return {{type: ActionTypes.DELETE_FEATURE, feature: feature}} */ export function deleteFeature(feature) { return { type: ActionTypes.DELETE_FEATURE, feature }; } /** Set the map mode * @memberof visStateActions * @param {string} mode one of EDITOR_MODES * @return {{type: ActionTypes. SET_EDITOR_MODE, mode: *}} * @public * @example * import {setMapMode} from 'kepler.gl/actions'; * import {EDITOR_MODES} from 'kepler.gl/constants'; * * this.props.dispatch(setMapMode(EDITOR_MODES.DRAW_POLYGON)); */ export function setEditorMode(mode) { return { type: ActionTypes.SET_EDITOR_MODE, mode }; } /** * Trigger CPU filter of selected dataset * @memberof visStateActions * @param {string | Arrary<string>} dataId - single dataId or an array of dataIds * @returns {{type: ActionTypes.APPLY_CPU_FILTER, dataId: string}} * @public */ export function applyCPUFilter(dataId) { return { type: ActionTypes.APPLY_CPU_FILTER, dataId }; } /** * Toggle editor layer visibility * @memberof visStateActions * @return {{type: ActionTypes.TOGGLE_EDITOR_VISIBILITY}} */ export function toggleEditorVisibility() { return { type: ActionTypes.TOGGLE_EDITOR_VISIBILITY }; } /** * This declaration is needed to group actions in docs */ /** * Actions handled mostly by `visState` reducer. * They manage how data is processed, filtered and displayed on the map by operates on layers, * filters and interaction settings. * * @public */ /* eslint-disable no-unused-vars */ const visStateActions = null; /* eslint-enable no-unused-vars */