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 2017/04/19 12:17:23 UTC
[4/4] qpid-dispatch git commit: DISPATCH-745 Remove symlinks from
hawtio to stand-alone
DISPATCH-745 Remove symlinks from hawtio to stand-alone
Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/6a1e6632
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/6a1e6632
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/6a1e6632
Branch: refs/heads/master
Commit: 6a1e66322cf8b1298acc76bf3ed9d5bfeade2c3f
Parents: 4c14b0a
Author: Ernest Allen <ea...@redhat.com>
Authored: Wed Apr 19 08:16:53 2017 -0400
Committer: Ernest Allen <ea...@redhat.com>
Committed: Wed Apr 19 08:16:53 2017 -0400
----------------------------------------------------------------------
.../hawtio/src/main/webapp/plugin/js/navbar.js | 302 ++-
.../hawtio/src/main/webapp/plugin/js/qdrList.js | 788 ++++++-
.../src/main/webapp/plugin/js/qdrListChart.js | 142 +-
.../src/main/webapp/plugin/js/qdrNewNode.js | 446 +++-
.../src/main/webapp/plugin/js/qdrOverview.js | 1767 +++++++++++++-
.../plugin/js/qdrOverviewLogsController.js | 68 +-
.../src/main/webapp/plugin/js/qdrTopology.js | 2161 +++++++++++++++++-
console/stand-alone/plugin/js/navbar.js | 43 +-
console/stand-alone/plugin/js/qdrList.js | 13 +-
console/stand-alone/plugin/js/qdrListChart.js | 835 ++++++-
console/stand-alone/plugin/js/qdrNewNode.js | 10 +-
console/stand-alone/plugin/js/qdrOverview.js | 309 ++-
.../plugin/js/qdrOverviewLogsController.js | 4 +-
console/stand-alone/plugin/js/qdrTopology.js | 88 +-
14 files changed, 6709 insertions(+), 267 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6a1e6632/console/hawtio/src/main/webapp/plugin/js/navbar.js
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/js/navbar.js b/console/hawtio/src/main/webapp/plugin/js/navbar.js
deleted file mode 120000
index e88b618..0000000
--- a/console/hawtio/src/main/webapp/plugin/js/navbar.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../stand-alone/plugin/js/navbar.js
\ No newline at end of file
diff --git a/console/hawtio/src/main/webapp/plugin/js/navbar.js b/console/hawtio/src/main/webapp/plugin/js/navbar.js
new file mode 100644
index 0000000..5125748
--- /dev/null
+++ b/console/hawtio/src/main/webapp/plugin/js/navbar.js
@@ -0,0 +1,301 @@
+/*
+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
+ */
+var QDR = (function (QDR) {
+
+ /**
+ * @property breadcrumbs
+ * @type {{content: string, title: string, isValid: isValid, href: string}[]}
+ *
+ * Data structure that defines the sub-level tabs for
+ * our plugin, used by the navbar controller to show
+ * or hide tabs based on some criteria
+ */
+ QDR.breadcrumbs = [
+ {
+ content: '<i class="icon-cogs"></i> Connect',
+ title: "Connect to a router",
+ isValid: function () { return true; },
+ href: "#" + QDR.pluginRoot + "/connect"
+ },
+ {
+ content: '<i class="icon-home"></i> Overview',
+ title: "View router overview",
+ isValid: function (QDRService) { return QDRService.isConnected(); },
+ href: "#" + QDR.pluginRoot + "/overview"
+ },
+ {
+ content: '<i class="icon-list "></i> Entities',
+ title: "View the attributes of the router entities",
+ isValid: function (QDRService) { return QDRService.isConnected(); },
+ href: "#" + QDR.pluginRoot + "/list"
+ },
+ {
+ content: '<i class="icon-star-empty"></i> Topology',
+ title: "View router network topology",
+ isValid: function (QDRService) { return QDRService.isConnected(); },
+ href: "#" + QDR.pluginRoot + "/topology"
+ },
+ {
+ content: '<i class="icon-bar-chart"></i> Charts',
+ title: "View charts",
+ isValid: function (QDRService, $location) { return QDRService.isConnected() && QDR.isStandalone; },
+ href: "#/charts"
+ },
+ {
+ content: '<i class="icon-align-left"></i> Schema',
+ title: "View dispatch schema",
+ isValid: function (QDRService) { return QDRService.isConnected(); },
+ href: "#" + QDR.pluginRoot + "/schema",
+ right: true
+ }
+ ];
+ /**
+ * @function NavBarController
+ *
+ * @param $scope
+ * @param workspace
+ *
+ * The controller for this plugin's navigation bar
+ *
+ */
+ QDR.module.controller("QDR.NavBarController", ['$scope', 'QDRService', 'QDRChartService', '$routeParams', '$location', function($scope, QDRService, QDRChartService, $routeParams, $location) {
+ $scope.breadcrumbs = QDR.breadcrumbs;
+ $scope.isValid = function(link) {
+ return link.isValid(QDRService, $location);
+ };
+
+ $scope.isActive = function(href) {
+ // highlight the connect tab if we are on the root page
+ if (($location.path() === QDR.pluginRoot) && (href.split("#")[1] === QDR.pluginRoot + "/connect"))
+ return true
+ return href.split("#")[1] == $location.path();
+ };
+
+ $scope.isRight = function (link) {
+ return angular.isDefined(link.right);
+ };
+
+ $scope.hasChart = function (link) {
+ if (link.href == "#/charts") {
+ return QDRChartService.charts.some(function (c) { return c.dashboard });
+ }
+ }
+
+ $scope.isDashboardable = function () {
+ return ($location.path().indexOf("schema") < 0 && $location.path().indexOf("connect") < 0);
+ }
+
+ $scope.addToDashboardLink = function () {
+ var href = "#" + $location.path();
+ var size = angular.toJson({
+ size_x: 2,
+ size_y: 2
+ });
+
+ var routeParams = angular.toJson($routeParams);
+ var title = "Dispatch Router";
+ return "/hawtio/#/dashboard/add?tab=dashboard" +
+ "&href=" + encodeURIComponent(href) +
+ "&routeParams=" + encodeURIComponent(routeParams) +
+ "&title=" + encodeURIComponent(title) +
+ "&size=" + encodeURIComponent(size);
+ };
+
+ }]);
+
+ // controller for the edit/configure chart dialog
+ QDR.module.controller("QDR.ChartDialogController", function($scope, QDRChartService, $location, dialog, chart, updateTick, dashboard, adding) {
+ var dialogSvgChart = null;
+ $scope.svgDivId = "dialogEditChart"; // the div id for the svg chart
+
+ var updateTimer = null;
+ $scope.chart = chart; // the underlying chart object from the dashboard
+ $scope.dialogChart = $scope.chart.copy(); // the chart object for this dialog
+ $scope.userTitle = $scope.chart.title();
+
+ $scope.$watch('userTitle', function(newValue, oldValue) {
+ if (newValue !== oldValue) {
+ $scope.dialogChart.title(newValue);
+ dialogSvgChart.tick($scope.svgDivId);
+ }
+ })
+ $scope.$watch("dialogChart.areaColor", function (newValue, oldValue) {
+ if (newValue !== oldValue) {
+ if (dialogSvgChart)
+ dialogSvgChart.tick($scope.svgDivId);
+ }
+ })
+ $scope.$watch("dialogChart.lineColor", function (newValue, oldValue) {
+ if (newValue !== oldValue) {
+ if (dialogSvgChart)
+ dialogSvgChart.tick($scope.svgDivId);
+ }
+ })
+ $scope.$watch("dialogChart.type", function (newValue, oldValue) {
+ if (newValue !== oldValue) {
+ if (dialogSvgChart)
+ dialogSvgChart.tick($scope.svgDivId);
+ }
+ })
+
+ // the stored rateWindow is in milliseconds, but the slider is in seconds
+ $scope.rateWindow = $scope.chart.rateWindow / 1000;
+
+ $scope.addChartsPage = function () {
+ QDRChartService.addDashboard(dialogSvgChart.chart);
+ };
+
+ $scope.showChartsPage = function () {
+ cleanup();
+ dialog.close(true);
+ $location.path(QDR.pluginRoot + "/charts");
+ };
+
+ var cleanup = function () {
+ if (updateTimer) {
+ clearTimeout(updateTimer);
+ updateTimer = null;
+ }
+ if (!$scope.isOnChartsPage())
+ QDRChartService.unRegisterChart($scope.dialogChart); // remove the chart
+ }
+ $scope.okClick = function () {
+ cleanup();
+ dialog.close(true);
+ };
+
+ var initRateSlider = function () {
+ if (document.getElementById('rateSlider')) {
+ $( "#rateSlider" ).slider({
+ value: $scope.rateWindow,
+ min: 1,
+ max: 10,
+ step: 1,
+ slide: function( event, ui ) {
+ $scope.rateWindow = ui.value;
+ $scope.dialogChart.rateWindow = ui.value * 1000;
+ $scope.$apply();
+ if (dialogSvgChart)
+ dialogSvgChart.tick($scope.svgDivId);
+ }
+ });
+ } else {
+ setTimeout(initRateSlider, 100)
+ }
+ }
+ initRateSlider();
+
+ var initDurationSlider = function () {
+ if (document.getElementById('durationSlider')) {
+ $( "#durationSlider" ).slider({
+ value: $scope.dialogChart.visibleDuration,
+ min: 1,
+ max: 10,
+ step: 1,
+ slide: function( event, ui ) {
+ $scope.visibleDuration = $scope.dialogChart.visibleDuration = ui.value;
+ $scope.$apply();
+ if (dialogSvgChart)
+ dialogSvgChart.tick($scope.svgDivId);
+ }
+ });
+ } else {
+ setTimeout(initDurationSlider, 100)
+ }
+ }
+ initDurationSlider();
+
+ $scope.adding = function () {
+ return adding
+ }
+
+ $scope.isOnChartsPage = function () {
+ if (adding)
+ return dialogSvgChart ? dialogSvgChart.chart.dashboard : false;
+ else
+ return $scope.chart.dashboard
+ }
+
+ // handle the Apply button click
+ // update the dashboard chart's properties
+ $scope.apply = function () {
+ $scope.chart.areaColor = $scope.dialogChart.areaColor;
+ $scope.chart.lineColor = $scope.dialogChart.lineColor;
+ $scope.chart.type = $scope.dialogChart.type;
+ $scope.chart.rateWindow = $scope.rateWindow * 1000;
+ $scope.chart.title($scope.dialogChart.title());
+ $scope.chart.visibleDuration = $scope.dialogChart.visibleDuration;
+ QDRChartService.saveCharts();
+ if (typeof updateTick === "function")
+ updateTick();
+ }
+
+ // add a new chart to the dashboard based on the current dialog settings
+ $scope.copyToDashboard = function () {
+ var chart = $scope.dialogChart.copy();
+ // set the new chart's dashboard state
+ QDRChartService.addDashboard(chart);
+ // notify the chart controller that it needs to display a new chart
+ dashboard.addChart(chart);
+ }
+
+ // update the chart on the popup dialog
+ var updateDialogChart = function () {
+ // draw the chart using the current data
+ if (dialogSvgChart)
+ dialogSvgChart.tick($scope.svgDivId);
+
+ // draw the chart again in 1 second
+ var updateRate = localStorage['updateRate'] ? localStorage['updateRate'] : 5000;
+ if (updateTimer)
+ clearTimeout(updateTimer);
+ updateTimer = setTimeout(updateDialogChart, updateRate);
+ }
+
+ var showChart = function () {
+ // ensure the div for our chart is loaded in the dom
+ var div = angular.element("#" + $scope.svgDivId);
+ if (!div.width()) {
+ setTimeout(showChart, 100);
+ return;
+ }
+ dialogSvgChart = new QDRChartService.AreaChart($scope.dialogChart);
+ $('input[name=lineColor]').val($scope.dialogChart.lineColor);
+ $('input[name=areaColor]').val($scope.dialogChart.areaColor);
+ $('input[name=areaColor]').on('input', function (e) {
+ $scope.dialogChart.areaColor = $(this).val();
+ updateDialogChart()
+ })
+ $('input[name=lineColor]').on('input', function (e) {
+ $scope.dialogChart.lineColor = $(this).val();
+ updateDialogChart()
+ })
+ if (updateTimer)
+ clearTimeout(updateTimer);
+ updateDialogChart();
+ }
+ showChart();
+ });
+
+ return QDR;
+
+} (QDR || {}));
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6a1e6632/console/hawtio/src/main/webapp/plugin/js/qdrList.js
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrList.js b/console/hawtio/src/main/webapp/plugin/js/qdrList.js
deleted file mode 120000
index 3955db5..0000000
--- a/console/hawtio/src/main/webapp/plugin/js/qdrList.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../stand-alone/plugin/js/qdrList.js
\ No newline at end of file
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrList.js b/console/hawtio/src/main/webapp/plugin/js/qdrList.js
new file mode 100644
index 0000000..ec2efb2
--- /dev/null
+++ b/console/hawtio/src/main/webapp/plugin/js/qdrList.js
@@ -0,0 +1,787 @@
+/*
+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
+ */
+var QDR = (function(QDR) {
+
+ /**
+ * @method ListController
+ * @param $scope
+ * @param QDRService
+ *
+ * Controller for the main interface
+ */
+ QDR.module.controller("QDR.ListController", ['$scope', '$location', '$dialog', '$filter', '$timeout', 'QDRService', 'QDRChartService',
+ function ($scope, $location, $dialog, $filter, $timeout, QDRService, QDRChartService) {
+
+ var updateIntervalHandle = undefined;
+ var updateInterval = 5000;
+ var ListExpandedKey = "QDRListExpanded";
+ $scope.details = {};
+
+ $scope.tmplListTree = QDR.templatePath + 'tmplListTree.html';
+ $scope.selectedEntity = localStorage['QDRSelectedEntity'] || "address";
+ $scope.selectedNode = localStorage['QDRSelectedNode'];
+ $scope.selectedNodeId = localStorage['QDRSelectedNodeId'];
+ $scope.selectedRecordName = localStorage['QDRSelectedRecordName'];
+ $scope.nodes = []
+ $scope.currentNode = undefined;
+ $scope.modes = [
+ {
+ content: '<a><i class="icon-list"></i> Attributes</a>',
+ id: 'attributes',
+ op: 'READ',
+ title: "View router attributes",
+ isValid: function () { return true; }
+ },
+ {
+ content: '<a><i class="icon-edit"></i> Update</a>',
+ id: 'operations',
+ op: 'UPDATE',
+ title: "Update this attribute",
+ isValid: function () {
+ //QDR.log.debug("isValid UPDAATE? " + this.op)
+ //console.dump($scope.operations)
+ return $scope.operations.indexOf(this.op) > -1
+ }
+ },
+ {
+ content: '<a><i class="icon-plus"></i> Create</a>',
+ id: 'operations',
+ op: 'CREATE',
+ title: "Create a new attribute",
+ isValid: function () { return $scope.operations.indexOf(this.op) > -1 }
+ },
+ {
+ content: '<a><i class="icon-remove"></i> Delete</a>',
+ id: 'delete',
+ op: 'DELETE',
+ title: "Delete",
+ isValid: function () { return $scope.operations.indexOf(this.op) > -1 }
+ },
+ {
+ content: '<a><i class="icon-eye-open"></i> Fetch</a>',
+ id: 'log',
+ op: 'GET-LOG',
+ title: "Fetch recent log entries",
+ isValid: function () { return ($scope.selectedEntity === 'log') }
+ }
+ ];
+ $scope.operations = []
+ $scope.currentMode = $scope.modes[0];
+ $scope.isModeSelected = function (mode) {
+ return mode === $scope.currentMode;
+ }
+ $scope.fetchingLog = false;
+ $scope.selectMode = function (mode) {
+ $scope.currentMode = mode;
+ if (mode.id === 'log') {
+ $scope.logResults = [];
+ $scope.fetchingLog = true;
+ var entity; // undefined since it is not supported in the GET-LOG call
+ QDRService.sendMethod($scope.currentNode.id, entity, {}, $scope.currentMode.op, {}, function (nodeName, entity, response, context) {
+ $scope.fetchingLog = false;
+ var statusCode = context.message.application_properties.statusCode;
+ if (statusCode < 200 || statusCode >= 300) {
+ Core.notification('error', context.message.application_properties.statusDescription);
+ //QDR.log.debug(context.message.application_properties.statusDescription)
+ return;
+ }
+ $scope.logResults = response.filter( function (entry) {
+ return entry[0] === $scope.detailsObject.module
+ }).sort( function (a, b) {
+ return b[5] - a[5]
+ }).map( function (entry) {
+ return {
+ type: entry[1],
+ message: entry[2],
+ source: entry[3],
+ line: entry[4],
+ time: Date(entry[5]).toString()
+ }
+ })
+ $scope.$apply();
+ })
+ }
+ }
+ $scope.isValid = function (mode) {
+ return mode.isValid()
+ }
+
+ $scope.expandAll = function () {
+ $("#entityTree").dynatree("getRoot").visit(function(node){
+ node.expand(true);
+ });
+ }
+ $scope.contractAll = function () {
+ $("#entityTree").dynatree("getRoot").visit(function(node){
+ node.expand(false);
+ });
+ }
+
+ if (!QDRService.connected) {
+ // we are not connected. we probably got here from a bookmark or manual page reload
+ QDRService.redirectWhenConnected("list");
+ return;
+ }
+ // we are currently connected. setup a handler to get notified if we are ever disconnected
+ QDRService.addDisconnectAction( function () {
+ QDRService.redirectWhenConnected("list")
+ $scope.$apply();
+ })
+
+ $scope.nodes = []
+ var excludedEntities = ["management", "org.amqp.management", "operationalEntity", "entity", "configurationEntity", "dummy", "console"];
+ var aggregateEntities = ["router.address"];
+ var classOverrides = {
+ "connection": function (row, nodeId) {
+ var isConsole = QDRService.isAConsole (row.properties.value, row.identity.value, row.role.value, nodeId)
+ return isConsole ? "console" : row.role.value === "inter-router" ? "inter-router" : "external";
+ },
+ "router.link": function (row, nodeId) {
+ var link = {nodeId: nodeId, connectionId: row.connectionId.value}
+ var isConsole = QDRService.isConsoleLink(link)
+ return isConsole ? "console" : row.linkType.value;
+ },
+ "router.address": function (row) {
+ var identity = QDRService.identity_clean(row.identity.value)
+ var address = QDRService.addr_text(identity)
+ var cls = QDRService.addr_class(identity)
+ if (address === "$management")
+ cls = "internal " + cls
+ return cls
+ }
+ }
+
+ var lookupOperations = function () {
+ var ops = QDRService.schema.entityTypes[$scope.selectedEntity].operations.filter( function (op) { return op !== 'READ'});
+ $scope.operation = ops.length ? ops[0] : "";
+ return ops;
+ }
+
+ var entityTreeChildren = [];
+ var expandedList = angular.fromJson(localStorage[ListExpandedKey]) || [];
+ var onTreeNodeExpanded = function (expanded, node) {
+ // save the list of entities that are expanded
+ var tree = $("#entityTree").dynatree("getTree");
+ var list = [];
+ tree.visit( function (tnode) {
+ if (tnode.isExpanded()) {
+ list.push(tnode.data.key)
+ }
+ })
+ localStorage[ListExpandedKey] = JSON.stringify(list)
+
+ if (expanded)
+ onTreeSelected(node);
+ }
+ // a tree node was selected
+ var onTreeSelected = function (selectedNode) {
+ $timeout( function () {
+ if ($scope.currentMode.id === 'operations')
+ $scope.currentMode = $scope.modes[0];
+ else if ($scope.currentMode.id === 'log')
+ $scope.selectMode($scope.currentMode)
+ else if ($scope.currentMode.id === 'delete') {
+ // clicked on a tree node while on the delete screen -> switch to attribute screen
+ $scope.currentMode = $scope.modes[0];
+ }
+ if (selectedNode.data.typeName === "entity") {
+ $scope.selectedEntity = selectedNode.data.key;
+ $scope.operations = lookupOperations()
+ } else if (selectedNode.data.typeName === 'attribute') {
+ $scope.selectedEntity = selectedNode.parent.data.key;
+ $scope.operations = lookupOperations()
+ $scope.selectedRecordName = selectedNode.data.key;
+ updateDetails(selectedNode.data.details); // update the table on the right
+ $("#entityTree").dynatree("getRoot").visit(function(node){
+ node.select(false);
+ });
+ selectedNode.select();
+ }
+ })
+ }
+
+ // fill in an empty results recoord based on the entities schema
+ var fromSchema = function (entityName) {
+ var row = {}
+ var schemaEntity = QDRService.schema.entityTypes[entityName]
+ for (attr in schemaEntity.attributes) {
+ var entity = schemaEntity.attributes[attr]
+ var value = ""
+ if (angular.isDefined(entity['default']))
+ value = entity['default']
+ row[attr] = {
+ value: value,
+ type: entity.type,
+ graph: false,
+ title: entity.description,
+ aggregate: false,
+ aggregateTip: '',
+ 'default': entity['default']
+ }
+ }
+ return row;
+ }
+ $scope.hasCreate = function () {
+ var schemaEntity = QDRService.schema.entityTypes[$scope.selectedEntity]
+ return (schemaEntity.operations.indexOf("CREATE") > -1)
+ }
+
+ var stopUpdating = function () {
+ if (angular.isDefined(updateIntervalHandle)) {
+ clearInterval(updateIntervalHandle);
+ }
+ updateIntervalHandle = undefined;
+ }
+
+ // the data for the selected entity is available, populate the tree
+ var updateEntityChildren = function (entity, tableRows, expand) {
+ var tree = $("#entityTree").dynatree("getTree");
+ if (!tree.getNodeByKey) {
+ return stopUpdating()
+ }
+ var node = tree.getNodeByKey(entity)
+ var updatedDetails = false;
+ var scrollTreeDiv = $('.qdr-attributes.pane.left .pane-viewport')
+ var scrollTop = scrollTreeDiv.scrollTop();
+ node.removeChildren();
+ if (tableRows.length == 0) {
+ node.addChild({
+ addClass: "no-data",
+ typeName: "none",
+ title: "no data",
+ key: node.data.key + ".1"
+ })
+ if (expand) {
+ updateDetails(fromSchema(entity));
+ $scope.selectedRecordName = entity;
+ }
+ } else {
+ tableRows.forEach( function (row) {
+ var addClass = entity;
+ if (classOverrides[entity]) {
+ addClass += " " + classOverrides[entity](row, $scope.currentNode.id);
+ }
+ var child = {
+ typeName: "attribute",
+ addClass: addClass,
+ tooltip: addClass,
+ key: row.name.value,
+ title: row.name.value,
+ details: row
+ }
+ if (row.name.value === $scope.selectedRecordName) {
+ if (expand)
+ updateDetails(row); // update the table on the right
+ child.select = true;
+ updatedDetails = true;
+ }
+ node.addChild(child)
+ })
+ }
+ // if the selectedRecordName was not found, select the 1st one
+ if (expand && !updatedDetails && tableRows.length > 0) {
+ var row = tableRows[0];
+ $scope.selectedRecordName = row.name.value;
+ var node = tree.getNodeByKey($scope.selectedRecordName);
+ node.select(true);
+ updateDetails(row) // update the table on the right
+ }
+ scrollTreeDiv.scrollTop(scrollTop)
+ }
+
+ var schemaProps = function (entityName, key, currentNode) {
+ var typeMap = {integer: 'number', string: 'text', path: 'text', boolean: 'boolean', map: 'textarea'};
+
+ var entity = QDRService.schema.entityTypes[entityName]
+ var value = entity.attributes[key]
+ // skip identity and depricated fields
+ if (!value)
+ return {input: 'input', type: 'disabled', required: false, selected: "", rawtype: 'string', disabled: true, 'default': ''}
+ var description = value.description || ""
+ var val = value['default'];
+ var disabled = (key == 'identity' || description.startsWith('Deprecated'))
+ // special cases
+ if (entityName == 'log' && key == 'module') {
+ return {input: 'input', type: 'disabled', required: false, selected: "", rawtype: 'string', disabled: true, 'default': ''}
+ }
+ if (entityName === 'linkRoutePattern' && key === 'connector') {
+ // turn input into a select. the values will be populated later
+ value.type = []
+ // find all the connector names and populate the select
+ QDRService.fetchEntity(currentNode.id, '.connector', ['name'], function (nodeName, dotentity, response) {
+ $scope.detailFields.some( function (field) {
+ if (field.name === 'connector') {
+ field.rawtype = response.results.map (function (result) {return result[0]})
+ return true;
+ }
+ })
+ });
+ }
+ return { name: key,
+ humanName: QDRService.humanify(key),
+ description:value.description,
+ type: disabled ? 'disabled' : typeMap[value.type],
+ rawtype: value.type,
+ input: typeof value.type == 'string' ? value.type == 'boolean' ? 'boolean' : 'input'
+ : 'select',
+ selected: val ? val : undefined,
+ 'default': value['default'],
+ value: val,
+ required: value.required,
+ unique: value.unique,
+ disabled: disabled
+ };
+ }
+ $scope.getAttributeValue = function (attribute) {
+ var value = attribute.attributeValue;
+ if ($scope.currentMode.op === "CREATE" && attribute.name === 'identity')
+ value = "<assigned by system>"
+ return value;
+ }
+
+ // update the table on the right
+ var updateDetails = function (row) {
+ var details = [];
+ $scope.detailsObject = {};
+ var attrs = Object.keys(row).sort();
+ attrs.forEach( function (attr) {
+ var changed = $scope.detailFields.filter(function (old) {
+ return (old.name === attr) ? old.graph && old.rawValue != row[attr].value : false;
+ })
+ var schemaEntity = schemaProps($scope.selectedEntity, attr, $scope.currentNode)
+ details.push( {
+ attributeName: QDRService.humanify(attr),
+ attributeValue: attr === 'port' ? row[attr].value : QDRService.pretty(row[attr].value),
+ name: attr,
+ changed: changed.length,
+ rawValue: row[attr].value,
+ graph: row[attr].graph,
+ title: row[attr].title,
+ aggregateValue: QDRService.pretty(row[attr].aggregate),
+ aggregateTip: row[attr].aggregateTip,
+
+ input: schemaEntity.input,
+ type: schemaEntity.type,
+ required: schemaEntity.required,
+ selected: schemaEntity.selected,
+ rawtype: schemaEntity.rawtype,
+ disabled: schemaEntity.disabled,
+ 'default': schemaEntity['default']
+ })
+ $scope.detailsObject[attr] = row[attr].value;
+ })
+ setTimeout(applyDetails, 1, details)
+ }
+
+ var applyDetails = function (details) {
+ $scope.detailFields = details;
+ aggregateColumn();
+ $scope.$apply();
+ // ng-grid bug? the entire table doesn't always draw unless a reflow is triggered;
+ $(window).trigger('resize');
+ }
+
+ var restartUpdate = function () {
+ stopUpdating();
+ updateTableData($scope.selectedEntity, true);
+ updateIntervalHandle = setInterval(updateExpandedEntities, updateInterval);
+ }
+ var updateExpandedEntities = function () {
+ var tree = $("#entityTree").dynatree("getTree");
+ if (tree.visit) {
+ tree.visit( function (node) {
+ if (node.isExpanded()) {
+ updateTableData(node.data.key, node.data.key === $scope.selectedEntity)
+ }
+ })
+ } else {
+ stopUpdating();
+ }
+ }
+
+ $scope.selectNode = function(node) {
+ $scope.selectedNode = node.name;
+ $scope.selectedNodeId = node.id;
+ setCurrentNode();
+ restartUpdate();
+ };
+ $scope.$watch('selectedEntity', function(newValue, oldValue) {
+ if (newValue !== oldValue) {
+ localStorage['QDRSelectedEntity'] = $scope.selectedEntity;
+ restartUpdate();
+ $scope.operations = lookupOperations()
+ }
+ })
+ $scope.$watch('selectedNode', function(newValue, oldValue) {
+ if (newValue !== oldValue) {
+ localStorage['QDRSelectedNode'] = $scope.selectedNode;
+ localStorage['QDRSelectedNodeId'] = $scope.selectedNodeId;
+ }
+ })
+ $scope.$watch('selectedRecordName', function(newValue, oldValue) {
+ if (newValue != oldValue) {
+ localStorage['QDRSelectedRecordName'] = $scope.selectedRecordName;
+ }
+ })
+
+ /* Called periodically to refresh the data on the page */
+ var updateTableData = function (entity, expand) {
+ if (!QDRService.connected) {
+ // we are no longer connected. bail back to the connect page
+ $location.path("/" + QDR.pluginName + "/connect")
+ $location.search('org', "list");
+ return;
+ }
+ // don't update the data when on the operations tab
+ if ($scope.currentMode.id === 'operations') {
+ return;
+ }
+
+ var gotNodeInfo = function (nodeName, dotentity, response) {
+ var tableRows = [];
+ var records = response.results;
+ var aggregates = response.aggregates;
+ var attributeNames = response.attributeNames;
+ // If !attributeNmes then there was an error getting the records for this entity
+ if (attributeNames) {
+ var nameIndex = attributeNames.indexOf("name");
+ var identityIndex = attributeNames.indexOf("identity");
+ var ent = QDRService.schema.entityTypes[entity];
+ for (var i=0; i<records.length; ++i) {
+ var record = records[i];
+ var aggregate = aggregates ? aggregates[i] : undefined;
+ var row = {};
+ var rowName;
+ if (nameIndex > -1) {
+ rowName = record[nameIndex];
+ if (!rowName && identityIndex > -1) {
+ rowName = record[nameIndex] = (dotentity + '/' + record[identityIndex])
+ }
+ }
+ if (!rowName) {
+ QDR.log.error("response attributeNames did not contain a name field");
+ console.dump(response.attributeNames);
+ return;
+ }
+ for (var j=0; j<attributeNames.length; ++j) {
+ var col = attributeNames[j];
+ row[col] = {value: record[j], type: undefined, graph: false, title: '', aggregate: '', aggregateTip: ''};
+ if (ent) {
+ var att = ent.attributes[col];
+ if (att) {
+ row[col].type = att.type;
+ row[col].graph = att.graph;
+ row[col].title = att.description;
+
+ if (aggregate) {
+ if (att.graph) {
+ row[col].aggregate = att.graph ? aggregate[j].sum : '';
+ var tip = [];
+ aggregate[j].detail.forEach( function (line) {
+ tip.push(line);
+ })
+ row[col].aggregateTip = angular.toJson(tip);
+ }
+ }
+ }
+ }
+ }
+ tableRows.push(row);
+ }
+ }
+
+ tableRows.sort( function (a, b) { return a.name.value.localeCompare(b.name.value) })
+ setTimeout(selectRow, 0, {entity: dotentity, rows: tableRows, expand: expand});
+ }
+ // if this entity should show an aggregate column, send the request to get the info for this entity from all the nedes
+ if (aggregateEntities.indexOf(entity) > -1) {
+ var nodeInfo = QDRService.topology.nodeInfo();
+ QDRService.getMultipleNodeInfo(Object.keys(nodeInfo), entity, [], gotNodeInfo, $scope.selectedNodeId);
+ } else {
+ QDRService.fetchEntity($scope.selectedNodeId, entity, [], gotNodeInfo);
+ }
+ };
+
+ // tableRows are the records that were returned, this populates the left hand table on the page
+ var selectRow = function (info) {
+ updateEntityChildren(info.entity, info.rows, info.expand);
+ fixTooltips();
+ }
+
+ var titleFromAlt = function (alt) {
+ if (alt && alt.length) {
+ var data = angular.fromJson(alt);
+ var table = "<table class='tiptable'><tbody>";
+ data.forEach (function (row) {
+ table += "<tr>";
+ table += "<td>" + row.node + "</td><td align='right'>" + QDRService.pretty(row.val) + "</td>";
+ table += "</tr>"
+ })
+ table += "</tbody></table>"
+ return table;
+ }
+ return '';
+ }
+
+ var fixTooltips = function () {
+ if ($('.hastip').length == 0) {
+ setTimeout(fixTooltips, 100);
+ return;
+ }
+ $('.hastip').each( function (i, tip) {
+ var tipset = tip.getAttribute('tipset')
+ if (!tipset) {
+ $(tip).tipsy({html: true, className: 'subTip', opacity: 1, title: function () {
+ return titleFromAlt(this.getAttribute('alt'))
+ } });
+ tip.setAttribute('tipset', true)
+ } else {
+ var title = titleFromAlt(tip.getAttribute('alt'))
+ tip.setAttribute('original-title', title)
+ }
+ })
+ }
+
+ $scope.detailFields = [];
+
+ $scope.addToGraph = function(rowEntity) {
+ var chart = QDRChartService.registerChart(
+ {nodeId: $scope.selectedNodeId,
+ entity: "." + $scope.selectedEntity,
+ name: $scope.selectedRecordName,
+ attr: rowEntity.name,
+ forceCreate: true});
+ doDialog('tmplListChart.html', chart);
+ }
+
+ $scope.addAllToGraph = function(rowEntity) {
+ var chart = QDRChartService.registerChart({
+ nodeId: $scope.selectedNodeId,
+ entity: $scope.selectedEntity,
+ name: $scope.selectedRecordName,
+ attr: rowEntity.name,
+ type: "rate",
+ rateWindow: updateInterval,
+ visibleDuration: 1,
+ forceCreate: true,
+ aggregate: true});
+ doDialog('tmplListChart.html', chart);
+ }
+
+ $scope.detailCols = [];
+ var aggregateColumn = function () {
+ if ((aggregateEntities.indexOf($scope.selectedEntity) > -1 && $scope.detailCols.length != 3) ||
+ (aggregateEntities.indexOf($scope.selectedEntity) == -1 && $scope.detailCols.length != 2)) {
+ // column defs have to be reassigned and not spliced, so no push/pop
+ $scope.detailCols = [
+ {
+ field: 'attributeName',
+ displayName: 'Attribute',
+ cellTemplate: '<div title="{{row.entity.title}}" class="listAttrName">{{row.entity[col.field]}}<i ng-if="row.entity.graph" ng-click="addToGraph(row.entity)" ng-class="{\'icon-bar-chart\': row.entity.graph == true }"></i></div>'
+ },
+ {
+ field: 'attributeValue',
+ displayName: 'Value',
+ cellTemplate: '<div class="ngCellText" ng-class="{\'changed\': row.entity.changed == 1}"><span>{{row.getProperty(col.field)}}</span></div>'
+ }
+ ]
+ if (aggregateEntities.indexOf($scope.selectedEntity) > -1) {
+ $scope.detailCols.push(
+ {
+ width: '10%',
+ field: 'aggregateValue',
+ displayName: 'Aggregate',
+ cellTemplate: '<div class="hastip" alt="{{row.entity.aggregateTip}}"><span ng-class="{\'changed\': row.entity.changed == 1}">{{row.entity[col.field]}}</span><i ng-if="row.entity.graph" ng-click="addAllToGraph(row.entity)" ng-class="{\'icon-bar-chart\': row.entity.graph == true }"></i></div>',
+ cellClass: 'aggregate'
+ }
+ )
+ }
+ }
+ if ($scope.selectedRecordName === "")
+ $scope.detailCols = [];
+ }
+
+ // the table on the right of the page contains a row for each field in the selected record in the table on the left
+ $scope.details = {
+ data: 'detailFields',
+ columnDefs: "detailCols",
+ enableColumnResize: true,
+ multiSelect: false,
+ beforeSelectionChange: function() {
+ return false;
+ }
+ };
+ $scope.$on("$destroy", function( event ) {
+ //QDR.log.debug("scope destroyed for qdrList");
+ stopUpdating();
+ });
+
+ 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);
+ //QDR.log.debug(context.message.application_properties.statusDescription)
+ } else {
+ var note = entity + " " + $filter('Pascalcase')($scope.currentMode.op) + "d"
+ Core.notification('success', note);
+ $scope.selectMode($scope.modes[0]);
+ restartUpdate();
+ }
+ }
+ $scope.ok = function () {
+ var attributes = {}
+ $scope.detailFields.forEach( function (field) {
+ var value = field.rawValue;
+ if (field.input === 'input') {
+ if (field.type === 'text' || field.type === 'disabled')
+ value = field.attributeValue;
+ } else if (field.input === 'select') {
+ value = field.selected;
+ } else if (field.input === 'boolean') {
+ value = field.rawValue
+ }
+ if (value === "")
+ value = undefined;
+
+ if ((value && value != field['default']) || field.required || (field.name === 'role')) {
+ if (field.name !== 'identity')
+ attributes[field.name] = value
+ }
+ })
+ QDRService.sendMethod($scope.currentNode.id, $scope.selectedEntity, attributes, $scope.currentMode.op, undefined, gotMethodResponse)
+ }
+ $scope.remove = function () {
+ var attributes = {type: $scope.selectedEntity, name: $scope.selectedRecordName}
+ QDRService.sendMethod($scope.currentNode.id, $scope.selectedEntity, attributes, $scope.currentMode.op, undefined, gotMethodResponse)
+ }
+
+ function doDialog(tmpl, chart) {
+ var d = $dialog.dialog({
+ backdrop: true,
+ keyboard: true,
+ backdropClick: true,
+ templateUrl: QDR.templatePath + tmpl,
+ controller: "QDR.ListChartController",
+ resolve: {
+ chart: function() {
+ return chart
+ },
+ nodeName: function () {
+ return $scope.selectedNode
+ }
+ }
+ });
+
+ d.open().then(function(result) { console.log("d.open().then"); });
+
+ };
+
+ var setCurrentNode = function () {
+ $scope.nodes.some( function (node, i) {
+ if (node.name === $scope.selectedNode) {
+ $scope.currentNode = $scope.nodes[i]
+ return true;
+ }
+ })
+ }
+
+ var treeReady = false;
+ var serviceReady = false;
+ $scope.largeNetwork = QDRService.isLargeNetwork()
+ // called after we know for sure the schema is fetched and the routers are all ready
+ QDRService.addUpdatedAction("initList", function () {
+ QDRService.stopUpdating();
+ QDRService.delUpdatedAction("initList")
+
+ $scope.nodes = QDRService.nodeList().sort(function (a, b) { return a.name.toLowerCase() > b.name.toLowerCase()});
+ // unable to get node list? Bail.
+ if ($scope.nodes.length == 0) {
+ $location.path("/" + QDR.pluginName + "/connect")
+ $location.search('org', "list");
+ }
+ if (!angular.isDefined($scope.selectedNode)) {
+ //QDR.log.debug("selectedNode was " + $scope.selectedNode);
+ if ($scope.nodes.length > 0) {
+ $scope.selectedNode = $scope.nodes[0].name;
+ $scope.selectedNodeId = $scope.nodes[0].id;
+ //QDR.log.debug("forcing selectedNode to " + $scope.selectedNode);
+ }
+ }
+ setCurrentNode();
+ if ($scope.currentNode == undefined) {
+ if ($scope.nodes.length > 0) {
+ $scope.selectedNode = $scope.nodes[0].name;
+ $scope.selectedNodeId = $scope.nodes[0].id;
+ $scope.currentNode = $scope.nodes[0];
+ }
+ }
+ var sortedEntities = Object.keys(QDRService.schema.entityTypes).sort();
+ sortedEntities.forEach( function (entity) {
+ if (excludedEntities.indexOf(entity) == -1) {
+ if (!angular.isDefined($scope.selectedEntity)) {
+ $scope.selectedEntity = entity;
+ $scope.operations = lookupOperations()
+ }
+ var e = new Folder(entity)
+ e.typeName = "entity"
+ e.key = entity
+ e.expand = (expandedList.indexOf(entity) > -1)
+ var placeHolder = new Folder("loading...")
+ placeHolder.addClass = "loading"
+ e.children = [placeHolder]
+ entityTreeChildren.push(e)
+ }
+ })
+ serviceReady = true;
+ initTree();
+ })
+ $scope.treeReady = function () {
+ treeReady = true;
+ initTree();
+ }
+
+ var initTree = function () {
+ if (!treeReady || !serviceReady)
+ return;
+ $('#entityTree').dynatree({
+ onActivate: onTreeSelected,
+ onExpand: onTreeNodeExpanded,
+ selectMode: 1,
+ autoCollapse: $scope.largeNetwork,
+ activeVisible: !$scope.largeNetwork,
+ debugLevel: 0,
+ children: entityTreeChildren
+ })
+ restartUpdate()
+ updateExpandedEntities();
+ };
+ QDRService.ensureAllEntities({entity: ".connection"}, function () {
+ QDRService.setUpdateEntities([".connection"])
+ QDRService.startUpdating();
+ })
+
+
+ }]);
+
+ return QDR;
+
+} (QDR || {}));
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6a1e6632/console/hawtio/src/main/webapp/plugin/js/qdrListChart.js
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrListChart.js b/console/hawtio/src/main/webapp/plugin/js/qdrListChart.js
deleted file mode 120000
index d1fcf4a..0000000
--- a/console/hawtio/src/main/webapp/plugin/js/qdrListChart.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../stand-alone/plugin/js/qdrListChart.js
\ No newline at end of file
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrListChart.js b/console/hawtio/src/main/webapp/plugin/js/qdrListChart.js
new file mode 100644
index 0000000..93391f1
--- /dev/null
+++ b/console/hawtio/src/main/webapp/plugin/js/qdrListChart.js
@@ -0,0 +1,141 @@
+/*
+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
+ */
+var QDR = (function(QDR) {
+
+ QDR.module.controller('QDR.ListChartController', function ($scope, dialog, $dialog, $location, QDRChartService, chart, nodeName) {
+ $scope.chart = chart;
+ $scope.dialogSvgChart = null;
+ var updateTimer = null;
+ $scope.svgDivId = "dialogChart"; // the div id for the svg chart
+
+ $scope.showChartsPage = function () {
+ cleanup();
+ dialog.close(true);
+ $location.path(QDR.pluginRoot + "/charts");
+ };
+
+ $scope.addHChart = function () {
+ QDRChartService.addHDash($scope.chart);
+ cleanup();
+ dialog.close(true);
+ }
+
+ $scope.addToDashboardLink = function () {
+ var href = "#/" + QDR.pluginName + "/charts";
+ var size = angular.toJson({
+ size_x: 2,
+ size_y: 2
+ });
+
+ var params = angular.toJson({chid: $scope.chart.id()});
+ var title = "Dispatch - " + nodeName;
+ return "/hawtio/#/dashboard/add?tab=dashboard" +
+ "&href=" + encodeURIComponent(href) +
+ "&routeParams=" + encodeURIComponent(params) +
+ "&title=" + encodeURIComponent(title) +
+ "&size=" + encodeURIComponent(size);
+ };
+
+
+ $scope.addChartsPage = function () {
+ QDRChartService.addDashboard($scope.chart);
+ };
+
+ $scope.delChartsPage = function () {
+ QDRChartService.delDashboard($scope.chart);
+ };
+
+ $scope.isOnChartsPage = function () {
+ return $scope.chart.dashboard;
+ }
+
+ var showChart = function () {
+ // the chart divs are generated by angular and aren't available immediately
+ var div = angular.element("#" + $scope.svgDivId);
+ if (!div.width()) {
+ setTimeout(showChart, 100);
+ return;
+ }
+ dialogSvgChart = new QDRChartService.AreaChart($scope.chart);
+ $scope.dialogSvgChart = dialogSvgChart;
+ updateDialogChart();
+ }
+ showChart();
+
+ var updateDialogChart = function () {
+ if ($scope.dialogSvgChart)
+ $scope.dialogSvgChart.tick($scope.svgDivId);
+ if (updateTimer)
+ clearTimeout(updateTimer)
+ updateTimer = setTimeout(updateDialogChart, 1000);
+ }
+
+ var cleanup = function () {
+ if (updateTimer) {
+ clearTimeout(updateTimer);
+ updateTimer = null;
+ }
+ if (!$scope.chart.hdash && !$scope.chart.dashboard)
+ QDRChartService.unRegisterChart($scope.chart); // remove the chart
+
+ }
+ $scope.ok = function () {
+ cleanup();
+ dialog.close(true);
+ };
+
+ $scope.editChart = function () {
+ doDialog('tmplChartConfig.html', chart)
+ }
+
+ function doDialog(template, chart) {
+
+ $dialog.dialog({
+ backdrop: true,
+ keyboard: true,
+ backdropClick: true,
+ templateUrl: QDR.templatePath + template,
+ controller: "QDR.ChartDialogController",
+ resolve: {
+ chart: function() {
+ return chart;
+ },
+ updateTick: function () {
+ return function () {};
+ },
+ dashboard: function () {
+ return $scope;
+ },
+ adding: function () {
+ return true
+ }
+ }
+ }).open().then(function(result) {
+ $scope.ok()
+ });
+ };
+
+ });
+
+ return QDR;
+
+} (QDR || {}));
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/6a1e6632/console/hawtio/src/main/webapp/plugin/js/qdrNewNode.js
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrNewNode.js b/console/hawtio/src/main/webapp/plugin/js/qdrNewNode.js
deleted file mode 120000
index 16b0e42..0000000
--- a/console/hawtio/src/main/webapp/plugin/js/qdrNewNode.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../stand-alone/plugin/js/qdrNewNode.js
\ No newline at end of file
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrNewNode.js b/console/hawtio/src/main/webapp/plugin/js/qdrNewNode.js
new file mode 100644
index 0000000..f6d035a
--- /dev/null
+++ b/console/hawtio/src/main/webapp/plugin/js/qdrNewNode.js
@@ -0,0 +1,445 @@
+/*
+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
+ */
+var QDR = (function(QDR) {
+
+ QDR.module.controller("QDR.NodeDialogController", function($scope, QDRService, dialog, newname) {
+ var schema = QDRService.schema;
+ var myEntities = ['router', 'log', 'listener'];
+ var typeMap = {
+ integer: 'number',
+ string: 'text',
+ path: 'text',
+ boolean: 'boolean'
+ };
+ var newLinks = $('path.temp').toArray(); // jquery array of new links for the added router
+ var nodeInfo = QDRService.topology.nodeInfo();
+ var separatedEntities = []; // additional entities required if a link is reversed
+ var myPort = 0,
+ myAddr = '0.0.0.0'; // port and address for new router
+ $scope.entities = [];
+
+ // find max port number that is used in all the listeners
+ var getMaxPort = function(nodeInfo) {
+ var maxPort = 5674;
+ for (var key in nodeInfo) {
+ var node = nodeInfo[key];
+ var listeners = node['.listener'];
+ var attrs = listeners.attributeNames;
+ for (var i = 0; i < listeners.results.length; ++i) {
+ var res = listeners.results[i];
+ var port = QDRService.valFor(attrs, res, 'port');
+ if (parseInt(port, 10) > maxPort)
+ maxPort = parseInt(port, 10);
+ }
+ }
+ return maxPort;
+ }
+ var maxPort = getMaxPort(nodeInfo);
+
+ // construct an object that contains all the info needed for a single tab's fields
+ var entity = function(actualName, tabName, humanName, ent, icon, link) {
+ var nameIndex = -1; // the index into attributes that the name field was placed
+ var index = 0;
+ var info = {
+ actualName: actualName,
+ tabName: tabName,
+ humanName: humanName,
+ description: ent.description,
+ icon: angular.isDefined(icon) ? icon : '',
+ references: ent.references,
+ link: link,
+
+ attributes: $.map(ent.attributes, function(value, key) {
+ // skip identity and depricated fields
+ if (key == 'identity' || value.description.startsWith('Deprecated'))
+ return null;
+ var val = value['default'];
+ if (key == 'name')
+ nameIndex = index;
+ index++;
+ return {
+ name: key,
+ humanName: QDRService.humanify(key),
+ description: value.description,
+ type: typeMap[value.type],
+ rawtype: value.type,
+ input: typeof value.type == 'string' ? value.type == 'boolean' ? 'boolean' : 'input' : 'select',
+ selected: val ? val : undefined,
+ 'default': value['default'],
+ value: val,
+ required: value.required,
+ unique: value.unique
+ };
+ })
+ }
+ // move the 'name' attribute to the 1st position
+ if (nameIndex > -1) {
+ var tmp = info.attributes[0];
+ info.attributes[0] = info.attributes[nameIndex];
+ info.attributes[nameIndex] = tmp;
+ }
+ return info;
+ }
+
+ // remove the annotation fields
+ var stripAnnotations = function(entityName, ent, annotations) {
+ if (ent.references) {
+ var newEnt = {
+ attributes: {}
+ };
+ ent.references.forEach(function(annoKey) {
+ if (!annotations[annoKey])
+ annotations[annoKey] = {};
+ annotations[annoKey][entityName] = true; // create the key/consolidate duplicates
+ var keys = Object.keys(schema.annotations[annoKey].attributes);
+ for (var attrib in ent.attributes) {
+ if (keys.indexOf(attrib) == -1) {
+ newEnt.attributes[attrib] = ent.attributes[attrib];
+ }
+ }
+ // add a field for the reference name
+ newEnt.attributes[annoKey] = {
+ type: 'string',
+ description: 'Name of the ' + annoKey + ' section.',
+ 'default': annoKey,
+ required: true
+ };
+ })
+ newEnt.references = ent.references;
+ newEnt.description = ent.description;
+ return newEnt;
+ }
+ return ent;
+ }
+
+ var annotations = {};
+ myEntities.forEach(function(entityName) {
+ var ent = schema.entityTypes[entityName];
+ var hName = QDRService.humanify(entityName);
+ if (entityName == 'listener')
+ hName = "Listener for clients";
+ var noAnnotations = stripAnnotations(entityName, ent, annotations);
+ var ediv = entity(entityName, entityName, hName, noAnnotations, undefined);
+ if (ediv.actualName == 'router') {
+ ediv.attributes.filter(function(attr) {
+ return attr.name == 'name'
+ })[0].value = newname;
+ // if we have any new links (connectors), then the router's mode should be interior
+ if (newLinks.length) {
+ var roleAttr = ediv.attributes.filter(function(attr) {
+ return attr.name == 'mode'
+ })[0];
+ roleAttr.value = roleAttr.selected = "interior";
+ }
+ }
+ if (ediv.actualName == 'container') {
+ ediv.attributes.filter(function(attr) {
+ return attr.name == 'containerName'
+ })[0].value = newname + "-container";
+ }
+ if (ediv.actualName == 'listener') {
+ // find max port number that is used in all the listeners
+ ediv.attributes.filter(function(attr) {
+ return attr.name == 'port'
+ })[0].value = ++maxPort;
+ }
+ // special case for required log.module since it doesn't have a default
+ if (ediv.actualName == 'log') {
+ var moduleAttr = ediv.attributes.filter(function(attr) {
+ return attr.name == 'module'
+ })[0];
+ moduleAttr.value = moduleAttr.selected = "DEFAULT";
+ }
+ $scope.entities.push(ediv);
+ })
+
+ // add a tab for each annotation that was found
+ var annotationEnts = [];
+ for (var key in annotations) {
+ ent = angular.copy(schema.annotations[key]);
+ ent.attributes.name = {
+ type: "string",
+ unique: true,
+ description: "Unique name that is used to refer to this set of attributes."
+ }
+ var ediv = entity(key, key + 'tab', QDRService.humanify(key), ent, undefined);
+ ediv.attributes.filter(function(attr) {
+ return attr.name == 'name'
+ })[0].value = key;
+ $scope.entities.push(ediv);
+ annotationEnts.push(ediv);
+ }
+
+ // add an additional listener tab if any links are reversed
+ ent = schema.entityTypes['listener'];
+ newLinks.some(function(link) {
+ if (link.__data__.right) {
+ var noAnnotations = stripAnnotations('listener', ent, annotations);
+ var ediv = entity("listener", "listener0", "Listener (internal)", noAnnotations, undefined);
+ ediv.attributes.filter(function(attr) {
+ return attr.name == 'port'
+ })[0].value = ++maxPort;
+ // connectors from other routers need to connect to this addr:port
+ myPort = maxPort;
+ myAddr = ediv.attributes.filter(function(attr) {
+ return attr.name == 'host'
+ })[0].value
+
+ // override the role. 'normal' is the default, but we want inter-router
+ ediv.attributes.filter(function(attr) {
+ return attr.name == 'role'
+ })[0].selected = 'inter-router';
+ separatedEntities.push(ediv);
+ return true; // stop looping
+ }
+ return false; // continue looping
+ })
+
+ // Add connector tabs for each new link on the topology graph
+ ent = schema.entityTypes['connector'];
+ newLinks.forEach(function(link, i) {
+ var noAnnotations = stripAnnotations('connector', ent, annotations);
+ var ediv = entity('connector', 'connector' + i, " " + link.__data__.source.name, noAnnotations, link.__data__.right, link)
+
+ // override the connector role. 'normal' is the default, but we want inter-router
+ ediv.attributes.filter(function(attr) {
+ return attr.name == 'role'
+ })[0].selected = 'inter-router';
+
+ // find the addr:port of the inter-router listener to use
+ var listener = nodeInfo[link.__data__.source.key]['.listener'];
+ var attrs = listener.attributeNames;
+ for (var i = 0; i < listener.results.length; ++i) {
+ var res = listener.results[i];
+ var role = QDRService.valFor(attrs, res, 'role');
+ if (role == 'inter-router') {
+ ediv.attributes.filter(function(attr) {
+ return attr.name == 'host'
+ })[0].value =
+ QDRService.valFor(attrs, res, 'host')
+ ediv.attributes.filter(function(attr) {
+ return attr.name == 'port'
+ })[0].value =
+ QDRService.valFor(attrs, res, 'port')
+ break;
+ }
+ }
+ if (link.__data__.right) {
+ // connectors from other nodes need to connect to the new router's listener addr:port
+ ediv.attributes.filter(function(attr) {
+ return attr.name == 'port'
+ })[0].value = myPort;
+ ediv.attributes.filter(function(attr) {
+ return attr.name == 'host'
+ })[0].value = myAddr;
+
+ separatedEntities.push(ediv)
+ } else
+ $scope.entities.push(ediv);
+ })
+ Array.prototype.push.apply($scope.entities, separatedEntities);
+
+ // update the description on all the annotation tabs
+ annotationEnts.forEach(function(ent) {
+ var shared = Object.keys(annotations[ent.actualName]);
+ ent.description += " These fields are shared by " + shared.join(" and ") + ".";
+
+ })
+
+ $scope.testPattern = function(attr) {
+ if (attr.rawtype == 'path')
+ return /^(\/)?([^/\0]+(\/)?)+$/;
+ //return /^(.*\/)([^/]*)$/;
+ return /(.*?)/;
+ }
+
+ $scope.attributeDescription = '';
+ $scope.attributeType = '';
+ $scope.attributeRequired = '';
+ $scope.attributeUnique = '';
+ $scope.active = 'router'
+ $scope.fieldsetDivs = "/fieldsetDivs.html"
+ $scope.setActive = function(tabName) {
+ $scope.active = tabName
+ }
+ $scope.isActive = function(tabName) {
+ return $scope.active === tabName
+ }
+ $scope.showDescription = function(attr, e) {
+ $scope.attributeDescription = attr.description;
+ var offset = jQuery(e.currentTarget).offset()
+ jQuery('.attr-description').offset({
+ top: offset.top
+ })
+
+ $scope.attributeType = "Type: " + JSON.stringify(attr.rawtype);
+ $scope.attributeRequired = attr.required ? 'required' : '';
+ $scope.attributeUnique = attr.unique ? 'Must be unique' : '';
+ }
+ // handle the download button click
+ // copy the dialog's values to the original node
+ $scope.download = function() {
+ dialog.close({
+ entities: $scope.entities,
+ annotations: annotations
+ });
+ }
+ $scope.cancel = function() {
+ dialog.close()
+ };
+
+ $scope.selectAnnotationTab = function(tabName) {
+ var tabs = $("#tabs").tabs();
+ tabs.tabs("select", tabName);
+ }
+
+ var initTabs = function() {
+ var div = angular.element("#tabs");
+ if (!div.width()) {
+ setTimeout(initTabs, 100);
+ return;
+ }
+ $("#tabs")
+ .tabs()
+ .addClass('ui-tabs-vertical ui-helper-clearfix');
+ }
+ // start the update loop
+ initTabs();
+
+ });
+
+ QDR.module.controller("QDR.DownloadDialogController", function($scope, QDRService, $templateCache, $window, dialog, results) {
+ var result = results.entities;
+ var annotations = results.annotations;
+ var annotationKeys = Object.keys(annotations);
+ var annotationSections = {};
+
+ // use the router's name as the file name if present
+ $scope.newRouterName = 'router';
+ result.forEach(function(e) {
+ if (e.actualName == 'router') {
+ e.attributes.forEach(function(a) {
+ if (a.name == 'name') {
+ $scope.newRouterName = a.value;
+ }
+ })
+ }
+ })
+ $scope.newRouterName = $scope.newRouterName + ".conf";
+
+ var template = $templateCache.get('config-file-header.html');
+ $scope.verbose = true;
+ $scope.$watch('verbose', function(newVal) {
+ if (newVal !== undefined) {
+ // recreate output using current verbose setting
+ getOutput();
+ }
+ })
+
+ var getOutput = function() {
+ $scope.output = template + '\n';
+ $scope.parts = [];
+ var commentChar = '#'
+ result.forEach(function(entity) {
+ // don't output a section for annotations, they get flattened into the entities
+ var section = "";
+ if (entity.icon) {
+ section += "##\n## Add to " + entity.link.__data__.source.name + "'s configuration file\n##\n";
+ }
+ section += "##\n## " + QDRService.humanify(entity.actualName) + " - " + entity.description + "\n##\n";
+ section += entity.actualName + " {\n";
+ entity.attributes.forEach(function(attribute) {
+ if (attribute.input == 'select')
+ attribute.value = attribute.selected;
+
+ // treat values with all spaces and empty strings as undefined
+ attribute.value = String(attribute.value).trim();
+ if (attribute.value === 'undefined' || attribute.value === '')
+ attribute.value = undefined;
+
+ if ($scope.verbose) {
+ commentChar = attribute.required || attribute.value != attribute['default'] ? ' ' : '#';
+ if (!attribute.value) {
+ commentChar = '#';
+ attribute.value = '';
+ }
+ section += commentChar + " " + attribute.name + ":" + Array(Math.max(20 - attribute.name.length, 1)).join(" ") + attribute.value + Array(Math.max(20 - ((attribute.value) + "").length, 1)).join(" ") + '# ' + attribute.description + "\n";
+ } else {
+ if (attribute.value) {
+ if (attribute.value != attribute['default'] || attribute.required)
+ section += " " + attribute.name + ":" + Array(20 - attribute.name.length).join(" ") + attribute.value + "\n";
+
+ }
+ }
+ })
+ section += "}\n\n";
+ // if entity.icon is true, this is a connector intended for another router
+ if (entity.icon)
+ $scope.parts.push({
+ output: section,
+ link: entity.link,
+ name: entity.link.__data__.source.name,
+ references: entity.references
+ });
+ else
+ $scope.output += section;
+
+ // if this section is actually an annotation
+ if (annotationKeys.indexOf(entity.actualName) > -1) {
+ annotationSections[entity.actualName] = section;
+ }
+ })
+ // go back and add annotation sections to the parts
+ $scope.parts.forEach(function(part) {
+ for (var section in annotationSections) {
+ if (part.references.indexOf(section) > -1) {
+ part.output += annotationSections[section];
+ }
+ }
+ })
+ QDR.log.debug($scope.output);
+ }
+
+ // handle the download button click
+ $scope.download = function() {
+ var output = $scope.output + "\n\n"
+ var blob = new Blob([output], {
+ type: 'text/plain;charset=utf-16'
+ });
+ saveAs(blob, $scope.newRouterName);
+ }
+
+ $scope.downloadPart = function(part) {
+ var linkName = part.link.__data__.source.name + 'additional.conf';
+ var blob = new Blob([part.output], {
+ type: 'text/plain;charset=utf-16'
+ });
+ saveAs(blob, linkName);
+ }
+
+ $scope.done = function() {
+ dialog.close();
+ }
+ });
+
+ return QDR;
+}(QDR || {}));
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org