GUI -- Migrating the add/update device functionality to the Topology View. (WIP)
- still a lot of work to do.
Change-Id: I0453b7e2ec20a8a8149fd9d6440a13a3d43fbfd6
diff --git a/web/gui/src/main/webapp/app/fw/svg/icon.css b/web/gui/src/main/webapp/app/fw/svg/icon.css
index 20d8440..ff1bb5a 100644
--- a/web/gui/src/main/webapp/app/fw/svg/icon.css
+++ b/web/gui/src/main/webapp/app/fw/svg/icon.css
@@ -70,3 +70,7 @@
.dark svg.embeddedIcon .icon rect {
stroke: #ccc;
}
+
+svg .svgIcon {
+ fill-rule: evenodd;
+}
diff --git a/web/gui/src/main/webapp/app/fw/svg/icon.js b/web/gui/src/main/webapp/app/fw/svg/icon.js
index d8c2584..21f9b9d 100644
--- a/web/gui/src/main/webapp/app/fw/svg/icon.js
+++ b/web/gui/src/main/webapp/app/fw/svg/icon.js
@@ -26,15 +26,17 @@
cornerSize = vboxSize / 10,
viewBox = '0 0 ' + vboxSize + ' ' + vboxSize;
- // maps icon id to the glyph id it uses.
- // note: icon id maps to a CSS class for styling that icon
+ // Maps icon ID to the glyph ID it uses.
+ // NOTE: icon ID maps to a CSS class for styling that icon
var glyphMapping = {
- deviceOnline: 'checkMark',
- deviceOffline: 'xMark',
- tableColSortAsc: 'triangleUp',
- tableColSortDesc: 'triangleDown',
- tableColSortNone: '-'
- };
+ deviceOnline: 'checkMark',
+ deviceOffline: 'xMark',
+ tableColSortAsc: 'triangleUp',
+ tableColSortDesc: 'triangleDown',
+ tableColSortNone: '-'
+ };
+
+
function ensureIconLibDefs() {
var body = d3.select('body'),
@@ -48,6 +50,108 @@
return svg.select('defs');
}
+ // div is a D3 selection of the <DIV> element into which icon should load
+ // iconCls is the CSS class used to identify the icon
+ // size is dimension of icon in pixels. Defaults to 20.
+ // installGlyph, if truthy, will cause the glyph to be added to
+ // well-known defs element. Defaults to false.
+ // svgClass is the CSS class used to identify the SVG layer.
+ // Defaults to 'embeddedIcon'.
+ function loadIcon(div, iconCls, size, installGlyph, svgClass) {
+ var dim = size || 20,
+ svgCls = svgClass || 'embeddedIcon',
+ gid = glyphMapping[iconCls] || 'unknown',
+ svg, g;
+
+ if (installGlyph) {
+ gs.loadDefs(ensureIconLibDefs(), [gid], true);
+ }
+
+ svg = div.append('svg').attr({
+ 'class': svgCls,
+ width: dim,
+ height: dim,
+ viewBox: viewBox
+ });
+
+ g = svg.append('g').attr({
+ 'class': 'icon ' + iconCls
+ });
+
+ g.append('rect').attr({
+ width: vboxSize,
+ height: vboxSize,
+ rx: cornerSize
+ });
+
+ if (gid !== '-') {
+ g.append('use').attr({
+ width: vboxSize,
+ height: vboxSize,
+ 'class': 'glyph',
+ 'xlink:href': '#' + gid
+ });
+ }
+ }
+
+ function loadEmbeddedIcon(div, iconCls, size) {
+ loadIcon(div, iconCls, size, true);
+ }
+
+
+ // configuration for device and host icons in the topology view
+ var config = {
+ device: {
+ dim: 36,
+ rx: 4
+ },
+ host: {
+ radius: {
+ noGlyph: 9,
+ withGlyph: 14
+ },
+ glyphed: {
+ endstation: 1,
+ bgpSpeaker: 1,
+ router: 1
+ }
+ }
+ };
+
+
+ // Adds a device icon to the specified element, using the given glyph.
+ // Returns the D3 selection of the icon.
+ function addDeviceIcon(elem, glyphId) {
+ var cfg = config.device,
+ g = elem.append('g')
+ .attr('class', 'svgIcon deviceIcon');
+
+ g.append('rect').attr({
+ x: 0,
+ y: 0,
+ rx: cfg.rx,
+ width: cfg.dim,
+ height: cfg.dim
+ });
+
+ g.append('use').attr({
+ 'xlink:href': '#' + glyphId,
+ width: cfg.dim,
+ height: cfg.dim
+ });
+
+ g.dim = cfg.dim;
+ return g;
+ }
+
+ function addHostIcon(elem, glyphId) {
+ // TODO:
+ }
+
+
+ // =========================
+ // === DEFINE THE MODULE
+
angular.module('onosSvg')
.factory('IconService', ['$log', 'FnService', 'GlyphService',
function (_$log_, _fs_, _gs_) {
@@ -55,57 +159,12 @@
fs = _fs_;
gs = _gs_;
- // div is a D3 selection of the <DIV> element into which icon should load
- // iconCls is the CSS class used to identify the icon
- // size is dimension of icon in pixels. Defaults to 20.
- // installGlyph, if truthy, will cause the glyph to be added to
- // well-known defs element. Defaults to false.
- // svgClass is the CSS class used to identify the SVG layer.
- // Defaults to 'embeddedIcon'.
- function loadIcon(div, iconCls, size, installGlyph, svgClass) {
- var dim = size || 20,
- svgCls = svgClass || 'embeddedIcon',
- gid = glyphMapping[iconCls] || 'unknown',
- svg, g;
-
- if (installGlyph) {
- gs.loadDefs(ensureIconLibDefs(), [gid], true);
- }
-
- svg = div.append('svg').attr({
- 'class': svgCls,
- width: dim,
- height: dim,
- viewBox: viewBox
- });
-
- g = svg.append('g').attr({
- 'class': 'icon ' + iconCls
- });
-
- g.append('rect').attr({
- width: vboxSize,
- height: vboxSize,
- rx: cornerSize
- });
-
- if (gid !== '-') {
- g.append('use').attr({
- width: vboxSize,
- height: vboxSize,
- 'class': 'glyph',
- 'xlink:href': '#' + gid
- });
- }
- }
-
- function loadEmbeddedIcon(div, iconCls, size) {
- loadIcon(div, iconCls, size, true);
- }
-
return {
loadIcon: loadIcon,
- loadEmbeddedIcon: loadEmbeddedIcon
+ loadEmbeddedIcon: loadEmbeddedIcon,
+ addDeviceIcon: addDeviceIcon,
+ addHostIcon: addHostIcon,
+ iconConfig: function () { return config; }
};
}]);
diff --git a/web/gui/src/main/webapp/app/fw/svg/map.js b/web/gui/src/main/webapp/app/fw/svg/map.js
index f44ffe0..1faf6e2 100644
--- a/web/gui/src/main/webapp/app/fw/svg/map.js
+++ b/web/gui/src/main/webapp/app/fw/svg/map.js
@@ -22,45 +22,53 @@
The Map Service provides a simple API for loading geographical maps into
an SVG layer. For example, as a background to the Topology View.
- e.g. var ok = MapService.loadMapInto(svgLayer, '*continental-us');
+ e.g. var promise = MapService.loadMapInto(svgLayer, '*continental-us');
The Map Service makes use of the GeoDataService to load the required data
from the server and to create the appropriate geographical projection.
+ A promise is returned to the caller, which is resolved with the
+ map projection once created.
*/
(function () {
'use strict';
// injected references
- var $log, fs, gds;
+ var $log, $q, fs, gds;
+
+ function loadMapInto(mapLayer, id, opts) {
+ var promise = gds.fetchTopoData(id),
+ deferredProjection = $q.defer();
+
+ if (!promise) {
+ $log.warn('Failed to load map: ' + id);
+ return false;
+ }
+
+ promise.then(function () {
+ var gen = gds.createPathGenerator(promise.topodata, opts);
+
+ deferredProjection.resolve(gen.settings.projection);
+
+ mapLayer.selectAll('path')
+ .data(gen.geodata.features)
+ .enter()
+ .append('path')
+ .attr('d', gen.pathgen);
+ });
+ return deferredProjection.promise;
+ }
+
angular.module('onosSvg')
- .factory('MapService', ['$log', 'FnService', 'GeoDataService',
- function (_$log_, _fs_, _gds_) {
+ .factory('MapService', ['$log', '$q', 'FnService', 'GeoDataService',
+ function (_$log_, _$q_, _fs_, _gds_) {
$log = _$log_;
+ $q = _$q_;
fs = _fs_;
gds = _gds_;
- function loadMapInto(mapLayer, id, opts) {
- var promise = gds.fetchTopoData(id);
- if (!promise) {
- $log.warn('Failed to load map: ' + id);
- return false;
- }
-
- promise.then(function () {
- var gen = gds.createPathGenerator(promise.topodata, opts);
-
- mapLayer.selectAll('path')
- .data(gen.geodata.features)
- .enter()
- .append('path')
- .attr('d', gen.pathgen);
- });
- return true;
- }
-
return {
loadMapInto: loadMapInto
};
diff --git a/web/gui/src/main/webapp/app/fw/svg/svgUtil.js b/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
index bef8248..3a35e9f 100644
--- a/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
+++ b/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
@@ -240,13 +240,18 @@
el.style('visibility', (b ? 'visible' : 'hidden'));
}
+ function safeId(s) {
+ return s.replace(/[^a-z0-9]/gi, '-');
+ }
+
return {
createDragBehavior: createDragBehavior,
loadGlow: loadGlow,
cat7: cat7,
translate: translate,
stripPx: stripPx,
- makeVisible: makeVisible
+ makeVisible: makeVisible,
+ safeId: safeId
};
}]);
}());