CanvasExtensions.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. 'use strict';
  2. /*
  3. *+------------------------------------------------------------------------+
  4. *| Licensed Materials - Property of IBM
  5. *| IBM Cognos Products: Dashboard
  6. *| (C) Copyright IBM Corp. 2017, 2019
  7. *|
  8. *| US Government Users Restricted Rights - Use, duplication or disclosure
  9. *| restricted by GSA ADP Schedule Contract with IBM Corp.
  10. *+------------------------------------------------------------------------+
  11. */
  12. define(['../../lib/@waca/core-client/js/core-client/utils/ClassFactory', '../glass/SplitPaneView'], function (ClassFactory, SplitPaneView) {
  13. var _canvasExtensions = {
  14. _ClassFactory: ClassFactory,
  15. _SplitPaneView: SplitPaneView,
  16. /**
  17. * @param {object} options
  18. * @param {object} options.services
  19. * @param {object} options.eventRouter
  20. * @param {object} options.handlers - object of handers
  21. * @param {object} options.topNode - top position jquery node
  22. * @param {object} options.bottomNode - bottom position jquery node
  23. * @param {object[]} options.canvasExtensions
  24. * @param {integer} options.canvasExtensions[].order - the order, compared to other extensions to show in the DOM
  25. * @param {('top'|'bottom')} options.canvasExtensions[].position - The position in the DOM to place the extension.
  26. * @param {string} options.canvasExtensions[].class - The view class. MUST implement render() and return a promise.
  27. * @param {object} options.canvasExtensions[].class.$el - the node to be placed on the DOM
  28. * @param {function} [options.canvasExtensions[].class.initialize] - a method which returns a promise. Will be called BEFORE class.render
  29. * @param {function} options.canvasExtensions[].class.render - a method which returns a promise. Will be called BEFORE attaching $el to the DOM. Operations performed on $el ahead of time must be able to be constructed detached from the DOM
  30. * @param {function} options.canvasExtensions[].class.remove - will be called before the DOM node is removed
  31. */
  32. init: function init(options) {
  33. this.dashboardApi = options.dashboardApi;
  34. this.topNode = options.topNode;
  35. this.bottomNode = options.bottomNode;
  36. this.canvasExtensions = options.canvasExtensions || [];
  37. this.services = options.services;
  38. this.eventRouter = options.eventRouter;
  39. this.appSettings = options.appSettings;
  40. this.handlers = options.handlers;
  41. this.consumeHideHandles = [];
  42. this.views = new Map([]);
  43. },
  44. destroy: function destroy() {
  45. this.views.forEach(function (value) {
  46. if (typeof value.remove === 'function') {
  47. value.remove();
  48. } else {
  49. console.warn('view.remove should be implemented');
  50. }
  51. });
  52. this.views = new Map([]);
  53. if (this.splitPaneView) {
  54. this.splitPaneView.remove();
  55. }
  56. },
  57. render: function render() {
  58. var promise = Promise.resolve();
  59. if (this.canvasExtensions.length > 0) {
  60. this.canvasExtensions.sort(function (a, b) {
  61. return a.order - b.order;
  62. });
  63. var splitterItems = [];
  64. this.canvasExtensions.forEach(function (extension) {
  65. promise = promise.then(this._ClassFactory.loadModule.bind(this._ClassFactory, extension.class)).then(function (View) {
  66. var _this = this;
  67. var options = {
  68. //DO NOT add any more parameters here. The appSettings, services and eventrouter is all an extension needs. if you found your way here looking to add a dependency, you're doing it wrong.
  69. appSettings: this.appSettings,
  70. services: this.services,
  71. eventRouter: this.eventRouter,
  72. dashboardApi: this.dashboardApi
  73. };
  74. if (extension.extraOptions) {
  75. options.extraOptions = extension.extraOptions;
  76. }
  77. var view = new View(options);
  78. var initializationPromise;
  79. if (typeof view.initialize === 'function') {
  80. initializationPromise = view.initialize();
  81. } else {
  82. initializationPromise = Promise.resolve();
  83. }
  84. return initializationPromise.then(function () {
  85. var hasApi = !!view.getApi;
  86. if (hasApi) {
  87. return _this.dashboardApi.getCanvas().registerFeature(extension.name, view.getApi());
  88. }
  89. }).then(function () {
  90. var promise;
  91. if (extension.position === 'top') {
  92. _this.topNode.append(view.$el);
  93. } else if (extension.position === 'bottom') {
  94. _this.bottomNode.append(view.$el);
  95. } else if (extension.position === 'splitter') {
  96. promise = view.getSplitterOpts().then(function (opts) {
  97. if (opts.hideInConsume) {
  98. this.consumeHideHandles.push(opts.handleClass);
  99. if (!this.handlers.isAuthorMode()) {
  100. opts.hidden = true;
  101. }
  102. }
  103. splitterItems.push(opts);
  104. return opts;
  105. }.bind(_this));
  106. }
  107. _this.views.set(extension.name, view);
  108. return promise || Promise.resolve();
  109. }).then(function () {
  110. var renderPromise;
  111. if (extension.position !== 'splitter') {
  112. renderPromise = view.render();
  113. }
  114. return renderPromise || Promise.resolve();
  115. });
  116. }.bind(this));
  117. }.bind(this));
  118. promise = promise.then(function () {
  119. if (splitterItems.length > 0) {
  120. return this._createSplitPaneView(splitterItems);
  121. }
  122. }.bind(this));
  123. }
  124. return promise;
  125. },
  126. _createSplitPaneView: function _createSplitPaneView(splitterItems) {
  127. if (!this.splitPaneView) {
  128. this.splitPaneView = new this._SplitPaneView({
  129. splitterItems: splitterItems,
  130. handlers: {
  131. getParentSize: this.handlers.getParentSize
  132. },
  133. dashboardApi: this.dashboardApi,
  134. services: this.services
  135. });
  136. this._setupHideHandles();
  137. return this.splitPaneView.render().then(function () {
  138. this.bottomNode.prepend(this.splitPaneView.$el.children()); //TODO shouldn't need to take the children
  139. return this.splitPaneView.onContainerReady();
  140. }.bind(this));
  141. }
  142. return Promise.resolve();
  143. },
  144. _setupHideHandles: function _setupHideHandles() {
  145. this.eventRouter.on('mode:change', function (payload) {
  146. switch (this.handlers.getSplitterState()) {
  147. case 'close':
  148. this.splitPaneView.close();
  149. break;
  150. case 'open':
  151. this.splitPaneView.open();
  152. break;
  153. case 'nochange':
  154. default:
  155. break;
  156. }
  157. this.consumeHideHandles.forEach(function (handle) {
  158. if (payload.authoring) {
  159. this.splitPaneView.showHandle(handle);
  160. } else {
  161. this.splitPaneView.hideHandle(handle);
  162. }
  163. }.bind(this));
  164. }, this);
  165. },
  166. // Used to set a persistent state for the session
  167. setState: function setState(state) {
  168. if (state.bottomNode.isOpen) {
  169. this.splitPaneView.open();
  170. } else {
  171. this.splitPaneView.close();
  172. }
  173. },
  174. // Used to get the state from the saved options object
  175. getState: function getState() {
  176. return {
  177. bottomNode: {
  178. isOpen: this.bottomNode[0].clientHeight > 0 ? true : false
  179. }
  180. };
  181. },
  182. /**
  183. * @param {String} name extension name
  184. * @returns a registered extensions
  185. */
  186. getExtension: function getExtension(name) {
  187. return this.views.get(name);
  188. }
  189. };
  190. function CanvasExtensions(options) {
  191. this.init(options);
  192. }
  193. Object.keys(_canvasExtensions).forEach(function (key) {
  194. CanvasExtensions.prototype[key] = _canvasExtensions[key];
  195. });
  196. return CanvasExtensions;
  197. });
  198. //# sourceMappingURL=CanvasExtensions.js.map