UNPKG

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
"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 _uniq = _interopRequireDefault(require("lodash/uniq")); var _pick = _interopRequireDefault(require("lodash/pick")); var _flattenDeep = _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, _uniq["default"])((0, _flattenDeep["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, _pick["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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfdW5pcSIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiX3BpY2siLCJfZmxhdHRlbkRlZXAiLCJfZGVlcG1lcmdlIiwiX3V0aWxzIiwiX2VmZmVjdHMiLCJfY29tbW9uVXRpbHMiLCJfY29uc3RhbnRzIiwiX3NjaGVtYXMiLCJfdGFibGUiLCJfbGF5ZXJVdGlscyIsIl9leGNsdWRlZCIsIl9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyIiwiciIsImUiLCJ0IiwiU3ltYm9sIiwiaXRlcmF0b3IiLCJBcnJheSIsImlzQXJyYXkiLCJfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkiLCJsZW5ndGgiLCJfbiIsIkYiLCJzIiwibiIsImRvbmUiLCJ2YWx1ZSIsImYiLCJUeXBlRXJyb3IiLCJvIiwiYSIsInUiLCJjYWxsIiwibmV4dCIsIl9hcnJheUxpa2VUb0FycmF5IiwidG9TdHJpbmciLCJzbGljZSIsImNvbnN0cnVjdG9yIiwibmFtZSIsImZyb20iLCJ0ZXN0IiwiX3RvUHJvcGVydHlLZXkiLCJpIiwiX3RvUHJpbWl0aXZlIiwiX3R5cGVvZiIsInRvUHJpbWl0aXZlIiwiU3RyaW5nIiwiTnVtYmVyIiwib3duS2V5cyIsIk9iamVjdCIsImtleXMiLCJnZXRPd25Qcm9wZXJ0eVN5bWJvbHMiLCJmaWx0ZXIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJkZWZpbmVQcm9wZXJ0eSIsIm1lcmdlRmlsdGVycyIsInN0YXRlIiwiZmlsdGVyc1RvTWVyZ2UiLCJmcm9tQ29uZmlnIiwicHJlc2VydmVGaWx0ZXJPcmRlciIsIm1hcCIsImwiLCJpZCIsIl92YWxpZGF0ZUZpbHRlcnNVcGRhdCIsInZhbGlkYXRlRmlsdGVyc1VwZGF0ZURhdGFzZXRzIiwidmFsaWRhdGVkIiwiZmFpbGVkIiwidXBkYXRlZERhdGFzZXRzIiwidXBkYXRlZEZpbHRlcnMiLCJpbnNlcnRJdGVtQmFzZWRPblByZXNlcnZlZE9yZGVyIiwiZmlsdGVycyIsInJlc2V0RmlsdGVyR3B1TW9kZSIsImFzc2lnbkdwdUNoYW5uZWxzIiwiZGF0YXNldHNUb0ZpbHRlciIsInVuaXEiLCJmbGF0dGVuRGVlcCIsImRhdGFJZCIsImZpbHRlcmVkIiwiYXBwbHlGaWx0ZXJzVG9EYXRhc2V0cyIsImxheWVycyIsImRhdGFzZXRzIiwiZmlsdGVyVG9CZU1lcmdlZCIsImNvbmNhdCIsIl90b0NvbnN1bWFibGVBcnJheTIiLCJyZXBsYWNlRmlsdGVyRGF0YXNldElkcyIsInNhdmVkRmlsdGVyIiwiZGF0YUlkVG9Vc2UiLCJyZXBsYWNlZCIsImluY2x1ZGVzIiwiX2ZpbHRlciRwbG90VHlwZSIsIm5ld0RhdGFJZCIsImQiLCJwbG90VHlwZSIsImNvbG9yc0J5RGF0YUlkIiwiX2ZpbHRlciRwbG90VHlwZTIiLCJfcmVmIiwiY29sb3IiLCJyZXN0IiwiX29iamVjdFdpdGhvdXRQcm9wZXJ0aWVzMiIsImlzU2F2ZWRMYXllckNvbmZpZ1YxIiwibGF5ZXJDb25maWciLCJ2aXN1YWxDaGFubmVscyIsInBhcnNlTGF5ZXJDb25maWciLCJzY2hlbWEiLCJfc2NoZW1hJHBhcnNlU2F2ZWRDb24iLCJzYXZlZENvbmZpZyIsInZlcnNpb24iLCJDVVJSRU5UX1ZFUlNJT04iLCJjb25maWciLCJ2aXNTdGF0ZSIsImxheWVyT3JkZXIiLCJwYXJzZVNhdmVkQ29uZmlnIiwiY3VycmVudEl0ZW1zIiwiaXRlbXMiLCJwcmVzZXJ2ZWRPcmRlciIsInVuZGVmaW5lZCIsImRlZmF1bHRTdGFydCIsIm5ld0l0ZW1zIiwiX2l0ZXJhdG9yIiwiX3N0ZXAiLCJpdGVtIiwiZXhwZWN0ZWRJZHgiLCJpbmRleE9mIiwiaW5zZXJ0QXQiLCJwcmVjZWVkSWR4IiwiX2xvb3AiLCJwcmVjZWVkSXRlbUlkIiwiZmluZEluZGV4IiwiYXJyYXlJbnNlcnQiLCJlcnIiLCJjcmVhdGVMYXllckZyb21Db25maWciLCJwYXJzZWRMYXllckNvbmZpZyIsIl92YWxpZGF0ZUxheWVyc0J5RGF0YSIsInZhbGlkYXRlTGF5ZXJzQnlEYXRhc2V0cyIsImxheWVyQ2xhc3NlcyIsImFsbG93RW1wdHlDb2x1bW4iLCJuZXdMYXllciIsInVwZGF0ZUxheWVyRG9tYWluIiwic2VyaWFsaXplRmlsdGVyIiwibmV3RmlsdGVyIiwiX3NlcmlhbGl6ZWRWaXNTdGF0ZSRmIiwic2VyaWFsaXplZFZpc1N0YXRlIiwic2VyaWFsaXplVmlzU3RhdGUiLCJzZXJpYWxpemVMYXllciIsIl9zZXJpYWxpemVkVmlzU3RhdGUkbCIsInNlcmlhbGl6ZUVmZmVjdCIsIm5ld0VmZmVjdCIsIl9zZXJpYWxpemVkVmlzU3RhdGUkZSIsImVmZmVjdHMiLCJlZmZlY3RPcmRlciIsIl9zY2hlbWEkcGFyc2VTYXZlZENvbjIiLCJzYXZlZFN0YXRlIiwiZ2V0Q29uZmlnVG9TYXZlIiwibWVyZ2VMYXllcnMiLCJsYXllcnNUb01lcmdlIiwicHJlc2VydmVMYXllck9yZGVyIiwiZ2V0TGF5ZXJPcmRlckZyb21MYXllcnMiLCJ1bm1lcmdlZCIsInRvTWVyZ2UiLCJfbCRjb25maWciLCJpc01lcmdpbmdEYXRhc2V0cyIsIl92YWxpZGF0ZUxheWVyc0J5RGF0YTIiLCJtZXJnZWRMYXllciIsIl9pbnNlcnRMYXllckF0UmlnaHRPciIsImluc2VydExheWVyQXRSaWdodE9yZGVyIiwibmV3TGF5ZXJPcmRlciIsIm5ld0xheWVycyIsImxheWVyVG9CZU1lcmdlZCIsImN1cnJlbnRMYXllcnMiLCJsYXllcnNUb0luc2VydCIsImN1cnJlbnRPcmRlciIsImN1cnJlbnRMYXllclF1ZXVlIiwiZmluZEJ5SWQiLCJsYXllciIsIkJvb2xlYW4iLCJuZXdMYXllck9yZGVyUXVldWUiLCJtZXJnZUludGVyYWN0aW9ucyIsImludGVyYWN0aW9uVG9CZU1lcmdlZCIsIm1lcmdlZCIsImtleSIsImludGVyYWN0aW9uQ29uZmlnIiwiY3VycmVudENvbmZpZyIsIl9yZWYyIiwiZW5hYmxlZCIsImNvbmZpZ1NhdmVkIiwiY29uZmlnVG9NZXJnZSIsIl9tZXJnZUludGVyYWN0aW9uVG9vbCIsIm1lcmdlSW50ZXJhY3Rpb25Ub29sdGlwQ29uZmlnIiwibWVyZ2VkVG9vbHRpcCIsInVubWVyZ2VkVG9vbHRpcCIsImZpZWxkc1RvU2hvdyIsInRvb2x0aXAiLCJwaWNrIiwibmV4dFN0YXRlIiwic2F2ZWRVbm1lcmdlZEludGVyYWN0aW9uIiwiY29tYmluZUludGVyYWN0aW9uQ29uZmlncyIsImNvbmZpZ3MiLCJjb21iaW5lZCIsIl9sb29wMiIsInRvQmVDb21iaW5lZFByb3BzIiwiYyIsInNvbWUiLCJwIiwiY29tcGFyZU1vZGUiLCJjb21wYXJlVHlwZSIsImdldFZhbHVlV2l0aEhpZ2hlc3RPY2N1cnJlbmNlIiwicmVkdWNlIiwiYWNjIiwibmV4dEZpZWxkc1RvU2hvdyIsIl9sb29wMyIsIm5leHREYXRhSWRLZXkiLCJuZXh0VG9vbHRpcEZpZWxkcyIsIm5leHRURiIsImZpbmQiLCJfcmVmMyIsIl9hZ2dyZWdhdGUiLCJzaXplIiwiYWdncmVnYXRlIiwiQUdHUkVHQVRJT05fVFlQRVMiLCJtYXhpbXVtIiwiX3VubWVyZ2VkJHRvb2x0aXAiLCJfdW5tZXJnZWQkdG9vbHRpcDIiLCJfc3RhdGUkaW50ZXJhY3Rpb25Ub0IiLCJfdW5tZXJnZWQkdG9vbHRpcDMiLCJyZXBsYWNlSW50ZXJhY3Rpb25EYXRhc2V0SWRzIiwiZGF0YUlkVG9SZXBsYWNlIiwiX2ludGVyYWN0aW9uQ29uZmlnJHRvIiwiX2ludGVyYWN0aW9uQ29uZmlnJHRvMiIsIm1lcmdlU3BsaXRNYXBzIiwic3BsaXRNYXBzIiwic20iLCJlbnRyaWVzIiwiX3JlZjQiLCJfcmVmNSIsIl9zbGljZWRUb0FycmF5MiIsInB1c2hUbyIsImdldEluaXRpYWxNYXBMYXllcnNGb3JTcGxpdE1hcCIsInNwbGl0TWFwc1RvQmVNZXJnZWQiLCJtZXJnZUVmZmVjdHMiLCJuZXdFZmZlY3RzIiwiZWZmZWN0IiwiY3JlYXRlRWZmZWN0IiwiZGVlcG1lcmdlIiwiYWxsIiwiaXNDb25maWdBY3RpdmUiLCJpc1ZhbGlkVG9TYXZlIiwidG9vbHRpcENvbmZpZyIsIl9sb29wNCIsImFsbEZpZWxkcyIsImZpZWxkcyIsImZvdW5kRmllbGRzVG9TaG93IiwiZmllbGQiLCJtZXJnZUxheWVyQmxlbmRpbmciLCJsYXllckJsZW5kaW5nIiwiTEFZRVJfQkxFTkRJTkdTIiwiY29tYmluZUxheWVyQmxlbmRpbmdDb25maWdzIiwibWVyZ2VPdmVybGF5QmxlbmRpbmciLCJvdmVybGF5QmxlbmRpbmciLCJPVkVSTEFZX0JMRU5ESU5HUyIsImNvbWJpbmVPdmVybGF5QmxlbmRpbmdDb25maWdzIiwibWVyZ2VBbmltYXRpb25Db25maWciLCJhbmltYXRpb24iLCJjdXJyZW50VGltZSIsImFuaW1hdGlvbkNvbmZpZyIsImRvbWFpbiIsImNvbWJpbmVBbmltYXRpb25Db25maWdzIiwiX2FnZ3JlZ2F0ZTIiLCJfYWdncmVnYXRlMyIsIm1pbmltdW0iLCJzcGVlZCIsInZhbGlkYXRlU2F2ZWRMYXllckNvbHVtbnMiLCJzYXZlZENvbHMiLCJlbXB0eUNvbHMiLCJvcHRpb25zIiwiY29sdW1ucyIsIl9sb29wNSIsIl9PYmplY3Qka2V5cyIsIl9pIiwic2F2ZWQiLCJmaWVsZElkeCIsIl9yZWY2IiwiYWxsQ29sRm91bmQiLCJldmVyeSIsInZhbGlkYXRlQ29sdW1uIiwicnYiLCJ0aHJvd09uRXJyb3IiLCJyZXF1aXJlZENvbHVtbnMiLCJrIiwib3B0aW9uYWwiLCJtaXNzaW5nQ29sdW1ucyIsIkVycm9yIiwiam9pbiIsImNvbmZpZ0NvbHVtbnMiLCJpbnZhbGlkQ29sdW1ucyIsIl9jb2x1bW5zJGsiLCJjb2x1bW4iLCJ2YWxpZGF0b3IiLCJ2YWxpZGF0ZVNhdmVkVGV4dExhYmVsIiwiX3JlZjciLCJzYXZlZFRleHRMYWJlbCIsIl9yZWY4IiwibGF5ZXJUZXh0TGFiZWwiLCJzYXZlZFRleHRMYWJlbHMiLCJ0ZXh0TGFiZWwiLCJmZCIsIkpTT04iLCJzdHJpbmdpZnkiLCJhY2N1IiwidmFsaWRhdGVTYXZlZFZpc3VhbENoYW5uZWxzIiwic2F2ZWRMYXllciIsInZhbHVlcyIsIl9yZWY5Iiwic2NhbGUiLCJmb3VuZEZpZWxkIiwiZm91bmRDaGFubmVsIiwidXBkYXRlTGF5ZXJDb25maWciLCJ2YWxpZGF0ZVZpc3VhbENoYW5uZWwiLCJfc2F2ZWRMYXllciRjb25maWciLCJfbmV3TGF5ZXIkY29uZmlnJGZpZWwiLCJmaWVsZE5hbWUiLCJfbGF5ZXIkY29uZmlnIiwidmFsaWRhdGVMYXllciIsInZhbGlkYXRlTGF5ZXJXaXRoRGF0YSIsIl9nZXRDb2x1bW5Db25maWdGb3JWYWxpZGF0aW9uIiwiY29sdW1uQ29uZmlnIiwiZ2V0TGF5ZXJDb2x1bW5zIiwiY29sTW9kZUNvbmZpZyIsImNvbHVtbk1vZGUiLCJzdXBwb3J0ZWRDb2x1bW5Nb2RlcyIsImNvbE1vZGUiLCJvcHRpb25hbENvbHVtbnMiLCJkYXRhc2V0IiwidHlwZSIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwibGFiZWwiLCJpc1Zpc2libGUiLCJoaWRkZW4iLCJoaWdobGlnaHRDb2xvciIsImNvcGllZFZpc0NvbmZpZyIsImNvcHlMYXllckNvbmZpZyIsInZpc0NvbmZpZyIsInNoYWxsb3dDb3B5IiwidmFsaWRhdGVWaXNDb25maWciLCJtZXJnZUVkaXRvciIsInNhdmVkRWRpdG9yIiwiX3NhdmVkRWRpdG9yJHZpc2libGUiLCJlZGl0b3IiLCJmZWF0dXJlcyIsInZpc2libGUiLCJjb21iaW5lRWRpdG9yQ29uZmlncyIsIm5leHRDb25maWciLCJtZXJnZURhdGFzZXRzQnlPcmRlciIsIm5ld0RhdGFFbnRyaWVzIiwicHJlc2VydmVEYXRhc2V0T3JkZXIiLCJuZXdEYXRhc2V0SWRzIiwiX3N0YXRlJHByZXNlcnZlRGF0YXNlIiwiYXJyIiwiX3JlZjEzIiwidGFsbHlzIiwiTWFwIiwibm90TnVsbG9yVW5kZWZpbmVkIiwiaGFzIiwic2V0IiwiZ2V0IiwiVklTX1NUQVRFX01FUkdFUlMiLCJleHBvcnRzIiwibWVyZ2UiLCJwcm9wIiwidG9NZXJnZVByb3AiLCJwcmVzZXJ2ZU9yZGVyIiwicmVwbGFjZVBhcmVudERhdGFzZXRJZHMiLCJzYXZlVW5tZXJnZWQiLCJjb21iaW5lQ29uZmlncyJdLCJzb3VyY2VzIjpbIi4uL3NyYy92aXMtc3RhdGUtbWVyZ2VyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCB1bmlxIGZyb20gJ2xvZGFzaC91bmlxJztcbmltcG9ydCBwaWNrIGZyb20gJ2xvZGFzaC9waWNrJztcbmltcG9ydCBmbGF0dGVuRGVlcCBmcm9tICdsb2Rhc2gvZmxhdHRlbkRlZXAnO1xuaW1wb3J0IGRlZXBtZXJnZSBmcm9tICdkZWVwbWVyZ2UnO1xuaW1wb3J0IHtcbiAgYXJyYXlJbnNlcnQsXG4gIGdldEluaXRpYWxNYXBMYXllcnNGb3JTcGxpdE1hcCxcbiAgYXBwbHlGaWx0ZXJzVG9EYXRhc2V0cyxcbiAgdmFsaWRhdGVGaWx0ZXJzVXBkYXRlRGF0YXNldHMsXG4gIGZpbmRCeUlkLFxuICBhZ2dyZWdhdGVcbn0gZnJvbSAnQGtlcGxlci5nbC91dGlscyc7XG5cbmltcG9ydCB7TGF5ZXJ9IGZyb20gJ0BrZXBsZXIuZ2wvbGF5ZXJzJztcbmltcG9ydCB7Y3JlYXRlRWZmZWN0fSBmcm9tICdAa2VwbGV