DataQueryUtils.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. 'use strict';
  2. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3. /**
  4. * Licensed Materials - Property of IBM
  5. * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2019, 2021
  6. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  7. */
  8. define(['../../../apiHelpers/SlotAPIHelper', '../../../lib/@waca/dashboard-common/dist/utils/ContentUtil', 'underscore'], function (SlotAPIHelper, ContentUtil, _) {
  9. return function () {
  10. function DataQueryUtils() {
  11. _classCallCheck(this, DataQueryUtils);
  12. }
  13. /**
  14. * @public
  15. * Convert exclude empty values filters to include all filters for non OLAP data sources since there might be joins defined in model,
  16. * and remove such filters for OLAP sources since OLAP doesn't have the concept of joins so these filters won't affect the query at all.
  17. * @param {filterSpec[]} filterSpecList
  18. * @example
  19. * Convert exclude all filter from
  20. * {
  21. * 'id': 'dataSetDemo_csv.Product_line',
  22. * 'columnId': 'dataSetDemo_csv.Product_line',
  23. * 'values': [],
  24. * 'excludedValues': [],
  25. * 'operator': 'notin',
  26. * 'type': null,
  27. * 'binsLabel': 'Product line'
  28. * }
  29. * to
  30. * {
  31. * "operator": "in",
  32. * "itemId": "dataSetDemo_csv.Product_line",
  33. * "values": ["dataSetDemo_csv.Product_line"]
  34. * }
  35. */
  36. DataQueryUtils.convertExcludeEmptyValuesFilters = function convertExcludeEmptyValuesFilters(filterSpecList, dataSource) {
  37. var remainingFilters = [];
  38. var excludeEmptyValuesFilters = _.filter(filterSpecList, function (filterSpec) {
  39. var isExcludeEmptyValues = filterSpec.operator === 'notin' && (!filterSpec.values || !filterSpec.values.length) && !filterSpec.conditions;
  40. if (!isExcludeEmptyValues) {
  41. remainingFilters.push(filterSpec);
  42. }
  43. return isExcludeEmptyValues;
  44. });
  45. if (excludeEmptyValuesFilters) {
  46. excludeEmptyValuesFilters.forEach(function (excludeEmptyValuesFilter) {
  47. var column = dataSource.getMetadataColumn(excludeEmptyValuesFilter.columnId);
  48. if (!column.isOlapColumn()) {
  49. var valueDataItemSpec = {
  50. id: excludeEmptyValuesFilter.id || excludeEmptyValuesFilter.columnId,
  51. itemId: excludeEmptyValuesFilter.columnId
  52. };
  53. var filterSpec = {
  54. operator: 'in',
  55. columnId: valueDataItemSpec.itemId
  56. };
  57. filterSpec.values = [{ u: valueDataItemSpec.itemId, d: valueDataItemSpec.itemId }];
  58. remainingFilters.push(filterSpec);
  59. }
  60. });
  61. }
  62. return remainingFilters;
  63. };
  64. DataQueryUtils.findFirstKeyOfMap = function findFirstKeyOfMap(mapObj) {
  65. /** the code here is to support IE. */
  66. var allKeys = [];
  67. mapObj.forEach(function (val, key) {
  68. allKeys.push(key);
  69. });
  70. return allKeys[0];
  71. };
  72. /**
  73. * @public
  74. * NonProjected range filters cannot be applied to any layer whose categories are not the same as the first mapped layer
  75. * (because the aggregate of different categories is different.)
  76. */
  77. DataQueryUtils.shouldExcludeNonProjectedRangeFilters = function shouldExcludeNonProjectedRangeFilters(layerToQuerySlotsMap, layerId) {
  78. var excludeNonProjectedRangeFilters = layerToQuerySlotsMap.size; // Should have at least one mapped layer.
  79. if (!excludeNonProjectedRangeFilters) {
  80. return false;
  81. }
  82. var firstKey = DataQueryUtils.findFirstKeyOfMap(layerToQuerySlotsMap);
  83. var categoryItemsForFirstMappedLayer = DataQueryUtils._getCategoryItemsForLayer(layerToQuerySlotsMap.get(firstKey)) || [];
  84. var categoryItemsForThisLayer = DataQueryUtils._getCategoryItemsForLayer(layerToQuerySlotsMap.get(layerId)) || [];
  85. return DataQueryUtils._categoriesAreDifferent(categoryItemsForFirstMappedLayer, categoryItemsForThisLayer);
  86. };
  87. //@returns true if categorySet1 and categorySet2 are different (in both directions)
  88. DataQueryUtils._categoriesAreDifferent = function _categoriesAreDifferent(categorySet1, categorySet2) {
  89. return _.difference(categorySet1 || [], categorySet2 || []).length > 0 || _.difference(categorySet2 || [], categorySet1 || []).length > 0;
  90. };
  91. //@returns the categorical items for the specified layer
  92. DataQueryUtils._getCategoryItemsForLayer = function _getCategoryItemsForLayer(slots) {
  93. var columnIdList = [];
  94. slots && slots.forEach(function (slot) {
  95. columnIdList.push.apply(columnIdList, _.map(slot.getDataItemList(), function (dataItem) {
  96. return dataItem.getColumnId();
  97. }));
  98. });
  99. return columnIdList;
  100. };
  101. DataQueryUtils.removeForecastFilters = function removeForecastFilters(spec) {
  102. //@returns querySpecList with values of form '"__ibm_ba_forecast__[0-9]*"' replaced by '""'.
  103. // Defect 286105: This is a temporary fix for sending filters on forecasted points to query service without them complaining
  104. // Resulting response would be empty if only a forecasted point filter is sent, or filtering on other selections
  105. // if filter includes other values. Filtering on forecasted points happens only when viz are brushed/filtered.
  106. var regex = new RegExp('"__ibm_ba_forecast__[0-9]*"', 'g');
  107. return JSON.parse(JSON.stringify(spec).replace(regex, '""'));
  108. };
  109. /**
  110. * Get the list of global filters that applies to the given visualization
  111. * @param {VisualizationAPI} visualization
  112. * @returns {Object[]} list of global filter specifications
  113. */
  114. DataQueryUtils.getFilterSpecListByVisualization = function getFilterSpecListByVisualization(content, dashboard) {
  115. var eventGroups = dashboard.getFeature('EventGroups');
  116. var globalFilters = dashboard.getFeature('GlobalFilters');
  117. var visualization = content.getFeature('Visualization');
  118. var filterQuerySpecList = [];
  119. var dataSource = visualization.getDataSource();
  120. var type = dashboard.getAppConfig('pageContainerType');
  121. var page = ContentUtil.getPageContent(content, type);
  122. var pageId = page && page.getId();
  123. if (dataSource) {
  124. filterQuerySpecList.push.apply(filterQuerySpecList, globalFilters.getFilterList({
  125. origin: 'filter',
  126. sourceId: dataSource.getId(),
  127. scope: pageId
  128. }, content.getId()));
  129. if (visualization.getDefinition().getProperty('reactToExternalBrushing') !== false) {
  130. var eventGroupId = eventGroups.getGroupId(content.getId());
  131. filterQuerySpecList.push.apply(filterQuerySpecList, globalFilters.getFilterList({
  132. origin: 'visualization',
  133. sourceId: dataSource.getId(),
  134. scope: pageId,
  135. eventGroupId: eventGroupId
  136. }, content.getId()));
  137. }
  138. }
  139. // Exclude binning filters since they are not fully supported by query service.
  140. return _.filter(filterQuerySpecList, function (filterSpec) {
  141. return !filterSpec.filterBins;
  142. });
  143. };
  144. /**
  145. * @function DataQueryUtils#getRelatedModelItemsForQueryHint
  146. * @description Get related model items used for query hint preferredModelItems
  147. * @public
  148. * @param {Object} Content API
  149. * @param {Object} Dashboard API
  150. * @return {Array} An arry of related model items
  151. */
  152. DataQueryUtils.getRelatedModelItemsForQueryHint = function getRelatedModelItemsForQueryHint(content, dashboard) {
  153. var eventGroups = dashboard.getFeature('EventGroups');
  154. var visualization = content.getFeature('Visualization');
  155. var dataSource = visualization.getDataSource();
  156. var sourceId = dataSource.getId();
  157. var contentId = content.getId();
  158. var groupId = eventGroups.getGroupId(contentId);
  159. var contentIdList = eventGroups.getContentIdList(groupId);
  160. if (!contentIdList) {
  161. return [];
  162. }
  163. var otherContentsInSameGroup = contentIdList.filter(function (id) {
  164. return id !== contentId;
  165. }).map(function (id) {
  166. return dashboard.getCanvas().getContent(id);
  167. });
  168. // TODO: back to it in R5, when deleting a widget, it has to get deleted from content.
  169. // Also, the content is null for the case we open a saved dashboard that it's vipr bundle is deleted, so it is in error state.
  170. // when deleting it, the content has null value
  171. otherContentsInSameGroup = otherContentsInSameGroup.filter(function (content) {
  172. var isValid = !!content;
  173. if (isValid) {
  174. var _visualization = content.getFeature('Visualization');
  175. var visDefinition = _visualization && _visualization.getDefinition();
  176. isValid = !(visDefinition && visDefinition.getState().getError());
  177. }
  178. return isValid;
  179. });
  180. var otherContentsInSameGroupWithSameSource = otherContentsInSameGroup.filter(function (content) {
  181. var otherVisualization = content.getFeature('Visualization');
  182. var dataSource = otherVisualization && otherVisualization.getDataSource();
  183. return dataSource && dataSource.getId() === sourceId;
  184. });
  185. var columnIdSet = {};
  186. otherContentsInSameGroupWithSameSource.forEach(function (content) {
  187. var slots = content.getFeature('Visualization').getSlots();
  188. slots.getDataItemList().forEach(function (dataItem) {
  189. // skip the fake multimeasure series dataitem
  190. if (!SlotAPIHelper.isMultiMeasuresSeriesOrValueDataItem(dataItem)) {
  191. var metadataColumn = dataItem.getMetadataColumn();
  192. if (metadataColumn && !metadataColumn.isOlapColumn()) {
  193. // Add related column id only when it exists and is not an olap column.
  194. columnIdSet[metadataColumn.getId()] = true;
  195. }
  196. }
  197. });
  198. });
  199. return Object.keys(columnIdSet);
  200. };
  201. return DataQueryUtils;
  202. }();
  203. });
  204. //# sourceMappingURL=DataQueryUtils.js.map