Source

App.js

  1. // This import is needed so that webpack adds datatables to the bundle
  2. import psdatatables from './thirdparty/datatables/datatables.min';
  3. import MarkerClusterer from '@google/markerclustererplus';
  4. require('./libs/bullet.js');
  5. import Request from '@devoinc/applications-data-library/requests/Request';
  6. import TabsBar from './TabsBar';
  7. import dataTree from './data/dataTree';
  8. import requests from './data/requests';
  9. import { v4 } from 'uuid';
  10. /**
  11. * @class
  12. * This is the main class to create an application.
  13. *
  14. * All applications has the same structure:
  15. * `App → Tabs → Sections → Widgets`
  16. */
  17. class App {
  18. /**
  19. * The default _settings_ configuration is:
  20. * ```
  21. * {
  22. * firstTabIndex: 0, // First tab index
  23. * transition: {
  24. * effect: 'none', // Effect: 'fade', 'slide' or 'none'.
  25. * duration: 0 // Effect duration in milliseconds.
  26. * },
  27. * onInit: null // function to call on initialize the application.
  28. * }
  29. * ```
  30. * @constructor
  31. * @param {string} id - Id of the aplication
  32. * @param {Object} [settings={}] - Settings object
  33. */
  34. constructor(id, settings = {}) {
  35. this.status = 'loading';
  36. this.id = id;
  37. this.data = dataTree.root;
  38. this.el = document.querySelector('.lt-vapp');
  39. // Init MarkerClusterer (required for circle map widget)
  40. if(!window.MarkerClusterer) {
  41. window.MarkerClusterer = MarkerClusterer;
  42. window.MarkerClusterer.IMAGE_PATH = "static/assets/img/components/widgets/circleWorldMap/m"
  43. }
  44. // Create global namespace for apps framework stuff
  45. if (!window.vapp_framework) {
  46. window.vapp_framework = {};
  47. }
  48. this.settings = Object.assign(
  49. {
  50. firstTabIndex: 0,
  51. transition: {
  52. effect: 'none',
  53. duration: 0,
  54. },
  55. onInit: null,
  56. },
  57. settings
  58. );
  59. this.tabsBar = new TabsBar(this.settings);
  60. this.tabs = this.tabsBar.tabs; // For quick reference
  61. this.settingsPanel = null;
  62. this._setListeners();
  63. }
  64. /**
  65. * Set settings panel.
  66. * @param {Object} settingsPanel - Set the settings panel.
  67. */
  68. setSettingsPanel(settingsPanel) {
  69. this.settingsPanel = settingsPanel;
  70. }
  71. // Set default listeners
  72. _setListeners() {
  73. let onChangeContainer = (evt) => {
  74. evt.preventDefault();
  75. if (evt.detail.page.endsWith(`/${this.id}`)) {
  76. evt.currentTarget.removeEventListener(evt.type, onChangeContainer);
  77. this.status = 'ready';
  78. }
  79. };
  80. document.addEventListener('changeContainer', onChangeContainer);
  81. }
  82. /**
  83. * Add a tab to the aplication.
  84. * This method add a tab to the TabsBar object of the App.
  85. * @param {Tab} tab - The tab to add
  86. */
  87. addTab(tab) {
  88. this.data.append(tab.data);
  89. this.tabsBar.addTab(tab);
  90. }
  91. /**
  92. * Init the app when ready.
  93. * @param {Function} onInit - Callback Javascript function.
  94. */
  95. init(onInit = null) {
  96. console.log('Devo Applications Builder: Starting vapp framework');
  97. this._installLoadPageProxy();
  98. this._checkReady(onInit);
  99. }
  100. // Check if the app is ready
  101. _checkReady(onInit = null) {
  102. if (this.status === 'ready') {
  103. this.tabsBar.init();
  104. if (onInit) onInit(this);
  105. } else
  106. setTimeout(() => {
  107. this._checkReady(onInit);
  108. }, 0);
  109. }
  110. /**
  111. * Proxy the baseWeb.baseWebUtils.loadPage function. This function
  112. * is used by the web whenever the user changes from one page to another
  113. * and it's ideal to install code to free resources like freeing
  114. * datatables or setIntervals.
  115. */
  116. _installLoadPageProxy() {
  117. console.log(
  118. 'Devo Applications Builder: Installing app change handler on baseWeb.baseWebUtils.loadPage'
  119. );
  120. const appID = v4();
  121. let oldLt;
  122. if (lt) {
  123. oldLt = lt;
  124. lt = Object.assign({}, lt, { app: { appId: appID } });
  125. console.log(appID);
  126. }
  127. const freeResources = (event) => {
  128. event.preventDefault();
  129. // abort all queries
  130. requests.abortAll();
  131. // Free global datatables stuff
  132. if ($.fn.psDataTable.tables !== undefined) {
  133. console.log(
  134. `Devo Applications Builder: App change detected: freeing ${
  135. $.fn.psDataTable.tables().length
  136. } datatables`
  137. );
  138. $.fn.psDataTable.tables({ api: true }).destroy();
  139. }
  140. // Free any registered setIntervals
  141. if (window.vapp_framework.registered_intervals !== undefined) {
  142. console.log(
  143. `Devo Applications Builder: App change detected: freeing ${window.vapp_framework.registered_intervals.length} setIntervals`
  144. );
  145. for (let interval of window.vapp_framework.registered_intervals) {
  146. clearInterval(interval);
  147. }
  148. }
  149. console.log(`Devo Applications Builder: Resources freed!`);
  150. };
  151. document.addEventListener('beforeChangeContainer', freeResources);
  152. }
  153. }
  154. export default App;