SceneLoader.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. 'use strict';
  2. /**
  3. * Licensed Materials - Property of IBM
  4. * IBM Cognos Products: Storytelling (C) Copyright IBM Corp. 2017, 2019
  5. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  6. */
  7. define(['baglass/core-client/js/core-client/ui/core/Class', 'react-dom', '../util/WidgetHelper'], function (Class, ReactDOM, WidgetHelper) {
  8. var SceneLoader = Class.extend({
  9. init: function init(options) {
  10. SceneLoader.inherited('init', this, arguments);
  11. this.logger = options.logger;
  12. this.dashboardApi = options.dashboardApi;
  13. this.layoutController = options.layoutController;
  14. this._loadTimeout = options.loadTimeout || 10000;
  15. this._sceneLoadPromises = {};
  16. this._loadSequence = [];
  17. this._loadSequenceGeneration = 0;
  18. this.widgetHelper = new WidgetHelper({ dashboardApi: this.dashboardApi });
  19. },
  20. loadScene: function loadScene(scene, options) {
  21. var _this = this;
  22. var refreshData = options && options.refreshData;
  23. // might be a better way, but for now we peek in the scene to see if there is anything to load.
  24. if (scene.isOverview) {
  25. return Promise.resolve();
  26. }
  27. if (!this._sceneLoadPromises[scene.id] || refreshData) {
  28. var view = scene.getLayoutView();
  29. // here we depend on the default scene css being having the hidden class (display:none)
  30. // so we remove that and set the scale to 0
  31. // calling render() will kick the render sequence of the widgets since they are now 'visible'
  32. scene.$el.addClass('hiddenBackgroundLoadingScene').removeClass('hiddenScene');
  33. view.render();
  34. this._sceneLoadPromises[scene.id] = Promise.resolve(this.layoutController.whenPageRenderComplete(view.model)).then(function () {
  35. if (refreshData) {
  36. return _this._refreshData(view.model);
  37. }
  38. }).then(function () {
  39. _this.logger.debug('SceneLoader:loadScene: done loading scene: ', scene.id);
  40. _this._doneSceneBackgroundLoad(scene);
  41. });
  42. }
  43. return this._sceneLoadPromises[scene.id];
  44. },
  45. _doneSceneBackgroundLoad: function _doneSceneBackgroundLoad(scene) {
  46. scene.$el.removeClass('hiddenBackgroundLoadingScene');
  47. // In StoryView.js#render we render the React CenterLoadingSpinner before anything else
  48. // Here we attempt to remove it (once a single scene is done loading)
  49. var $contentViewEl = this.dashboardApi.getCurrentContentView().$el;
  50. ReactDOM.unmountComponentAtNode($contentViewEl[0]);
  51. },
  52. waitForSceneToLoad: function waitForSceneToLoad(scene, options) {
  53. var _this2 = this;
  54. var showLoadingTimeout;
  55. return Promise.try(function () {
  56. // if the view is not ready within 500ms we display a loading screen to give the user feedback.
  57. showLoadingTimeout = setTimeout(function () {
  58. _this2.layoutController.getTopLayoutView().setLoading(true);
  59. }, 500);
  60. if (options && options.refreshData) {
  61. return _this2.loadScene(scene, options);
  62. }
  63. return _this2.loadScene(scene, options).timeout(_this2._loadTimeout);
  64. }).catch(Promise.TimeoutError, function () {
  65. _this2.logger.warn('Scene taking more than ' + _this2._loadTimeout / 1000 + ' seconds to load, loading the rest in background.');
  66. _this2._doneSceneBackgroundLoad(scene);
  67. }).catch(function (error) {
  68. _this2.logger.error('SceneLoader:waitForSceneToLoad: Error ocurred loading scene: ', error);
  69. _this2._doneSceneBackgroundLoad(scene);
  70. // if we don't rethrow the error the returned promise will be resolved.. this seems to be the gemini way for now.
  71. // at some point we should rethrow and have the caller do something.
  72. }).finally(function () {
  73. clearTimeout(showLoadingTimeout);
  74. _this2.layoutController.getTopLayoutView().setLoading(false);
  75. });
  76. },
  77. /**
  78. * Starts loading an array of scenes in the background.
  79. * returns a promise that resolves when the all the scenes are loaded
  80. * @param scenes array of scenes.
  81. */
  82. startBackgroundLoad: function startBackgroundLoad(scenes, options) {
  83. this._loadSequence = scenes.slice();
  84. this._loadSequenceGeneration += 1;
  85. return Promise.try(function () {
  86. return this._doSequentialLoad(this._loadSequenceGeneration, options);
  87. }.bind(this)).catch(function (error) {
  88. this.logger.error('SceneLoader:waitForSceneToLoad:Error occurred pre-loading scene: ', error);
  89. // if we don't rethrow the error the returned promise will be resolved.. this seems to be the gemini way for now.
  90. // at some point we should rethrow and have the caller do something.
  91. return null;
  92. }.bind(this));
  93. },
  94. stopBackgroundLoad: function stopBackgroundLoad() {
  95. // this stops the loop in _doSequentialLoad
  96. this._loadSequenceGeneration = -1;
  97. },
  98. _doSequentialLoad: function _doSequentialLoad(loadSequenceGeneration, options) {
  99. // if startBackgroundLoad is called again we stop since the order might have changed.
  100. if (loadSequenceGeneration !== this._loadSequenceGeneration) {
  101. return null;
  102. }
  103. var scene = this._loadSequence.shift();
  104. if (!scene) {
  105. return null;
  106. }
  107. return this.loadScene(scene, options).then(function () {
  108. return this._doSequentialLoad(loadSequenceGeneration, options);
  109. }.bind(this));
  110. },
  111. _refreshData: function _refreshData(layoutModel) {
  112. var _this3 = this;
  113. var renderPromises = [];
  114. var widgetLayouts = layoutModel.findDescendantsWithType('widget');
  115. widgetLayouts.forEach(function (widgetLayout) {
  116. var widget = _this3.widgetHelper.getWidget(widgetLayout.id);
  117. if (widget.getType() === 'live') {
  118. renderPromises.push(widget.getVisApi().ownerWidget.reRender({ sender: 'realtimeRefresh' }));
  119. }
  120. });
  121. return Promise.all(renderPromises);
  122. }
  123. });
  124. return SceneLoader;
  125. });
  126. //# sourceMappingURL=SceneLoader.js.map