123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 |
- 'use strict';
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
- /**
- *+------------------------------------------------------------------------+
- *| Licensed Materials - Property of IBM
- *| IBM Cognos Products: Dashboard
- *| (C) Copyright IBM Corp. 2017, 2020
- *|
- *| US Government Users Restricted Rights - Use, duplication or disclosure
- *| restricted by GSA ADP Schedule Contract with IBM Corp.
- *+------------------------------------------------------------------------+
- */
- define(['underscore', '../../lib/@waca/core-client/js/core-client/ui/core/Class', '../../dataSources/ModuleUtils', '../../widgets/livewidget/query/QueryFilterSpec', '../../widgets/livewidget/nls/StringResources', './VIPRUtils'], function (_, Class, ModuleUtils, QueryFilterSpec, stringResources, VIPRUtils) {
- 'use strict';
- // IDataRequestHandler implementation to provide secondary query results to VIPR
- var VIPRHandler = Class.extend({
- CATALYST_OP: {
- KEYDRIVER: 'GetKeyDrivers',
- DECISIONTREE: 'GetDecisionTree'
- },
- // view warning ids
- GEO_AMBIGUOUS_ID: 'geo_ambiguous',
- GEO_UNMATCHED_ID: 'geo_unmatched',
- PREDICT_ERROR_ID: 'predict_error',
- PREDICT_WARNING_ID: 'predict_warning',
- TILED_MAP_ATLAS: 'tiledMap_atlas',
- TYPE_ATLAS: 'atlas',
- _lastRequestData: {},
- init: function init(options) {
- this.logger = options.logger;
- this.visAPI = options.visAPI;
- this.queryService = this.visAPI.getQueryManager().queryService;
- this.visView = options.visView;
- this.dashboardApi = this.visAPI.ownerWidget.getDashboardApi();
- /*Each request could specify a request complete callback*/
- this._callbacks = {
- 'Atlas': this._geoQueryCallback.bind(this),
- 'MapPolygons': this._geoQueryCallback.bind(this),
- 'Catalyst': this._fastPredictCallback.bind(this)
- };
- this._customData = null;
- },
- resetCustomData: function resetCustomData() {
- this._customData = null;
- },
- _geoQueryCallback: function _geoQueryCallback(visView, data) {
- if (visView && visView.infoIndicator && data) {
- var candidates = [{
- id: this.GEO_AMBIGUOUS_ID,
- property: 'ambiguous',
- resourceId: 'geomapAmbiguousLocations'
- }, {
- id: this.GEO_UNMATCHED_ID,
- property: 'unmatched',
- resourceId: 'geomapUnrecognizedLocations'
- }];
- visView.infoIndicator.addInfo(_.map(candidates, function (e) {
- return {
- id: e.id,
- label: stringResources.get(e.resourceId),
- items: _.map(data[e.property], function (s) {
- return {
- id: '_' + s.replace(/\s/g, '_'),
- label: s
- };
- })
- };
- }));
- }
- },
- _addErrorsAndWarningsForCandidates: function _addErrorsAndWarningsForCandidates(visView, candidates, predictStatus) {
- _.each(candidates, function (candidate) {
- var properties = predictStatus[candidate.property];
- if (properties && properties.length) {
- visView.infoIndicator.addInfo([{
- id: candidate.id,
- label: stringResources.get(candidate.resourceId),
- items: _.map(properties, function (prop) {
- return {
- id: prop.id,
- label: prop.caption
- };
- })
- }]);
- }
- });
- },
- /**
- * FPD requests may result in messages being added that we want
- * displayed in the insights indicator dialog. We should check
- * for those here and notify needed managers to the changes.
- */
- _addFPDInsightMessages: function _addFPDInsightMessages(predictStatus) {
- // Only log messages if the bundle is configured to accept it.
- if (VIPRUtils.doesConfigPropertyMatchExpected(this.visAPI.getVisId(), 'shouldLogFPDInsightMessages', true)) {
- var smartsAnnotationManager = this.visAPI.getSmartAnnotationsManger();
- // no point doing anything if we have no manager to report to
- if (smartsAnnotationManager) {
- var messages = null; // Default to no messages
- if (predictStatus && predictStatus.messages && predictStatus.messages.length > 0) {
- messages = predictStatus.messages;
- }
- smartsAnnotationManager.addFPDInsightMessages(messages);
- this.visView.updateSmartAnnotationsIndicator();
- }
- }
- },
- _fastPredictCallback: function _fastPredictCallback(visView, data) {
- if (visView && visView.infoIndicator && data && data.predictStatus) {
- // check for FPD call back messages and report them if needed
- this._addFPDInsightMessages(data.predictStatus);
- var predictStatus = data.predictStatus;
- var candidates = [{
- id: this.PREDICT_ERROR_ID,
- property: 'errors',
- resourceId: 'predict_errors'
- }, {
- id: this.PREDICT_WARNING_ID,
- property: 'warnings',
- resourceId: 'predict_warnings'
- }];
- this._addErrorsAndWarningsForCandidates(visView, candidates, predictStatus);
- }
- },
- // Implement IDataRequestHandler
- request: function request(_request) {
- switch (_request.name) {
- case 'Schematics':
- this._handleSchematicRequest(_request);
- break;
- case 'Atlas':
- case 'MapPolygons':
- this._handleGeoRequest(_request);
- break;
- case 'Catalyst':
- this._handleKeyDriversRequest(_request);
- break;
- default:
- this._requestFail(_request);
- }
- },
- /**
- * Log a notification from VIPR
- * @param {String} level (Severity) The severity of the notification, e.g. "info", "warn" or "error".
- * @param {String} message The message of the notification.
- * @param {Object} [payload] Optional: payload of the notification, for truncations when data is clipped
- */
- _logNotification: function _logNotification(level, message, payload) {
- var _this = this;
- switch (level) {
- case 'warn':
- {
- this.logger.warn(message);
- if (payload && payload.truncations) {
- payload.truncations.forEach(function (truncation) {
- _this.logger.warn(truncation.toString());
- });
- }
- break;
- }
- case 'error':
- {
- this.logger.error(message);
- if (payload && payload.truncations) {
- payload.truncations.forEach(function (truncation) {
- _this.logger.error(truncation.toString());
- });
- }
- break;
- }
- }
- },
- /**
- * Display a notification from VIPR
- * @param {String} level (Severity) The severity of the notification, e.g. "info", "warn" or "error".
- * @param {String} message The message of the notification.
- * @param {Object} [payload] Optional: payload of the notification, for truncations when data is clipped
- */
- _addNotifyMessagesToInfoIndicator: function _addNotifyMessagesToInfoIndicator(level, message, payload, id, type) {
- var _this2 = this;
- // If there is a message lets add it to our info indicator.
- if (this.visView && this.visView.infoIndicator && message) {
- var candidates = [{
- id: 'visualization_notifications',
- property: 'visualizationnotifications',
- resourceId: 'visualizationNotifications'
- }];
- var items = [];
- items.push(this._getMessageLabel(message, false, id, type));
- if (payload && payload.truncations) {
- payload.truncations.forEach(function (truncation) {
- (function (message) {
- items.push(this._getMessageLabel(message, true /* isSubMessage */));
- }).bind(_this2)(truncation.toString());
- });
- }
- this.visView.infoIndicator.addInfo(_.map(candidates, function (e) {
- return {
- id: e.id,
- label: stringResources.get(e.resourceId),
- items: items
- };
- }));
- }
- },
- /**
- * @param {String} messageString - message to add
- * @param {Boolean} isSubMessage - is this a sub message of a main message (more clipping info for example)
- * @returns {Object} in form needed for the info indicator view
- *
- */
- _getMessageLabel: function _getMessageLabel(messageString, isSubMessage, id, type) {
- return {
- id: id || '_' + messageString.replace(/\s/g, '_'),
- type: type,
- label: messageString,
- isSubMessage: isSubMessage ? isSubMessage : false
- };
- },
- _isNotificationAGeoWarning: function _isNotificationAGeoWarning(level, id) {
- return level === 'warn' && id === this.TILED_MAP_ATLAS;
- },
- /**
- * Handle a notification from VIPR
- * @param {String} level (Severity) The severity of the notification, e.g. "info", "warn" or "error".
- * @param {String} message The message of the notification.
- * @param {Object} [payload] Optional: payload of the notification, for truncations when data is clipped
- * @param {String} id - id of the message being returned
- */
- notify: function notify(_notification) {
- this._logNotification(_notification.level, _notification.localizedMessage, _notification.payload);
- /* Geo messages are a little different then others. We currently listen to
- * the responses coming back from the geo query. We also listen to the notifications
- * being sent back from Vida. They both state the same thing so we see them both in the
- * Info Indicator dialog. Normally we'd ignore the geo response and listen only
- * to Vida, but Vida returns its warnings as a formatted string such as
- * 'Ambigous locations: ["Canada"]' which means we'd have to parse it interpret
- * it to add it to the info indicator in the way we want. The geo response
- * provides it in a key value pair that makes this very easy. So, we will
- * listen to the geo response, add it to the info indicator, but in this
- * notify message we will only log it and not add it to the info indicator.
- */
- if (_notification.type === 'clear') {
- this._clearIndicatorWarning(_notification);
- } else if (!this._isNotificationAGeoWarning(_notification.level, _notification.id)) {
- this._addNotifyMessagesToInfoIndicator(_notification.level, _notification.localizedMessage, _notification.payload, _notification.id, _notification.type);
- }
- },
- _clearIndicatorWarning: function _clearIndicatorWarning(notification) {
- var _this3 = this;
- if (notification.payload && notification.payload.length) {
- notification.payload.forEach(function (item) {
- if (item.id === _this3.TILED_MAP_ATLAS && item.type === _this3.TYPE_ATLAS) {
- _this3.visView.infoIndicator.clearMessagesWithIds([_this3.GEO_AMBIGUOUS_ID, _this3.GEO_UNMATCHED_ID]);
- } else {
- _this3.visView.infoIndicator.clearMessagesByIdAndSubtype(item);
- }
- });
- }
- },
- _setDefaultSelections: function _setDefaultSelections() {
- var enableSelection = this.dashboardApi.getConfiguration('enableCustomDataSelection') || VIPRUtils.supportsCustomDataSelection(this.visAPI.getVisId());
- if (enableSelection) {
- var customDataSelections = this.visAPI.getDecoratedCustomData('selected');
- var renderingNewData = !!(this.visView && this.visView.getRenderingNewData());
- // Default to the first customData to be selected
- if (renderingNewData && customDataSelections.length === 0 && this._customData.length > 0) {
- var defaultSelection = this._customData[0];
- var defaultSelections = [];
- var defaultSelectionIds = [];
- // For comet: default first value should be grouped with others if they have the same valueFloored
- if (defaultSelection.hasOwnProperty('valueFloored')) {
- defaultSelections = this._customData.filter(function (data) {
- return data.valueFloored === defaultSelection.valueFloored;
- });
- defaultSelectionIds = defaultSelections.map(function (data) {
- return { id: data.id, value: true };
- });
- } else {
- defaultSelections.push(defaultSelection);
- defaultSelectionIds.push({ id: defaultSelection.id, value: true });
- }
- this.visAPI.setCustomDataDecoration('selected', defaultSelectionIds, { silent: true });
- customDataSelections.push.apply(customDataSelections, defaultSelections);
- }
- customDataSelections.forEach(function (item) {
- item.setDecoration && item.setDecoration('selected', true);
- }.bind(this));
- }
- },
- setCustomData: function setCustomData(type, customData) {
- if (!this._customData) {
- this._customData = customData;
- this._setDefaultSelections();
- }
- },
- getCustomData: function getCustomData() {
- return this._customData;
- },
- _invokeCallback: function _invokeCallback(name, data) {
- var fnCallback = this._callbacks[name];
- if (fnCallback) {
- fnCallback(this.visView, data);
- }
- },
- _requestComplete: function _requestComplete(_request, data) {
- var shouldCache = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
- if (shouldCache) {
- this.setLastRequestData(_request.name, data);
- }
- if (_request.name === 'Catalyst') {
- //for catalyst we always cache the raw data, then filter it on demand
- //so that predict data can be shared by decision tree and other driver analysis
- var operation = this._getCatalystOperation(_request);
- var methods = this._getFastPatternDetectionMethods(operation);
- data = this._filterPredictResults(data, methods);
- }
- this._invokeCallback(_request.name, data);
- _request.complete(data);
- },
- _requestFail: function _requestFail(_request, data) {
- var shouldCache = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
- if (shouldCache) {
- this.setLastRequestData(_request.name, null);
- }
- this._invokeCallback(_request.name, data);
- _request.fail(data);
- },
- /**
- * Last request data setter
- *
- * @param {string} key - key to identify the request
- * @param {object} data - data to store
- */
- setLastRequestData: function setLastRequestData(key, data) {
- this._lastRequestData[key] = data;
- },
- /**
- * Last request data getter
- *
- * @param {string} key - key to identify the request
- *
- * @return {object} previously stored data
- */
- getLastRequestData: function getLastRequestData(key) {
- return this._lastRequestData[key];
- },
- /**
- * Make the rest API call to query for the SVG associated with a schematic
- * @param {json object} payload. payload are in the following format:
- * payload = { method: "get", library: <schematic-library-id>, type: "meta" }
- * payload = { method: "get", library: <schematic-library-id>, name: <schematic-image-source-path> }
- * @returns {json object} for first payload it return the content of bi/v1/visualizations/[id]/content/meta.json in json format.
- * for second payload it returns content svg in json format.
- */
- _handleSchematicRequest: function _handleSchematicRequest(_request) {
- var _this4 = this;
- var getSchematicContent = this.visView.visualization.getDefinition().getProperty('getSchematicContent');
- if (getSchematicContent && _request.payload) {
- return getSchematicContent(_request.payload, this.dashboardApi).then(function (data) {
- _this4._requestComplete(_request, data);
- }, function (err) {
- _this4._requestFail(_request, err);
- });
- } else {
- this._requestFail(_request, new Error(stringResources.get('schematicServiceRequestError')));
- }
- },
- _getGeoEndpoint: function _getGeoEndpoint() {
- var endpoint = this.dashboardApi.getConfiguration('geoService');
- // force to use the default endpoint for "CA"
- return endpoint === 'CA' ? null : endpoint;
- },
- _handleGeoRequest: function _handleGeoRequest(_request) {
- this.visView.infoIndicator.clearMessagesWithIds([this.GEO_AMBIGUOUS_ID, this.GEO_UNMATCHED_ID]);
- this.queryService.runGeoQuery(_request.payload, this._getGeoEndpoint()).then(function (data) {
- if (_request.payload.useMapBoxPB) {
- Object.defineProperty(data, 'results', Object.getOwnPropertyDescriptor(data, 'mapboxData'));
- }
- this._requestComplete(_request, data);
- }.bind(this), function (err) {
- this._requestFail(_request, err);
- }.bind(this));
- },
- _getCatalystOperation: function _getCatalystOperation(_request) {
- return _request && _request.payload && _request.payload.catalystOperation;
- },
- _getFastPatternDetectionMethods: function _getFastPatternDetectionMethods(op) {
- return op === this.CATALYST_OP.DECISIONTREE ? ['tree'] : ['drivers', 'tree'];
- },
- /**
- * If the request errored out, then we want to add the error
- * to the view info indicator and not call predict. This means
- * we need to return an empty result set to Vida so they don't error out
- * and can render the empty FPD base charts.
- * @param {Object} _request - original vida request
- * @param {Object} errorDesc - description of the current error state
- * @returns {Object} empty result and predict status.
- */
- _handleErrorPossibleKeyDriverRequest: function _handleErrorPossibleKeyDriverRequest(_request, errorDesc) {
- var visView = this.visAPI.ownerWidget.getCurrentVis();
- // If we have a vis view add an error to the info indicator.
- if (visView && visView.infoIndicator) {
- var msg = errorDesc.error.caption;
- var catId = errorDesc.error && errorDesc.error.categoryId ? errorDesc.error.categoryId : 'predict_error';
- visView.infoIndicator.addInfo([{
- id: catId,
- label: stringResources.get(catId),
- items: [{
- id: '_' + msg.replace(/\s/g, '_'),
- label: msg
- }]
- }]);
- }
- // We need to return an empty result so Vida isn't left hanging.
- var data = {
- result: [],
- predictStatus: {}
- };
- this._requestComplete(_request, data);
- },
- /**
- * The cataclyst service does not behave well when sending queries with empty
- * possible drivers. So, we won't send the query (which saves time and resources)
- * anyway. Instead we create our own dummy response with an empty result and
- * complete the request. Note, we do not need to add a warning here as Vida
- * will notify us with a message for the user that the target has no key drivers.
- * @param {Object} _request - the original request from Vida.
- */
- _handleEmptyPossibleKeyDriverRequest: function _handleEmptyPossibleKeyDriverRequest(_request) {
- var data = {
- result: [],
- predictStatus: {}
- };
- this._requestComplete(_request, data);
- },
- /**
- * If the FPD request fails outright (say with a 500) it will return a response
- * with errors we can add to the info indicator. We should log those before
- * failing the initial request.
- * @param {Object} _request - the initial request
- * @param {Object} errorData - holds, among other props, an array of errors
- * TODO: We now have a number of ways of dealing with adding information to the
- * info indicator depending on what endpoint we are hitting, if there are network
- * failures, if the query fails, etc... We need to work to simplify this and add
- * consistency with the endpoints and what they return.
- */
- _fpdRequestFailed: function _fpdRequestFailed(_request, errorData) {
- // Deal with adding the failure messages to the info indicator and logging them.
- if (this.visView && this.visView.infoIndicator) {
- var info = {
- label: stringResources.get('predict_errors'),
- id: this.PREDICT_ERROR_ID,
- items: []
- };
- if (errorData && errorData.errors && errorData.errors.length) {
- errorData.errors.forEach(function (errorDesc) {
- info.items.push({
- id: errorDesc.code,
- label: errorDesc.message
- });
- });
- } else {
- // use a generic server message if nothing is supplied
- info.items.push({
- id: errorData && errorData.code || 500,
- label: stringResources.get('catalyst_service_error')
- });
- }
- this.visView.infoIndicator.addInfo([info]);
- }
- // Notify the caller the request failed.
- this._requestFail(_request, new Error(stringResources.get('catalyst_service_internal_server_error')));
- },
- _handleKeyDriversRequest: function _handleKeyDriversRequest(_request) {
- var _this5 = this;
- this.visView.infoIndicator.clearMessagesWithIds([this.PREDICT_ERROR_ID, this.PREDICT_WARNING_ID]);
- var targetId = this._getTargetId(_request);
- var operation = this._getCatalystOperation(_request);
- var methods = this._getFastPatternDetectionMethods(operation);
- var possibleKeyDriversDesc = this.visAPI.getEnabledPossibleKeyDrivers(targetId);
- /*
- * There are two possible scenarios when getting the possible key drivers
- * 1) There is an error condition.
- * b) There are valid possible key drivers
- */
- // Case 1: error state.
- if (possibleKeyDriversDesc.errorState && possibleKeyDriversDesc.errorState.inErrorState) {
- this._handleErrorPossibleKeyDriverRequest(_request, possibleKeyDriversDesc.errorState);
- } else {
- // Case b) which includes empty list of possible key drivers.
- var possibleKeyDrivers = possibleKeyDriversDesc.possibleKeyDrivers;
- try {
- this.visAPI.executeFastPatternDetectionRequest(targetId, possibleKeyDrivers, methods).then(function (data) {
- _this5._requestComplete(_request, data);
- }, function (e) {
- _this5._fpdRequestFailed(_request, e && e.data);
- });
- } catch (err) {
- this.logger.error(err);
- }
- }
- },
- _getValidPredictResultTypes: function _getValidPredictResultTypes(methods) {
- var validTypes = [];
- _.each(methods, function (method) {
- switch (method) {
- case 'tree':
- validTypes.push('TREE');
- break;
- case 'oneway':
- validTypes.push('ONE_WAY');
- break;
- case 'twoway':
- validTypes.push('TWO_WAY');
- break;
- case 'drivers':
- validTypes.push('ONE_WAY');
- validTypes.push('TWO_WAY');
- break;
- default:
- }
- });
- return validTypes;
- },
- _filterPredictResults: function _filterPredictResults(data, methods) {
- var validTypes = this._getValidPredictResultTypes(methods);
- if (validTypes && validTypes.length > 0) {
- data.results = _.filter(data.results, function (result) {
- return validTypes.indexOf(result.type) > -1;
- });
- }
- return data;
- },
- _getTargetId: function _getTargetId(_request) {
- var wa_attributeUniqueName;
- var targetId = _request.payload.catalystPayload.target;
- // TODO: massage the targetId to the Predict expected format for now
- // This will be removed once the bugs have been resolved between VIPR & Predict
- var targetMetaDataColumns = this.visAPI.getModule().getMetadataColumns(function (metaDataColumn) {
- return metaDataColumn.getId() === targetId;
- });
- if (targetMetaDataColumns.length) {
- wa_attributeUniqueName = ModuleUtils.getColumnPropertyValue(targetMetaDataColumns[0], 'wa_attributeUniqueName');
- }
- return wa_attributeUniqueName || targetId;
- },
- _addLocalFiltersToRequest: function _addLocalFiltersToRequest(params) {
- var aFilters = this._getWidgetLocalFilters();
- if (aFilters) {
- params.sessionShapingChange = true;
- params.localFilters = this._normalizeFilters(aFilters);
- }
- },
- /**
- * Get localFilters of the current widget.
- */
- _getWidgetLocalFilters: function _getWidgetLocalFilters() {
- var localFiltersDefinition = this.visAPI.getLocalFilters();
- var queryFilterSpec = new QueryFilterSpec();
- queryFilterSpec.addFiltersToSpec(localFiltersDefinition);
- if (queryFilterSpec.hasFilterSpec()) {
- return queryFilterSpec.getFilterSpec();
- }
- return null;
- },
- _normalizeFilters: function _normalizeFilters(aFilters) {
- var aFiltersStrings = [];
- _.each(aFilters, function (filter) {
- // Sort the filter values alphabetically to make sure prediction service will have the same
- // cache key if the filter content is the same but the order of filter values are different
- // or the order of attributes in the filter expression are different.
- filter = this._doSort(filter);
- aFiltersStrings.push(JSON.stringify(filter));
- }.bind(this));
- aFiltersStrings.sort();
- var aSortedFilters = [];
- _.each(aFiltersStrings, function (filterStr) {
- aSortedFilters.push(JSON.parse(filterStr));
- });
- return aSortedFilters;
- },
- _doSort: function _doSort(sortObj) {
- var sortedArray = [];
- var sortedObj;
- var aKeys = _.keys(sortObj);
- if (aKeys && aKeys.length > 1) {
- aKeys.sort();
- }
- for (var i = 0; i < aKeys.length; i++) {
- var key = aKeys[i];
- if (key === 'values') {
- // If the key is values, will sort an array of value Strings in alphabetically order.
- sortedObj = sortObj.values.sort();
- } else if (_typeof(sortObj[key]) === 'object') {
- sortedObj = this._doSort(sortObj[key]);
- } else {
- sortedObj = sortObj[key];
- }
- var obj = {};
- obj[key] = sortedObj;
- sortedArray.push(obj);
- }
- return this._toSortedObject(sortedArray);
- },
- _toSortedObject: function _toSortedObject(sortedArray) {
- return _.extend.apply(null, sortedArray);
- }
- });
- return VIPRHandler;
- });
- //# sourceMappingURL=VIPRDataRequestHandler.js.map
|