blob: 64042857b747942edb20cefbc5578b0cc5a34591 [file] [log] [blame]
/*
* 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.
*/
define([
"brooklyn", "underscore", "jquery", "backbone",
"model/application", "model/app-tree", "model/location",
"model/server-extended-status",
"view/home", "view/editor", "view/application-explorer", "view/catalog", "view/script-groovy",
"text!tpl/help/page.html","text!tpl/labs/page.html", "text!tpl/home/server-caution.html"
], function (Brooklyn, _, $, Backbone,
Application, AppTree, Location,
serverStatus,
HomeView, EditorView, ExplorerView, CatalogView, ScriptGroovyView,
HelpHtml, LabsHtml, ServerCautionHtml) {
var ServerCautionOverlay = Backbone.View.extend({
template: _.template(ServerCautionHtml),
scheduledRedirect: false,
initialize: function() {
var that = this;
this.carryOnRegardless = false;
_.bindAll(this);
serverStatus.addCallback(this.renderAndAddCallback);
},
renderAndAddCallback: function() {
this.renderOnUpdate();
serverStatus.addCallback(this.renderAndAddCallback);
},
renderOnUpdate: function() {
var that = this;
if (this.carryOnRegardless) return this.renderEmpty();
var state = {
loaded: serverStatus.loaded,
up: serverStatus.isUp(),
shuttingDown: serverStatus.isShuttingDown(),
healthy: serverStatus.isHealthy(),
master: serverStatus.isMaster(),
masterUri: serverStatus.getMasterUri(),
};
if (state.loaded && state.up && state.healthy && state.master) {
// this div shows nothing in normal operation
return this.renderEmpty();
}
this.warningActive = true;
this.$el.html(this.template(state));
$('#application-content').fadeTo(500,0.1);
this.$el.fadeTo(200,1);
$("#dismiss-standby-warning", this.$el).click(function() {
that.carryOnRegardless = true;
if (that.redirectPending) {
log("Cancelling redirect, using this non-master instance");
clearTimeout(that.redirectPending);
that.redirectPending = null;
}
that.renderOnUpdate();
});
if (!state.master && state.masterUri) {
if (!this.scheduledRedirect && !this.redirectPending) {
log("Not master; will redirect shortly to: "+state.masterUri);
var destination = state.masterUri + "#" + Backbone.history.fragment;
var time = 10;
this.scheduledRedirect = true;
log("Redirecting to " + destination + " in " + time + " seconds");
this.redirectPending = setTimeout(function () {
// re-check, in case the server's status changed in the wait
if (!serverStatus.isMaster()) {
if (that.redirectPending) {
window.location.href = destination;
} else {
log("Cancelled redirect, using this non-master instance");
}
} else {
log("Cancelled redirect, this instance is now master");
}
}, time * 1000);
}
}
return this;
},
renderEmpty: function() {
var that = this;
this.warningActive = false;
this.$el.fadeTo(200,0.2, function() {
if (!that.warningActive)
that.$el.empty();
});
$('#application-content').fadeTo(200,1);
return this;
},
beforeClose: function() {
this.stopListening();
},
warnIfNotLoaded: function() {
if (!this.loaded)
this.renderOnUpdate();
}
});
// look for ha-standby-overlay for compatibility with older index.html copies
var serverCautionOverlay = new ServerCautionOverlay({ el: $("#server-caution-overlay").length ? $("#server-caution-overlay") : $("#ha-standby-overlay")});
serverCautionOverlay.render();
var Router = Backbone.Router.extend({
routes:{
'v1/home/*trail':'homePage',
//'v1/editor/*trail':'editorPage',
'v1/editor(/)(:type)(/)(:typeId)(/:content)':'editorPage',
'v1/applications/:app/entities/*trail':'applicationsPage',
'v1/applications/*trail':'applicationsPage',
'v1/applications':'applicationsPage',
'v1/locations':'catalogPage',
'v1/catalog/:kind(/:id)':'catalogPage',
'v1/catalog':'catalogPage',
'v1/script/groovy':'scriptGroovyPage',
'v1/help':'helpPage',
'labs':'labsPage',
'*path':'defaultRoute'
},
showView: function(selector, view) {
// close the previous view - does binding clean-up and avoids memory leaks
if (this.currentView) {
this.currentView.close();
}
// render the view inside the selector element
$(selector).html(view.render().el);
this.currentView = view;
return view;
},
defaultRoute: function() {
this.homePage('auto')
},
applications: new Application.Collection,
appTree: new AppTree.Collection,
locations: new Location.Collection,
homePage:function (trail) {
var that = this;
var veryFirstViewLoad, homeView;
// render the page after we fetch the collection -- no rendering on error
function render() {
homeView = new HomeView({
collection:that.applications,
locations:that.locations,
cautionOverlay:serverCautionOverlay,
appRouter:that
});
veryFirstViewLoad = !that.currentView;
that.showView("#application-content", homeView);
}
this.applications.fetch({success:function () {
render();
// show add application wizard if none already exist and this is the first page load
if ((veryFirstViewLoad && trail=='auto' && that.applications.isEmpty()) || (trail=='add_application') ) {
if (serverStatus.isMaster()) {
homeView.createApplication();
}
}
}, error: render});
},
editorPage: function (type, typeId, content) {
var editorView = new EditorView({
collection: this.applications,
appRouter: this,
locations: this.locations,
type: type,
typeId: typeId,
content: content
});
this.showView("#application-content", editorView);
$(".nav1").removeClass("active");
$(".nav1_editor").addClass("active");
},
applicationsPage:function (app, trail, tab) {
if (trail === undefined) trail = app
var that = this
this.appTree.fetch({success:function () {
var appExplorer = new ExplorerView({
collection:that.appTree,
appRouter:that,
initialTrail:trail
});
that.showView("#application-content", appExplorer)
if (trail !== undefined) appExplorer.show(trail)
else appExplorer.showDefaultSelection();
}})
},
catalogPage: function (catalogItemKind, id) {
var catalogResource = new CatalogView({
locations: this.locations,
appRouter: this,
kind: catalogItemKind,
id: id
});
this.showView("#application-content", catalogResource);
},
scriptGroovyPage:function () {
if (this.scriptGroovyResource === undefined)
this.scriptGroovyResource = new ScriptGroovyView({})
this.showView("#application-content", this.scriptGroovyResource)
$(".nav1").removeClass("active")
$(".nav1_script").addClass("active")
$(".nav1_script_groovy").addClass("active")
},
helpPage:function () {
$("#application-content").html(_.template(HelpHtml, {}))
$(".nav1").removeClass("active")
$(".nav1_help").addClass("active")
},
labsPage:function () {
$("#application-content").html(_.template(LabsHtml, {}))
$(".nav1").removeClass("active")
},
/** Triggers the Backbone.Router process which drives this GUI through Backbone.history,
* after starting background server health checks and waiting for confirmation of health
* (or user click-through). */
startBrooklynGui: function() {
serverStatus.whenUp(function() { Backbone.history.start(); });
serverStatus.autoUpdate();
_.delay(serverCautionOverlay.warnIfNotLoaded, 2*1000)
}
});
$.ajax({
type: "GET",
url: "/v1/server/user",
dataType: "text"
}).done(function (data) {
if (data != null) {
$("#user").html(_.escape(data));
}
});
/*
* Prepend a base URL to REST API calls, and add the CSRF token if present.
*/
$.ajaxSetup({
beforeSend: function(jqXHR, settings) {
// var baseURL = "/api/brooklyn/";
var baseURL = "";
if (baseURL && settings.url.startsWith("/v1")) {
settings.url = (baseURL + settings.url).replace("//", "/");
}
// add CSRF token as header
var ca = document.cookie.split(';');
for (var i=0; i<ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1);
if (c.toLowerCase().indexOf('csrf-token') != -1) {
var parts = c.split('=');
jqXHR.setRequestHeader('X-'+parts[0], parts[1]);
}
}
}
});
return Router
})