| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| /** |
| * This should render the main content in the Application Explorer page. |
| * Components on this page should be rendered as sub-views. |
| * @type {*} |
| */ |
| define([ |
| "underscore", "jquery", "backbone", "view/viewutils", |
| "./application-add-wizard", "model/application", "model/entity-summary", "model/app-tree", "./application-tree", "./entity-details", |
| "text!tpl/apps/details.html", "text!tpl/apps/entity-not-found.html", "text!tpl/apps/page.html" |
| ], function (_, $, Backbone, ViewUtils, |
| AppAddWizard, Application, EntitySummary, AppTree, ApplicationTreeView, EntityDetailsView, |
| EntityDetailsEmptyHtml, EntityNotFoundHtml, PageHtml) { |
| |
| var ApplicationExplorerView = Backbone.View.extend({ |
| tagName:"div", |
| className:"container container-fluid", |
| id:'application-explorer', |
| template:_.template(PageHtml), |
| notFoundTemplate: _.template(EntityNotFoundHtml), |
| events:{ |
| 'click .application-tree-refresh': 'refreshApplicationsInPlace', |
| 'click #add-new-application':'createApplication', |
| 'click .delete':'deleteApplication' |
| }, |
| initialize: function () { |
| this.$el.html(this.template({})) |
| $(".nav1").removeClass("active"); |
| $(".nav1_apps").addClass("active"); |
| |
| this.treeView = new ApplicationTreeView({ |
| collection:this.collection, |
| appRouter:this.options.appRouter |
| }) |
| if (this.options.initialTrail) this.show(this.options.initialTrail, true); |
| this.treeView.on('entitySelected', function(e) { |
| this.displayEntityId(e.id, e.get('applicationId'), false); |
| }, this); |
| // don't draw these -- wait for the "show" command |
| this.$('div#app-tree').html(this.treeView.renderFull().el); |
| this.$('div#details').html(EntityDetailsEmptyHtml); |
| |
| ViewUtils.fetchRepeatedlyWithDelay(this, this.collection) |
| }, |
| refreshApplicationsInPlace: function() { |
| // fetch without reset sets of change events, which now get handled correctly |
| // (not a full visual recompute, which reset does - both in application-tree.js) |
| this.collection.fetch(); |
| }, |
| beforeClose: function () { |
| this.collection.off("reset", this.render); |
| this.treeView.close(); |
| if (this.detailsView) |
| this.detailsView.close(); |
| }, |
| show: function(entityId, isPre) { |
| var tab = ""; |
| var tabDetails = ""; |
| if (entityId) { |
| if (entityId[0]=='/') entityId = entityId.substring(1); |
| var slash = entityId.indexOf('/'); |
| if (slash>0) { |
| tab = entityId.substring(slash+1) |
| entityId = entityId.substring(0, slash); |
| } |
| } |
| if (tab) { |
| var slash = tab.indexOf('/'); |
| if (slash>0) { |
| tabDetails = tab.substring(slash+1) |
| tab = tab.substring(0, slash); |
| } |
| this.preselectTab(tab, tabDetails); |
| } |
| if (!this.treeView.selectEntity(entityId)) { |
| // needs a load, but only allowed if not pre-loading |
| if (isPre) { /* don't allow loading if this is a "pre-show" */ } |
| else { this.displayEntityId(entityId); } |
| } |
| }, |
| showDefaultSelection: function() { |
| if (!this.treeView.selectedEntityId && !this.treeView.requestedEntityId) { |
| var firstApp = _.first(this.collection.getApplications()); |
| if (firstApp) this.treeView.selectEntity(firstApp); |
| } |
| }, |
| createApplication:function () { |
| var that = this; |
| if (this._modal) { |
| this._modal.close() |
| } |
| var wizard = new AppAddWizard({ |
| appRouter:that.options.appRouter, |
| callback:function() { that.refreshApplicationsInPlace() } |
| }) |
| this._modal = wizard |
| this.$(".add-app #modal-container").html(wizard.render().el) |
| this.$(".add-app #modal-container .modal") |
| .on("hidden",function () { |
| wizard.close() |
| }).modal('show') |
| }, |
| deleteApplication:function (event) { |
| // call Backbone destroy() which does HTTP DELETE on the model |
| this.collection.get(event.currentTarget['id']).destroy({wait:true}) |
| }, |
| /** |
| * Causes the tab with the given name to be selected automatically when |
| * the view is next rendered. |
| */ |
| preselectTab: function(tab, tabDetails) { |
| this.currentTab = tab; |
| this.currentTabDetails = tabDetails; |
| }, |
| showDetails: function(app, entitySummary) { |
| var that = this; |
| ViewUtils.cancelFadeOnceLoaded($("div#details")); |
| |
| if (this.detailsView) { |
| // if view open, take that tab, but clear the details if the id is different |
| if (this.detailsView.model && this.detailsView.model.id && this.detailsView.model.id != entitySummary.id) |
| this.detailsView.options.preselectTabDetails = null; |
| this.preselectTab( |
| //this.detailsView.$el.find(".tab-pane.active").attr("id") |
| this.detailsView.options.preselectTab, |
| this.detailsView.options.preselectTabDetails |
| ); |
| this.detailsView.close(); |
| } |
| if (!this.currentTab) { |
| // else if nothing preselect, use summary |
| this.preselectTab("summary"); |
| } |
| |
| this.detailsView = new EntityDetailsView({ |
| model: entitySummary, |
| application: app, |
| appRouter: this.options.appRouter, |
| preselectTab: this.currentTab, |
| preselectTabDetails: this.currentTabDetails, |
| }); |
| |
| this.detailsView.on("entity.expunged", function() { |
| that.preselectTab("summary"); |
| var id = that.selectedEntityId; |
| var model = that.collection.get(id); |
| if (model && model.get("parentId")) { |
| that.displayEntityId(model.get("parentId")); |
| } else if (that.collection) { |
| that.displayEntityId(that.collection.first().id); |
| } else if (id) { |
| that.displayEntityNotFound(id); |
| } else { |
| that.displayEntityNotFound("?"); |
| } |
| that.collection.fetch(); |
| }); |
| this.detailsView.render( $("div#details") ); |
| // force the routes to be updated, and clear activities detail possibly (the tab is already shown) |
| // (this causes activities view to lose selected sub-tasks, but that's okay) |
| this.detailsView.openTab(this.currentTab + (this.currentTabDetails ? '/'+this.currentTabDetails : '')); |
| }, |
| displayEntityId: function (id, appName, afterLoad) { |
| var that = this; |
| var entityLoadFailed = function() { |
| return that.displayEntityNotFound(id); |
| }; |
| if (appName === undefined) { |
| var $treebox = that.treeView.getTreebox(id); |
| appName = $treebox.children(".entity_tree_node_wrapper").children(".entity_tree_node").data("app-id"); |
| } |
| if (appName === undefined) { |
| if (!afterLoad) { |
| // try a reload if given an ID we don't recognise |
| this.collection.includeEntities([id]); |
| this.collection.fetch({ |
| success: function() { _.defer(function() { that.displayEntityId(id, appName, true); }); }, |
| error: function() { _.defer(function() { that.displayEntityId(id, appName, true); }); } |
| }); |
| ViewUtils.fadeToIndicateInitialLoad($("div#details")) |
| return; |
| } else { |
| // no such app |
| entityLoadFailed(); |
| return; |
| } |
| } |
| |
| var app = new Application.Model(); |
| var entitySummary = new EntitySummary.Model; |
| |
| app.url = "/v1/applications/" + appName; |
| entitySummary.url = "/v1/applications/" + appName + "/entities/" + id; |
| if (id !== this.treeView.selectedEntityId) |
| this.treeView.selectEntity(id); |
| |
| // in case the server response time is low, fade out while it refreshes |
| // (since we can't show updated details until we've retrieved app + entity details) |
| ViewUtils.fadeToIndicateInitialLoad($("div#details")); |
| |
| $.when(app.fetch(), entitySummary.fetch()) |
| .done(function() { |
| that.showDetails(app, entitySummary); |
| }) |
| .fail(entityLoadFailed); |
| }, |
| displayEntityNotFound: function(id) { |
| $("div#details").html(this.notFoundTemplate({"id": id})); |
| ViewUtils.cancelFadeOnceLoaded($("div#details")) |
| }, |
| }) |
| |
| return ApplicationExplorerView |
| }) |