dashboard.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. // jQuery UI style "widget" for editing an iTop "dashboard"
  2. ////////////////////////////////////////////////////////////////////////////////
  3. //
  4. // dashboard
  5. //
  6. $(function()
  7. {
  8. // the widget definition, where "itop" is the namespace,
  9. // "dashboard" the widget name
  10. $.widget( "itop.dashboard",
  11. {
  12. // default options
  13. options:
  14. {
  15. dashboard_id: '',
  16. layout_class: '',
  17. title: '',
  18. auto_reload: false,
  19. auto_reload_sec: 300,
  20. submit_to: 'index.php',
  21. submit_parameters: {},
  22. render_to: 'index.php',
  23. render_parameters: {},
  24. new_dashlet_parameters: {}
  25. },
  26. // the constructor
  27. _create: function()
  28. {
  29. var me = this;
  30. this.element
  31. .addClass('itop-dashboard')
  32. .bind('add_dashlet.itop_dashboard', function(event, oParams){
  33. me.add_dashlet(oParams);
  34. });
  35. this.ajax_div = $('<div></div>');
  36. this.element.after(this.ajax_div);
  37. this._make_draggable();
  38. // Make sure we don't click on something we'll regret
  39. $('.itop-dashboard').on('click', 'a', function(e) { e.preventDefault(); });
  40. },
  41. // called when created, and later when changing options
  42. _refresh: function()
  43. {
  44. },
  45. // events bound via _bind are removed automatically
  46. // revert other modifications here
  47. _destroy: function()
  48. {
  49. this.element
  50. .removeClass('itop-dashboard');
  51. this.ajax_div.remove();
  52. $(document).unbind('keyup.dashboard_editor');
  53. },
  54. // _setOptions is called with a hash of all options that are changing
  55. _setOptions: function()
  56. {
  57. // in 1.9 would use _superApply
  58. this._superApply(arguments);
  59. },
  60. // _setOption is called for each individual option that is changing
  61. _setOption: function( key, value )
  62. {
  63. // in 1.9 would use _super
  64. this._superApply(arguments);
  65. },
  66. _get_state: function(oMergeInto)
  67. {
  68. var oState = oMergeInto;
  69. oState.cells = [];
  70. this.element.find('.layout_cell').each(function() {
  71. var aList = [];
  72. $(this).find(':itop-dashlet').each(function() {
  73. var oDashlet = $(this).data('itopDashlet');
  74. if(oDashlet)
  75. {
  76. var oDashletParams = oDashlet.get_params();
  77. var sId = oDashletParams.dashlet_id;
  78. oState[sId] = oDashletParams;
  79. aList.push({dashlet_id: sId, dashlet_class: oDashletParams.dashlet_class} );
  80. }
  81. });
  82. if (aList.length == 0)
  83. {
  84. oState[0] = {dashlet_id: 0, dashlet_class: 'DashletEmptyCell'};
  85. aList.push({dashlet_id: 0, dashlet_class: 'DashletEmptyCell'});
  86. }
  87. oState.cells.push(aList);
  88. });
  89. oState.dashboard_id = this.options.dashboard_id;
  90. oState.layout_class = this.options.layout_class;
  91. oState.title = this.options.title;
  92. oState.auto_reload = this.options.auto_reload;
  93. oState.auto_reload_sec = this.options.auto_reload_sec;
  94. return oState;
  95. },
  96. _get_new_id: function()
  97. {
  98. var iMaxId = 0;
  99. this.element.find(':itop-dashlet').each(function() {
  100. var oDashlet = $(this).data('itopDashlet');
  101. if(oDashlet)
  102. {
  103. var oDashletParams = oDashlet.get_params();
  104. var id = parseInt(oDashletParams.dashlet_id, 10);
  105. if (id > iMaxId) iMaxId = id;
  106. }
  107. });
  108. return 1 + iMaxId;
  109. },
  110. _make_draggable: function()
  111. {
  112. var me = this;
  113. this.element.find('.dashlet').draggable({
  114. revert: 'invalid', appendTo: 'body', zIndex: 9999, distance: 10,
  115. helper: function() {
  116. var oDragItem = $(this).dashlet('get_drag_icon');
  117. return oDragItem;
  118. },
  119. cursorAt: { top: 16, left: 16 }
  120. });
  121. this.element.find('table td').droppable({
  122. accept: '.dashlet,.dashlet_icon',
  123. drop: function(event, ui) {
  124. $( this ).find( ".placeholder" ).remove();
  125. var bRefresh = $(this).hasClass('layout_extension');
  126. var oDropped = ui.draggable;
  127. if (oDropped.hasClass('dashlet'))
  128. {
  129. // moving around a dashlet
  130. oDropped.detach();
  131. oDropped.css({top: 0, left: 0});
  132. oDropped.appendTo($(this));
  133. var oDashlet = ui.draggable.data('itopDashlet');
  134. me.on_dashlet_moved(oDashlet, $(this), bRefresh);
  135. }
  136. else
  137. {
  138. // inserting a new dashlet
  139. var sDashletClass = ui.draggable.attr('dashlet_class');
  140. $('.itop-dashboard').trigger('add_dashlet', {dashlet_class: sDashletClass, container: $(this), refresh: bRefresh });
  141. }
  142. }
  143. });
  144. },
  145. add_dashlet: function(options)
  146. {
  147. // 1) Create empty divs for the dashlet and its properties
  148. //
  149. var sDashletId = this._get_new_id();
  150. var oDashlet = $('<div class="dashlet" id="dashlet_'+sDashletId+'"/>');
  151. oDashlet.appendTo(options.container);
  152. var oDashletProperties = $('<div class="dashlet_properties" id="dashlet_properties_'+sDashletId+'"/>');
  153. oDashletProperties.appendTo($('#dashlet_properties'));
  154. // 2) Ajax call to fill the divs with default values
  155. // => in return, it must call add_dashlet_finalize
  156. //
  157. this.add_dashlet_ajax(options, sDashletId);
  158. },
  159. add_dashlet_finalize: function(options, sDashletId, sDashletClass)
  160. {
  161. $('#dashlet_'+sDashletId)
  162. .dashlet({dashlet_id: sDashletId, dashlet_class: sDashletClass})
  163. .dashlet('deselect_all')
  164. .dashlet('select')
  165. .draggable({
  166. revert: 'invalid', appendTo: 'body', zIndex: 9999, distance: 10,
  167. helper: function() {
  168. var oDragItem = $(this).dashlet('get_drag_icon');
  169. return oDragItem;
  170. },
  171. cursorAt: { top: 16, left: 16 }
  172. });
  173. if (options.refresh)
  174. {
  175. this._refresh();
  176. }
  177. },
  178. on_dashlet_moved: function(oDashlet, oReceiver, bRefresh)
  179. {
  180. if (bRefresh)
  181. {
  182. // The layout was extended... refresh the whole dashboard
  183. this._refresh();
  184. }
  185. }
  186. });
  187. });
  188. ////////////////////////////////////////////////////////////////////////////////
  189. //
  190. // runtimedashboard (extends dashboard)
  191. //
  192. $(function()
  193. {
  194. // the widget definition, where "itop" is the namespace,
  195. // "dashboard" the widget name
  196. $.widget( "itop.runtimedashboard", $.itop.dashboard,
  197. {
  198. // default options
  199. options:
  200. {
  201. dashboard_id: '',
  202. layout_class: '',
  203. title: '',
  204. auto_reload: '',
  205. auto_reload_sec: '',
  206. submit_to: 'index.php',
  207. submit_parameters: {},
  208. render_to: 'index.php',
  209. render_parameters: {},
  210. new_dashlet_parameters: {}
  211. },
  212. // the constructor
  213. _create: function()
  214. {
  215. var me = this;
  216. this._superApply(arguments);
  217. this.element
  218. .addClass('itop-runtimedashboard')
  219. .bind('mark_as_modified.itop-dashboard', function(){me.mark_as_modified();} );
  220. this.bModified = false;
  221. },
  222. // events bound via _bind are removed automatically
  223. // revert other modifications here
  224. _destroy: function()
  225. {
  226. this.element
  227. .removeClass('itop-runtimedashboard');
  228. this._superApply(arguments);
  229. },
  230. // _setOptions is called with a hash of all options that are changing
  231. _setOptions: function()
  232. {
  233. this.bRefreshNeeded = false;
  234. this._superApply(arguments);
  235. if (this.bRefreshNeeded)
  236. {
  237. this._refresh();
  238. }
  239. },
  240. // _setOption is called for each individual option that is changing
  241. _setOption: function( key, value )
  242. {
  243. this._superApply(arguments);
  244. if ((key != 'auto_reload') && (key != 'auto_reload_sec'))
  245. {
  246. this.bRefreshNeeded = true;
  247. }
  248. },
  249. // called when created, and later when changing options
  250. _refresh: function()
  251. {
  252. this._super();
  253. var oParams = this._get_state(this.options.render_parameters);
  254. var me = this;
  255. $.post(this.options.render_to, oParams, function(data){
  256. me.element.html(data);
  257. me._make_draggable();
  258. });
  259. },
  260. // Modified means: at least one change has been applied
  261. mark_as_modified: function()
  262. {
  263. this.bModified = true;
  264. },
  265. is_modified: function()
  266. {
  267. return this.bModified;
  268. },
  269. // Dirty means: at least one change has not been committed yet
  270. is_dirty: function()
  271. {
  272. if ($('#dashboard_editor .ui-layout-east .itop-property-field-modified').size() > 0)
  273. {
  274. return true;
  275. }
  276. else
  277. {
  278. return false;
  279. }
  280. },
  281. // Force the changes of all the properties being "dirty"
  282. apply_changes: function()
  283. {
  284. $('#dashboard_editor .ui-layout-east .itop-property-field-modified').trigger('apply_changes');
  285. },
  286. save: function()
  287. {
  288. var oParams = this._get_state(this.options.submit_parameters);
  289. var me = this;
  290. $.post(this.options.submit_to, oParams, function(data){
  291. me.ajax_div.html(data);
  292. });
  293. },
  294. add_dashlet_ajax: function(options, sDashletId)
  295. {
  296. var oParams = this.options.new_dashlet_parameters;
  297. var sDashletClass = options.dashlet_class;
  298. oParams.dashlet_class = sDashletClass;
  299. oParams.dashlet_id = sDashletId;
  300. var me = this;
  301. $.post(this.options.render_to, oParams, function(data){
  302. me.ajax_div.html(data);
  303. me.add_dashlet_finalize(options, sDashletId, sDashletClass);
  304. me.mark_as_modified();
  305. });
  306. },
  307. on_dashlet_moved: function(oDashlet, oReceiver, bRefresh)
  308. {
  309. this._superApply(arguments);
  310. this.mark_as_modified();
  311. }
  312. });
  313. });
  314. ////////////////////////////////////////////////////////////////////////////////
  315. //
  316. // Helper to upload the file selected in the "import dashboard" dialog
  317. //
  318. function UploadDashboard(oOptions)
  319. {
  320. var sFileId = 'dashboard_upload_file';
  321. var oDlg = $('<div id="dashboard_upload_dlg"><form><p>'+oOptions.text+'</p><p><input type="file" id="'+sFileId+'" name="dashboard_upload_file"></p></form></div>');
  322. $('body').append(oDlg);
  323. oOptions.file_id = sFileId;
  324. oDlg.dashboard_upload_dlg(oOptions);
  325. }
  326. ////////////////////////////////////////////////////////////////////////////////
  327. //
  328. // dashboard_upload_dlg
  329. //
  330. //jQuery UI style "widget" for managing a "import dashboard" dialog (file upload)
  331. $(function()
  332. {
  333. // the widget definition, where "itop" is the namespace,
  334. // "dashboard-upload-dlg" the widget name
  335. $.widget( "itop.dashboard_upload_dlg",
  336. {
  337. // default options
  338. options:
  339. {
  340. dashboard_id: '',
  341. file_id: '',
  342. text: 'Select a dashboard file to import',
  343. title: 'Dahsboard Import',
  344. close_btn: 'Close',
  345. submit_to: GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?operation=import_dashboard'
  346. },
  347. // the constructor
  348. _create: function()
  349. {
  350. var me = this;
  351. var oButtons = {};
  352. oButtons[this.options.close_btn] = function() {
  353. me.element.dialog('close');
  354. //me.onClose();
  355. };
  356. $('#'+this.options.file_id).fileupload({
  357. url: me.options.submit_to+'&id='+me.options.dashboard_id,
  358. dataType: 'json',
  359. pasteZone: null, // Don't accept files via Chrome's copy/paste
  360. done: function (e, data) {
  361. if(typeof(data.result.error) != 'undefined')
  362. {
  363. if(data.result.error != '')
  364. {
  365. alert(data.result.error);
  366. me.element.dialog('close');
  367. }
  368. else
  369. {
  370. me.element.dialog('close');
  371. location.reload();
  372. }
  373. }
  374. },
  375. start: function() {
  376. $('#'+me.options.file_id).prop('disabled', true);
  377. }
  378. });
  379. this.element
  380. .addClass('itop-dashboard_upload_dlg')
  381. .dialog({
  382. modal: true,
  383. width: 500,
  384. height: 'auto',
  385. title: this.options.title,
  386. close: function() { me._onClose(); },
  387. buttons: oButtons
  388. });
  389. },
  390. // called when created, and later when changing options
  391. _refresh: function()
  392. {
  393. },
  394. // events bound via _bind are removed automatically
  395. // revert other modifications here
  396. _destroy: function()
  397. {
  398. this.element
  399. .removeClass('itop-dashboard_upload_dlg');
  400. },
  401. // _setOptions is called with a hash of all options that are changing
  402. _setOptions: function()
  403. {
  404. // in 1.9 would use _superApply
  405. this._superApply(arguments);
  406. this._refresh();
  407. },
  408. // _setOption is called for each individual option that is changing
  409. _setOption: function( key, value )
  410. {
  411. // in 1.9 would use _super
  412. this._superApply(arguments);
  413. },
  414. _onClose: function()
  415. {
  416. this.element.remove();
  417. }
  418. });
  419. });