diff options
author | Ashlee Young <ashlee@wildernessvoice.com> | 2015-11-03 14:08:10 -0800 |
---|---|---|
committer | Ashlee Young <ashlee@wildernessvoice.com> | 2015-11-03 14:08:10 -0800 |
commit | 643ee33289bd2cb9e6afbfb09b4ed72d467ba1c2 (patch) | |
tree | c2c376a44a359544fe3d4c45eb0cc0e2ec4a7080 /framework/src/onos/web | |
parent | 46eeb79b54345bdafb6055b8ee4bad4ce8b01274 (diff) |
This updates ONOS src tree to commit id
03fa5e571cabbd001ddb1598847e1150b11c7333
Change-Id: I13b554026d6f902933e35887d29bd5fdb669c0bd
Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/onos/web')
32 files changed, 598 insertions, 94 deletions
diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java index dd9b9fc3..312f6e35 100644 --- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java +++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java @@ -84,10 +84,9 @@ public class ClusterWebResource extends AbstractWebResource { public Response formCluster(InputStream config) throws IOException { JsonCodec<ControllerNode> codec = codec(ControllerNode.class); ObjectNode root = (ObjectNode) mapper().readTree(config); - String ipPrefix = root.path("ipPrefix").asText(); List<ControllerNode> nodes = codec.decode((ArrayNode) root.path("nodes"), this); - get(ClusterAdminService.class).formCluster(new HashSet<>(nodes), ipPrefix); + get(ClusterAdminService.class).formCluster(new HashSet<>(nodes)); return Response.ok().build(); } diff --git a/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java b/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java index 8acdc2cf..82b7a782 100644 --- a/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java +++ b/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java @@ -27,12 +27,14 @@ import org.onosproject.cluster.ClusterEventListener; import org.onosproject.cluster.ControllerNode; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; +import org.onosproject.core.DefaultApplicationId; import org.onosproject.event.Event; import org.onosproject.mastership.MastershipAdminService; import org.onosproject.mastership.MastershipEvent; import org.onosproject.mastership.MastershipListener; import org.onosproject.net.ConnectPoint; import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; import org.onosproject.net.Host; import org.onosproject.net.HostId; import org.onosproject.net.HostLocation; @@ -48,11 +50,14 @@ import org.onosproject.net.flow.TrafficTreatment; import org.onosproject.net.host.HostEvent; import org.onosproject.net.host.HostListener; import org.onosproject.net.intent.HostToHostIntent; +import org.onosproject.net.intent.Intent; import org.onosproject.net.intent.IntentEvent; import org.onosproject.net.intent.IntentListener; +import org.onosproject.net.intent.Key; import org.onosproject.net.intent.MultiPointToSinglePointIntent; import org.onosproject.net.link.LinkEvent; import org.onosproject.net.link.LinkListener; +import org.onosproject.ui.JsonUtils; import org.onosproject.ui.RequestHandler; import org.onosproject.ui.UiConnection; import org.onosproject.ui.impl.TrafficMonitor.Mode; @@ -76,7 +81,9 @@ import static org.onlab.util.Tools.groupedThreads; import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ADDED; import static org.onosproject.net.DeviceId.deviceId; import static org.onosproject.net.HostId.hostId; -import static org.onosproject.net.device.DeviceEvent.Type.*; +import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED; +import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_UPDATED; +import static org.onosproject.net.device.DeviceEvent.Type.PORT_STATS_UPDATED; import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED; import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED; import static org.onosproject.ui.JsonUtils.envelope; @@ -97,6 +104,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { private static final String REQ_NEXT_INTENT = "requestNextRelatedIntent"; private static final String REQ_PREV_INTENT = "requestPrevRelatedIntent"; private static final String REQ_SEL_INTENT_TRAFFIC = "requestSelectedIntentTraffic"; + private static final String SEL_INTENT = "selectIntent"; private static final String REQ_ALL_FLOW_TRAFFIC = "requestAllFlowTraffic"; private static final String REQ_ALL_PORT_TRAFFIC = "requestAllPortTraffic"; private static final String REQ_DEV_LINK_FLOWS = "requestDeviceLinkFlows"; @@ -117,9 +125,13 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { private static final String SPRITE_LIST_RESPONSE = "spriteListResponse"; private static final String SPRITE_DATA_RESPONSE = "spriteDataResponse"; private static final String UPDATE_INSTANCE = "updateInstance"; + private static final String TOPO_START_DONE = "topoStartDone"; // fields private static final String ID = "id"; + private static final String KEY = "key"; + private static final String APP_ID = "appId"; + private static final String APP_NAME = "appName"; private static final String DEVICE = "device"; private static final String HOST = "host"; private static final String CLASS = "class"; @@ -135,7 +147,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { private static final String DEACTIVATE = "deactivate"; - private static final String APP_ID = "org.onosproject.gui"; + private static final String MY_APP_ID = "org.onosproject.gui"; private static final long TRAFFIC_PERIOD = 5000; private static final long SUMMARY_PERIOD = 30000; @@ -176,7 +188,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { @Override public void init(UiConnection connection, ServiceDirectory directory) { super.init(connection, directory); - appId = directory.get(CoreService.class).registerApplication(APP_ID); + appId = directory.get(CoreService.class).registerApplication(MY_APP_ID); traffic = new TrafficMonitor(TRAFFIC_PERIOD, servicesBundle, this); } @@ -213,6 +225,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { new ReqNextIntent(), new ReqPrevIntent(), new ReqSelectedIntentTraffic(), + new SelIntent(), new CancelTraffic() ); @@ -241,6 +254,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { sendAllDevices(); sendAllLinks(); sendAllHosts(); + sendTopoStartDone(); } } @@ -344,11 +358,13 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { PropertyPanel pp = null; if (type.equals(DEVICE)) { - pp = deviceDetails(deviceId(id), sid); - overlayCache.currentOverlay().modifyDeviceDetails(pp); + DeviceId did = deviceId(id); + pp = deviceDetails(did, sid); + overlayCache.currentOverlay().modifyDeviceDetails(pp, did); } else if (type.equals(HOST)) { - pp = hostDetails(hostId(id), sid); - overlayCache.currentOverlay().modifyHostDetails(pp); + HostId hid = hostId(id); + pp = hostDetails(hid, sid); + overlayCache.currentOverlay().modifyHostDetails(pp, hid); } sendMessage(envelope(SHOW_DETAILS, sid, json(pp))); @@ -524,6 +540,31 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { } } + private final class SelIntent extends RequestHandler { + private SelIntent() { + super(SEL_INTENT); + } + + @Override + public void process(long sid, ObjectNode payload) { + int appId = Integer.parseInt(string(payload, APP_ID)); + String appName = string(payload, APP_NAME); + ApplicationId applicId = new DefaultApplicationId(appId, appName); + long intentKey = Long.decode(string(payload, KEY)); + + Key key = Key.of(intentKey, applicId); + log.debug("Attempting to select intent key={}", key); + + Intent intent = intentService.getIntent(key); + if (intent == null) { + log.debug("no such intent found!"); + } else { + log.debug("starting to monitor intent {}", key); + traffic.monitor(intent); + } + } + } + private final class CancelTraffic extends RequestHandler { private CancelTraffic() { super(CANCEL_TRAFFIC); @@ -623,6 +664,9 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { return hostIds; } + private void sendTopoStartDone() { + sendMessage(JsonUtils.envelope(TOPO_START_DONE, objectNode())); + } private synchronized void startSummaryMonitoring() { stopSummaryMonitoring(); diff --git a/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java b/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java index ea8ca3ea..f4b5598d 100644 --- a/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java +++ b/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java @@ -17,6 +17,7 @@ package org.onosproject.ui.impl; +import org.onosproject.net.DeviceId; import org.onosproject.ui.UiTopoOverlay; import org.onosproject.ui.topo.ButtonId; import org.onosproject.ui.topo.PropertyPanel; @@ -55,7 +56,7 @@ public class TrafficOverlay extends UiTopoOverlay { } @Override - public void modifyDeviceDetails(PropertyPanel pp) { + public void modifyDeviceDetails(PropertyPanel pp, DeviceId deviceId) { pp.addButton(SHOW_DEVICE_FLOWS) .addButton(SHOW_RELATED_TRAFFIC); } diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.css b/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.css index 46dbdb52..ded05cf1 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.css +++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.css @@ -34,6 +34,10 @@ border-radius: 6px; } +.floatpanel.dialog { + top: 180px; +} + html[data-platform='iPad'] .floatpanel { top: 80px; } diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.js b/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.js index aef71eee..10f04813 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.js @@ -171,7 +171,10 @@ } angular.module('onosLayer') - .factory('PanelService', ['$log', 'FnService', function (_$log_, _fs_) { + .factory('PanelService', + ['$log', '$window', 'FnService', + + function (_$log_, _$window_, _fs_) { $log = _$log_; fs = _fs_; @@ -210,5 +213,4 @@ destroyPanel: destroyPanel }; }]); - }()); diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js b/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js index 15b44bc9..12536361 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js @@ -37,6 +37,8 @@ play: 'play', stop: 'stop', + topo: 'topo', + refresh: 'refresh', garbage: 'garbage', diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.css b/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.css index 18b81ba6..356ac0f7 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.css +++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.css @@ -81,7 +81,7 @@ div.summary-list tr.no-data td { } .light div.summary-list tr.selected { - background-color: deepskyblue; + background-color: deepskyblue !important; } .dark div.summary-list tr.selected { diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js b/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js index 24161bbb..6a5ffb1f 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js @@ -47,6 +47,7 @@ resp = o.tag + 'DataResponse', onSel = fs.isF(o.selCb), onResp = fs.isF(o.respCb), + idKey = o.idKey || 'id', oldTableData = [], loaded = false, refreshPromise, loadingPromise; @@ -104,7 +105,8 @@ // === selecting a row functions ---------------- function selCb($event, selRow) { - o.scope.selId = (o.scope.selId === selRow.id) ? null : selRow.id; + var selId = selRow[idKey]; + o.scope.selId = (o.scope.selId === selId) ? null : selId; onSel && onSel($event, selRow); } o.scope.selectCallback = selCb; diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.css b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.css index ed9cd48d..dfa50c37 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.css +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.css @@ -23,7 +23,6 @@ } #ov-intent div.ctrl-btns { - width: 45px; } .light #ov-intent tr:nth-child(6n + 1), diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.html b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.html index 4883beed..98aa5659 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.html +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.html @@ -1,24 +1,13 @@ -<!-- - ~ Copyright 2015 Open Networking Laboratory - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> - <!-- Intent partial HTML --> <div id="ov-intent"> <div class="tabular-header"> <h2>Intents ({{tableData.length}} total)</h2> <div class="ctrl-btns"> + <div ng-class="{active: !!selId}" + icon icon-id="topo" icon-size="36" + tooltip tt-msg="topoTip" + ng-click="showIntent()"></div> + <div class="separator"></div> <div class="refresh" ng-class="{active: autoRefresh}" icon icon-size="36" icon-id="refresh" tooltip tt-msg="autoRefreshTip" @@ -51,6 +40,8 @@ </tr> <tr ng-repeat-start="intent in tableData track by $index" + ng-click="selectCallback($event, intent)" + ng-class="{selected: intent.key === selId}" ng-repeat-complete row-id="{{intent.key}}"> <td>{{intent.appId}}</td> <td>{{intent.key}}</td> @@ -58,10 +49,14 @@ <td>{{intent.priority}}</td> <td>{{intent.state}}</td> </tr> - <tr row-id="{{intent.key}}"> + <tr ng-click="selectCallback($event, intent)" + ng-class="{selected: intent.key === selId}" + row-id="{{intent.key}}"> <td class="resources" colspan="5">{{intent.resources}}</td> </tr> - <tr row-id="{{intent.key}}" ng-repeat-end> + <tr ng-click="selectCallback($event, intent)" + ng-class="{selected: intent.key === selId}" + row-id="{{intent.key}}" ng-repeat-end> <td class="details" colspan="5">{{intent.details}}</td> </tr> </table> diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.js b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.js index 5810f347..19f2c076 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.js @@ -23,14 +23,37 @@ angular.module('ovIntent', []) .controller('OvIntentCtrl', - ['$log', '$scope', 'TableBuilderService', + ['$log', '$scope', 'TableBuilderService', 'NavService', - function ($log, $scope, tbs) { - tbs.buildTable({ - scope: $scope, - tag: 'intent' - }); + function ($log, $scope, tbs, ns) { - $log.log('OvIntentCtrl has been created'); - }]); + function selCb($event, row) { + $log.debug('Got a click on:', row); + var m = /(\d+)\s:\s(.*)/.exec(row.appId), + id = m ? m[1] : null, + name = m ? m[2] : null; + + $scope.intentData = ($scope.selId && m) ? { + intentAppId: id, + intentAppName: name, + intentKey: row.key + } : null; + } + + tbs.buildTable({ + scope: $scope, + tag: 'intent', + selCb: selCb, + idKey: 'key' + }); + + $scope.topoTip = 'Show selected intent on topology view'; + + $scope.showIntent = function () { + var d = $scope.intentData; + d && ns.navTo('topo', d); + }; + + $log.log('OvIntentCtrl has been created'); + }]); }()); diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css index f4b089a0..dda6d5c6 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css @@ -96,6 +96,24 @@ html[data-platform='iPad'] #topo-p-detail { height: 30px; } +/* --- Topo Dialog Panel --- */ + +#topo-p-dialog .dialog-button { + display: inline-block; + cursor: pointer; + height: 20px; + padding: 2px 6px; + margin: 4px; + float: right; +} + +.light #topo-p-dialog .dialog-button { + background-color: #fec; +} +.dark #topo-p-dialog .dialog-button { + background-color: #369; +} + /* --- general topo-panel styling --- */ .topo-p div.header div.icon { @@ -427,6 +445,39 @@ html[data-platform='iPad'] #topo-p-detail { fill: #f90; } +/* Badges */ +/* (... works for both light and dark themes...) */ +#ov-topo svg .node .badge circle { + stroke: #aaa; +} + +#ov-topo svg .node .badge.badgeInfo circle { + fill: #ccf; +} + +#ov-topo svg .node .badge.badgeWarn circle { + fill: #da2; +} + +#ov-topo svg .node .badge.badgeError circle { + fill: #e44; +} + +#ov-topo svg .node .badge use { + fill: white; +} + +#ov-topo svg .node .badge.badgeInfo use { + fill: #448; +} + +#ov-topo svg .node .badge text { + fill: white; +} + +#ov-topo svg .node .badge.badgeInfo text { + fill: #448; +} /* Host Nodes */ diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js index 0dfd6281..7ddfd136 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js @@ -412,6 +412,12 @@ flash.enable(true); } + function topoStartDone() { + var d = $scope.intentData; + if (d) { + tts.selectIntent(d); + } + } // --- Controller Definition ----------------------------------------- @@ -430,7 +436,8 @@ _zs_, _gs_, _ms_, _sus_, _flash_, _wss_, _ps_, _tes_, _tfs_, _tps_, _tis_, _tss_, _tls_, _tts_, _tos_, _fltr_, _ttbs_, tspr, _ttip_, _tov_) { - var projection, + var params = $loc.search(), + projection, dim, uplink = { // provides function calls back into this space @@ -438,7 +445,8 @@ projection: function () { return projection; }, zoomLayer: function () { return zoomLayer; }, zoomer: function () { return zoomer; }, - opacifyMap: opacifyMap + opacifyMap: opacifyMap, + topoStartDone: topoStartDone }; $scope = _$scope_; @@ -469,6 +477,14 @@ ttip = _ttip_; tov = _tov_; + if (params.intentKey && params.intentAppId && params.intentAppName) { + $scope.intentData = { + key: params.intentKey, + appId: params.intentAppId, + appName: params.intentAppName + }; + } + $scope.notifyResize = function () { svgResized(fs.windowSize(mast.mastHeight())); }; diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js index 1f061dd6..1d2c5b10 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js @@ -55,8 +55,23 @@ height: 14 } }, + badgeConfig = { + radius: 12, + yoff: 5, + gdelta: 10 + }, icfg; + var status = { + i: 'badgeInfo', + w: 'badgeWarn', + e: 'badgeError' + }; + + function badgeStatus(badge) { + return status[badge.status] || status.i; + } + // internal state var deviceLabelIndex = 0, hostLabelIndex = 0; @@ -186,12 +201,15 @@ } - function updateDeviceLabel(d) { + function updateDeviceRendering(d) { var label = trimLabel(deviceLabel(d)), noLabel = !label, node = d.el, dim = icfg.device.dim, - box, dx, dy; + box, dx, dy, bsel, + bdg = d.badge, + bcr = badgeConfig.radius, + bcgd = badgeConfig.gdelta; node.select('text') .text(label) @@ -216,23 +234,34 @@ node.select('g.deviceIcon') .transition() .attr('transform', sus.translate(dx, dy)); - } - function updateDeviceBadge(d) { - // TODO: Fix this WIP - var node = d.el, - bsel; + // handle badge, if defined + if (bdg) { + node.select('g.badge').remove(); - if (d.badge) { bsel = node.append('g') .classed('badge', true) - .attr('transform', sus.translate(-14, -14)); + .classed(badgeStatus(bdg), true) + .attr('transform', sus.translate(dx + dim, dy)); bsel.append('circle') - .attr('r', 14); - bsel.append('text') - .attr('transform', sus.translate(-5, 3)) - .text('42'); + .attr('r', bcr); + + if (bdg.txt) { + bsel.append('text') + .attr('dy', badgeConfig.yoff) + .attr('text-anchor', 'middle') + .text(bdg.txt); + } else if (bdg.gid) { + bsel.append('use') + .attr({ + width: bcgd * 2, + height: bcgd * 2, + transform: sus.translate(-bcgd, -bcgd), + 'xlink:href': '#' + bdg.gid + }); + + } } } @@ -258,8 +287,7 @@ function deviceExisting(d) { var node = d.el; node.classed('online', d.online); - updateDeviceLabel(d); - updateDeviceBadge(d); + updateDeviceRendering(d); api.posNode(d, true); } @@ -574,7 +602,7 @@ deviceLabel: deviceLabel, trimLabel: trimLabel, - updateDeviceLabel: updateDeviceLabel, + updateDeviceLabel: updateDeviceRendering, updateHostLabel: updateHostLabel, updateDeviceColors: updateDeviceColors, diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoDialog.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoDialog.js new file mode 100644 index 00000000..93079183 --- /dev/null +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoDialog.js @@ -0,0 +1,183 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + ONOS GUI -- Topology Dialog Module. + Defines functions for manipulating a dialog box. + */ + +(function () { + 'use strict'; + + // injected refs + var $log, $window, $rootScope, fs, ps, bns; + + // constants + var pCls = 'topo-p dialog', + idDialog = 'topo-p-dialog', + panelOpts = { + width: 300, + edge: 'left' + }; + + // internal state + var pApi, panel, dApi; + + // TODO: ESC key invokes Cancel callback + // TODO: Enter invokes OK callback + + // create the dialog; return its API + function createDialog() { + var header, body, footer, + p = ps.createPanel(idDialog, panelOpts); + p.classed(pCls, true); + panel = p; + + function reset() { + p.empty(); + p.append('div').classed('header', true); + p.append('div').classed('body', true); + p.append('div').classed('footer', true); + + header = p.el().select('.header'); + body = p.el().select('.body'); + footer = p.el().select('.footer'); + } + + function hAppend(x) { + if (typeof x === 'string') { + return header.append(x); + } + header.node().appendChild(x.node()); + return header; + } + + function bAppend(x) { + if (typeof x === 'string') { + return body.append(x); + } + body.node().appendChild(x.node()); + return body; + } + + function fAppend(x) { + if (typeof x === 'string') { + return footer.append(x); + } + footer.node().appendChild(x.node()); + return footer; + } + + function destroy() { + ps.destroyPanel(idDialog); + } + + return { + reset: reset, + appendHeader: hAppend, + appendBody: bAppend, + appendFooter: fAppend, + destroy: destroy + }; + } + + function makeButton(text, callback) { + var cb = fs.isF(callback); + + function invoke() { + cb && cb(); + panel.hide(); + } + return createDiv('dialog-button') + .text(text) + .on('click', invoke); + } + + function addContent(content) { + if (pApi) { + pApi.appendBody(content); + } + return dApi; + } + + function addButton(text, cb) { + if (pApi) { + pApi.appendFooter(makeButton(text, cb)); + } + return dApi; + } + + // opens the dialog (creates if necessary) + function openDialog() { + $log.debug('Open DIALOG'); + if (!pApi) { + pApi = createDialog(); + } + pApi.reset(); + pApi.appendHeader('h2').text('=dialog='); + panel.show(); + + // return the dialog object API + dApi = { + addContent: addContent, + addButton: addButton + }; + return dApi; + } + + // closes the dialog (destroying panel) + function closeDialog() { + $log.debug('Close DIALOG'); + if (pApi) { + panel.hide(); + pApi.destroy(); + pApi = null; + dApi = null; + } + } + + // creates a detached div, returning D3 selection + // optional CSS class may be provided + function createDiv(cls) { + var div = d3.select(document.createElement('div')); + if (cls) { + div.classed(cls, true); + } + return div; + } + + // ========================== + + angular.module('ovTopo') + .factory('TopoDialogService', + ['$log', '$window', '$rootScope', 'FnService', 'PanelService', 'ButtonService', + + function (_$log_, _$window_, _$rootScope_, + _fs_, _ps_, _bns_) { + $log = _$log_; + $window = _$window_; + $rootScope = _$rootScope_; + fs = _fs_; + ps = _ps_; + bns = _bns_; + + return { + openDialog: openDialog, + closeDialog: closeDialog, + createDiv: createDiv + }; + }]); +}()); diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoEvent.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoEvent.js index 5fd38bf6..2957629a 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoEvent.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoEvent.js @@ -60,6 +60,8 @@ updateLink: tfs, removeLink: tfs, + topoStartDone: tfs, + spriteListResponse: tspr, spriteDataResponse: tspr }; diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js index f00b87fa..844d7dc9 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js @@ -240,6 +240,11 @@ } } + function topoStartDone(data) { + // called when the initial barrage of data has been sent from server + uplink.topoStartDone(); + } + // ======================== function nodeById(id) { @@ -1140,7 +1145,8 @@ removeHost: removeHost, addLink: addLink, updateLink: updateLink, - removeLink: removeLink + removeLink: removeLink, + topoStartDone: topoStartDone }; }]); }()); diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js index 9a3b4358..2dee4c40 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js @@ -34,7 +34,8 @@ // internal state var overlays = {}, - current = null; + current = null, + reset = true; function error(fn, msg) { $log.error(tos + fn + '(): ' + msg); @@ -144,7 +145,8 @@ payload[op] = oid; } - if (!same) { + if (reset || !same) { + reset = false; current && doop('deactivate'); current = overlays[id]; current && doop('activate'); @@ -390,6 +392,7 @@ tbSelection: tbSelection, installButtons: installButtons, addDetailButton: addDetailButton, + resetOnToolbarDestroy: function () { reset = true; }, hooks: { escape: escapeHook, emptySelect: emptySelectHook, diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoSelect.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoSelect.js index 483c4baa..4ad76903 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoSelect.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoSelect.js @@ -240,6 +240,33 @@ return cc; } + // returns a selection context, providing info about what is selected + function selectionContext() { + var devices = [], + hosts = [], + types = {}; + + angular.forEach(selections, function (d) { + var o = d.obj, + c = o.class; + + if (c === 'device') { + devices.push(o.id); + types[o.id] = o.type; + } + if (c === 'host') { + hosts.push(o.id); + types[o.id] = o.type; + } + }); + + return { + devices: devices, + hosts: hosts, + types: types + }; + } + // === ----------------------------------------------------- // === MODULE DEFINITION === @@ -280,7 +307,8 @@ selectOrder: function () { return selectOrder; }, somethingSelected: somethingSelected, - clickConsumed: clickConsumed + clickConsumed: clickConsumed, + selectionContext: selectionContext }; }]); }()); diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js index 3928cd21..06285442 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js @@ -243,6 +243,7 @@ function destroyToolbar() { tbs.destroyToolbar(name); + tov.resetOnToolbarDestroy(); } // allows us to ensure the button states track key strokes diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoTraffic.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoTraffic.js index ca379360..ff690c49 100644 --- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoTraffic.js +++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoTraffic.js @@ -152,6 +152,14 @@ } } + // force the system to create a single intent selection + function selectIntent(data) { + trafficMode = 'intents'; + hoverMode = null; + wss.sendEvent('selectIntent', data); + flash.flash('Selecting Intent ' + data.key); + } + // === ------------------------------------------------------ // action buttons on detail panel (multiple selection) @@ -207,6 +215,7 @@ showPrevIntent: showPrevIntent, showNextIntent: showNextIntent, showSelectedIntentTraffic: showSelectedIntentTraffic, + selectIntent: selectIntent, // invoked from mouseover/mouseout and selection change requestTrafficForMode: requestTrafficForMode, diff --git a/framework/src/onos/web/gui/src/main/webapp/index.html b/framework/src/onos/web/gui/src/main/webapp/index.html index 5df3c664..7e0d9b7d 100644 --- a/framework/src/onos/web/gui/src/main/webapp/index.html +++ b/framework/src/onos/web/gui/src/main/webapp/index.html @@ -98,6 +98,7 @@ <script src="app/view/topo/topo.js"></script> <script src="app/view/topo/topoD3.js"></script> <script src="app/view/topo/topoEvent.js"></script> + <script src="app/view/topo/topoDialog.js"></script> <script src="app/view/topo/topoFilter.js"></script> <script src="app/view/topo/topoForce.js"></script> <script src="app/view/topo/topoInst.js"></script> diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json new file mode 100644 index 00000000..4f35403f --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json @@ -0,0 +1,63 @@ +{ + "event": "showHighlights", + "payload": { + "devices": [ + { + "id": "of:0000000000000001", + "badge": { + "status": "i", + "gid": "xMark", + "msg": "x marks the spot" + } + }, + { + "id": "of:0000000000000002", + "badge": { + "status": "w", + "gid": "crown", + "msg": "it's good to be the King" + } + }, + { + "id": "of:0000000000000003", + "badge": { + "status": "e", + "gid": "chain", + "msg": "the weakest link" + } + }, + { + "id": "of:0000000000000004", + "badge": { + "status": "i", + "txt": "1", + "msg": "singular sensation" + } + }, + { + "id": "of:0000000000000005", + "badge": { + "status": "w", + "txt": "42", + "msg": "life, the universe, and everything!" + } + }, + { + "id": "of:0000000000000006", + "badge": { + "status": "e", + "txt": "99", + "msg": "cadbury's flake" + } + } + ], + "hosts": [], + "links": [ + { + "css": "primary", + "id": "of:0000000000000001/5-of:0000000000000002/7", + "label": "Foo!" + } + ] + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_showHighlights_clear.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json index 615efd25..615efd25 100644 --- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_showHighlights_clear.json +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addDevice_s3.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addDevice_s3.json new file mode 100644 index 00000000..57f3251b --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addDevice_s3.json @@ -0,0 +1,18 @@ +{ + "event": "addDevice", + "payload": { + "id": "of:0000000000000003", + "type": "switch", + "online": true, + "master": "ONOS", + "labels": [ + "", + "switch-3", + "of:0000000000000003" + ], + "metaUi": { + "x": 600, + "y": 200 + } + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_addDevice_s4.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_addDevice_s4.json new file mode 100644 index 00000000..bab00488 --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_addDevice_s4.json @@ -0,0 +1,18 @@ +{ + "event": "addDevice", + "payload": { + "id": "of:0000000000000004", + "type": "switch", + "online": true, + "master": "ONOS", + "labels": [ + "", + "switch-4", + "of:0000000000000004" + ], + "metaUi": { + "x": 200, + "y": 400 + } + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_addDevice_s5.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_addDevice_s5.json new file mode 100644 index 00000000..6ee18080 --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_addDevice_s5.json @@ -0,0 +1,18 @@ +{ + "event": "addDevice", + "payload": { + "id": "of:0000000000000005", + "type": "switch", + "online": true, + "master": "ONOS", + "labels": [ + "", + "switch-5", + "of:0000000000000005" + ], + "metaUi": { + "x": 400, + "y": 420 + } + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_showHighlights_stuff.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_showHighlights_stuff.json deleted file mode 100644 index 74c42c5c..00000000 --- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_showHighlights_stuff.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "event": "showHighlights", - "payload": { - "devices": [ - { - "id": "of:0000000000000001", - "badge": { - "status": "e", - "gid": "xMark", - "msg": "x marks the spot" - } - }, - { - "id": "of:0000000000000002", - "badge": { - "status": "w", - "txt": "7" - } - } - ], - "hosts": [], - "links": [ - { - "css": "primary", - "id": "of:0000000000000001/5-of:0000000000000002/7", - "label": "Antz!" - } - ] - } -} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_addDevice_s6.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_addDevice_s6.json new file mode 100644 index 00000000..4554996e --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_addDevice_s6.json @@ -0,0 +1,18 @@ +{ + "event": "addDevice", + "payload": { + "id": "of:0000000000000006", + "type": "switch", + "online": true, + "master": "ONOS", + "labels": [ + "", + "switch-6", + "of:0000000000000006" + ], + "metaUi": { + "x": 600, + "y": 400 + } + } +} diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addLink_1_2.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_8_addLink_1_2.json index fb952837..fb952837 100644 --- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addLink_1_2.json +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_8_addLink_1_2.json diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_showHighlights_clear.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json index 615efd25..615efd25 100644 --- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_showHighlights_clear.json +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json index 0ca4f4f4..ae093d69 100644 --- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json +++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json @@ -4,7 +4,7 @@ ], "title": "Demo adding badges", "params": { - "lastAuto": 5 + "lastAuto": 9 }, "description": [ "Demonstrate the device badging feature." |