PageRenderTime 67ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/cde-core/resource/resources/custom/components/ViewManager/dashboardViews.js

https://gitlab.com/pharos3d/cde
JavaScript | 319 lines | 252 code | 42 blank | 25 comment | 27 complexity | 6849d5dd24c291e9801bd37169ab89cc MD5 | raw file
  1. /*!
  2. * Copyright 2002 - 2015 Webdetails, a Pentaho company. All rights reserved.
  3. *
  4. * This software was developed by Webdetails and is provided under the terms
  5. * of the Mozilla Public License, Version 2.0, or any later version. You may not use
  6. * this file except in compliance with the license. If you need a copy of the license,
  7. * please go to http://mozilla.org/MPL/2.0/. The Initial Developer is Webdetails.
  8. *
  9. * Software distributed under the Mozilla Public License is distributed on an "AS IS"
  10. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
  11. * the license for the specific language governing your rights and limitations.
  12. */
  13. var wd = wd || {}
  14. wd.cdf = wd.cdf || {};
  15. wd.cdf.views = wd.cdf.views || {};
  16. wd.cdf.views.ViewModel = Backbone.Model.extend({
  17. defaults: {
  18. name: "Unsaved",
  19. description: "",
  20. id: null,
  21. params: {},
  22. unbound: [],
  23. user: "",
  24. solution: "",
  25. path: "",
  26. file: "",
  27. timestamp: 0
  28. },
  29. constructor: function() {
  30. Backbone.Model.apply(this, arguments);
  31. }
  32. });
  33. wd.cdf.views.ViewCollection = Backbone.Collection.extend({
  34. url: function() { return webAppPath + wd.helpers.views.getViewsEndpoint(); },
  35. model: wd.cdf.views.ViewModel,
  36. parse: function(response) {
  37. if(response.status === "error") {
  38. Dashboards.log(response.result, "warn");
  39. return;
  40. }
  41. return response.result;
  42. }
  43. });
  44. wd.cdf.views.ViewManagerView = Backbone.View.extend({
  45. model: wd.cdf.views.ViewModel,
  46. collection: wd.cdf.views.ViewCollection,
  47. events: {
  48. 'click .tab': "clickTab",
  49. 'click .manage-views, .save-panel .cancel': "toggleViewManager",
  50. 'click .view-item .delete': "deleteView",
  51. 'click .save-panel .save': "saveView"
  52. },
  53. tabs: [
  54. {label: "List", selector: ".list-panel", template: "viewListPanel"},
  55. {label: "Save", selector: ".save-panel", template: "viewSavePanel"}
  56. ],
  57. initialize: function() {
  58. this.collection = new wd.cdf.views.ViewCollection();
  59. this.collection.on("add change sync remove", this.render, this);
  60. // fetch data from server
  61. this.collection.fetch();
  62. },
  63. render: function() {
  64. //check if Dashboards.view exists and if there is a model saved with the same name
  65. var viewName = Dashboards.view ? Dashboards.view.name : undefined,
  66. viewDesc = Dashboards.view ? Dashboards.view.description : undefined;
  67. if(viewName) {
  68. var model = this.collection.filter(function(model) { return model.get("name") == viewName; })[0];
  69. if(model) {
  70. viewName = model.get("name");
  71. viewDesc = model.get("description");
  72. } else {
  73. viewName = "Unsaved";
  74. viewDesc = "";
  75. }
  76. } else {
  77. viewName = "Unsaved";
  78. viewDesc = "";
  79. }
  80. this.$el.html(templates.viewManager({
  81. currentView: viewName,
  82. views: this.collection,
  83. viewCount: this.collection.size()
  84. }));
  85. this.renderTabs(viewName, viewDesc);
  86. this.renderViewList();
  87. this.$(".view-manager").hide();
  88. },
  89. renderTabs: function(viewName, viewDesc) {
  90. var tabs = this.$(".tabs").empty(),
  91. tabContents = this.$(".tab-contents").empty();
  92. _(this.tabs).each(function(tab) {
  93. /* Render the tab */
  94. tabs.append(templates.viewManagerTab(tab));
  95. /* Render the panel corresponding to the tab */
  96. if(tab.template === "viewListPanel") {
  97. tabContents.append(templates[tab.template]({
  98. "views": this.collection,
  99. "viewCount": this.collection.size()
  100. }));
  101. } else if(tab.template === "viewSavePanel") {
  102. tabContents.append(templates[tab.template]({
  103. "currentView": viewName,
  104. "description": viewDesc
  105. }));
  106. }
  107. }, this);
  108. tabs.children().slice(0, 1).addClass('selected');
  109. tabContents.children().slice(1).hide();
  110. },
  111. renderViewList: function() {
  112. var $views = this.$(".list-panel .views").empty();
  113. this.collection.each(function(model) {
  114. var $view = $(templates.viewListItem({
  115. name: model.get("name"),
  116. viewUrl: wd.helpers.views.getUrl(
  117. model.get("solution"),
  118. model.get("path"),
  119. model.get("file"),
  120. model.get("name"))}));
  121. $view.data("model", model);
  122. $views.append($view);
  123. });
  124. },
  125. clickTab: function(evt) {
  126. var $tgt = $(evt.target),
  127. selector = $tgt.data('target');
  128. /* Make sure only the clicked tab is marked as selected */
  129. this.$(".tab").removeClass("selected");
  130. $tgt.addClass("selected");
  131. /* Make it so only the selected tab has its contents showing*/
  132. this.$('.panel').hide();
  133. this.$(selector).show();
  134. },
  135. toggleViewManager: function() {
  136. this.$('.manage-views').toggleClass("active");
  137. this.$('.view-manager').toggle();
  138. },
  139. saveView: function() {
  140. var myself = this,
  141. name = myself.$(".save-properties .name").val().trim(),
  142. desc = myself.$(".save-properties .description").val();
  143. if(!name || !name.length || name === "Unsaved") {
  144. Dashboards.log("Failed to save a dashboard view with no name or with the reserved name 'Unsaved'", "warn");
  145. return;
  146. }
  147. var tmpModel = Dashboards.view
  148. ? new wd.cdf.views.ViewModel(Dashboards.view)
  149. : new wd.cdf.views.ViewModel();
  150. tmpModel.set("name", name, {silent: true});
  151. tmpModel.set("description", desc, {silent: true});
  152. // OrientDB needs param to be base64 encoded
  153. tmpModel.set("params", Base64.encode(JSON.stringify(Dashboards.getViewParameters())), {silent: true});
  154. tmpModel.set("unbound", Dashboards.getUnboundParameters(), {silent: true});
  155. tmpModel.set("user", Dashboards.context.user, {silent: true});
  156. tmpModel.set("solution", Dashboards.context.solution, {silent: true});
  157. tmpModel.set("path", Dashboards.context.path, {silent: true});
  158. tmpModel.set("file", Dashboards.context.file, {silent: true});
  159. tmpModel.set("timestamp", (new Date()).getTime(), {silent: true});
  160. //if it's an update, use the same id (key) value, HTTP PUT is idempotent
  161. var filtered = myself.collection.filter(function(model) { return model.get("name") == name; });
  162. if($.isArray(filtered) && filtered.length > 0) {
  163. tmpModel.set("id", filtered[0].get("id"), {silent: true});
  164. }
  165. tmpModel.sync(
  166. 'update',
  167. tmpModel,
  168. {
  169. url: webAppPath + wd.helpers.views.getViewsEndpoint(name),
  170. contentType: 'application/json',
  171. dataType: 'json',
  172. processData: false,
  173. data: "view=" + JSON.stringify(tmpModel.toJSON()),
  174. success: function(response) {
  175. if(response.status === "error") {
  176. Dashboards.log(response.message, "warn");
  177. return;
  178. }
  179. Dashboards.view = response.result;
  180. Dashboards.restoreView();
  181. myself.collection.add(Dashboards.view, {merge: true, silent: false});
  182. },
  183. cache: false
  184. }
  185. );
  186. },
  187. deleteView: function(evt) {
  188. var myself = this,
  189. name = $(evt.target).parent().data("model").get("name").trim(),
  190. tmpModel;
  191. if(!name || !name.length) {
  192. Dashboards.log("Failed to delete a dashboard view with no name", "warn");
  193. return;
  194. }
  195. var filtered = myself.collection.filter(function(model) { return model.get("name") == name; })[0];
  196. if(filtered) {
  197. tmpModel = filtered;
  198. }
  199. // sync with server
  200. tmpModel.sync(
  201. 'delete',
  202. tmpModel,
  203. {
  204. url: webAppPath + wd.helpers.views.getViewsEndpoint(name),
  205. contentType: 'application/json',
  206. dataType: 'json',
  207. success: function(response) {
  208. if(response.status === "error") {
  209. Dashboards.log(response.message, "warn");
  210. return;
  211. }
  212. myself.collection.remove(tmpModel, {silent: false});
  213. // if we just deleted the current Dashboards.view previously saved
  214. // we need to remove the id so an update on a deleted view is not triggered
  215. if(Dashboards.view && Dashboards.view.name === name) {
  216. Dashboards.view.id = null;
  217. }
  218. },
  219. cache: false
  220. }
  221. );
  222. }
  223. });
  224. // Treat underscore templates as if they had a mustache
  225. // http://underscorejs.org/#template
  226. var _TemplateSettings = _.templateSettings;
  227. _.templateSettings = { interpolate: /\{\{(.+?)\}\}/g };
  228. var templates = templates || {};
  229. templates.viewManager = _.template(
  230. "<div class='view-manager-component'>" +
  231. " <div class='current-view'>" +
  232. " <span class='label'>Current View: </span>" +
  233. " <span class='value'>{{currentView}}</span>" +
  234. " </div>" +
  235. " <div class='big-button manage-views'>Manage Views</div>" +
  236. " <div class='view-manager'>" +
  237. " <div class='tabs'></div>" +
  238. " <div class='tab-contents'></div>" +
  239. " </div>" +
  240. "</div>");
  241. templates.viewManagerTab = _.template(
  242. "<div class='tab' data-target='{{selector}}'>" +
  243. " {{label}}" +
  244. "</div>");
  245. templates.viewListPanel = _.template(
  246. "<div class='list-panel panel'>" +
  247. " <div class='total-views'>" +
  248. " <span class='label'>Total Views: </span>" +
  249. " <span class='value'>{{viewCount}}</span>" +
  250. " </div>" +
  251. " <div class='views'></div>" +
  252. " <div class='view-all'>" +
  253. " <span class='label'>View All</span>" +
  254. " <span class='description'>(go to View Manager)</span>" +
  255. " </div>" +
  256. "</div>");
  257. templates.viewListItem = _.template(
  258. "<div class='view-item'>" +
  259. " <a class='name' href='{{viewUrl}}'>{{name}}</a>" +
  260. " <span class='delete'></span>" +
  261. "</div>");
  262. templates.viewSavePanel = _.template(
  263. "<div class='save-panel panel'>" +
  264. " <div class='current-view'>" +
  265. " <span class='label'>Current View:</span>" +
  266. " <span class='value'>{{currentView}}</span>" +
  267. " </div>" +
  268. " <div class='save-properties'>" +
  269. " <div><span class='label'>Name</span><input type='text' class='name' value='{{currentView}}'></div>" +
  270. " <div><span class='label'>Description</span><textarea class='description' placeholder='Enter a description'>{{description}}</textarea></div>" +
  271. " </div>" +
  272. " <div class='save-actions'>" +
  273. " <div class='big-button active save'>Save</div>" +
  274. " <div class='big-button cancel'>Cancel</div>" +
  275. " </div>" +
  276. "</div>");
  277. _.templateSettings = _TemplateSettings;