Topo2 Fixed device positions
Change-Id: I10e61981000b427ff1ebf6ae0c35bfb2cdbb9c4b
diff --git a/tools/test/topos/regions-topo-2 b/tools/test/topos/regions-topo-2
index 297bc65..4180c37 100755
--- a/tools/test/topos/regions-topo-2
+++ b/tools/test/topos/regions-topo-2
@@ -64,4 +64,13 @@
layout-add l3 r3 l2
layouts
-EOF
\ No newline at end of file
+EOF
+
+
+onos ${host} <<-EOF
+
+log:set DEBUG org.onosproject.ui.impl.topo.Topo2ViewMessageHandler
+log:set DEBUG org.onosproject.ui.impl.topo.Topo2Jsonifier
+log:set DEBUG org.onosproject.ui.impl.UiWebSocket
+log:list
+EOF
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
index 8ff3bb6..11aef1d 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
@@ -36,6 +36,7 @@
import org.onosproject.net.link.LinkService;
import org.onosproject.net.statistic.StatisticService;
import org.onosproject.net.topology.TopologyService;
+import org.onosproject.ui.JsonUtils;
import org.onosproject.ui.model.topo.UiClusterMember;
import org.onosproject.ui.model.topo.UiDevice;
import org.onosproject.ui.model.topo.UiHost;
@@ -482,4 +483,18 @@
return splitList;
}
+
+ /**
+ * Stores the memento for an element.
+ * This method assumes the payload has an id String, memento ObjectNode
+ *
+ * @param payload event payload
+ */
+ void updateMeta(ObjectNode payload) {
+
+ String id = JsonUtils.string(payload, "id");
+ metaUi.put(id, JsonUtils.node(payload, "memento"));
+
+ log.debug("Storing metadata for {}", id);
+ }
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
index 3513b79..4aa6fc9 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
@@ -60,6 +60,7 @@
private static final String START = "topo2Start";
private static final String NAV_REGION = "topo2navRegion";
private static final String STOP = "topo2Stop";
+ private static final String UPDATE_META2 = "updateMeta2";
// === Outbound event identifiers
private static final String ALL_INSTANCES = "topo2AllInstances";
@@ -87,7 +88,8 @@
return ImmutableSet.of(
new Topo2Start(),
new Topo2NavRegion(),
- new Topo2Stop()
+ new Topo2Stop(),
+ new Topo2UpdateMeta()
);
}
@@ -196,4 +198,15 @@
}
}
+ private final class Topo2UpdateMeta extends RequestHandler {
+ private Topo2UpdateMeta() {
+ super(UPDATE_META2);
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ t2json.updateMeta(payload);
+ }
+ }
+
}
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2.js b/web/gui/src/main/webapp/app/view/topo2/topo2.js
index 839a736..ef76ac1 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2.js
@@ -25,7 +25,7 @@
// references to injected services
var $scope, $log, fs, mast, ks, zs,
- gs, sus, ps, t2es, t2fs, t2is, t2bcs, t2kcs, t2ms;
+ gs, sus, ps, t2es, t2fs, t2is, t2bcs, t2kcs, t2ms, t2mcs;
// DOM elements
var ovtopo2, svg, defs, zoomLayer, forceG;
@@ -88,12 +88,13 @@
'WebSocketService', 'PrefsService', 'ThemeService',
'Topo2EventService', 'Topo2ForceService', 'Topo2InstanceService',
'Topo2BreadcrumbService', 'Topo2KeyCommandService', 'Topo2MapService',
+ 'Topo2MapConfigService',
function (_$scope_, _$log_, _$loc_,
_fs_, _mast_, _ks_, _zs_,
_gs_, _ms_, _sus_, _flash_,
_wss_, _ps_, _th_,
- _t2es_, _t2fs_, _t2is_, _t2bcs_, _t2kcs_, _t2ms_) {
+ _t2es_, _t2fs_, _t2is_, _t2bcs_, _t2kcs_, _t2ms_, _t2mcs_) {
var params = _$loc_.search(),
dim,
@@ -127,6 +128,7 @@
t2bcs = _t2bcs_;
t2kcs = _t2kcs_;
t2ms = _t2ms_;
+ t2mcs = _t2mcs_;
// capture selected intent parameters (if they are set in the
// query string) so that the traffic overlay can highlight
@@ -177,25 +179,25 @@
function (proj) {
var z = ps.getPrefs('topo_zoom', { tx: 0, ty: 0, sc: 1 });
zoomer.panZoom([z.tx, z.ty], z.sc);
+
+ t2mcs.projection(proj);
$log.debug('** Zoom restored:', z);
$log.debug('** We installed the projection:', proj);
+
+ // Now the map has load and we have a projection we can
+ // get the info from the server
+ t2es.start();
+
}
);
// initialize the force layout, ready to render the topology
forceG = zoomLayer.append('g').attr('id', 'topo-force');
+
t2fs.init(svg, forceG, uplink, dim);
t2bcs.init();
t2kcs.init(t2fs);
-
- // =-=-=-=-=-=-=-=-
- // TODO: in future, we will load background map data
- // asynchronously (hence the promise) and then chain off
- // there to send the topo2start event to the server.
- // For now, we'll send the event inline...
- t2es.start();
-
t2is.initInst({ showMastership: t2fs.showMastership });
// === ORIGINAL CODE ===
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js b/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
index c23bc7e..a02a844 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
@@ -22,7 +22,7 @@
(function () {
'use strict';
- var $log, sus, t2rs, t2d3, t2vs, t2ss;
+ var $log, wss, sus, t2rs, t2d3, t2vs, t2ss;
var uplink, linkG, linkLabelG, nodeG;
var link, node;
@@ -142,7 +142,7 @@
// once we've finished moving, pin the node in position
d.fixed = true;
d3.select(this).classed('fixed', true);
- // TODO: sendUpdateMeta(d);
+ sendUpdateMeta(d);
t2ss.clickConsumed(true);
}
@@ -153,6 +153,31 @@
return !nodeLock && !zoomingOrPanning(ev);
}
+ function sendUpdateMeta(d, clearPos) {
+ var metaUi = {},
+ ll;
+
+ // if we are not clearing the position data (unpinning),
+ // attach the x, y, (and equivalent longitude, latitude)...
+ if (!clearPos) {
+ ll = d.lngLatFromCoord([d.x, d.y]);
+ metaUi = {
+ x: d.x,
+ y: d.y,
+ equivLoc: {
+ lng: ll[0],
+ lat: ll[1]
+ }
+ };
+ }
+ d.metaUi = metaUi;
+ wss.sendEvent('updateMeta2', {
+ id: d.get('id'),
+ class: d.get('class'),
+ memento: metaUi
+ });
+ }
+
// predicate that indicates when clicking is active
function clickEnabled() {
return true;
@@ -396,12 +421,13 @@
angular.module('ovTopo2')
.factory('Topo2LayoutService',
[
- '$log', 'SvgUtilService', 'Topo2RegionService',
+ '$log', 'WebSocketService', 'SvgUtilService', 'Topo2RegionService',
'Topo2D3Service', 'Topo2ViewService', 'Topo2SelectService',
- function (_$log_, _sus_, _t2rs_, _t2d3_, _t2vs_, _t2ss_) {
+ function (_$log_, _wss_, _sus_, _t2rs_, _t2d3_, _t2vs_, _t2ss_) {
$log = _$log_;
+ wss = _wss_;
t2rs = _t2rs_;
t2d3 = _t2d3_;
t2vs = _t2vs_;
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Map.js b/web/gui/src/main/webapp/app/view/topo2/topo2Map.js
index 7176a76..4ff2162 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Map.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Map.js
@@ -55,7 +55,7 @@
if (mapFilePath === '*countries') {
cfilter = countryFilters[mapId] || countryFilters.uk;
- loadMap = ms.loadMapRegionInto
+ loadMap = ms.loadMapRegionInto;
}
promise = loadMap(mapG, mapFilePath, mapId, {
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2MapConfig.js b/web/gui/src/main/webapp/app/view/topo2/topo2MapConfig.js
new file mode 100644
index 0000000..ffb7f86
--- /dev/null
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2MapConfig.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016-present 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 Layout Module.
+ Module that contains the d3.force.layout logic
+ */
+
+(function () {
+ 'use strict';
+
+ // Injected refs
+ var $log;
+
+ // Internal State
+ var proj;
+
+ function projection(x) {
+ if (x) {
+ proj = x;
+ $log.debug("Set the projection");
+ }
+ return proj;
+ }
+
+ angular.module('ovTopo2')
+ .factory('Topo2MapConfigService',
+ ['$log',
+ function (_$log_) {
+
+ $log = _$log_;
+
+ return {
+ projection: projection
+ };
+ }
+ ]
+ );
+})();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
index 3f781c4..d4917a3 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
@@ -22,7 +22,7 @@
(function () {
'use strict';
- var randomService, ps, sus, is, ts;
+ var randomService, ps, sus, is, ts, t2mcs;
var fn;
// Internal state;
@@ -55,8 +55,7 @@
}
function positionNode(node, forUpdate) {
-
- var meta = node.metaUi,
+ var meta = node.get('metaUi'),
x = meta && meta.x,
y = meta && meta.y,
dim = [800, 600],
@@ -64,7 +63,6 @@
// If the device contains explicit LONG/LAT data, use that to position
if (setLongLat(node)) {
- // Indicate we want to update cached meta data...
return true;
}
@@ -103,13 +101,16 @@
}
function getDevice(cp) {
- // console.log(cp);
- // var d = lu[cp.device];
- // return d || rand();
return rand();
}
xy = (node.class === 'host') ? near(getDevice(node.cp)) : rand();
+
+ if (node.class === 'sub-region') {
+ xy = rand();
+ node.x = node.px = xy.x;
+ node.y = node.py = xy.y;
+ }
angular.extend(node, xy);
}
@@ -118,7 +119,7 @@
coord;
if (loc && loc.type === 'lnglat') {
- coord = [0, 0];
+ coord = coordFromLngLat(loc);
node.fixed = true;
node.px = node.x = coord[0];
node.py = node.y = coord[1];
@@ -126,11 +127,16 @@
}
}
+ function coordFromLngLat(loc) {
+ var p = t2mcs.projection();
+ return p ? p.invert([loc.lng, loc.lat]) : [0, 0];
+ }
+
angular.module('ovTopo2')
.factory('Topo2NodeModel',
['Topo2Model', 'FnService', 'RandomService', 'Topo2PrefsService',
- 'SvgUtilService', 'IconService', 'ThemeService',
- function (Model, _fn_, _RandomService_, _ps_, _sus_, _is_, _ts_) {
+ 'SvgUtilService', 'IconService', 'ThemeService', 'Topo2MapConfigService',
+ function (Model, _fn_, _RandomService_, _ps_, _sus_, _is_, _ts_, _t2mcs_) {
randomService = _RandomService_;
ts = _ts_;
@@ -138,11 +144,18 @@
ps = _ps_;
sus = _sus_;
is = _is_;
+ t2mcs = _t2mcs_;
return Model.extend({
initialize: function () {
this.node = this.createNode();
},
+ createNode: function () {
+ this.set('class', this.nodeType);
+ this.set('svgClass', this.svgClassName());
+ positionNode(this);
+ return this;
+ },
setUpEvents: function () {
var _this = this;
angular.forEach(this.events, function (handler, key) {
@@ -221,6 +234,10 @@
}
);
},
+ lngLatFromCoord: function (coord) {
+ var p = t2mcs.projection();
+ return p ? p.invert(coord) : [0, 0];
+ },
update: function () {
this.updateLabel();
},
@@ -236,15 +253,6 @@
.transition()
.attr(this.labelBox(devIconDim, labelWidth));
},
- createNode: function () {
- var node = angular.extend({}, this.attributes);
-
- // Augment as needed...
- node.class = this.nodeType;
- node.svgClass = this.svgClassName();
- positionNode(node);
- return node;
- },
onEnter: function (el) {
this.el = d3.select(el);
this.render();
diff --git a/web/gui/src/main/webapp/index.html b/web/gui/src/main/webapp/index.html
index 5acc0ca..6ef80d3 100644
--- a/web/gui/src/main/webapp/index.html
+++ b/web/gui/src/main/webapp/index.html
@@ -141,6 +141,7 @@
<script src="app/view/topo2/topo2Link.js"></script>
<script src="app/view/topo2/topo2Map.js"></script>
<script src="app/view/topo2/topo2MapCountryFilters.js"></script>
+ <script src="app/view/topo2/topo2MapConfig.js"></script>
<script src="app/view/topo2/topo2MapDialog.js"></script>
<script src="app/view/topo2/topo2Model.js"></script>
<script src="app/view/topo2/topo2NodeModel.js"></script>