You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ea...@apache.org on 2016/10/19 12:49:09 UTC
[10/10] qpid-dispatch git commit: DISPATCH-531 Initial version of
openstack horizon plugin
DISPATCH-531 Initial version of openstack horizon plugin
Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/0c58c381
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/0c58c381
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/0c58c381
Branch: refs/heads/master
Commit: 0c58c3814866cbe60f13ff69ad73c74a4d8692aa
Parents: 9790303
Author: Ernest Allen <ea...@redhat.com>
Authored: Wed Oct 19 08:48:34 2016 -0400
Committer: Ernest Allen <ea...@redhat.com>
Committed: Wed Oct 19 08:48:34 2016 -0400
----------------------------------------------------------------------
console/dispatch-dashboard/MANIFEST.in | 3 +
console/dispatch-dashboard/README.rst | 41 +
console/dispatch-dashboard/dispatch/__init__.py | 0
.../dispatch-dashboard/dispatch/dashboard.py | 23 +
.../dispatch/overv/__init__.py | 0
.../dispatch-dashboard/dispatch/overv/panel.py | 20 +
.../dispatch/overv/templates/overv/index.html | 13 +
.../dispatch-dashboard/dispatch/overv/tests.py | 19 +
.../dispatch-dashboard/dispatch/overv/urls.py | 20 +
.../dispatch-dashboard/dispatch/overv/views.py | 22 +
.../static/dashboard/dispatch/connect.json | 2 +
.../dashboard/dispatch/dispatch.comService.js | 935 +
.../dashboard/dispatch/dispatch.module.js | 256 +
.../static/dashboard/dispatch/dispatch.scss | 2135 ++
.../dashboard/dispatch/jquery.dynatree.min.js | 4 +
.../static/dashboard/dispatch/lib/d3.v3.min.js | 5 +
.../static/dashboard/dispatch/lib/rhea-min.js | 4 +
.../static/dashboard/dispatch/lib/slider.js | 233 +
.../dashboard/dispatch/lib/tooltipsy.min.js | 20 +
.../static/dashboard/dispatch/lib/ui-grid.js | 28540 +++++++++++++++++
.../dispatch/overv/overview.controller.js | 1428 +
.../dashboard/dispatch/overv/overview.module.js | 178 +
.../dashboard/dispatch/qdrChartService.js | 1109 +
.../dispatch/topology/config-file-header.html | 17 +
.../topology/download-dialog-template.html | 23 +
.../dispatch/topology/node-config-template.html | 51 +
.../dispatch/topology/topology.controller.js | 1703 +
.../topology/topology.download-controller.js | 150 +
.../topology/topology.form-controller.js | 73 +
.../dispatch/topology/topology.module.js | 112 +
.../topology/topology.node-controller.js | 294 +
.../dispatch/templates/dispatch/base.html | 10 +
.../dispatch/topology/__init__.py | 0
.../dispatch/topology/panel.py | 20 +
.../topology/templates/topology/index.html | 35 +
.../dispatch/topology/tests.py | 19 +
.../dispatch/topology/urls.py | 20 +
.../dispatch/topology/views.py | 22 +
.../enabled/_4000_dispatch.py | 33 +
.../enabled/_4030_dispatch_overv_panel.py | 9 +
.../enabled/_4050_dispatch_topology_panel.py | 9 +
console/dispatch-dashboard/setup.py | 42 +
42 files changed, 37652 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/MANIFEST.in
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/MANIFEST.in b/console/dispatch-dashboard/MANIFEST.in
new file mode 100644
index 0000000..1d1b591
--- /dev/null
+++ b/console/dispatch-dashboard/MANIFEST.in
@@ -0,0 +1,3 @@
+include setup.py
+
+recursive-include dispatch *
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/README.rst
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/README.rst b/console/dispatch-dashboard/README.rst
new file mode 100644
index 0000000..ac3b17c
--- /dev/null
+++ b/console/dispatch-dashboard/README.rst
@@ -0,0 +1,41 @@
+=========
+dispatch_dashboard
+=========
+
+Qpid Dispatch Router Horizon plugin
+
+Manual Installation
+-------------------
+
+Copy the contents of this directoty to /opt/stack/dispatch_plugin and setup the plugin::
+
+ cd /opt/stack/dispatch_plugin/
+ python setup.py sdist
+
+If needed, create a virtual environment and install Horizon dependencies::
+
+ cd /opt/stack/horizon
+ python tools/install_venv.py
+
+If needed, set up your ``local_settings.py`` file::
+
+ cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py
+
+
+Install the dispatch dashboard in your horizon virtual environment::
+
+ ./tools/with_venv.sh pip install ../dispatch-plugin/dist/dispatch-0.0.1.tar.gz
+
+And enable it in Horizon::
+
+ cp ../dispatch-plugin/enabled/_4*.py openstack_dashboard/local/enabled
+
+If needed, compress the files::
+
+ ./tools/with-venv.sh python manage.py compress
+
+Run a server in the virtual environment::
+
+ ./tools/with-venv.sh python manage.py runserver 0.0.0.0:8080
+
+The horizon dashboard will be available in your browser at http://localhost:8080/
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/dispatch/__init__.py
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/dispatch/__init__.py b/console/dispatch-dashboard/dispatch/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/dispatch/dashboard.py
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/dispatch/dashboard.py b/console/dispatch-dashboard/dispatch/dashboard.py
new file mode 100644
index 0000000..9fad953
--- /dev/null
+++ b/console/dispatch-dashboard/dispatch/dashboard.py
@@ -0,0 +1,23 @@
+# Licensed 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.
+
+from django.utils.translation import ugettext_lazy as _
+
+import horizon
+
+
+class Dispatch(horizon.Dashboard):
+ name = _("Qpid Dispatch")
+ slug = "dispatch"
+ default_panel = 'overv' # slug of the dashboard's default panel.
+
+horizon.register(Dispatch)
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/dispatch/overv/__init__.py
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/dispatch/overv/__init__.py b/console/dispatch-dashboard/dispatch/overv/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/dispatch/overv/panel.py
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/dispatch/overv/panel.py b/console/dispatch-dashboard/dispatch/overv/panel.py
new file mode 100644
index 0000000..315c7e0
--- /dev/null
+++ b/console/dispatch-dashboard/dispatch/overv/panel.py
@@ -0,0 +1,20 @@
+# Licensed 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.
+
+from django.utils.translation import ugettext_lazy as _
+
+import horizon
+
+
+class Overv(horizon.Panel):
+ name = _("Overview")
+ slug = "overv"
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/dispatch/overv/templates/overv/index.html
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/dispatch/overv/templates/overv/index.html b/console/dispatch-dashboard/dispatch/overv/templates/overv/index.html
new file mode 100644
index 0000000..afe47bd
--- /dev/null
+++ b/console/dispatch-dashboard/dispatch/overv/templates/overv/index.html
@@ -0,0 +1,13 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Overv" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Overview") %}
+{% endblock page_header %}
+
+{% block main %}
+ <ng-include src="'dispatch/overview.html'"></ng-include>
+{% endblock %}
+
+
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/dispatch/overv/tests.py
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/dispatch/overv/tests.py b/console/dispatch-dashboard/dispatch/overv/tests.py
new file mode 100644
index 0000000..47816a3
--- /dev/null
+++ b/console/dispatch-dashboard/dispatch/overv/tests.py
@@ -0,0 +1,19 @@
+# Licensed 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.
+
+from horizon.test import helpers as test
+
+
+class OvervTests(test.TestCase):
+ # Unit tests for overv.
+ def test_me(self):
+ self.assertTrue(1 + 1 == 2)
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/dispatch/overv/urls.py
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/dispatch/overv/urls.py b/console/dispatch-dashboard/dispatch/overv/urls.py
new file mode 100644
index 0000000..6debf00
--- /dev/null
+++ b/console/dispatch-dashboard/dispatch/overv/urls.py
@@ -0,0 +1,20 @@
+# Licensed 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.
+
+from django.conf.urls import url
+
+from dispatch.overv import views
+
+
+urlpatterns = [
+ url(r'^$', views.IndexView.as_view(), name='index'),
+]
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/dispatch/overv/views.py
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/dispatch/overv/views.py b/console/dispatch-dashboard/dispatch/overv/views.py
new file mode 100644
index 0000000..235a0d5
--- /dev/null
+++ b/console/dispatch-dashboard/dispatch/overv/views.py
@@ -0,0 +1,22 @@
+# Licensed 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.
+
+from horizon import views
+
+
+class IndexView(views.APIView):
+ # A very simple class-based view...
+ template_name = 'dispatch/overv/index.html'
+
+ def get_data(self, request, context, *args, **kwargs):
+ # Add data to the context here...
+ return context
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/connect.json
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/connect.json b/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/connect.json
new file mode 100644
index 0000000..2be876d
--- /dev/null
+++ b/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/connect.json
@@ -0,0 +1,2 @@
+)]}',
+{"address": "0.0.0.0", "port": 5673}
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/dispatch.comService.js
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/dispatch.comService.js b/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/dispatch.comService.js
new file mode 100644
index 0000000..ace792a
--- /dev/null
+++ b/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/dispatch.comService.js
@@ -0,0 +1,935 @@
+/*
+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.
+*/
+
+(function() {
+ console.dump = function(object) {
+ if (window.JSON && window.JSON.stringify)
+ QDR.log.info(JSON.stringify(object,undefined,2));
+ else
+ console.log(object);
+ };
+})();
+
+var QDR = (function(QDR) {
+ 'use strict';
+
+ // The QDR service handles the connection to
+ // the server in the background
+ angular
+ .module('horizon.dashboard.dispatch')
+ .factory('horizon.dashboard.dispatch.comService', QDRService);
+
+ QDRService.$inject = [
+ '$rootScope',
+ '$http',
+ '$timeout',
+ '$location',
+ 'horizon.dashboard.dispatch.basePath',
+ ];
+
+ function QDRService($rootScope, $http, $timeout, $location, basePath) {
+ var self = {
+
+ rhea: require("rhea"),
+
+ timeout: 10,
+ connectActions: [],
+ disconnectActions: [],
+ updatedActions: {},
+ stop: undefined, // update interval handle
+
+ addConnectAction: function(action) {
+ if (angular.isFunction(action)) {
+ self.connectActions.push(action);
+ }
+ },
+ addDisconnectAction: function(action) {
+ if (angular.isFunction(action)) {
+ self.disconnectActions.push(action);
+ }
+ },
+ addUpdatedAction: function(key, action) {
+ if (angular.isFunction(action)) {
+ self.updatedActions[key] = action;
+ }
+ },
+ delUpdatedAction: function(key) {
+ if (key in self.updatedActions)
+ delete self.updatedActions[key];
+ },
+
+ executeConnectActions: function() {
+ self.connectActions.forEach(function(action) {
+ //QDR.log.debug("executing connect action " + action);
+ try {
+ action.apply();
+ } catch (e) {
+ // in case the page that registered the handler has been unloaded
+ }
+ });
+ self.connectActions = [];
+
+ },
+ executeDisconnectActions: function() {
+ self.disconnectActions.forEach(function(action) {
+ try {
+ action.apply();
+ } catch (e) {
+ // in case the page that registered the handler has been unloaded
+ }
+ });
+ self.disconnectActions = [];
+ },
+ executeUpdatedActions: function() {
+ for (var action in self.updatedActions) {
+ try {
+ self.updatedActions[action].apply();
+ } catch (e) {
+ delete self.updatedActions[action]
+ }
+ }
+ },
+ redirectWhenConnected: function (org) {
+ //$location.path(basePath + "/connect")
+ //$location.search('org', org);
+ window.location.replace("/connect/");
+ },
+
+ notifyTopologyDone: function() {
+ //QDR.log.debug("got Toplogy done notice");
+
+ if (!angular.isDefined(self.schema))
+ return;
+ else if (self.topology._gettingTopo)
+ return;
+ if (!self.gotTopology) {
+ QDR.log.debug("topology was just initialized");
+ self.gotTopology = true;
+ self.executeConnectActions();
+ $rootScope.$apply();
+ } else {
+ //QDR.log.debug("topology model was just updated");
+ self.executeUpdatedActions();
+ }
+
+ },
+ /**
+ * @property options
+ * Holds a reference to the connection options when
+ * a connection is started
+ */
+ options: undefined,
+
+ /*
+ * @property message
+ * The proton message that is used to send commands
+ * and receive responses
+ */
+ sender: undefined,
+ receiver: undefined,
+ sendable: false,
+
+ schema: undefined,
+
+ toAddress: undefined,
+ connected: false,
+ gotTopology: false,
+ errorText: undefined,
+ connectionError: undefined,
+
+ isConnected: function() {
+ return self.connected;
+ },
+
+ correlator: {
+ _objects: {},
+ _corremationID: 0,
+
+ corr: function () {
+ var id = ++this._corremationID + "";
+ this._objects[id] = {resolver: null}
+ return id;
+ },
+ request: function() {
+ //QDR.log.debug("correlator:request");
+ return this;
+ },
+ then: function(id, resolver, error) {
+ //QDR.log.debug("registered then resolver for correlationID: " + id);
+ if (error) {
+ delete this._objects[id];
+ return;
+ }
+ this._objects[id].resolver = resolver;
+ },
+ // called by receiver's on('message') handler when a response arrives
+ resolve: function(context) {
+ var correlationID = context.message.properties.correlation_id;
+ this._objects[correlationID].resolver(context.message.body, context);
+ delete this._objects[correlationID];
+ }
+ },
+
+ onSubscription: function() {
+ self.getSchema();
+ },
+
+ startUpdating: function () {
+ self.stopUpdating();
+ QDR.log.info("startUpdating called")
+ self.topology.get();
+ self.stop = setInterval(function() {
+ self.topology.get();
+ }, 2000);
+ },
+ stopUpdating: function () {
+ if (angular.isDefined(self.stop)) {
+ QDR.log.info("stopUpdating called")
+ clearInterval(self.stop);
+ self.stop = undefined;
+ }
+ },
+
+ initProton: function() {
+ //self.loadConnectOptions()
+ },
+ cleanUp: function() {
+ },
+ error: function(line) {
+ if (line.num) {
+ QDR.log.debug("error - num: ", line.num, " message: ", line.message);
+ } else {
+ QDR.log.debug("error - message: ", line.message);
+ }
+ },
+ disconnected: function(line) {
+ QDR.log.debug("Disconnected from QDR server");
+ self.executeDisconnectActions();
+ },
+
+ nameFromId: function (id) {
+ return id.split('/')[3];
+ },
+
+ humanify: function (s) {
+ if (!s || s.length === 0)
+ return s;
+ var t = s.charAt(0).toUpperCase() + s.substr(1).replace(/[A-Z]/g, ' $&');
+ return t.replace(".", " ");
+ },
+ pretty: function(v) {
+ var formatComma = d3.format(",");
+ if (!isNaN(parseFloat(v)) && isFinite(v))
+ return formatComma(v);
+ return v;
+ },
+
+ nodeNameList: function() {
+ var nl = [];
+ // if we are in the middel of updating the topology
+ // then use the last known node info
+ var ni = self.topology._nodeInfo;
+ if (self.topology._gettingTopo)
+ ni = self.topology._lastNodeInfo;
+ for (var id in ni) {
+ nl.push(self.nameFromId(id));
+ }
+ return nl.sort();
+ },
+
+ nodeIdList: function() {
+ var nl = [];
+ // if we are in the middel of updating the topology
+ // then use the last known node info
+ var ni = self.topology._nodeInfo;
+ if (self.topology._gettingTopo)
+ ni = self.topology._lastNodeInfo;
+ for (var id in ni) {
+ nl.push(id);
+ }
+ return nl.sort();
+ },
+
+ nodeList: function () {
+ var nl = [];
+ var ni = self.topology._nodeInfo;
+ if (self.topology._gettingTopo)
+ ni = self.topology._lastNodeInfo;
+ for (var id in ni) {
+ nl.push({name: self.nameFromId(id), id: id});
+ }
+ return nl;
+ },
+
+ // given an attribute name array, find the value at the same index in the values array
+ valFor: function (aAr, vAr, key) {
+ var idx = aAr.indexOf(key);
+ if ((idx > -1) && (idx < vAr.length)) {
+ return vAr[idx];
+ }
+ return null;
+ },
+
+ isArtemis: function (d) {
+ return d.nodeType ==='on-demand' && !d.properties.product;
+ },
+
+ isQpid: function (d) {
+ return d.nodeType ==='on-demand' && (d.properties && d.properties.product === 'qpid-cpp');
+ },
+
+ isAConsole: function (properties, connectionId, nodeType, key) {
+ return self.isConsole({properties: properties, connectionId: connectionId, nodeType: nodeType, key: key})
+ },
+ isConsole: function (d) {
+ // use connection properties if available
+ if (d && d['properties'] && d['properties']['console_identifier'] == 'Dispatch console')
+ return true;
+ return false;
+ },
+
+ flatten: function (attributes, result) {
+ var flat = {}
+ attributes.forEach( function (attr, i) {
+ if (result && result.length > i)
+ flat[attr] = result[i]
+ })
+ return flat;
+ },
+ isConsoleLink: function (link) {
+ // find the connection for this link
+ var conns = self.topology.nodeInfo()[link.nodeId]['.connection']
+ var connIndex = conns.attributeNames.indexOf("identity")
+ var linkCons = conns.results.filter ( function (conn) {
+ return conn[connIndex] === link.connectionId;
+ })
+ var conn = self.flatten(conns.attributeNames, linkCons[0]);
+
+ return self.isConsole(conn)
+ },
+
+ quiesceLink: function (nodeId, name) {
+ function gotMethodResponse (nodeName, entity, response, context) {
+ var statusCode = context.message.application_properties.statusCode;
+ if (statusCode < 200 || statusCode >= 300) {
+ Core.notification('error', context.message.application_properties.statusDescription);
+ }
+ }
+ var attributes = {adminStatus: 'disabled', name: name};
+ self.sendMethod(nodeId, "router.link", attributes, "UPDATE", undefined, gotMethodResponse)
+ },
+
+ connectionOptions: {address: '0.0.0.0', port: 5673},
+ loadConnectOptions: function (callback) {
+ $http.get(basePath + 'connect.json').
+ success(function(data, status, headers, config) {
+ //QDR.log.debug("got connect info from file")
+ //console.dump(data)
+ self.connectionOptions = data;
+ if (callback)
+ callback()
+ }).
+ error(function(data, status, headers, config) {
+ //QDR.log.debug("did not get connect info from file")
+ //console.dump(status)
+ if (callback)
+ callback()
+ });
+ },
+
+ addr_text: function (addr) {
+ if (!addr)
+ return "-"
+ if (addr[0] == 'M')
+ return addr.substring(2)
+ else
+ return addr.substring(1)
+ },
+ addr_class: function (addr) {
+ if (!addr) return "-"
+ if (addr[0] == 'M') return "mobile"
+ if (addr[0] == 'R') return "router"
+ if (addr[0] == 'A') return "area"
+ if (addr[0] == 'L') return "local"
+ if (addr[0] == 'C') return "link-incoming"
+ if (addr[0] == 'D') return "link-outgoing"
+ if (addr[0] == 'T') return "topo"
+ return "unknown: " + addr[0]
+ },
+ identity_clean: function (identity) {
+ if (!identity)
+ return "-"
+ var pos = identity.indexOf('/')
+ if (pos >= 0)
+ return identity.substring(pos + 1)
+ return identity
+ },
+
+ /*
+ * send the management messages that build up the topology
+ *
+ *
+ */
+ topology: {
+ _gettingTopo: false,
+ _nodeInfo: {},
+ _lastNodeInfo: {},
+ _expected: {},
+ _timerHandle: null,
+
+ nodeInfo: function () {
+ return this._gettingTopo ? this._lastNodeInfo : this._nodeInfo;
+ },
+
+ get: function () {
+ if (this._gettingTopo)
+ return;
+ if (!self.connected) {
+ QDR.log.debug("topology get failed because !self.connected")
+ return;
+ }
+ this._lastNodeInfo = angular.copy(this._nodeInfo);
+ this._gettingTopo = true;
+
+ self.errorText = undefined;
+ this.cleanUp(this._nodeInfo);
+ this._nodeInfo = {};
+ this._expected = {};
+
+ // get the list of nodes to query.
+ // once this completes, we will get the info for each node returned
+ self.getRemoteNodeInfo( function (response, context) {
+ //QDR.log.debug("got remote node list of ");
+ //console.dump(response);
+ if( Object.prototype.toString.call( response ) === '[object Array]' ) {
+ if (response.length === 0) {
+ // there is only one router, get its node id from the reeciiver
+ //"amqp:/_topo/0/Router.A/temp.aSO3+WGaoNUgGVx"
+ var address = context.receiver.remote.attach.source.address;
+ var addrParts = address.split('/')
+ addrParts.splice(addrParts.length-1, 1, '$management')
+ response = [addrParts.join('/')]
+ }
+ // we expect a response for each of these nodes
+ self.topology.wait(self.timeout);
+ for (var i=0; i<response.length; ++i) {
+ self.makeMgmtCalls(response[i]);
+ }
+ };
+ });
+ },
+
+ cleanUp: function (obj) {
+ //if (obj)
+ // delete obj;
+ },
+ wait: function (timeout) {
+ this.timerHandle = setTimeout(this.timedOut, timeout * 1000);
+ },
+ timedOut: function () {
+ // a node dropped out. this happens when the get-mgmt-nodex
+ // results contains more nodes than actually respond within
+ // the timeout. However, if the responses we get don't contain
+ // the missing node, assume we are done.
+ QDR.log.info("timed out waiting for management responses");
+ // note: can't use 'this' in a timeout handler
+ self.topology.miniDump("state at timeout");
+ // check if _nodeInfo is consistent
+ if (self.topology.isConsistent()) {
+ //TODO: notify controllers which node was dropped
+ // so they can keep an event log
+ self.topology.ondone();
+ return;
+ }
+ self.topology.onerror(Error("Timed out waiting for management responses"));
+ },
+ isConsistent: function () {
+ // see if the responses we have so far reference any nodes
+ // for which we don't have a response
+ var gotKeys = {};
+ for (var id in this._nodeInfo) {
+ var onode = this._nodeInfo[id];
+ var conn = onode['.connection'];
+ // get list of node names in the connection data
+ if (conn) {
+ var containerIndex = conn.attributeNames.indexOf('container');
+ var connectionResults = conn.results;
+ if (containerIndex >= 0)
+ for (var j=0; j < connectionResults.length; ++j) {
+ // inter-router connection to a valid dispatch connection name
+ gotKeys[connectionResults[j][containerIndex]] = ""; // just add the key
+ }
+ }
+ }
+ // gotKeys now contains all the container names that we have received
+ // Are any of the keys that are still expected in the gotKeys list?
+ var keys = Object.keys(gotKeys);
+ for (var id in this._expected) {
+ var key = self.nameFromId(id);
+ if (key in keys)
+ return false;
+ }
+ return true;
+ },
+
+ addNodeInfo: function (id, entity, values) {
+ // save the results in the nodeInfo object
+ if (id) {
+ if (!(id in self.topology._nodeInfo)) {
+ self.topology._nodeInfo[id] = {};
+ }
+ self.topology._nodeInfo[id][entity] = values;
+ }
+
+ // remove the id / entity from _expected
+ if (id in self.topology._expected) {
+ var entities = self.topology._expected[id];
+ var idx = entities.indexOf(entity);
+ if (idx > -1) {
+ entities.splice(idx, 1);
+ if (entities.length == 0)
+ delete self.topology._expected[id];
+ }
+ }
+ // see if the expected obj is empty
+ if (Object.getOwnPropertyNames(self.topology._expected).length == 0)
+ self.topology.ondone();
+ self.topology.cleanUp(values);
+ },
+ expect: function (id, key) {
+ if (!key || !id)
+ return;
+ if (!(id in this._expected))
+ this._expected[id] = [];
+ if (this._expected[id].indexOf(key) == -1)
+ this._expected[id].push(key);
+ },
+ ondone: function () {
+ clearTimeout(this.timerHandle);
+ this._gettingTopo = false;
+ //this.miniDump();
+ //this.dump();
+ self.notifyTopologyDone();
+ },
+ dump: function (prefix) {
+ if (prefix)
+ QDR.log.info(prefix);
+ QDR.log.info("---");
+ for (var key in this._nodeInfo) {
+ QDR.log.info(key);
+ console.dump(this._nodeInfo[key]);
+ QDR.log.info("---");
+ }
+ QDR.log.debug("was still expecting:");
+ console.dump(this._expected);
+ },
+ miniDump: function (prefix) {
+ if (prefix)
+ QDR.log.info(prefix);
+ QDR.log.info("---");
+ console.dump(Object.keys(this._nodeInfo));
+ QDR.log.info("---");
+ },
+ onerror: function (err) {
+ this._gettingTopo = false;
+ QDR.log.debug("Err:" + err);
+ self.executeDisconnectActions();
+
+ }
+
+ },
+
+ getRemoteNodeInfo: function (callback) {
+ //QDR.log.debug("getRemoteNodeInfo called");
+ var ret;
+ // first get the list of remote node names
+ self.correlator.request(
+ ret = self.sendMgmtQuery('GET-MGMT-NODES')
+ ).then(ret.id, function(response, context) {
+ callback(response, context);
+ self.topology.cleanUp(response);
+ }, ret.error);
+ },
+
+ makeMgmtCalls: function (id) {
+ var keys = [".router", ".connection", ".container", ".router.node", ".listener", ".router.link"];
+ $.each(keys, function (i, key) {
+ self.topology.expect(id, key);
+ self.getNodeInfo(id, key, [], self.topology.addNodeInfo);
+ });
+ },
+
+ getNodeInfo: function (nodeName, entity, attrs, callback) {
+ //QDR.log.debug("getNodeInfo called with nodeName: " + nodeName + " and entity " + entity);
+ var ret;
+ self.correlator.request(
+ ret = self.sendQuery(nodeName, entity, attrs)
+ ).then(ret.id, function(response) {
+ callback(nodeName, entity, response);
+ //self.topology.addNodeInfo(nodeName, entity, response);
+ //self.topology.cleanUp(response);
+ }, ret.error);
+ },
+
+ getMultipleNodeInfo: function (nodeNames, entity, attrs, callback, selectedNodeId, aggregate) {
+ if (!angular.isDefined(aggregate))
+ aggregate = true;
+ var responses = {};
+ var gotNodesResult = function (nodeName, dotentity, response) {
+ responses[nodeName] = response;
+ if (Object.keys(responses).length == nodeNames.length) {
+ if (aggregate)
+ self.aggregateNodeInfo(nodeNames, entity, selectedNodeId, responses, callback);
+ else {
+ callback(nodeNames, entity, responses)
+ }
+ }
+ }
+
+ nodeNames.forEach( function (id) {
+ self.getNodeInfo(id, '.'+entity, attrs, gotNodesResult);
+ })
+ //TODO: implement a timeout in case not all requests complete
+ },
+
+ aggregateNodeInfo: function (nodeNames, entity, selectedNodeId, responses, callback) {
+ //QDR.log.debug("got all results for " + entity);
+ // aggregate the responses
+ var newResponse = {};
+ var thisNode = responses[selectedNodeId];
+ newResponse['attributeNames'] = thisNode.attributeNames;
+ newResponse['results'] = thisNode.results;
+ newResponse['aggregates'] = [];
+ for (var i=0; i<thisNode.results.length; ++i) {
+ var result = thisNode.results[i];
+ var vals = [];
+ result.forEach( function (val) {
+ vals.push({sum: val, detail: []})
+ })
+ newResponse.aggregates.push(vals);
+ }
+ var nameIndex = thisNode.attributeNames.indexOf("name");
+ var ent = self.schema.entityTypes[entity];
+ var ids = Object.keys(responses);
+ ids.sort();
+ ids.forEach( function (id) {
+ var response = responses[id];
+ var results = response.results;
+ results.forEach( function (result) {
+ // find the matching result in the aggregates
+ var found = newResponse.aggregates.some( function (aggregate, j) {
+ if (aggregate[nameIndex].sum === result[nameIndex]) {
+ // result and aggregate are now the same record, add the graphable values
+ newResponse.attributeNames.forEach( function (key, i) {
+ if (ent.attributes[key] && ent.attributes[key].graph) {
+ if (id != selectedNodeId)
+ aggregate[i].sum += result[i];
+ }
+ aggregate[i].detail.push({node: self.nameFromId(id)+':', val: result[i]})
+ })
+ return true; // stop looping
+ }
+ return false; // continute looking for the aggregate record
+ })
+ if (!found) {
+ // this attribute was not found in the aggregates yet
+ // because it was not in the selectedNodeId's results
+ var vals = [];
+ result.forEach( function (val) {
+ vals.push({sum: val, detail: [{node: self.nameFromId(id), val: val}]})
+ })
+ newResponse.aggregates.push(vals)
+ }
+ })
+ })
+ callback(nodeNames, entity, newResponse);
+ },
+
+
+ getSchema: function () {
+ //QDR.log.debug("getting schema");
+ var ret;
+ self.correlator.request(
+ ret = self.sendMgmtQuery('GET-SCHEMA')
+ ).then(ret.id, function(response) {
+ //QDR.log.debug("Got schema response");
+ // remove deprecated
+ for (var entityName in response.entityTypes) {
+ var entity = response.entityTypes[entityName]
+ if (entity.deprecated) {
+ // deprecated entity
+ delete response.entityTypes[entityName]
+ } else {
+ for (var attributeName in entity.attributes) {
+ var attribute = entity.attributes[attributeName]
+ if (attribute.deprecated) {
+ // deprecated attribute
+ delete response.entityTypes[entityName].attributes[attributeName]
+ }
+ }
+ }
+ }
+ self.schema = response;
+ self.topology.get();
+ }, ret.error);
+ },
+
+ getNodeInfo: function (nodeName, entity, attrs, callback) {
+ //QDR.log.debug("getNodeInfo called with nodeName: " + nodeName + " and entity " + entity);
+ var ret;
+ self.correlator.request(
+ ret = self.sendQuery(nodeName, entity, attrs)
+ ).then(ret.id, function(response) {
+ callback(nodeName, entity, response);
+ //self.topology.addNodeInfo(nodeName, entity, response);
+ //self.topology.cleanUp(response);
+ }, ret.error);
+ },
+
+ sendMethod: function (nodeId, entity, attrs, operation, props, callback) {
+ var ret;
+ self.correlator.request(
+ ret = self._sendMethod(nodeId, entity, attrs, operation, props)
+ ).then(ret.id, function (response, context) {
+ callback(nodeId, entity, response, context);
+ }, ret.error);
+ },
+
+ _fullAddr: function (toAddr) {
+ var toAddrParts = toAddr.split('/');
+ if (toAddrParts.shift() != "amqp:") {
+ self.topology.error(Error("unexpected format for router address: " + toAddr));
+ return;
+ }
+ //var fullAddr = self.toAddress + "/" + toAddrParts.join('/');
+ var fullAddr = toAddrParts.join('/');
+ return fullAddr;
+ },
+
+ _sendMethod: function (toAddr, entity, attrs, operation, props) {
+ var fullAddr = self._fullAddr(toAddr);
+ var ret = {id: self.correlator.corr()};
+ if (!self.sender || !self.sendable) {
+ ret.error = "no sender"
+ return ret;
+ }
+ try {
+ var application_properties = {
+ operation: operation
+ }
+ if (entity) {
+ var ent = self.schema.entityTypes[entity];
+ var fullyQualifiedType = ent ? ent.fullyQualifiedType : entity;
+ application_properties.type = fullyQualifiedType || entity;
+ }
+ if (attrs.name)
+ application_properties.name = attrs.name;
+ if (props) {
+ jQuery.extend(application_properties, props);
+ }
+ var msg = {
+ body: attrs,
+ properties: {
+ to: fullAddr,
+ reply_to: self.receiver.remote.attach.source.address,
+ correlation_id: ret.id
+ },
+ application_properties: application_properties
+ }
+ self.sender.send( msg );
+ console.dump("------- method called -------")
+ console.dump (msg)
+ }
+ catch (e) {
+ error = "error sending: " + e;
+ QDR.log.error(error)
+ ret.error = error;
+ }
+ return ret;
+ },
+
+ sendQuery: function(toAddr, entity, attrs, operation) {
+ operation = operation || "QUERY"
+ var fullAddr = self._fullAddr(toAddr);
+
+ var body;
+ if (attrs)
+ body = {
+ "attributeNames": attrs,
+ }
+ else
+ body = {
+ "attributeNames": [],
+ }
+ if (entity[0] === '.')
+ entity = entity.substr(1, entity.length-1)
+ var prefix = "org.apache.qpid.dispatch."
+ var configs = ["address", "autoLink", "linkRoute"]
+ if (configs.indexOf(entity) > -1)
+ prefix += "router.config."
+ return self._send(body, fullAddr, operation, prefix + entity);
+ },
+
+ sendMgmtQuery: function (operation) {
+ return self._send([], "/$management", operation);
+ },
+
+ _send: function (body, to, operation, entityType) {
+ var ret = {id: self.correlator.corr()};
+ if (!self.sender || !self.sendable) {
+ ret.error = "no sender"
+ return ret;
+ }
+ try {
+ var application_properties = {
+ operation: operation,
+ type: "org.amqp.management",
+ name: "self"
+ };
+ if (entityType)
+ application_properties.entityType = entityType;
+
+ self.sender.send({
+ body: body,
+ properties: {
+ to: to,
+ reply_to: self.receiver.remote.attach.source.address,
+ correlation_id: ret.id
+ },
+ application_properties: application_properties
+ })
+ }
+ catch (e) {
+ error = "error sending: " + e;
+ QDR.log.error(error)
+ ret.error = error;
+ }
+ return ret;
+ },
+
+ disconnect: function() {
+ self.connection.close();
+ self.errorText = "Disconnected."
+ },
+
+ connect: function(overrideConnectOptions) {
+ QDR.log.debug("****** calling rhea.connect ********")
+ var options = self.connectionOptions;
+ if (overrideConnectOptions)
+ options = overrideConnectOptions;
+ self.topologyInitialized = false;
+ if (!self.connected) {
+ var okay = {connection: false, sender: false, receiver: false}
+ var port = options.port || 5673;
+ var baseAddress = options.address + ':' + port;
+ var ws = self.rhea.websocket_connect(WebSocket);
+ self.toAddress = "amqp://" + baseAddress;
+ self.connectionError = undefined;
+
+ var stop = function (context) {
+ //self.stopUpdating();
+ okay.sender = false;
+ okay.receiver = false;
+ okay.connected = false;
+ self.connected = false;
+ self.sender = null;
+ self.receiver = null;
+ self.sendable = false;
+ self.gotTopology = false;
+ }
+ var maybeStart = function () {
+ if (okay.connection && okay.sender && okay.receiver && self.sendable && !self.connected) {
+ QDR.log.info("okay to start")
+ self.connected = true;
+ self.connection = connection;
+ self.sender = sender;
+ self.receiver = receiver;
+ self.onSubscription();
+ self.gotTopology = false;
+ }
+ }
+ var onDisconnect = function () {
+ //QDR.log.warn("Disconnected");
+ self.connectionError = true;
+ stop();
+ self.executeDisconnectActions();
+ }
+
+ var connection;
+ try {
+QDR.log.debug("trying to connect to ws://" + baseAddress)
+ connection = self.rhea.connect({
+ connection_details:ws('ws://' + baseAddress, ["binary", "base64", "AMQWSB10"]),
+ reconnect:true,
+ properties: {console_identifier: 'Dispatch console'}
+ });
+ }
+ catch (e) {
+ QDR.log.debug("exception caught on connect")
+ self.errorText = "Connection failed"
+ onDisconnect();
+ }
+ if (!self.connectionError) {
+ connection.on('connection_open', function (context) {
+ QDR.log.debug("connection_opened")
+ okay.connection = true;
+ okay.receiver = false;
+ okay.sender = false;
+ })
+ connection.on('disconnected', function (context) {
+ QDR.log.debug("connection disconnected")
+ self.errorText = "Unable to connect"
+ onDisconnect();
+ })
+ connection.on('connection_close', function (context) {
+ QDR.log.debug("connection closed")
+ self.errorText = "Disconnected"
+ onDisconnect();
+ })
+
+ var sender = connection.open_sender();
+ sender.on('sender_open', function (context) {
+ QDR.log.debug("sender_opened")
+ okay.sender = true
+ maybeStart()
+ })
+ sender.on('sendable', function (context) {
+ //QDR.log.debug("sendable")
+ self.sendable = true;
+ maybeStart();
+ })
+
+ var receiver = connection.open_receiver({source: {dynamic: true}});
+ receiver.on('receiver_open', function (context) {
+ QDR.log.debug("receiver_opened")
+ okay.receiver = true;
+ maybeStart()
+ })
+ receiver.on("message", function (context) {
+ self.correlator.resolve(context);
+ });
+ }
+ }
+ }
+ }
+ return self;
+ };
+
+ return QDR;
+}(QDR || {}));
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/0c58c381/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/dispatch.module.js
----------------------------------------------------------------------
diff --git a/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/dispatch.module.js b/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/dispatch.module.js
new file mode 100644
index 0000000..48cc85f
--- /dev/null
+++ b/console/dispatch-dashboard/dispatch/static/dashboard/dispatch/dispatch.module.js
@@ -0,0 +1,256 @@
+/*
+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.
+*/
+/**
+ * @module QDR
+ * @main QDR
+ *
+ * The main entry point for the QDR module
+ *
+ */
+var QDR = (function(QDR) {
+
+ /**
+ * @property pluginName
+ * @type {string}
+ *
+ * The name of this plugin
+ */
+ QDR.pluginName = "QDR";
+ QDR.pluginRoot = "";
+ QDR.isStandalone = true;
+ QDR.isHorizon = true;
+ QDR.offsetParent = ".col-xs-12";
+
+ /**
+ * @property log
+ * @type {Logging.Logger}
+ *
+ * This plugin's logger instance
+ */
+ //HIO QDR.log = Logger.get(QDR.pluginName);
+ /**
+ * @property templatePath
+ * @type {string}
+ *
+ * The top level path to this plugin's partials
+ */
+ QDR.srcBase = "plugin/";
+ QDR.templatePath = QDR.srcBase + "html/";
+ QDR.cssPath = QDR.srcBase + "css/";
+ /**
+ * @property SETTINGS_KEY
+ * @type {string}
+ *
+ * The key used to fetch our settings from local storage
+ */
+ QDR.SETTINGS_KEY = 'QDRSettings';
+ QDR.LAST_LOCATION = "QDRLastLocation";
+
+ /**
+ * @property module
+ * @type {object}
+ *
+ * This plugin's angularjs module instance
+ */
+ QDR.module = angular.module('horizon.dashboard.dispatch',
+ [
+ 'ui.grid',
+ 'ui.grid.resizeColumns',
+ 'ui.grid.selection',
+ 'ui.bootstrap',
+ 'ui.slider',
+ 'horizon.dashboard.dispatch.overv',
+ 'horizon.dashboard.dispatch.topology'
+ ])
+
+ Core = {
+ notification: function (severity, msg) {
+ $.notify(msg, severity);
+ }
+ }
+
+ QDR.module.config(['$provide', '$windowProvider',
+ function ($provide, $windowProvider) {
+ var path = $windowProvider.$get().STATIC_URL + 'dashboard/dispatch/';
+ $provide.constant('horizon.dashboard.dispatch.basePath', path);
+ }
+ ]);
+
+ QDR.module.config(['$compileProvider',
+ function($compileProvider) {
+ $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|blob):/);
+ }
+ ]);
+
+ QDR.module.filter('to_trusted', ['$sce', function($sce){
+ return function(text) {
+ return $sce.trustAsHtml(text);
+ };
+ }]);
+
+ QDR.module.filter('humanify', ['horizon.dashboard.dispatch.comService', function (QDRService) {
+ return function (input) {
+ return QDRService.humanify(input);
+ };
+ }]);
+
+ QDR.module.filter('Pascalcase', function () {
+ return function (str) {
+ if (!str)
+ return "";
+ return str.replace(/(\w)(\w*)/g,
+ function(g0,g1,g2){return g1.toUpperCase() + g2.toLowerCase();});
+ }
+ })
+
+ QDR.module.filter('safePlural', function () {
+ return function (str) {
+ var es = ['x', 'ch', 'ss', 'sh']
+ for (var i=0; i<es.length; ++i) {
+ if (str.endsWith(es[i]))
+ return str + 'es'
+ }
+ if (str.endsWith('y'))
+ return str.substr(0, str.length-2) + 'ies'
+ if (str.endsWith('s'))
+ return str;
+ return str + 's'
+ }
+ })
+
+ QDR.logger = function ($log) {
+ var log = $log;
+
+ this.debug = function (msg) { msg = "QDR: " + msg; log.debug(msg)};
+ this.error = function (msg) {msg = "QDR: " + msg; log.error(msg)}
+ this.info = function (msg) {msg = "QDR: " + msg; log.info(msg)}
+ this.warn = function (msg) {msg = "QDR: " + msg; log.warn(msg)}
+
+ return this;
+ }
+ // one-time initialization happens in the run function
+ // of our module
+ QDR.module.run(
+ ["$rootScope",
+ '$route',
+ '$timeout',
+ "$location",
+ "$log",
+ "horizon.dashboard.dispatch.comService",
+ "horizon.dashboard.dispatch.chartService",
+ function (
+ $rootScope,
+ $route,
+ $timeout,
+ $location,
+ $log,
+ QDRService,
+ QDRChartService) {
+ QDR.log = new QDR.logger($log);
+ QDR.log.info("*************creating Dispatch Console************");
+
+ var curPath = $location.path()
+ var org = curPath.substr(1)
+ if (org && org.length > 0 && org !== "connect") {
+ // $location.search('org', org)
+ } else {
+ // $location.search('org', null)
+ }
+
+ QDRService.initProton();
+ var settings = angular.fromJson(localStorage[QDR.SETTINGS_KEY]);
+ QDRService.addConnectAction(function() {
+ QDRChartService.init(); // initialize charting service after we are connected
+ });
+
+ if (settings && settings.autostart) {
+ QDRService.addDisconnectAction( function () {
+ $timeout(function () {
+ var lastLocation = localStorage[QDR.LAST_LOCATION] || "/overview";
+ org = lastLocation.substr(1)
+ //$location.path("/connect");
+ //$location.search('org', org)
+debugger;
+ window.location.replace("/dispatch/connect/");
+ })
+ })
+ QDRService.addConnectAction(function() {
+ var searchObject = $location.search();
+ // the redirect will be handled by QDRService when connected
+ if (searchObject.org) {
+ return;
+ }
+ // there was no org= parameter, so redirect to last known location
+ $timeout(function () {
+ var lastLocation = localStorage[QDR.LAST_LOCATION] || "/overview";
+ //$location.path(lastLocation);
+ })
+ });
+ QDRService.connect(settings);
+ } else {
+QDR.log.debug("QDR.module run called with location of " + $location.path());
+ $timeout(function () {
+ //$location.path('/connect')
+ //$location.search('org', org)
+//debugger;
+// window.location.replace("/dispatch/connect/");
+ })
+ }
+
+ $rootScope.$on('$routeChangeSuccess', function() {
+ var path = $location.path();
+ if (path !== "/connect") {
+ localStorage[QDR.LAST_LOCATION] = path;
+ }
+ });
+ }]);
+
+ QDR.module.controller ("QDR.Core", function ($scope, $rootScope) {
+ $scope.alerts = [];
+ $scope.closeAlert = function(index) {
+ $scope.alerts.splice(index, 1);
+ };
+ $scope.$on('newAlert', function(event, data) {
+ $scope.alerts.push(data);
+ $scope.$apply();
+ });
+ $scope.$on("clearAlerts", function () {
+ $scope.alerts = [];
+ $scope.$apply();
+ })
+
+ })
+
+ return QDR;
+}(QDR || {}));
+
+var Folder = (function () {
+ function Folder(title) {
+ this.title = title;
+ this.children = [];
+ this.folder = true;
+ }
+ return Folder;
+})();
+var Leaf = (function () {
+ function Leaf(title) {
+ this.title = title;
+ }
+ return Leaf;
+})();
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org