kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
990 lines (955 loc) • 137 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.VIS_STATE_MERGERS = void 0;
exports.createLayerFromConfig = createLayerFromConfig;
exports.insertLayerAtRightOrder = insertLayerAtRightOrder;
exports.isSavedLayerConfigV1 = isSavedLayerConfigV1;
exports.mergeAnimationConfig = mergeAnimationConfig;
exports.mergeDatasetsByOrder = mergeDatasetsByOrder;
exports.mergeEditor = mergeEditor;
exports.mergeEffects = mergeEffects;
exports.mergeFilters = mergeFilters;
exports.mergeInteractionTooltipConfig = mergeInteractionTooltipConfig;
exports.mergeInteractions = mergeInteractions;
exports.mergeLayerBlending = mergeLayerBlending;
exports.mergeLayers = mergeLayers;
exports.mergeOverlayBlending = mergeOverlayBlending;
exports.mergeSplitMaps = mergeSplitMaps;
exports.parseLayerConfig = parseLayerConfig;
exports.replaceFilterDatasetIds = replaceFilterDatasetIds;
exports.serializeEffect = serializeEffect;
exports.serializeFilter = serializeFilter;
exports.serializeLayer = serializeLayer;
exports.serializeVisState = serializeVisState;
exports.validateColumn = validateColumn;
exports.validateLayerWithData = validateLayerWithData;
exports.validateLayersByDatasets = validateLayersByDatasets;
exports.validateSavedLayerColumns = validateSavedLayerColumns;
exports.validateSavedTextLabel = validateSavedTextLabel;
exports.validateSavedVisualChannels = validateSavedVisualChannels;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _lodash = _interopRequireDefault(require("lodash.uniq"));
var _lodash2 = _interopRequireDefault(require("lodash.pick"));
var _lodash3 = _interopRequireDefault(require("lodash.flattendeep"));
var _deepmerge = _interopRequireDefault(require("deepmerge"));
var _utils = require("@kepler.gl/utils");
var _effects = require("@kepler.gl/effects");
var _commonUtils = require("@kepler.gl/common-utils");
var _constants = require("@kepler.gl/constants");
var _schemas = require("@kepler.gl/schemas");
var _table = require("@kepler.gl/table");
var _layerUtils = require("./layer-utils");
var _excluded = ["enabled"];
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
/**
* Merge loaded filters with current state, if no fields or data are loaded
* save it for later
*
*/
function mergeFilters(state, filtersToMerge, fromConfig) {
var preserveFilterOrder = fromConfig ? filtersToMerge === null || filtersToMerge === void 0 ? void 0 : filtersToMerge.map(function (l) {
return l.id;
}) : state.preserveFilterOrder;
if (!Array.isArray(filtersToMerge) || !filtersToMerge.length) {
return state;
}
var _validateFiltersUpdat = (0, _utils.validateFiltersUpdateDatasets)(state, filtersToMerge),
validated = _validateFiltersUpdat.validated,
failed = _validateFiltersUpdat.failed,
updatedDatasets = _validateFiltersUpdat.updatedDatasets;
var updatedFilters = insertItemBasedOnPreservedOrder(state.filters, validated, preserveFilterOrder);
// merge filter with existing
updatedFilters = (0, _table.resetFilterGpuMode)(updatedFilters);
updatedFilters = (0, _table.assignGpuChannels)(updatedFilters);
// filter data
var datasetsToFilter = (0, _lodash["default"])((0, _lodash3["default"])(validated.map(function (f) {
return f.dataId;
})));
var filtered = (0, _utils.applyFiltersToDatasets)(datasetsToFilter, updatedDatasets, updatedFilters, state.layers);
return _objectSpread(_objectSpread({}, state), {}, {
filters: updatedFilters,
datasets: filtered,
preserveFilterOrder: preserveFilterOrder,
filterToBeMerged: [].concat((0, _toConsumableArray2["default"])(state.filterToBeMerged), (0, _toConsumableArray2["default"])(failed))
});
}
// replace dataId in saved Filter
function replaceFilterDatasetIds(savedFilter, dataId, dataIdToUse) {
var replaced = [];
savedFilter.forEach(function (filter) {
if (filter.dataId.includes(dataId)) {
var _filter$plotType;
var newDataId = filter.dataId.map(function (d) {
return d === dataId ? dataIdToUse : d;
});
var plotType;
// TODO: more generic approach to save plotType.colorsByDataId
if ((_filter$plotType = filter.plotType) !== null && _filter$plotType !== void 0 && (_filter$plotType = _filter$plotType.colorsByDataId) !== null && _filter$plotType !== void 0 && _filter$plotType[dataId]) {
var _filter$plotType2;
// replace colorByDataId in filter.plotType
var _ref = ((_filter$plotType2 = filter.plotType) === null || _filter$plotType2 === void 0 ? void 0 : _filter$plotType2.colorsByDataId) || {},
color = _ref[dataId],
rest = (0, _objectWithoutProperties2["default"])(_ref, [dataId].map(_toPropertyKey));
plotType = _objectSpread(_objectSpread({}, filter.plotType), {}, {
colorsByDataId: _objectSpread(_objectSpread({}, rest), {}, (0, _defineProperty2["default"])({}, dataIdToUse, color))
});
}
replaced.push(_objectSpread(_objectSpread({}, filter), {}, {
dataId: newDataId
}, plotType ? {
plotType: plotType
} : {}));
}
});
return replaced.length ? replaced : null;
}
function isSavedLayerConfigV1(layerConfig) {
// exported layer configuration contains visualChannels property
return layerConfig === null || layerConfig === void 0 ? void 0 : layerConfig.visualChannels;
}
function parseLayerConfig(schema, layerConfig) {
var _schema$parseSavedCon;
// assume the layer config is current version
var savedConfig = {
version: _schemas.CURRENT_VERSION,
config: {
visState: {
layers: [layerConfig],
layerOrder: [layerConfig.id]
}
}
};
return (_schema$parseSavedCon = schema.parseSavedConfig(savedConfig)) === null || _schema$parseSavedCon === void 0 || (_schema$parseSavedCon = _schema$parseSavedCon.visState) === null || _schema$parseSavedCon === void 0 || (_schema$parseSavedCon = _schema$parseSavedCon.layers) === null || _schema$parseSavedCon === void 0 ? void 0 : _schema$parseSavedCon[0];
}
function insertItemBasedOnPreservedOrder(currentItems, items) {
var preservedOrder = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
var defaultStart = arguments.length > 3 ? arguments[3] : undefined;
var newItems = (0, _toConsumableArray2["default"])(currentItems);
var _iterator = _createForOfIteratorHelper(items),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var item = _step.value;
var expectedIdx = preservedOrder.indexOf(item.id);
// insertAt the end by default
var insertAt = defaultStart ? 0 : newItems.length;
if (expectedIdx > 0) {
// look for layer to insert after
var i = expectedIdx + 1;
var preceedIdx = -1;
var _loop = function _loop() {
// keep looking for preceed layer that is already loaded
var preceedItemId = preservedOrder[i - 1];
preceedIdx = newItems.findIndex(function (d) {
return d.id === preceedItemId;
});
};
while (i-- > 0 && preceedIdx < 0) {
_loop();
}
if (preceedIdx > -1) {
// if found
insertAt = preceedIdx + 1;
}
}
newItems = (0, _utils.arrayInsert)(newItems, insertAt, item);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return newItems;
}
function createLayerFromConfig(state, layerConfig) {
// check if the layer config is parsed
var parsedLayerConfig = isSavedLayerConfigV1(layerConfig) ? parseLayerConfig(state.schema, layerConfig) : layerConfig;
if (!parsedLayerConfig) {
return null;
}
// first validate config against dataset
var _validateLayersByData = validateLayersByDatasets(state.datasets, state.layerClasses, [parsedLayerConfig], {
allowEmptyColumn: true
}),
validated = _validateLayersByData.validated,
failed = _validateLayersByData.failed;
if (failed !== null && failed !== void 0 && failed.length || !validated.length) {
// failed
return null;
}
var newLayer = validated[0];
newLayer.updateLayerDomain(state.datasets);
return newLayer;
}
/**
* Get loaded filter from state
*/
function serializeFilter(newFilter, schema) {
var _serializedVisState$f;
var serializedVisState = serializeVisState({
filters: [newFilter]
}, schema);
return serializedVisState === null || serializedVisState === void 0 || (_serializedVisState$f = serializedVisState.filters) === null || _serializedVisState$f === void 0 ? void 0 : _serializedVisState$f[0];
}
/**
* Get loaded layer from state
*/
function serializeLayer(newLayer, schema) {
var _serializedVisState$l;
var serializedVisState = serializeVisState({
layers: [newLayer],
layerOrder: [newLayer.id]
}, schema);
return serializedVisState === null || serializedVisState === void 0 || (_serializedVisState$l = serializedVisState.layers) === null || _serializedVisState$l === void 0 ? void 0 : _serializedVisState$l[0];
}
/**
* Get loaded effect from state
*/
function serializeEffect(newEffect, schema) {
var _serializedVisState$e;
var serializedVisState = serializeVisState({
effects: [newEffect],
effectOrder: [newEffect.id]
}, schema);
return serializedVisState === null || serializedVisState === void 0 || (_serializedVisState$e = serializedVisState.effects) === null || _serializedVisState$e === void 0 ? void 0 : _serializedVisState$e[0];
}
/**
* Get vis state config
*/
function serializeVisState(visState, schema) {
var _schema$parseSavedCon2;
var savedState = schema.getConfigToSave({
visState: visState
});
return savedState ? (_schema$parseSavedCon2 = schema.parseSavedConfig(savedState)) === null || _schema$parseSavedCon2 === void 0 ? void 0 : _schema$parseSavedCon2.visState : undefined;
}
/**
* Merge layers from de-serialized state, if no fields or data are loaded
* save it for later
*
*/
function mergeLayers(state) {
var layersToMerge = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var fromConfig = arguments.length > 2 ? arguments[2] : undefined;
var preserveLayerOrder = fromConfig ? (0, _layerUtils.getLayerOrderFromLayers)(layersToMerge) : state.preserveLayerOrder;
if (!Array.isArray(layersToMerge) || !layersToMerge.length) {
return state;
}
// don't merge layer if dataset is being merged
var unmerged = [];
var toMerge = [];
layersToMerge.forEach(function (l) {
var _l$config;
if (l !== null && l !== void 0 && (_l$config = l.config) !== null && _l$config !== void 0 && _l$config.dataId && state.isMergingDatasets[l.config.dataId]) {
unmerged.push(l);
} else {
toMerge.push(l);
}
});
var _validateLayersByData2 = validateLayersByDatasets(state.datasets, state.layerClasses, toMerge),
mergedLayer = _validateLayersByData2.validated,
failed = _validateLayersByData2.failed;
unmerged.push.apply(unmerged, (0, _toConsumableArray2["default"])(failed));
// put new layers in front of current layers
var _insertLayerAtRightOr = insertLayerAtRightOrder(state.layers, mergedLayer, state.layerOrder, preserveLayerOrder),
newLayerOrder = _insertLayerAtRightOr.newLayerOrder,
newLayers = _insertLayerAtRightOr.newLayers;
return _objectSpread(_objectSpread({}, state), {}, {
layers: newLayers,
layerOrder: newLayerOrder,
preserveLayerOrder: preserveLayerOrder,
layerToBeMerged: [].concat((0, _toConsumableArray2["default"])(state.layerToBeMerged), unmerged)
});
}
function insertLayerAtRightOrder(currentLayers, layersToInsert, currentOrder) {
var preservedOrder = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
if (!(layersToInsert !== null && layersToInsert !== void 0 && layersToInsert.length)) {
return {
newLayers: currentLayers,
newLayerOrder: currentOrder
};
}
// perservedOrder ['a', 'b', 'c'];
// layerOrder ['a', 'b', 'c']
var currentLayerQueue = currentOrder.map(function (id) {
return (0, _utils.findById)(id)(currentLayers);
}).filter(function (layer) {
return Boolean(layer);
});
var newLayers = currentLayers.concat(layersToInsert);
var newLayerOrderQueue = insertItemBasedOnPreservedOrder(currentLayerQueue, layersToInsert, preservedOrder, true);
// reconstruct layerOrder after insert
var newLayerOrder = (0, _layerUtils.getLayerOrderFromLayers)(newLayerOrderQueue);
return {
newLayerOrder: newLayerOrder,
newLayers: newLayers
};
}
/**
* Merge interactions with saved config
*
*/
function mergeInteractions(state, interactionToBeMerged) {
var merged = {};
var unmerged = {};
if (interactionToBeMerged) {
Object.keys(interactionToBeMerged).forEach(function (key) {
if (!state.interactionConfig[key]) {
return;
}
var currentConfig = key === 'tooltip' || key === 'brush' ? state.interactionConfig[key].config : null;
var _ref2 = interactionToBeMerged[key] || {},
enabled = _ref2.enabled,
configSaved = (0, _objectWithoutProperties2["default"])(_ref2, _excluded);
var configToMerge = configSaved;
if (key === 'tooltip') {
var _mergeInteractionTool = mergeInteractionTooltipConfig(state, configSaved),
mergedTooltip = _mergeInteractionTool.mergedTooltip,
unmergedTooltip = _mergeInteractionTool.unmergedTooltip;
// merge new dataset tooltips with original dataset tooltips
configToMerge = {
fieldsToShow: _objectSpread(_objectSpread({}, currentConfig.fieldsToShow), mergedTooltip)
};
if (Object.keys(unmergedTooltip).length) {
// @ts-expect-error
unmerged.tooltip = {
fieldsToShow: unmergedTooltip,
enabled: Boolean(enabled)
};
}
}
merged[key] = _objectSpread(_objectSpread({}, state.interactionConfig[key]), {}, {
enabled: Boolean(enabled)
}, currentConfig ? {
config: (0, _lodash2["default"])(_objectSpread(_objectSpread({}, currentConfig), configToMerge), Object.keys(currentConfig))
} : {});
});
}
var nextState = _objectSpread(_objectSpread({}, state), {}, {
interactionConfig: _objectSpread(_objectSpread({}, state.interactionConfig), merged),
interactionToBeMerged: savedUnmergedInteraction(state, unmerged)
});
return nextState;
}
function combineInteractionConfigs(configs) {
var combined = _objectSpread({}, configs[0]);
// handle each property key of an `InteractionConfig`, e.g. tooltip, geocoder, brush, coordinate
// by combining values for each among all passed in configs
var _loop2 = function _loop2(key) {
var toBeCombinedProps = configs.map(function (c) {
return c[key];
});
// all of these have an enabled boolean
combined[key] = {
// are any of the configs' enabled values true?
enabled: toBeCombinedProps.some(function (p) {
return p === null || p === void 0 ? void 0 : p.enabled;
})
};
if (key === 'tooltip') {
// are any of the configs' compareMode values true?
combined[key].compareMode = toBeCombinedProps.some(function (p) {
return p === null || p === void 0 ? void 0 : p.compareMode;
});
// return the compare type mode, it will be either absolute or relative
combined[key].compareType = getValueWithHighestOccurrence(toBeCombinedProps.map(function (p) {
return p.compareType;
}));
// combine fieldsToShow among all dataset ids
combined[key].fieldsToShow = toBeCombinedProps.map(function (p) {
return p.fieldsToShow;
}).reduce(function (acc, nextFieldsToShow) {
var _loop3 = function _loop3(nextDataIdKey) {
var nextTooltipFields = nextFieldsToShow[nextDataIdKey];
if (!acc[nextDataIdKey]) {
// if the dataset id is not present in the accumulator
// then add it with its tooltip fields
acc[nextDataIdKey] = nextTooltipFields;
} else {
// otherwise the dataset id is already present in the accumulator
// so only add the next tooltip fields for this dataset's array if they are not already present,
// using the tooltipField.name property for uniqueness
nextTooltipFields.forEach(function (nextTF) {
if (!acc[nextDataIdKey].find(function (_ref3) {
var name = _ref3.name;
return nextTF.name === name;
})) {
acc[nextDataIdKey].push(nextTF);
}
});
}
};
for (var nextDataIdKey in nextFieldsToShow) {
_loop3(nextDataIdKey);
}
return acc;
}, {});
}
if (key === 'brush') {
var _aggregate;
// keep the biggest brush size
combined[key].size = (_aggregate = (0, _utils.aggregate)(toBeCombinedProps, _constants.AGGREGATION_TYPES.maximum, function (p) {
return p.size;
})) !== null && _aggregate !== void 0 ? _aggregate : null;
}
};
for (var key in combined) {
_loop2(key);
}
return combined;
}
function savedUnmergedInteraction(state, unmerged) {
var _unmerged$tooltip, _unmerged$tooltip2, _state$interactionToB, _unmerged$tooltip3;
if (!(unmerged !== null && unmerged !== void 0 && (_unmerged$tooltip = unmerged.tooltip) !== null && _unmerged$tooltip !== void 0 && _unmerged$tooltip.fieldsToShow)) {
return state.interactionToBeMerged;
}
return {
tooltip: _objectSpread(_objectSpread(_objectSpread({}, state.interactionToBeMerged.tooltip), typeof (unmerged === null || unmerged === void 0 || (_unmerged$tooltip2 = unmerged.tooltip) === null || _unmerged$tooltip2 === void 0 ? void 0 : _unmerged$tooltip2.enabled) === 'boolean' ? {
enabled: unmerged.tooltip.enabled
} : {}), {}, {
fieldsToShow: _objectSpread(_objectSpread({}, (_state$interactionToB = state.interactionToBeMerged) === null || _state$interactionToB === void 0 || (_state$interactionToB = _state$interactionToB.tooltip) === null || _state$interactionToB === void 0 ? void 0 : _state$interactionToB.fieldsToShow), unmerged === null || unmerged === void 0 || (_unmerged$tooltip3 = unmerged.tooltip) === null || _unmerged$tooltip3 === void 0 ? void 0 : _unmerged$tooltip3.fieldsToShow)
})
};
}
function replaceInteractionDatasetIds(interactionConfig, dataId, dataIdToReplace) {
var _interactionConfig$to;
if (interactionConfig !== null && interactionConfig !== void 0 && (_interactionConfig$to = interactionConfig.tooltip) !== null && _interactionConfig$to !== void 0 && _interactionConfig$to.fieldsToShow[dataId]) {
var _interactionConfig$to2;
return _objectSpread(_objectSpread({}, interactionConfig), {}, {
tooltip: _objectSpread(_objectSpread({}, interactionConfig.tooltip), {}, {
fieldsToShow: (0, _defineProperty2["default"])({}, dataIdToReplace, interactionConfig === null || interactionConfig === void 0 || (_interactionConfig$to2 = interactionConfig.tooltip) === null || _interactionConfig$to2 === void 0 ? void 0 : _interactionConfig$to2.fieldsToShow[dataId])
})
});
}
return null;
}
/**
* Merge splitMaps config with current visStete.
* 1. if current map is split, but splitMap DOESNOT contain maps
* : don't merge anything
* 2. if current map is NOT split, but splitMaps contain maps
* : add to splitMaps, and add current layers to splitMaps
*/
function mergeSplitMaps(state) {
var splitMaps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var merged = (0, _toConsumableArray2["default"])(state.splitMaps);
var unmerged = [];
splitMaps.forEach(function (sm, i) {
var entries = Object.entries(sm.layers);
if (entries.length > 0) {
entries.forEach(function (_ref4) {
var _ref5 = (0, _slicedToArray2["default"])(_ref4, 2),
id = _ref5[0],
value = _ref5[1];
// check if layer exists
var pushTo = state.layers.find(function (l) {
return l.id === id;
}) ? merged : unmerged;
// create map panel if current map is not split
pushTo[i] = pushTo[i] || _objectSpread(_objectSpread({}, sm), {}, {
layers: pushTo === merged ? (0, _utils.getInitialMapLayersForSplitMap)(state.layers) : []
});
pushTo[i].layers = _objectSpread(_objectSpread({}, pushTo[i].layers), {}, (0, _defineProperty2["default"])({}, id, value));
});
} else {
// We are merging if there are no layers in both split map
merged.push(sm);
}
});
return _objectSpread(_objectSpread({}, state), {}, {
splitMaps: merged,
splitMapsToBeMerged: [].concat((0, _toConsumableArray2["default"])(state.splitMapsToBeMerged), unmerged)
});
}
/**
* Merge effects with saved config
*/
function mergeEffects(state, effects, fromConfig) {
var newEffects = [].concat((0, _toConsumableArray2["default"])(state.effects), (0, _toConsumableArray2["default"])((effects || []).map(function (effect) {
return fromConfig ? (0, _effects.createEffect)(_deepmerge["default"].all([effect, {
// collapse all panels when loading effects
isConfigActive: false
}])) : effect;
}).filter(function (effect) {
return Boolean(effect && effect.isValidToSave());
})));
return _objectSpread(_objectSpread({}, state), {}, {
effects: newEffects,
effectOrder: newEffects.map(function (effect) {
return effect.id;
})
});
}
/**
* Merge interactionConfig.tooltip with saved config,
* validate fieldsToShow
*
* @param state
* @param tooltipConfig
* @return - {mergedTooltip: {}, unmergedTooltip: {}}
*/
function mergeInteractionTooltipConfig(state) {
var tooltipConfig = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var unmergedTooltip = {};
var mergedTooltip = {};
if (!tooltipConfig || !tooltipConfig.fieldsToShow || !Object.keys(tooltipConfig.fieldsToShow).length) {
return {
mergedTooltip: mergedTooltip,
unmergedTooltip: unmergedTooltip
};
}
var _loop4 = function _loop4() {
if (!state.datasets[dataId] || state.isMergingDatasets[dataId]) {
// is not yet loaded
unmergedTooltip[dataId] = tooltipConfig.fieldsToShow[dataId];
} else {
// if dataset is loaded
var allFields = state.datasets[dataId].fields.map(function (d) {
return d.name;
});
var foundFieldsToShow = tooltipConfig.fieldsToShow[dataId].filter(function (field) {
return allFields.includes(field.name);
});
mergedTooltip[dataId] = foundFieldsToShow;
}
};
for (var dataId in tooltipConfig.fieldsToShow) {
_loop4();
}
return {
mergedTooltip: mergedTooltip,
unmergedTooltip: unmergedTooltip
};
}
/**
* Merge layerBlending with saved
*
*/
function mergeLayerBlending(state, layerBlending) {
if (layerBlending && _constants.LAYER_BLENDINGS[layerBlending]) {
return _objectSpread(_objectSpread({}, state), {}, {
layerBlending: layerBlending
});
}
return state;
}
/**
* Combines multiple layer blending configs into a single string
* by returning the one with the highest occurrence
*/
function combineLayerBlendingConfigs(configs) {
// return the mode of the layer blending type
return getValueWithHighestOccurrence(configs);
}
/**
* Merge overlayBlending with saved
*/
function mergeOverlayBlending(state, overlayBlending) {
if (overlayBlending && _constants.OVERLAY_BLENDINGS[overlayBlending]) {
return _objectSpread(_objectSpread({}, state), {}, {
overlayBlending: overlayBlending
});
}
return state;
}
/**
* Combines multiple overlay blending configs into a single string
* by returning the one with the highest occurrence
**/
function combineOverlayBlendingConfigs(configs) {
// return the mode of the overlay blending type
return getValueWithHighestOccurrence(configs);
}
/**
* Merge animation config
*/
function mergeAnimationConfig(state, animation) {
if (animation && animation.currentTime) {
return _objectSpread(_objectSpread({}, state), {}, {
animationConfig: _objectSpread(_objectSpread(_objectSpread({}, state.animationConfig), animation), {}, {
domain: null
})
});
}
return state;
}
function combineAnimationConfigs(configs) {
var _aggregate2, _aggregate3;
// get the smallest values of currentTime and speed among all configs
return {
currentTime: (_aggregate2 = (0, _utils.aggregate)(configs, _constants.AGGREGATION_TYPES.minimum, function (c) {
return c.currentTime;
})) !== null && _aggregate2 !== void 0 ? _aggregate2 : null,
speed: (_aggregate3 = (0, _utils.aggregate)(configs, _constants.AGGREGATION_TYPES.minimum, function (c) {
return c.speed;
})) !== null && _aggregate3 !== void 0 ? _aggregate3 : null
};
}
/**
* Validate saved layer columns with new data,
* update fieldIdx based on new fields
*
* @param fields
* @param savedCols
* @param emptyCols
* @param options
* @return - validated columns or null
*/
function validateSavedLayerColumns(fields) {
var savedCols = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var emptyCols = arguments.length > 2 ? arguments[2] : undefined;
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
// Prepare columns for the validator
var columns = {};
var _loop5 = function _loop5() {
var key = _Object$keys[_i];
columns[key] = _objectSpread({}, emptyCols[key]);
var saved = savedCols[key];
if (saved) {
var fieldIdx = fields.findIndex(function (_ref6) {
var name = _ref6.name;
return name === saved;
});
if (fieldIdx > -1) {
// update found columns
columns[key].fieldIdx = fieldIdx;
columns[key].value = saved;
}
}
};
for (var _i = 0, _Object$keys = Object.keys(emptyCols); _i < _Object$keys.length; _i++) {
_loop5();
}
// find actual column fieldIdx, in case it has changed
var allColFound = Object.keys(columns).every(function (key) {
return validateColumn(columns[key], columns, fields);
});
var rv = allColFound ? columns : null;
if (options.throwOnError) {
var requiredColumns = Object.keys(emptyCols).filter(function (k) {
return !emptyCols[k].optional;
});
var missingColumns = requiredColumns.filter(function (k) {
return !(columns !== null && columns !== void 0 && columns[k].value);
});
if (missingColumns.length) {
throw new Error("Layer has missing or invalid columns: ".concat(missingColumns.join(', ')));
}
var configColumns = Object.keys(savedCols);
var invalidColumns = configColumns.filter(function (k) {
var _columns$k;
return !(columns !== null && columns !== void 0 && (_columns$k = columns[k]) !== null && _columns$k !== void 0 && _columns$k.value);
});
if (invalidColumns.length) {
throw new Error("Layer has invalid columns: ".concat(invalidColumns.join(', ')));
}
}
return rv;
}
/**
* Validate layer column
*/
function validateColumn(column, columns, allFields) {
if (column.optional || column.value) {
return true;
}
if (column.validator) {
return column.validator(column, columns, allFields);
}
return false;
}
/**
* Validate saved text label config with new data
* refer to vis-state-schema.js TextLabelSchemaV1
*
* @param {Array<Object>} fields
* @param {Object} savedTextLabel
* @param {Object} options
* @return {Object} - validated textlabel
*/
function validateSavedTextLabel(fields, _ref7, savedTextLabel) {
var _ref8 = (0, _slicedToArray2["default"])(_ref7, 1),
layerTextLabel = _ref8[0];
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
var savedTextLabels = Array.isArray(savedTextLabel) ? savedTextLabel : [savedTextLabel];
// validate field
return savedTextLabels.map(function (textLabel) {
var field = textLabel.field ? fields.find(function (fd) {
return Object.keys(textLabel.field).every(function (key) {
return textLabel.field[key] === fd[key];
});
}) : null;
if (field === undefined && options.throwOnError) {
throw new Error("Layer has invalid text label field: ".concat(JSON.stringify(textLabel.field)));
}
return Object.keys(layerTextLabel).reduce(function (accu, key) {
return _objectSpread(_objectSpread({}, accu), {}, (0, _defineProperty2["default"])({}, key, key === 'field' ? field : textLabel[key] || layerTextLabel[key]));
}, {});
});
}
/**
* Validate saved visual channels config with new data,
* refer to vis-state-schema.js VisualChannelSchemaV1
*/
function validateSavedVisualChannels(fields, newLayer, savedLayer) {
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
Object.values(newLayer.visualChannels).forEach(function (_ref9) {
var field = _ref9.field,
scale = _ref9.scale,
key = _ref9.key;
var foundField;
if (savedLayer.config) {
if (savedLayer.config[field]) {
foundField = fields.find(function (fd) {
return savedLayer.config && fd.name === savedLayer.config[field].name;
});
}
var foundChannel = _objectSpread(_objectSpread({}, foundField ? (0, _defineProperty2["default"])({}, field, foundField) : {}), savedLayer.config[scale] ? (0, _defineProperty2["default"])({}, scale, savedLayer.config[scale]) : {});
if (Object.keys(foundChannel).length) {
newLayer.updateLayerConfig(foundChannel);
}
newLayer.validateVisualChannel(key);
if (options.throwOnError) {
var _savedLayer$config, _newLayer$config$fiel;
var fieldName = (_savedLayer$config = savedLayer.config) === null || _savedLayer$config === void 0 || (_savedLayer$config = _savedLayer$config[field]) === null || _savedLayer$config === void 0 ? void 0 : _savedLayer$config.name;
if (fieldName && fieldName !== ((_newLayer$config$fiel = newLayer.config[field]) === null || _newLayer$config$fiel === void 0 ? void 0 : _newLayer$config$fiel.name)) {
throw new Error("Layer has invalid visual channel field: ".concat(field));
}
}
}
});
return newLayer;
}
function validateLayersByDatasets(datasets, layerClasses) {
var layers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
var options = arguments.length > 3 ? arguments[3] : undefined;
var validated = [];
var failed = [];
layers.forEach(function (layer) {
var _layer$config;
var validateLayer = null;
if (layer !== null && layer !== void 0 && (_layer$config = layer.config) !== null && _layer$config !== void 0 && _layer$config.dataId) {
if (datasets[layer.config.dataId]) {
// datasets are already loaded
validateLayer = validateLayerWithData(datasets[layer.config.dataId], layer, layerClasses, options);
}
}
if (validateLayer) {
validated.push(validateLayer);
} else {
// datasets not yet loaded
failed.push(layer);
}
});
return {
validated: validated,
failed: failed
};
}
/**
* Get required columns for validation based on column mode
*/
function _getColumnConfigForValidation(newLayer) {
// find column fieldIdx
var columnConfig = newLayer.getLayerColumns();
// if columnMode is defined, find column mode config
var colModeConfig = newLayer.config.columnMode ? (newLayer.supportedColumnModes || []).find(function (colMode) {
return colMode.key === newLayer.config.columnMode;
}) : null;
if (colModeConfig) {
// only validate columns in column mode
columnConfig = [].concat((0, _toConsumableArray2["default"])(colModeConfig.requiredColumns || []), (0, _toConsumableArray2["default"])(colModeConfig.optionalColumns || [])).reduce(function (accu, key) {
return _objectSpread(_objectSpread({}, accu), {}, (0, _defineProperty2["default"])({}, key, columnConfig[key]));
}, {});
}
return columnConfig;
}
/**
* Validate saved layer config with new data,
* update fieldIdx based on new fields
*/
// eslint-disable-next-line complexity
function validateLayerWithData(dataset, savedLayer, layerClasses) {
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
var fields = dataset.fields,
dataId = dataset.id;
var type = savedLayer.type;
var throwOnError = options.throwOnError;
// layer doesnt have a valid type
if (!type || !Object.prototype.hasOwnProperty.call(layerClasses, type) || !savedLayer.config) {
if (throwOnError) {
throw new Error("Layer has invalid type \"".concat(type, "\" or config is missing"));
}
return null;
}
var newLayer = new layerClasses[type]({
id: savedLayer.id,
dataId: dataId,
label: savedLayer.config.label,
color: savedLayer.config.color,
isVisible: savedLayer.config.isVisible,
hidden: savedLayer.config.hidden,
columnMode: savedLayer.config.columnMode,
highlightColor: savedLayer.config.highlightColor
});
var columnConfig = _getColumnConfigForValidation(newLayer);
if (Object.keys(columnConfig)) {
var columns = validateSavedLayerColumns(fields, savedLayer.config.columns, columnConfig, options);
if (columns) {
newLayer.updateLayerConfig({
columns: _objectSpread(_objectSpread({}, newLayer.config.columns), columns)
});
} else if (!options.allowEmptyColumn) {
return null;
}
}
var textLabel = savedLayer.config.textLabel && newLayer.config.textLabel ? validateSavedTextLabel(fields, newLayer.config.textLabel, savedLayer.config.textLabel, options) : newLayer.config.textLabel;
// copy visConfig over to emptyLayer to make sure it has all the props
var copiedVisConfig = newLayer.copyLayerConfig(newLayer.config.visConfig, savedLayer.config.visConfig || {}, {
shallowCopy: ['colorRange', 'strokeColorRange']
});
// call layer methods to validate visConfig when switching dataset
var visConfig = newLayer.validateVisConfig ? newLayer.validateVisConfig(dataset, copiedVisConfig) : copiedVisConfig;
newLayer.updateLayerConfig({
visConfig: visConfig,
textLabel: textLabel
});
// visual channel field is saved to be {name, type}
// find visual channel field by matching both name and type
// refer to vis-state-schema.js VisualChannelSchemaV1
newLayer = validateSavedVisualChannels(fields, newLayer, savedLayer, options);
if (throwOnError) {
if (!newLayer.isValidToSave()) {
throw new Error("Layer is not valid to save: ".concat(newLayer.id));
}
}
return newLayer;
}
function mergeEditor(state, savedEditor) {
var _savedEditor$visible;
if (!savedEditor) {
return state;
}
return _objectSpread(_objectSpread({}, state), {}, {
editor: _objectSpread(_objectSpread({}, state.editor), {}, {
features: [].concat((0, _toConsumableArray2["default"])(state.editor.features), (0, _toConsumableArray2["default"])(savedEditor.features || [])),
// if savedEditor.visible is undefined keep state.editor.visible
visible: (_savedEditor$visible = savedEditor.visible) !== null && _savedEditor$visible !== void 0 ? _savedEditor$visible : state.editor.visible
})
});
}
function combineEditorConfigs(configs) {
return configs.reduce(function (acc, nextConfig) {
return _objectSpread(_objectSpread({}, acc), {}, {
features: [].concat((0, _toConsumableArray2["default"])(acc.features), (0, _toConsumableArray2["default"])(nextConfig.features || []))
});
}, {
// start with:
// - empty array for features accumulation
// - and are any of the configs' visible values true?
features: [],
visible: configs.some(function (c) {
return c === null || c === void 0 ? void 0 : c.visible;
})
});
}
/**
* Validate saved layer config with new data,
* update fieldIdx based on new fields
*/
function mergeDatasetsByOrder(state, newDataEntries) {
var merged = _objectSpread(_objectSpread({}, state.datasets), newDataEntries);
if (Array.isArray(state.preserveDatasetOrder)) {
// preserveDatasetOrder might not include the new datasets
var newDatasetIds = Object.keys(merged).filter(function (id) {
var _state$preserveDatase;
return !((_state$preserveDatase = state.preserveDatasetOrder) !== null && _state$preserveDatase !== void 0 && _state$preserveDatase.includes(id));
});
return [].concat((0, _toConsumableArray2["default"])(state.preserveDatasetOrder), (0, _toConsumableArray2["default"])(newDatasetIds)).reduce(function (accu, dataId) {
return _objectSpread(_objectSpread({}, accu), merged[dataId] ? (0, _defineProperty2["default"])({}, dataId, merged[dataId]) : {});
}, {});
}
return merged;
}
/**
* Simliar purpose to aggregation utils `getMode` function,
* but returns the mode in the same value type without coercing to a string.
* It ignores `undefined` or `null` values, but returns `null` if no mode could be calculated.
*/
function getValueWithHighestOccurrence(arr) {
var _ref13;
var tallys = new Map();
arr.forEach(function (value) {
if ((0, _commonUtils.notNullorUndefined)(value)) {
if (!tallys.has(value)) {
tallys.set(value, 1);
} else {
tallys.set(value, tallys.get(value) + 1);
}
}
});
// return the value with the highest total occurrence count
if (tallys.size === 0) {
return null;
}
return (_ref13 = (0, _toConsumableArray2["default"])(tallys.entries())) === null || _ref13 === void 0 ? void 0 : _ref13.reduce(function (acc, next) {
return next[1] > acc[1] ? next : acc;
})[0];
}
var VIS_STATE_MERGERS = exports.VIS_STATE_MERGERS = [{
merge: mergeLayers,
prop: 'layers',
toMergeProp: 'layerToBeMerged',
preserveOrder: 'preserveLayerOrder'
}, {
merge: mergeFilters,
prop: 'filters',
toMergeProp: 'filterToBeMerged',
preserveOrder: 'preserveFilterOrder',
replaceParentDatasetIds: replaceFilterDatasetIds
}, {
merge: mergeEffects,
prop: 'effects'
}, {
merge: mergeInteractions,
prop: 'interactionConfig',
toMergeProp: 'interactionToBeMerged',
replaceParentDatasetIds: replaceInteractionDatasetIds,
saveUnmerged: savedUnmergedInteraction,
combineConfigs: combineInteractionConfigs
}, {
merge: mergeLayerBlending,
prop: 'layerBlending',
combineConfigs: combineLayerBlendingConfigs
}, {
merge: mergeOverlayBlending,
prop: 'overlayBlending',
combineConfigs: combineOverlayBlendingConfigs
}, {
merge: mergeSplitMaps,
prop: 'splitMaps',
toMergeProp: 'splitMapsToBeMerged'
}, {
merge: mergeAnimationConfig,
prop: 'animationConfig',
combineConfigs: combineAnimationConfigs
}, {
merge: mergeEditor,
prop: 'editor',
combineConfigs: combineEditorConfigs
}];
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9kYXNoIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfbG9kYXNoMiIsIl9sb2Rhc2gzIiwiX2RlZXBtZXJnZSIsIl91dGlscyIsIl9lZmZlY3RzIiwiX2NvbW1vblV0aWxzIiwiX2NvbnN0YW50cyIsIl9zY2hlbWFzIiwiX3RhYmxlIiwiX2xheWVyVXRpbHMiLCJfZXhjbHVkZWQiLCJfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlciIsInIiLCJlIiwidCIsIlN5bWJvbCIsIml0ZXJhdG9yIiwiQXJyYXkiLCJpc0FycmF5IiwiX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5IiwibGVuZ3RoIiwiX24iLCJGIiwicyIsIm4iLCJkb25lIiwidmFsdWUiLCJmIiwiVHlwZUVycm9yIiwibyIsImEiLCJ1IiwiY2FsbCIsIm5leHQiLCJfYXJyYXlMaWtlVG9BcnJheSIsInRvU3RyaW5nIiwic2xpY2UiLCJjb25zdHJ1Y3RvciIsIm5hbWUiLCJmcm9tIiwidGVzdCIsIl90b1Byb3BlcnR5S2V5IiwiaSIsIl90b1ByaW1pdGl2ZSIsIl90eXBlb2YiLCJ0b1ByaW1pdGl2ZSIsIlN0cmluZyIsIk51bWJlciIsIm93bktleXMiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwiZmlsdGVyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwiZW51bWVyYWJsZSIsInB1c2giLCJhcHBseSIsIl9vYmplY3RTcHJlYWQiLCJhcmd1bWVudHMiLCJmb3JFYWNoIiwiX2RlZmluZVByb3BlcnR5MiIsImdldE93blByb3BlcnR5RGVzY3JpcHRvcnMiLCJkZWZpbmVQcm9wZXJ0aWVzIiwiZGVmaW5lUHJvcGVydHkiLCJtZXJnZUZpbHRlcnMiLCJzdGF0ZSIsImZpbHRlcnNUb01lcmdlIiwiZnJvbUNvbmZpZyIsInByZXNlcnZlRmlsdGVyT3JkZXIiLCJtYXAiLCJsIiwiaWQiLCJfdmFsaWRhdGVGaWx0ZXJzVXBkYXQiLCJ2YWxpZGF0ZUZpbHRlcnNVcGRhdGVEYXRhc2V0cyIsInZhbGlkYXRlZCIsImZhaWxlZCIsInVwZGF0ZWREYXRhc2V0cyIsInVwZGF0ZWRGaWx0ZXJzIiwiaW5zZXJ0SXRlbUJhc2VkT25QcmVzZXJ2ZWRPcmRlciIsImZpbHRlcnMiLCJyZXNldEZpbHRlckdwdU1vZGUiLCJhc3NpZ25HcHVDaGFubmVscyIsImRhdGFzZXRzVG9GaWx0ZXIiLCJ1bmlxIiwiZmxhdHRlbkRlZXAiLCJkYXRhSWQiLCJmaWx0ZXJlZCIsImFwcGx5RmlsdGVyc1RvRGF0YXNldHMiLCJsYXllcnMiLCJkYXRhc2V0cyIsImZpbHRlclRvQmVNZXJnZWQiLCJjb25jYXQiLCJfdG9Db25zdW1hYmxlQXJyYXkyIiwicmVwbGFjZUZpbHRlckRhdGFzZXRJZHMiLCJzYXZlZEZpbHRlciIsImRhdGFJZFRvVXNlIiwicmVwbGFjZWQiLCJpbmNsdWRlcyIsIl9maWx0ZXIkcGxvdFR5cGUiLCJuZXdEYXRhSWQiLCJkIiwicGxvdFR5cGUiLCJjb2xvcnNCeURhdGFJZCIsIl9maWx0ZXIkcGxvdFR5cGUyIiwiX3JlZiIsImNvbG9yIiwicmVzdCIsIl9vYmplY3RXaXRob3V0UHJvcGVydGllczIiLCJpc1NhdmVkTGF5ZXJDb25maWdWMSIsImxheWVyQ29uZmlnIiwidmlzdWFsQ2hhbm5lbHMiLCJwYXJzZUxheWVyQ29uZmlnIiwic2NoZW1hIiwiX3NjaGVtYSRwYXJzZVNhdmVkQ29uIiwic2F2ZWRDb25maWciLCJ2ZXJzaW9uIiwiQ1VSUkVOVF9WRVJTSU9OIiwiY29uZmlnIiwidmlzU3RhdGUiLCJsYXllck9yZGVyIiwicGFyc2VTYXZlZENvbmZpZyIsImN1cnJlbnRJdGVtcyIsIml0ZW1zIiwicHJlc2VydmVkT3JkZXIiLCJ1bmRlZmluZWQiLCJkZWZhdWx0U3RhcnQiLCJuZXdJdGVtcyIsIl9pdGVyYXRvciIsIl9zdGVwIiwiaXRlbSIsImV4cGVjdGVkSWR4IiwiaW5kZXhPZiIsImluc2VydEF0IiwicHJlY2VlZElkeCIsIl9sb29wIiwicHJlY2VlZEl0ZW1JZCIsImZpbmRJbmRleCIsImFycmF5SW5zZXJ0IiwiZXJyIiwiY3JlYXRlTGF5ZXJGcm9tQ29uZmlnIiwicGFyc2VkTGF5ZXJDb25maWciLCJfdmFsaWRhdGVMYXllcnNCeURhdGEiLCJ2YWxpZGF0ZUxheWVyc0J5RGF0YXNldHMiLCJsYXllckNsYXNzZXMiLCJhbGxvd0VtcHR5Q29sdW1uIiwibmV3TGF5ZXIiLCJ1cGRhdGVMYXllckRvbWFpbiIsInNlcmlhbGl6ZUZpbHRlciIsIm5ld0ZpbHRlciIsIl9zZXJpYWxpemVkVmlzU3RhdGUkZiIsInNlcmlhbGl6ZWRWaXNTdGF0ZSIsInNlcmlhbGl6ZVZpc1N0YXRlIiwic2VyaWFsaXplTGF5ZXIiLCJfc2VyaWFsaXplZFZpc1N0YXRlJGwiLCJzZXJpYWxpemVFZmZlY3QiLCJuZXdFZmZlY3QiLCJfc2VyaWFsaXplZFZpc1N0YXRlJGUiLCJlZmZlY3RzIiwiZWZmZWN0T3JkZXIiLCJfc2NoZW1hJHBhcnNlU2F2ZWRDb24yIiwic2F2ZWRTdGF0ZSIsImdldENvbmZpZ1RvU2F2ZSIsIm1lcmdlTGF5ZXJzIiwibGF5ZXJzVG9NZXJnZSIsInByZXNlcnZlTGF5ZXJPcmRlciIsImdldExheWVyT3JkZXJGcm9tTGF5ZXJzIiwidW5tZXJnZWQiLCJ0b01lcmdlIiwiX2wkY29uZmlnIiwiaXNNZXJnaW5nRGF0YXNldHMiLCJfdmFsaWRhdGVMYXllcnNCeURhdGEyIiwibWVyZ2VkTGF5ZXIiLCJfaW5zZXJ0TGF5ZXJBdFJpZ2h0T3IiLCJpbnNlcnRMYXllckF0UmlnaHRPcmRlciIsIm5ld0xheWVyT3JkZXIiLCJuZXdMYXllcnMiLCJsYXllclRvQmVNZXJnZWQiLCJjdXJyZW50TGF5ZXJzIiwibGF5ZXJzVG9JbnNlcnQiLCJjdXJyZW50T3JkZXIiLCJjdXJyZW50TGF5ZXJRdWV1ZSIsImZpbmRCeUlkIiwibGF5ZXIiLCJCb29sZWFuIiwibmV3TGF5ZXJPcmRlclF1ZXVlIiwibWVyZ2VJbnRlcmFjdGlvbnMiLCJpbnRlcmFjdGlvblRvQmVNZXJnZWQiLCJtZXJnZWQiLCJrZXkiLCJpbnRlcmFjdGlvbkNvbmZpZyIsImN1cnJlbnRDb25maWciLCJfcmVmMiIsImVuYWJsZWQiLCJjb25maWdTYXZlZCIsImNvbmZpZ1RvTWVyZ2UiLCJfbWVyZ2VJbnRlcmFjdGlvblRvb2wiLCJtZXJnZUludGVyYWN0aW9uVG9vbHRpcENvbmZpZyIsIm1lcmdlZFRvb2x0aXAiLCJ1bm1lcmdlZFRvb2x0aXAiLCJmaWVsZHNUb1Nob3ciLCJ0b29sdGlwIiwicGljayIsIm5leHRTdGF0ZSIsInNhdmVkVW5tZXJnZWRJbnRlcmFjdGlvbiIsImNvbWJpbmVJbnRlcmFjdGlvbkNvbmZpZ3MiLCJjb25maWdzIiwiY29tYmluZWQiLCJfbG9vcDIiLCJ0b0JlQ29tYmluZWRQcm9wcyIsImMiLCJzb21lIiwicCIsImNvbXBhcmVNb2RlIiwiY29tcGFyZVR5cGUiLCJnZXRWYWx1ZVdpdGhIaWdoZXN0T2NjdXJyZW5jZSIsInJlZHVjZSIsImFjYyIsIm5leHRGaWVsZHNUb1Nob3ciLCJfbG9vcDMiLCJuZXh0RGF0YUlkS2V5IiwibmV4dFRvb2x0aXBGaWVsZHMiLCJuZXh0VEYiLCJmaW5kIiwiX3JlZjMiLCJfYWdncmVnYXRlIiwic2l6ZSIsImFnZ3JlZ2F0ZSIsIkFHR1JFR0FUSU9OX1RZUEVTIiwibWF4aW11bSIsIl91bm1lcmdlZCR0b29sdGlwIiwiX3VubWVyZ2VkJHRvb2x0aXAyIiwiX3N0YXRlJGludGVyYWN0aW9uVG9CIiwiX3VubWVyZ2VkJHRvb2x0aXAzIiwicmVwbGFjZUludGVyYWN0aW9uRGF0YXNldElkcyIsImRhdGFJZFRvUmVwbGFjZSIsIl9pbnRlcmFjdGlvbkNvbmZpZyR0byIsIl9pbnRlcmFjdGlvbkNvbmZpZyR0bzIiLCJtZXJnZVNwbGl0TWFwcyIsInNwbGl0TWFwcyIsInNtIiwiZW50cmllcyIsIl9yZWY0IiwiX3JlZjUiLCJfc2xpY2VkVG9BcnJheTIiLCJwdXNoVG8iLCJnZXRJbml0aWFsTWFwTGF5ZXJzRm9yU3BsaXRNYXAiLCJzcGxpdE1hcHNUb0JlTWVyZ2VkIiwibWVyZ2VFZmZlY3RzIiwibmV3RWZmZWN0cyIsImVmZmVjdCIsImNyZWF0ZUVmZmVjdCIsImRlZXBtZXJnZSIsImFsbCIsImlzQ29uZmlnQWN0aXZlIiwiaXNWYWxpZFRvU2F2ZSIsInRvb2x0aXBDb25maWciLCJfbG9vcDQiLCJhbGxGaWVsZHMiLCJmaWVsZHMiLCJmb3VuZEZpZWxkc1RvU2hvdyIsImZpZWxkIiwibWVyZ2VMYXllckJsZW5kaW5nIiwibGF5ZXJCbGVuZGluZyIsIkxBWUVSX0JMRU5ESU5HUyIsImNvbWJpbmVMYXllckJsZW5kaW5nQ29uZmlncyIsIm1lcmdlT3ZlcmxheUJsZW5kaW5nIiwib3ZlcmxheUJsZW5kaW5nIiwiT1ZFUkxBWV9CTEVORElOR1MiLCJjb21iaW5lT3ZlcmxheUJsZW5kaW5nQ29uZmlncyIsIm1lcmdlQW5pbWF0aW9uQ29uZmlnIiwiYW5pbWF0aW9uIiwiY3VycmVudFRpbWUiLCJhbmltYXRpb25Db25maWciLCJkb21haW4iLCJjb21iaW5lQW5pbWF0aW9uQ29uZmlncyIsIl9hZ2dyZWdhdGUyIiwiX2FnZ3JlZ2F0ZTMiLCJtaW5pbXVtIiwic3BlZWQiLCJ2YWxpZGF0ZVNhdmVkTGF5ZXJDb2x1bW5zIiwic2F2ZWRDb2xzIiwiZW1wdHlDb2xzIiwib3B0aW9ucyIsImNvbHVtbnMiLCJfbG9vcDUiLCJfT2JqZWN0JGtleXMiLCJfaSIsInNhdmVkIiwiZmllbGRJZHgiLCJfcmVmNiIsImFsbENvbEZvdW5kIiwiZXZlcnkiLCJ2YWxpZGF0ZUNvbHVtbiIsInJ2IiwidGhyb3dPbkVycm9yIiwicmVxdWlyZWRDb2x1bW5zIiwiayIsIm9wdGlvbmFsIiwibWlzc2luZ0NvbHVtbnMiLCJFcnJvciIsImpvaW4iLCJjb25maWdDb2x1bW5zIiwiaW52YWxpZENvbHVtbnMiLCJfY29sdW1ucyRrIiwiY29sdW1uIiwidmFsaWRhdG9yIiwidmFsaWRhdGVTYXZlZFRleHRMYWJlbCIsIl9yZWY3Iiwic2F2ZWRUZXh0TGFiZWwiLCJfcmVmOCIsImxheWVyVGV4dExhYmVsIiwic2F2ZWRUZXh0TGFiZWxzIiwidGV4dExhYmVsIiwiZmQiLCJKU09OIiwic3RyaW5naWZ5IiwiYWNjdSIsInZhbGlkYXRlU2F2ZWRWaXN1YWxDaGFubmVscyIsInNhdmVkTGF5ZXIiLCJ2YWx1ZXMiLCJfcmVmOSIsInNjYWxlIiwiZm91bmRGaWVsZCIsImZvdW5kQ2hhbm5lbCIsInVwZGF0ZUxheWVyQ29uZmlnIiwidmFsaWRhdGVWaXN1YWxDaGFubmVsIiwiX3NhdmVkTGF5ZXIkY29uZmlnIiwiX25ld0xheWVyJGNvbmZpZyRmaWVsIiwiZmllbGROYW1lIiwiX2xheWVyJGNvbmZpZyIsInZhbGlkYXRlTGF5ZXIiLCJ2YWxpZGF0ZUxheWVyV2l0aERhdGEiLCJfZ2V0Q29sdW1uQ29uZmlnRm9yVmFsaWRhdGlvbiIsImNvbHVtbkNvbmZpZyIsImdldExheWVyQ29sdW1ucyIsImNvbE1vZGVDb25maWciLCJjb2x1bW5Nb2RlIiwic3VwcG9ydGVkQ29sdW1uTW9kZXMiLCJjb2xNb2RlIiwib3B0aW9uYWxDb2x1bW5zIiwiZGF0YXNldCIsInR5cGUiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImxhYmVsIiwiaXNWaXNpYmxlIiwiaGlkZGVuIiwiaGlnaGxpZ2h0Q29sb3IiLCJjb3BpZWRWaXNDb25maWciLCJjb3B5TGF5ZXJDb25maWciLCJ2aXNDb25maWciLCJzaGFsbG93Q29weSIsInZhbGlkYXRlVmlzQ29uZmlnIiwibWVyZ2VFZGl0b3IiLCJzYXZlZEVkaXRvciIsIl9zYXZlZEVkaXRvciR2aXNpYmxlIiwiZWRpdG9yIiwiZmVhdHVyZXMiLCJ2aXNpYmxlIiwiY29tYmluZUVkaXRvckNvbmZpZ3MiLCJuZXh0Q29uZmlnIiwibWVyZ2VEYXRhc2V0c0J5T3JkZXIiLCJuZXdEYXRhRW50cmllcyIsInByZXNlcnZlRGF0YXNldE9yZGVyIiwibmV3RGF0YXNldElkcyIsIl9zdGF0ZSRwcmVzZXJ2ZURhdGFzZSIsImFyciIsIl9yZWYxMyIsInRhbGx5cyIsIk1hcCIsIm5vdE51bGxvclVuZGVmaW5lZCIsImhhcyIsInNldCIsImdldCIsIlZJU19TVEFURV9NRVJHRVJTIiwiZXhwb3J0cyIsIm1lcmdlIiwicHJvcCIsInRvTWVyZ2VQcm9wIiwicHJlc2VydmVPcmRlciIsInJlcGxhY2VQYXJlbnREYXRhc2V0SWRzIiwic2F2ZVVubWVyZ2VkIiwiY29tYmluZUNvbmZpZ3MiXSwic291cmNlcyI6WyIuLi9zcmMvdmlzLXN0YXRlLW1lcmdlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQgdW5pcSBmcm9tICdsb2Rhc2gudW5pcSc7XG5pbXBvcnQgcGljayBmcm9tICdsb2Rhc2gucGljayc7XG5pbXBvcnQgZmxhdHRlbkRlZXAgZnJvbSAnbG9kYXNoLmZsYXR0ZW5kZWVwJztcbmltcG9ydCBkZWVwbWVyZ2UgZnJvbSAnZGVlcG1lcmdlJztcbmltcG9ydCB7XG4gIGFycmF5SW5zZXJ0LFxuICBnZXRJbml0aWFsTWFwTGF5ZXJzRm9yU3BsaXRNYXAsXG4gIGFwcGx5RmlsdGVyc1RvRGF0YXNldHMsXG4gIHZhbGlkYXRlRmlsdGVyc1VwZGF0ZURhdGFzZXRzLFxuICBmaW5kQnlJZCxcbiAgYWdncmVnYXRlXG59IGZyb20gJ0BrZXBsZXIuZ2wvdXRpbHMnO1xuXG5pbXBvcnQge0xheWVyfSBmcm9tICdAa2VwbGVyLmdsL2xheWVycyc7XG5pbXBvcnQge2NyZWF0ZUVmZmVjdH0gZnJvbSAnQGtlc