kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
181 lines (162 loc) • 5.15 kB
JavaScript
// Copyright (c) 2019 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.
import {
generateHashId,
notNullorUndefined,
isPlainObject
} from '../utils/utils';
import DefaultWidgetIcon from './default-layer-icon';
export default class Widget {
constructor(props = {}) {
this.id = props.id || generateHashId(6);
// meta
this.meta = {};
// visConfigSettings
// this.visConfigSettings = {};
this.config = this.getDefaultWidgetConfig({
...props
});
}
get type() {
return null;
}
get name() {
return this.type;
}
get widgetIcon() {
return DefaultWidgetIcon;
}
get isWidgetAggregated() {
return false;
}
get requiredLayer() {
return [];
}
get widgetInfoModal() {
return null;
}
get widgetAggregatedData() {
return null;
}
calculateAggregationData(widget, state) {
return {newWidget: widget, updatedState: state};
}
getDefaultWidgetConfig(props = {}) {
return {
categoryField: props.categoryField || null,
dataId: props.dataId || null,
label: props.label || 'new widget',
isVisible: props.isVisible || false,
isConfigActive: props.isConfigActive || false,
fieldName: null,
selectedLayer: props.selectedLayer || null,
isCalculating: props.isCalculating || false,
bounds: props.bounds || true,
aggregatedData: props.aggregatedData || null,
aggregationType: props.aggregationType || null
};
}
updateWidgetConfig(newConfig) {
this.config = {...this.config, ...newConfig};
return this;
}
updateMeta(meta) {
this.meta = {...this.meta, ...meta};
}
assignConfigToWidget(configToCopy) {
const currentConfig = this.config;
const copied = this.copyWidgetConfig(currentConfig, configToCopy);
this.updateWidgetConfig(copied);
}
get aggregatedDataAffectingProps() {
// console.log('inside aggregatedDataAffectingProps');
return ['aggregationType', 'fieldName', 'mapState', 'bounds'];
}
/**
* Check whether layer has all columns
*
* @param {object} widget
* @returns {boolean} yes or no
*/
hasAllValues() {
const {aggregationType} = this.config;
return aggregationType;
}
isValidToSave() {
return this.type && this.hasAllValues();
}
shouldCalculateAggregatedData(props) {
return props.some(p => this.aggregatedDataAffectingProps.includes(p));
}
/*
* Recursively copy config over to an empty layer
* when received saved config, or copy config over from a different layer type
* make sure to only copy over value to existing keys
* @param {object} currentConfig - existing config to be override
* @param {object} configToCopy - new Config to copy over
* @param {string[]} notToDeepMerge - array of properties to not to be deep copied
* @param {string[]} notToCopy - array of properties not to copy
* @returns {object} - copied config
*/
copyWidgetConfig(currentConfig, configToCopy) {
const copied = {};
Object.keys(currentConfig).forEach(key => {
if (
isPlainObject(currentConfig[key]) &&
isPlainObject(configToCopy[key])
) {
// recursively assign object value
copied[key] = this.copyWidgetConfig(
currentConfig[key],
configToCopy[key]
);
} else if (notNullorUndefined(configToCopy[key])) {
// copy
copied[key] = configToCopy[key];
} else {
// keep existing
copied[key] = currentConfig[key];
}
});
return copied;
}
/**
* Assign a field to layer column, return column config
* @param key - Column Key
* @param field - Selected field
* @returns {{}} - Column config
*/
assignColumn(key, field) {
// field value could be null for optional columns
const update = field
? {
value: field.name,
fieldIdx: field.tableFieldIndex - 1
}
: {value: null, fieldIdx: -1};
return {
...this.config.columns,
[key]: {
...this.config.columns[key],
...update
}
};
}
}