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/09/22 17:23:14 UTC
[04/19] qpid-dispatch git commit: DISPATCH-834 Initial commit of
config file editor
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/93b9fa51/console/config/html/qdrTopology.html
----------------------------------------------------------------------
diff --git a/console/config/html/qdrTopology.html b/console/config/html/qdrTopology.html
new file mode 100644
index 0000000..0f605bd
--- /dev/null
+++ b/console/config/html/qdrTopology.html
@@ -0,0 +1,219 @@
+<!--
+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.
+-->
+<div class="qdrTopology row-fluid" ng-controller="QDR.TopologyController">
+ <div id="buttonBar" class="navbar-primary">
+ Current topology
+ <select ng-model="mockTopologyDir" ng-options="item for item in mockTopologies"></select>
+ <button class="btn btn-primary" type="button" ng-click="Publish()">Publish</button>
+ <button class="btn btn-primary" type="button" ng-click="Clear()">Clear</button>
+ <button class="btn btn-primary pull-right" type="button" ng-click="doSettings()">Settings</button>
+ <button class="btn btn-primary pull-right" type="button" ng-click="showNewDlg()">New Topology</button>
+ <div class="selected-node pull-right">
+ <button class="btn btn-primary" type="button" ng-click="addAnotherNode(true)"><b class="plus caret"></b> Add new router</button>
+ <button id="action_button" class="btn btn-primary" type="button" ng-disabled="!selected_node" ng-click="showActions($event)">Actions <b class="down caret"></b></button> on selected router
+ </div>
+ </div>
+ <div id="topology"><!-- d3 toplogy here --></div>
+ <div id="svg_context_menu" class="contextMenu">
+ <ul>
+ <li ng-click="addAnotherNode()">Add a new router</li>
+ </ul>
+ </div>
+ <div id="link_context_menu" class="contextMenu">
+ <ul>
+ <li ng-click="reverseLink()">Reverse connection direction</li>
+ <li ng-click="removeLink()">Remove connection</li>
+ <li class="context-separator"></li>
+ <li ng-click="linkConfig()">Set port for connection.</li>
+ </ul>
+ </div>
+ <div id="svg_legend"></div>
+ <div id="action_menu" class="contextMenu">
+ <ul>
+ <li ng-click="editSection(selected_node, 'router')">Edit router info</li>
+ <li ng-click="setRouterHost(selected_node)">Set router host</li>
+
+ <li class="context-separator"></li>
+ <li ng-click="editSection(selected_node, 'log', 'new')">Add new log section</li>
+ <li ng-repeat="log in getSectionList(selected_node, 'log')" ng-click="editSection(selected_node, 'log', log)">Edit/Delete {{log}} log section</li>
+
+ <li class="context-separator"></li>
+ <li ng-click="editSection(selected_node, 'sslProfile', 'new')">Add new sslProfile section</li>
+ <li ng-repeat="ssl in getSectionList(selected_node, 'sslProfile')" ng-click="editSection(selected_node, 'sslProfile', ssl)">Edit/Delete {{ssl}} sslProfile section</li>
+
+ <li class="context-separator"></li>
+ <li ng-click="editSection(selected_node, 'connector', 'new')">Add new connector section</li>
+ <li ng-click="editSection(selected_node, 'connector', 'artemis')">Add new connector for Artemis broker</li>
+ <li ng-click="editSection(selected_node, 'connector', 'qpid')">Add new connector for Qpid broker</li>
+ <!-- <li ng-repeat="connector in getSectionList(selected_node, 'connector')" ng-click="editSection(selected_node, 'connector', connector)">Edit/Delete {{connector}} connector section</li> -->
+
+ <li class="context-separator"></li>
+ <li ng-click="editSection(selected_node, 'listener', 'new')">Add new listener section</li>
+ <li ng-if="!hasConsoleListener()" ng-click="addConsoleListener(selected_node)">Add listener for console</li>
+ <li ng-if="hasConsoleListener(selected_node)" ng-click="delConsoleListener(selected_node)">Delete listener for console</li>
+ <!-- <li ng-repeat="listener in getSectionList(selected_node, 'listener')" ng-click="editSection(selected_node, 'listener', listener)">Edit/Delete listener on port {{listener}} </li> -->
+
+ <li class="context-separator"></li>
+ <li ng-click="delNode(selected_node)">Delete this node</li>
+ <li ng-click="showConfig(selected_node)">Show generated config</li>
+ </ul>
+ </div>
+ <div id="client_context_menu" class="contextMenu">
+ <ul>
+ <li ng-click="delNode(selected_node)">Delete</li>
+ <li class="context-separator"></li>
+ <li ng-click="editThisSection(selected_node)">Edit</li>
+ </ul>
+ </div>
+</div>
+
+
+<script type="text/ng-template" id="settings-template.html">
+ <form novalidate name="editForm" ng-submit="setSettings()">
+ <div class="modal-header">
+ <h3 class="modal-title">Global settings</h3>
+ </div>
+ <div class="modal-body">
+
+ <fieldset>
+ <div ng-repeat="attribute in entity.attributes">
+ <label class="form-label" for="{{attribute.name}}">{{attribute.humanName}}</label>
+<!-- we can't do <input type="{angular expression}"> because... jquery throws an exception because...??? -->
+ <div ng-if="attribute.input == 'input'">
+ <!-- ng-pattern="testPattern(attribute)" -->
+ <input ng-if="attribute.type == 'number'" type="number" name="{{attribute.name}}" id="{{attribute.name}}" ng-model="attribute.value" ng-required="attribute.required" class="ui-widget-content ui-corner-all"/>
+ <input ng-if="attribute.type == 'text'" type="text" name="{{attribute.name}}" id="{{attribute.name}}" ng-model="attribute.value" ng-required="attribute.required" class="ui-widget-content ui-corner-all"/>
+ </div>
+ <div ng-if="attribute.input == 'select'">
+ <select id="{{attribute.name}}" ng-model="attribute.selected" ng-options="item for item in attribute.rawtype"></select>
+ </div>
+ <div ng-if="attribute.input == 'boolean'" class="boolean">
+ <label><input name="{{attribute.name}}" type="radio" ng-model="attribute.value" ng-value="true"> True</label>
+ <label><input name="{{attribute.name}}" type="radio" ng-model="attribute.value" ng-value="false"> False</label>
+ </div>
+ <div ng-if="attribute.input == 'file'">
+ <input type="file" id="FileUpload" custom-on-change="uploadFile" webkitdirectory mozdirectory msdirectory odirectory directory multiple />
+ </div>
+ </div>
+ </fieldset>
+
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-primary" type="submit" ng-click="setSettings()" ng-disabled="editForm.$invalid" >OK</button>
+ <button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
+ </div>
+ </form>
+</script>
+
+
+<!--
+ This is the template for the node add/edit dialog
+-->
+<script type="text/ng-template" id="node-config-template.html">
+ <form novalidate name="editForm" ng-submit="save()">
+ <div class="modal-header">
+ <h3 class="modal-title">{{title}}</h3>
+ </div>
+ <div class="modal-body">
+
+ <fieldset>
+ <div ng-repeat="attribute in entities[0].attributes">
+ <div class="form-input-container" tooltip-append-to-body="true" tooltip-placement="right" uib-tooltip-html="attributeDescription" ng-mouseenter="setDescription(attribute, $event)" tooltip-class="edit-tooltip">
+ <label class="form-label" for="{{attribute.name}}">{{attribute.humanName}}</label>
+ <div ng-if="attribute.input == 'input'">
+ <input class="edit_input" ng-if="attribute.type == 'number'" type="number" name="{{attribute.name}}" id="{{attribute.name}}" ng-model="attribute.value" ng-required="attribute.required" class="ui-widget-content ui-corner-all"/>
+ <input class="edit_input" ng-if="attribute.type == 'text'" type="text" name="{{attribute.name}}" id="{{attribute.name}}" ng-model="attribute.value" ng-required="attribute.required" class="ui-widget-content ui-corner-all"/>
+ </div>
+ <div ng-if="attribute.input == 'select'">
+ <select class="edit_input" id="{{attribute.name}}" ng-model="attribute.selected" ng-options="item for item in attribute.rawtype"></select>
+ </div>
+ <div ng-if="attribute.input == 'boolean'" class="boolean">
+ <label><input type="radio" ng-model="attribute.value" value="true"> True</label>
+ <label><input type="radio" ng-model="attribute.value" value="false"> False</label>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-primary" type="submit" ng-disabled="editForm.$invalid" ng-click="save()">OK</button>
+ <button ng-if="showDelete()" class="btn btn-secondary" type="button" ng-click="del()">Delete</button>
+ <button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
+ </div>
+ </form>
+</script>
+
+<script type="text/ng-template" id="show-config-template.html">
+ <form novalidate ng-submit="ok()">
+ <div class="modal-header">
+ <h3 class="modal-title">Current config file if published</h3>
+ </div>
+ <div class="modal-body">
+ <fieldset>
+ <pre class="config-area">{{config}}</pre>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-primary" type="submit" ng-click="ok()">OK</button>
+ </div>
+ </form>
+</script>
+
+<script type="text/ng-template" id="new-config-template.html">
+
+ <form novalidate name="editForm" ng-submit="setSettings()">
+ <div class="modal-header">
+ <h3 class="modal-title">Create new topology</h3>
+ </div>
+ <div class="modal-body">
+
+ <label for="newTopo" class="entity-description">Enter a new topology directory name</label>
+ <fieldset>
+ <input type="text" name="newTopo" id="newTopo" ng-model="newTopology" ng-required="true" class="ui-widget-content ui-corner-all"/>
+ </fieldset>
+
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-primary" type="submit" ng-click="setSettings()">OK</button>
+ <button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
+ </div>
+ </form>
+</script>
+
+<script type="text/ng-template" id="set-router-host.html">
+ <form novalidate name="editForm" ng-submit="setSettings()">
+ <div class="modal-header">
+ <h3 class="modal-title">Set router host</h3>
+ </div>
+ <div class="modal-body">
+ <div class="description">
+ Set the host of all listeners on this router. Also ensure that all internal connectors to this router use this host.
+ </div>
+ <label for="host" class="entity-description">Enter a new topology directory name</label>
+ <fieldset>
+ <input type="text" name="host" id="host" ng-model="host" ng-required="true" class="ui-widget-content ui-corner-all"/>
+ </fieldset>
+
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-primary" type="submit" ng-click="setSettings()">OK</button>
+ <button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
+ </div>
+ </form>
+</script>
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/93b9fa51/console/config/index.html
----------------------------------------------------------------------
diff --git a/console/config/index.html b/console/config/index.html
new file mode 100644
index 0000000..64eb53a
--- /dev/null
+++ b/console/config/index.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+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.
+-->
+<html xmlns:ng="http://angularjs.org">
+
+<head>
+
+ <meta charset="utf-8"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
+ <title>Qpid Dispatch Config Processor</title>
+
+ <link rel="shortcut icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />
+
+ <link href='bower_components/font-awsome/css/font-awesome.min.css' type="text/css">
+ <link href="bower_components/jquery-ui/themes/smoothness/jquery-ui.min.css" rel="stylesheet" type='text/css'>
+ <link href="bower_components/patternfly/dist/css/patternfly.min.css" rel="stylesheet" type='text/css'>
+ <link href="bower_components/patternfly/dist/css/patternfly-additions.min.css" rel="stylesheet" type='text/css'>
+
+ <link rel="stylesheet" href="css/plugin.css" type="text/css"/>
+ <link rel="stylesheet" href="css/dispatch.css" type="text/css"/>
+ <link rel="stylesheet" href="css/site-base.css" type="text/css"/>
+ <link rel="stylesheet" href="css/mock.css" type="text/css"/>
+
+</head>
+
+<body ng-app="QDR">
+
+ <nav class="navbar navbar-default navbar-pf" role="navigation">
+ <div class="navbar-header">
+ <a class="navbar-brand" href="/">
+ <span class="logo">Qpid Dispatch config file processor</span>
+ </a>
+ </div>
+ </nav>
+
+ <div class="container-fluid">
+ <div class="row">
+ <div id="main-container">
+ <div ng-view></div>
+ </div>
+ </div>
+ </div>
+
+
+<!--[if lt IE 9]>
+<script src="bower_components/html5shiv/dist/html5shiv.min.js"></script>
+<![endif]-->
+
+<script src="bower_components/jquery/dist/jquery.min.js"></script>
+<script src="bower_components/jquery-ui/jquery-ui.min.js"></script>
+
+<!-- Angular -->
+<script src="bower_components/angular/angular.min.js"></script>
+<script src="bower_components/angular-route/angular-route.min.js"></script>
+<script src="bower_components/angular-resource/angular-resource.min.js"></script>
+<script src="bower_components/angular-animate/angular-animate.min.js"></script>
+<script src="bower_components/angular-sanitize/angular-sanitize.min.js"></script>
+<script src="bower_components/angular-bootstrap/ui-bootstrap.min.js"></script>
+<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
+
+<script src='bower_components/d3/d3.min.js'></script>
+<script src="bower_components/notifyjs/dist/notify.js"></script>
+
+<script type="text/javascript" src="js/dispatchPlugin.js"></script>
+<script type="text/javascript" src="js/qdrService.js"></script>
+<script type="text/javascript" src="js/qdrTopology.js"></script>
+<script type="text/javascript" src="js/qdrNewNode.js"></script>
+
+
+<script type="text/javascript">
+ //angular.element(document.getElementsByTagName('head')).append(angular.element('<base href="' + window.location.pathname + '" />'));
+</script>
+
+</body>
+</html>
+
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/93b9fa51/console/config/js/dispatchPlugin.js
----------------------------------------------------------------------
diff --git a/console/config/js/dispatchPlugin.js b/console/config/js/dispatchPlugin.js
new file mode 100644
index 0000000..fa18322
--- /dev/null
+++ b/console/config/js/dispatchPlugin.js
@@ -0,0 +1,165 @@
+/*
+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 = "";
+
+ /**
+ * @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 = "";
+ 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(QDR.pluginName, ['ngAnimate', 'ngResource', 'ngRoute', 'ngSanitize', 'ui.bootstrap']);
+
+ Core = {
+ notification: function (severity, msg) {
+ $.notify(msg, severity)
+ }
+ }
+
+ // set up the routing for this plugin
+ QDR.module.config(function($routeProvider) {
+ $routeProvider
+ .otherwise({
+ templateUrl: QDR.templatePath + 'qdrTopology.html'
+ })
+ });
+
+ QDR.module.config(function ($compileProvider) {
+ $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|file|blob):/);
+ $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension):/);
+ })
+
+ QDR.module.filter('to_trusted', ['$sce', function($sce){
+ return function(text) {
+ return $sce.trustAsHtml(text);
+ };
+ }]);
+
+ QDR.module.filter('humanify', 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", "QDRService", function ($rootScope, $route, $timeout, $location, $log, QDRService) {
+ QDR.log = new QDR.logger($log);
+ QDR.log.info("*************creating config editor************");
+ QDRService.getSchema(function () {
+ QDR.log.debug("got schema")
+ })
+ }]);
+
+ QDR.module.config(['$qProvider', function ($qProvider) {
+ $qProvider.errorOnUnhandledRejections(false);
+ }]);
+
+ 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;
+})();
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/93b9fa51/console/config/js/qdrNewNode.js
----------------------------------------------------------------------
diff --git a/console/config/js/qdrNewNode.js b/console/config/js/qdrNewNode.js
new file mode 100644
index 0000000..39cafdf
--- /dev/null
+++ b/console/config/js/qdrNewNode.js
@@ -0,0 +1,299 @@
+/*
+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, $sce, $uibModalInstance, QDRService, node, entityType, context, entityKey, maxPort, hasLinks) {
+ var newname = node.name
+ $scope.context = context
+ if (!angular.isDefined(context))
+ $scope.context = 'new'
+ var newContext = {"new":maxPort+1, "artemis":61616, "qpid":5672, 'log':'', 'sslProfile':''}
+ $scope.title = ((context && context in newContext) ? "Edit " : "Add ") + entityType + " section"
+ if (context === 'artemis')
+ $scope.title += " to an Artemis broker"
+ if (context === 'qpid')
+ $scope.title += " to a Qpid broker"
+ var schema = QDRService.schema;
+ var myEntities = []
+ myEntities.push(entityType)
+ var readOnlyAttrs = { 'router': ['version', 'id', 'identity'],
+ 'log': ['name', 'identity'],
+ 'linkRoute': ['identity'],
+ "sslProfile": ['identity'],
+ "connector": ['identity']}
+
+ var typeMap = {
+ integer: 'number',
+ string: 'text',
+ path: 'text',
+ boolean: 'boolean'
+ };
+ 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 = [];
+
+ var getEdivAttr = function (ediv, key) {
+ for (var i=0; i<ediv.attributes.length; i++) {
+ if (ediv.attributes[i].name === key)
+ return ediv.attributes[i]
+ }
+ }
+
+ // 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 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 read-only fields
+ if (readOnlyAttrs[tabName] && readOnlyAttrs[tabName].indexOf(key) >= 0)
+ return null;
+ // skip deprecated and statistics fields
+ if (key == value.description.startsWith('Deprecated') || value.graph)
+ return null;
+ var val = value['default'];
+ 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 || key === entityKey || key === 'host')? true : false,
+ unique: value.unique
+ };
+ })
+ }
+ 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 (node[entityName+'s'] && context in node[entityName+'s']) {
+ // fill form with existing data
+ var o = node[entityName+'s'][context]
+ ediv.attributes.forEach( function (attr) {
+ if (attr['name'] in o) {
+ attr['value'] = o[attr['name']]
+ if (attr['type'] === 'number') {
+ try {
+ attr['value'] = parseInt(attr['value'])
+ }
+ catch (e) {
+ attr['value'] = 0
+ }
+ }
+
+ // if the form has a select dropdown, set the selected to the current value
+ if (Array.isArray(attr['rawtype']))
+ attr.selected = attr['value']
+ }
+ })
+ }
+
+ if (ediv.actualName == 'router') {
+ ediv.attributes.forEach( function (attr) {
+ if (attr['name'] in node) {
+ attr['value'] = node[attr['name']]
+ }
+ })
+ // if we have any new links (connectors), then the router's mode should be interior
+ var roleAttr = getEdivAttr(ediv, 'mode')
+ if (hasLinks && roleAttr) {
+ roleAttr.value = roleAttr.selected = "interior";
+ } else {
+ roleAttr.value = roleAttr.selected = "standalone";
+ }
+ }
+ if (ediv.actualName == 'listener' && context === 'new') {
+ // find max port number that is used in all the listeners
+ var port = getEdivAttr(ediv, 'port')
+ if (port)
+ port.value = ++maxPort
+ var host = getEdivAttr(ediv, 'host')
+ if (host && node.host)
+ host.value = node.host
+ }
+ if (ediv.actualName == 'connector' && context in newContext) {
+ // find max port number that is used in all the listeners
+ var port = getEdivAttr(ediv, 'port')
+ if (port) {
+ port.value = newContext[context]
+ }
+ if (context === 'artemis' || context === 'qpid') {
+ var role = getEdivAttr(ediv, 'role')
+ if (role) {
+ role.value = role.selected = 'route-container'
+ }
+ }
+ context = 'new'
+ }
+ // special case for required log.module since it doesn't have a default
+ if (ediv.actualName == 'log') {
+ // initialize module to 'DEFAULT'
+ var moduleAttr = getEdivAttr(ediv, 'module')
+ if (moduleAttr)
+ moduleAttr.value = moduleAttr.selected = "DEFAULT"
+ // adding a new log section and we already have a section. select 1st unused module
+ if (context === 'new' && node.logs) {
+ var modules = ent.attributes.module.type
+ var availableModules = modules.filter( function (module) {
+ return !(module in node.logs)
+ })
+ if (availableModules.length > 0) {
+ moduleAttr.value = moduleAttr.selected = availableModules[0]
+ }
+ } else if (node.logs && context in node.logs) {
+ // fill form with existing data
+ var log = node.logs[context]
+ ediv.attributes.forEach( function (attr) {
+ if (attr['name'] in log) {
+ attr['value'] = log[attr['name']]
+ if (attr['name'] == 'module')
+ attr.selected = attr['value']
+ }
+ })
+ }
+ }
+ // sort ediv.attributes on name
+ var allNames = ediv.attributes.map( function (attr) {
+ return attr['name']
+ })
+ allNames.sort()
+
+ // move all required entities to the top
+ for (var i=0; i<ediv.attributes.length; i++) {
+ var attr = ediv.attributes[i]
+ if (attr.required) {
+ allNames.move(allNames.indexOf(attr.name), 0)
+ }
+ }
+
+ // move entities key into first position
+ var keyIndex = allNames.findIndex(function (name) {
+ return name === entityKey
+ })
+ if (keyIndex > 0) {
+ allNames.move(keyIndex, 0)
+ }
+ // now order the entity attributes by allNames
+ ediv.attributes.sort(function(attr1, attr2){
+ return allNames.indexOf(attr1['name']) - allNames.indexOf(attr2['name'])
+ });
+ $scope.entities.push(ediv);
+ })
+
+ $scope.testPattern = function(attr) {
+ if (attr.rawtype == 'path')
+ return /^(\/)?([^/\0]+(\/)?)+$/;
+ 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.setDescription = function(attr, e) {
+ $scope.attributeDescription = $sce.trustAsHtml(attr.description +
+ '<div class="attr-type">Type: ' + JSON.stringify(attr.rawtype, null, 1) + '</div>' +
+ '<div class="attr-required">' + (attr.required ? "required" : '') + '</div>' +
+ '<div class="attr-unique">' + (attr.unique ? "Must be unique" : '') + '</div>')
+ }
+ // handle the save button click
+ // copy the dialog's values to the original node
+ $scope.save = function() {
+ $uibModalInstance.close({
+ entities: $scope.entities,
+ });
+ }
+ $scope.cancel = function() {
+ $uibModalInstance.close()
+ };
+ $scope.del = function() {
+ $uibModalInstance.close({del: true})
+ }
+ $scope.showDelete = function () {
+ return !(context === 'new' || !context)
+ }
+
+ });
+
+ return QDR;
+}(QDR || {}));
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/93b9fa51/console/config/js/qdrService.js
----------------------------------------------------------------------
diff --git a/console/config/js/qdrService.js b/console/config/js/qdrService.js
new file mode 100644
index 0000000..149f94e
--- /dev/null
+++ b/console/config/js/qdrService.js
@@ -0,0 +1,327 @@
+/*
+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) {
+
+ // The QDR service handles the connection to
+ // the server in the background
+ QDR.module.factory("QDRService", ['$rootScope', '$http', '$timeout', '$resource', '$location', function($rootScope, $http, $timeout, $resource, $location) {
+ var self = {
+
+ connectActions: [],
+ schema: undefined,
+
+ addConnectAction: function(action) {
+ if (angular.isFunction(action)) {
+ self.connectActions.push(action);
+ }
+ },
+ executeConnectActions: function() {
+ self.connectActions.forEach(function(action) {
+ try {
+ action.apply();
+ } catch (e) {
+ // in case the page that registered the handler has been unloaded
+ QDR.log.info(e.message)
+ }
+ });
+ self.connectActions = [];
+ },
+ 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;
+ },
+
+ // 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 === 'route-container' && d.properties.product === 'apache-activemq-artemis';
+ },
+
+ isQpid: function(d) {
+ return d.nodeType === 'route-container' && (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
+ return (d && d['properties'] && d['properties']['console_identifier'] === 'Dispatch console')
+ },
+
+ flatten: function(attributes, result) {
+ var flat = {}
+ attributes.forEach(function(attr, i) {
+ if (result && result.length > i)
+ flat[attr] = result[i]
+ })
+ return flat;
+ },
+ getSchema: function(callback) {
+ self.sendMethod("GET-SCHEMA", {}, function (response) {
+ for (var entityName in response.entityTypes) {
+ var entity = response.entityTypes[entityName]
+ if (entity.deprecated) {
+ delete response.entityTypes[entityName]
+ } else {
+ for (var attributeName in entity.attributes) {
+ var attribute = entity.attributes[attributeName]
+ if (attribute.deprecated) {
+ delete response.entityTypes[entityName].attributes[attributeName]
+ }
+ }
+ }
+ }
+ self.schema = response
+ callback()
+ })
+ },
+
+ sendMethod: function(operation, props, callback) {
+ setTimeout(function () {
+ props['operation'] = operation
+ $.post( "http://localhost:8000", JSON.stringify(props), function (response, status) {
+ callback(response)
+ }, "json" )
+ }, 1)
+ }
+
+ }
+ return self;
+ }]);
+
+ return QDR;
+
+}(QDR || {}));
+
+(function() {
+ console.dump = function(o) {
+ if (window.JSON && window.JSON.stringify)
+ QDR.log.info(JSON.stringify(o, undefined, 2));
+ else
+ console.log(o);
+ };
+})();
+
+function ngGridFlexibleHeightPlugin (opts) {
+ var self = this;
+ self.grid = null;
+ self.scope = null;
+ self.init = function (scope, grid, services) {
+ self.domUtilityService = services.DomUtilityService;
+ self.grid = grid;
+ self.scope = scope;
+ var recalcHeightForData = function () { setTimeout(innerRecalcForData, 1); };
+ var innerRecalcForData = function () {
+ var gridId = self.grid.gridId;
+ var footerPanelSel = '.' + gridId + ' .ngFooterPanel';
+ if (!self.grid.$topPanel || !self.grid.$canvas)
+ return;
+ var extraHeight = self.grid.$topPanel.height() + $(footerPanelSel).height();
+ var naturalHeight = self.grid.$canvas.height() + 1;
+ if (opts != null) {
+ if (opts.minHeight != null && (naturalHeight + extraHeight) < opts.minHeight) {
+ naturalHeight = opts.minHeight - extraHeight - 2;
+ }
+ if (opts.maxHeight != null && (naturalHeight + extraHeight) > opts.maxHeight) {
+ naturalHeight = opts.maxHeight;
+ }
+ }
+
+ var newViewportHeight = naturalHeight + 3;
+ if (!self.scope.baseViewportHeight || self.scope.baseViewportHeight !== newViewportHeight) {
+ self.grid.$viewport.css('height', newViewportHeight + 'px');
+ self.grid.$root.css('height', (newViewportHeight + extraHeight) + 'px');
+ self.scope.baseViewportHeight = newViewportHeight;
+ self.domUtilityService.RebuildGrid(self.scope, self.grid);
+ }
+ };
+ self.scope.catHashKeys = function () {
+ var hash = '',
+ idx;
+ for (idx in self.scope.renderedRows) {
+ hash += self.scope.renderedRows[idx].$$hashKey;
+ }
+ return hash;
+ };
+ self.scope.$watch('catHashKeys()', innerRecalcForData);
+ self.scope.$watch(self.grid.config.data, recalcHeightForData);
+ };
+}
+
+if (!String.prototype.startsWith) {
+ String.prototype.startsWith = function (searchString, position) {
+ return this.substr(position || 0, searchString.length) === searchString
+ }
+}
+
+if (!String.prototype.endsWith) {
+ String.prototype.endsWith = function(searchString, position) {
+ var subjectString = this.toString();
+ if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
+ position = subjectString.length;
+ }
+ position -= searchString.length;
+ var lastIndex = subjectString.lastIndexOf(searchString, position);
+ return lastIndex !== -1 && lastIndex === position;
+ };
+}
+
+if (typeof Object.assign != 'function') {
+ // Must be writable: true, enumerable: false, configurable: true
+ Object.defineProperty(Object, "assign", {
+ value: function assign(target, varArgs) { // .length of function is 2
+ 'use strict';
+ if (target == null) { // TypeError if undefined or null
+ throw new TypeError('Cannot convert undefined or null to object');
+ }
+
+ var to = Object(target);
+
+ for (var index = 1; index < arguments.length; index++) {
+ var nextSource = arguments[index];
+
+ if (nextSource != null) { // Skip over if undefined or null
+ for (var nextKey in nextSource) {
+ // Avoid bugs when hasOwnProperty is shadowed
+ if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
+ to[nextKey] = nextSource[nextKey];
+ }
+ }
+ }
+ }
+ return to;
+ },
+ writable: true,
+ configurable: true
+ });
+}
+
+if (!String.prototype.repeat) {
+ String.prototype.repeat = function(count) {
+ 'use strict';
+ if (this == null) {
+ throw new TypeError('can\'t convert ' + this + ' to object');
+ }
+ var str = '' + this;
+ count = +count;
+ if (count != count) {
+ count = 0;
+ }
+ if (count < 0) {
+ throw new RangeError('repeat count must be non-negative');
+ }
+ if (count == Infinity) {
+ throw new RangeError('repeat count must be less than infinity');
+ }
+ count = Math.floor(count);
+ if (str.length == 0 || count == 0) {
+ return '';
+ }
+ // Ensuring count is a 31-bit integer allows us to heavily optimize the
+ // main part. But anyway, most current (August 2014) browsers can't handle
+ // strings 1 << 28 chars or longer, so:
+ if (str.length * count >= 1 << 28) {
+ throw new RangeError('repeat count must not overflow maximum string size');
+ }
+ var rpt = '';
+ for (var i = 0; i < count; i++) {
+ rpt += str;
+ }
+ return rpt;
+ }
+}
+
+if (!Array.prototype.move) {
+ Array.prototype.move = function(from, to) {
+ this.splice(to, 0, this.splice(from, 1)[0]);
+ };
+}
+
+// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex
+if (!Array.prototype.findIndex) {
+ Object.defineProperty(Array.prototype, 'findIndex', {
+ value: function(predicate) {
+ // 1. Let O be ? ToObject(this value).
+ if (this == null) {
+ throw new TypeError('"this" is null or not defined');
+ }
+
+ var o = Object(this);
+
+ // 2. Let len be ? ToLength(? Get(O, "length")).
+ var len = o.length >>> 0;
+
+ // 3. If IsCallable(predicate) is false, throw a TypeError exception.
+ if (typeof predicate !== 'function') {
+ throw new TypeError('predicate must be a function');
+ }
+
+ // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
+ var thisArg = arguments[1];
+
+ // 5. Let k be 0.
+ var k = 0;
+
+ // 6. Repeat, while k < len
+ while (k < len) {
+ // a. Let Pk be ! ToString(k).
+ // b. Let kValue be ? Get(O, Pk).
+ // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
+ // d. If testResult is true, return k.
+ var kValue = o[k];
+ if (predicate.call(thisArg, kValue, k, o)) {
+ return k;
+ }
+ // e. Increase k by 1.
+ k++;
+ }
+
+ // 7. Return -1.
+ return -1;
+ }
+ });
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org