VisDnDSlotToSlotProvider.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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 Business Analytics (C) Copyright IBM Corp. 2020
  6. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  7. */
  8. /**
  9. * @class VisDnDSlotToSlotProvider
  10. * @hideconstructor
  11. *
  12. * @classdesc Handles drag and drop of metadata from slot to slot.
  13. */
  14. define(['underscore', 'dashboard-analytics/apiHelpers/SlotAPIHelper'], function (_, SlotAPIHelper) {
  15. return function () {
  16. function VisDnDSlotToSlotProvider() {
  17. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  18. _classCallCheck(this, VisDnDSlotToSlotProvider);
  19. this.visDnDUtils = options.visDnDUtils;
  20. this.dashboardAPI = options.dashboardAPI;
  21. this.content = options.content;
  22. this.visualization = options.visualization;
  23. }
  24. VisDnDSlotToSlotProvider.prototype.destroy = function destroy() {
  25. this.visDnDUtils = null;
  26. this.dashboardAPI = null;
  27. this.content = null;
  28. };
  29. /**
  30. * @param {Object} source - the DndSource defined by whichever source starts the drag
  31. * @param {Object} target - the DnDTarget defined by the drop target which includes target specific information.
  32. * @param {String} target.el - the drop node.
  33. * @param {String} target.type - the type of the target (eg. slot.item)
  34. * @param {String} target.info - a target-specific function which includes information about that target.
  35. * @return {boolean} true if this provider supports the dndSource and target.
  36. */
  37. VisDnDSlotToSlotProvider.prototype.supports = function supports(source, target) {
  38. //Normally slots can accept the content of other slots. VisOverLay slots explicitly wire this off.
  39. return source.type === 'SLOT_ITEM' && source.data.source && !target.info.isVisOverlay;
  40. };
  41. VisDnDSlotToSlotProvider.prototype.accepts = function accepts(source, target) {
  42. if (!this.supports(source, target)) {
  43. return false;
  44. }
  45. return this._acceptsSlotItem(source, target);
  46. };
  47. VisDnDSlotToSlotProvider.prototype.onDrop = function onDrop(source, target) {
  48. //TODO: use a more generic onDrop callback rather than the full slotDataItemHandler.
  49. // and use slotAPI's/mappedDataItemAPI's instead.
  50. // same for SlotToSlotProvider
  51. if (!this.supports(source, target)) {
  52. return false;
  53. }
  54. target.info.onDrop(source, target);
  55. };
  56. //Can this slotDataItem accept a dataItem from this slot or another slot?
  57. VisDnDSlotToSlotProvider.prototype._acceptsSlotItem = function _acceptsSlotItem(source, target) {
  58. var sourceSlot = source.data.source.slot;
  59. var sourceIndexInSlot = source.data.source.indexInSlot;
  60. var targetSlotId = target.info.slot.getId();
  61. //You CAN'T add nothing
  62. if (!sourceSlot) {
  63. return false;
  64. }
  65. //You CAN'T add an item on itself or after the item before it within the same slot
  66. //(it is legitimate to swap an item with the item before it though)
  67. if (targetSlotId === sourceSlot.getId() && (sourceIndexInSlot === target.info.indexInSlot || (target.info.addAfter && sourceIndexInSlot - target.info.indexInSlot) === 1)) {
  68. return false;
  69. }
  70. //You CAN'T drop metadatacolumns that have certain taxonomy characteristics
  71. var sourceDataItem = sourceSlot.getDataItemList()[sourceIndexInSlot];
  72. var sourceMetadataColumn = sourceDataItem.getMetadataColumn();
  73. if (!this.isMeasureGroupItem(sourceSlot, sourceIndexInSlot) && !this._itemsSupported([sourceMetadataColumn], target.info.slot)) {
  74. return false;
  75. }
  76. //You CAN'T drop on top of the placeholder dataItem 'Measure Group (n)' from another item (you can drop after it)
  77. //EXCEPTION: You CAN drop on top if the source item is in the same slot.
  78. if (!target.info.addAfter && this.isMeasureGroupItem(target.info.slot, target.info.indexInSlot) && targetSlotId !== sourceSlot.getId()) {
  79. return false;
  80. }
  81. //You CAN'T drop 'Measure Group (n)' on any ordinal slot
  82. //TODO: follow rule from old slot editor which only checked ordinal slots (not any slots with finalSlotType=ordinal). Should it?
  83. if (target.info.slot.getDefinition().getType() === 'ordinal' && this.isMeasureGroupItem(sourceSlot, sourceIndexInSlot)) {
  84. return false;
  85. }
  86. // Can't swap a measure group if the dataset doesn't match
  87. var sourceDatasetIdList = sourceSlot.getDefinition().getDatasetIdList();
  88. var targetDatasetIdList = target.info.slot.getDefinition().getDatasetIdList();
  89. if (this.isMeasureGroupItem(sourceSlot, sourceIndexInSlot) && !_.isEqual(sourceDatasetIdList, targetDatasetIdList)) {
  90. return false;
  91. }
  92. return this._acceptsCommon(source, target, /*countOfItems*/1, target.info.addAfter);
  93. };
  94. VisDnDSlotToSlotProvider.prototype.isMeasureGroupItem = function isMeasureGroupItem(slot, indexInSlot) {
  95. if (SlotAPIHelper.isMultiMeasuresSeriesSlot(slot)) {
  96. var thisDataItem = slot.getDataItemList()[indexInSlot];
  97. return thisDataItem && thisDataItem.getColumnId() === '_multiMeasuresSeries';
  98. }
  99. return false;
  100. };
  101. VisDnDSlotToSlotProvider.prototype._itemsSupported = function _itemsSupported(metadataColumns, slot) {
  102. //convert to new metadataColumn api
  103. var sourceId = metadataColumns[0].getSourceId();
  104. var dataSource = sourceId && this.dashboardAPI.getFeature('DataSources').getDataSource(sourceId);
  105. if (dataSource) {
  106. var newMetadataColumnAPIs = metadataColumns.map(function (metadataColumn) {
  107. return dataSource.getMetadataColumn(metadataColumn.getId());
  108. });
  109. return slot.supportsColumns(newMetadataColumnAPIs);
  110. }
  111. return false;
  112. };
  113. VisDnDSlotToSlotProvider.prototype._acceptsCommon = function _acceptsCommon(source, target, countOfItemsToDrop, addAfter) {
  114. var sourceSlot = source.data.source.slot;
  115. var sourceIndexInSlot = source.data.source.indexInSlot;
  116. var targetSlotId = target.info.slot.getId();
  117. //IF this definition contains (or could contain) a multiMeasuresSeries item,
  118. //You CAN drop on or after in a values slot (even though values has maxItems of 1 => multi-items go where 'Measure Group (n)' is)
  119. if (target.info.slot.getId() === 'values' && SlotAPIHelper.isMultiMeasuresSeriesSlot(target.info.slot) || target.info.slot.getDefinition().isMultiMeasureSupported()) {
  120. return true;
  121. }
  122. //{ targetSlotId, sourceSlotId, indexInSourceSlot, sourceColumns, indexInTargetSlot, isReplace }
  123. var params = {
  124. targetSlotId: targetSlotId,
  125. sourceSlotId: sourceSlot.getId(),
  126. indexInSourceSlot: sourceIndexInSlot,
  127. sourceColumns: undefined,
  128. indexInTargetSlot: target.info.addAfter ? target.info.indexInSlot + 1 : target.info.indexInSlot,
  129. isReplace: !target.info.addAfter
  130. };
  131. var expandCollapseFeatureFlag = !this.dashboardAPI.getGlassCoreSvc('.FeatureChecker').checkValue('dashboard', 'expandCollapse', 'disabled');
  132. if (expandCollapseFeatureFlag && this.visualization.getType() === 'Crosstab') {
  133. if (!this.visDnDUtils.acceptsOlapV2(params)) {
  134. return false;
  135. }
  136. }
  137. //You CAN'T drop more items than the slot can allow.
  138. //(BUT you'll never exceed the slot limit if you're just re-arranging items in a single slot)
  139. return sourceSlot.getId() === targetSlotId || !this.visDnDUtils.exceedsItemsLimit(countOfItemsToDrop, target.info.indexInSlot, addAfter, target.info.slot);
  140. };
  141. return VisDnDSlotToSlotProvider;
  142. }();
  143. });
  144. //# sourceMappingURL=VisDnDSlotToSlotProvider.js.map