Simon Hunt

ONOS-1479 -- GUI - augmenting topology view for extensibility:

- Implemented server-side topo panel button descriptors, with overlay ability to remove core buttons and add custom buttons.

Change-Id: Id9ecc4c5e2d2db942232d2156ecf3bc858c0c61f
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + *
16 + */
17 +
18 +package org.onosproject.ui.topo;
19 +
20 +/**
21 + * Designates a descriptor for a button on the topology view panels.
22 + */
23 +public class ButtonDescriptor {
24 +
25 + private final String id;
26 + private final String glyphId;
27 + private final String tooltip;
28 +
29 + /**
30 + * Creates a button descriptor with the given identifier, glyph ID, and
31 + * tooltip text. To reference a custom glyph defined in the overlay itself,
32 + * prefix its ID with an asterisk, (e.g. {@code "*myGlyph"}). Alternatively,
33 + * use one of the {@link TopoConstants.Glyphs predefined constant}.
34 + *
35 + * @param id identifier for the button
36 + * @param glyphId identifier for the glyph
37 + * @param tooltip tooltip text
38 + */
39 + public ButtonDescriptor(String id, String glyphId, String tooltip) {
40 + this.id = id;
41 + this.glyphId = glyphId;
42 + this.tooltip = tooltip;
43 + }
44 +
45 + /**
46 + * Returns the identifier for this button.
47 + *
48 + * @return identifier
49 + */
50 + public String id() {
51 + return id;
52 + }
53 +
54 + /**
55 + * Returns the glyph identifier for this button.
56 + *
57 + * @return glyph identifier
58 + */
59 + public String glyphId() {
60 + return glyphId;
61 + }
62 +
63 + /**
64 + * Returns the tooltip text for this button.
65 + *
66 + * @return tooltip text
67 + */
68 + public String tooltip() {
69 + return tooltip;
70 + }
71 +
72 + @Override
73 + public boolean equals(Object o) {
74 + if (this == o) {
75 + return true;
76 + }
77 + if (o == null || getClass() != o.getClass()) {
78 + return false;
79 + }
80 +
81 + ButtonDescriptor that = (ButtonDescriptor) o;
82 + return id.equals(that.id);
83 +
84 + }
85 +
86 + @Override
87 + public int hashCode() {
88 + return id.hashCode();
89 + }
90 +}
...@@ -35,7 +35,7 @@ public class PropertyPanel { ...@@ -35,7 +35,7 @@ public class PropertyPanel {
35 private String typeId; 35 private String typeId;
36 private String id; 36 private String id;
37 private List<Prop> properties = new ArrayList<>(); 37 private List<Prop> properties = new ArrayList<>();
38 - private List<Button> buttons = new ArrayList<>(); 38 + private List<ButtonDescriptor> buttons = new ArrayList<>();
39 39
40 /** 40 /**
41 * Constructs a property panel model with the given title and 41 * Constructs a property panel model with the given title and
...@@ -181,7 +181,7 @@ public class PropertyPanel { ...@@ -181,7 +181,7 @@ public class PropertyPanel {
181 * @return the button list 181 * @return the button list
182 */ 182 */
183 // TODO: consider protecting this? 183 // TODO: consider protecting this?
184 - public List<Button> buttons() { 184 + public List<ButtonDescriptor> buttons() {
185 return buttons; 185 return buttons;
186 } 186 }
187 187
...@@ -216,14 +216,14 @@ public class PropertyPanel { ...@@ -216,14 +216,14 @@ public class PropertyPanel {
216 * @return self, for chaining 216 * @return self, for chaining
217 */ 217 */
218 public PropertyPanel removeProps(String... keys) { 218 public PropertyPanel removeProps(String... keys) {
219 - Set<String> keysForRemoval = Sets.newHashSet(keys); 219 + Set<String> forRemoval = Sets.newHashSet(keys);
220 - List<Prop> propsToKeep = new ArrayList<>(); 220 + List<Prop> toKeep = new ArrayList<>();
221 for (Prop p: properties) { 221 for (Prop p: properties) {
222 - if (!keysForRemoval.contains(p.key())) { 222 + if (!forRemoval.contains(p.key())) {
223 - propsToKeep.add(p); 223 + toKeep.add(p);
224 } 224 }
225 } 225 }
226 - properties = propsToKeep; 226 + properties = toKeep;
227 return this; 227 return this;
228 } 228 }
229 229
...@@ -238,13 +238,41 @@ public class PropertyPanel { ...@@ -238,13 +238,41 @@ public class PropertyPanel {
238 } 238 }
239 239
240 /** 240 /**
241 - * Adds a button descriptor with the given identifier, to the panel data. 241 + * Adds the given button descriptor to the panel data.
242 * 242 *
243 - * @param id button identifier 243 + * @param button button descriptor
244 * @return self, for chaining 244 * @return self, for chaining
245 */ 245 */
246 - public PropertyPanel addButton(String id) { 246 + public PropertyPanel addButton(ButtonDescriptor button) {
247 - buttons.add(new Button(id)); 247 + buttons.add(button);
248 + return this;
249 + }
250 +
251 + /**
252 + * Removes buttons with the given descriptors from the list.
253 + *
254 + * @param descriptors descriptors to remove
255 + * @return self, for chaining
256 + */
257 + public PropertyPanel removeButtons(ButtonDescriptor... descriptors) {
258 + Set<ButtonDescriptor> forRemoval = Sets.newHashSet(descriptors);
259 + List<ButtonDescriptor> toKeep = new ArrayList<>();
260 + for (ButtonDescriptor bd: buttons) {
261 + if (!forRemoval.contains(bd)) {
262 + toKeep.add(bd);
263 + }
264 + }
265 + buttons = toKeep;
266 + return this;
267 + }
268 +
269 + /**
270 + * Removes all currently defined buttons.
271 + *
272 + * @return self, for chaining
273 + */
274 + public PropertyPanel removeAllButtons() {
275 + buttons.clear();
248 return this; 276 return this;
249 } 277 }
250 278
...@@ -322,29 +350,4 @@ public class PropertyPanel { ...@@ -322,29 +350,4 @@ public class PropertyPanel {
322 } 350 }
323 } 351 }
324 352
325 - /**
326 - * Button descriptor. Note that these work in conjunction with
327 - * "buttons" defined in the JavaScript code for the overlay.
328 - */
329 - public static class Button {
330 - private final String id;
331 -
332 - /**
333 - * Constructs a button descriptor with the given identifier.
334 - *
335 - * @param id button identifier
336 - */
337 - public Button(String id) {
338 - this.id = id;
339 - }
340 -
341 - /**
342 - * Returns the identifier for this button.
343 - *
344 - * @return button identifier
345 - */
346 - public String id() {
347 - return id;
348 - }
349 - }
350 } 353 }
......
...@@ -79,6 +79,8 @@ public final class TopoConstants { ...@@ -79,6 +79,8 @@ public final class TopoConstants {
79 * details panels. 79 * details panels.
80 */ 80 */
81 public static final class Properties { 81 public static final class Properties {
82 + public static final String SEPARATOR = "-";
83 +
82 // summary panel 84 // summary panel
83 public static final String DEVICES = "Devices"; 85 public static final String DEVICES = "Devices";
84 public static final String LINKS = "Links"; 86 public static final String LINKS = "Links";
...@@ -106,4 +108,30 @@ public final class TopoConstants { ...@@ -106,4 +108,30 @@ public final class TopoConstants {
106 public static final String VLAN = "VLAN"; 108 public static final String VLAN = "VLAN";
107 } 109 }
108 110
111 + private static final class CoreButton extends ButtonDescriptor {
112 + private CoreButton(String tag, String glyphId, boolean extra) {
113 + super("show" + tag + "View",
114 + glyphId,
115 + "Show " + tag + " View" + (extra ? " for this Device" : ""));
116 + }
117 + }
118 +
119 + /**
120 + * Defines constants for core buttons that appear on the topology
121 + * details panel.
122 + */
123 + public static final class CoreButtons {
124 + public static final ButtonDescriptor SHOW_DEVICE_VIEW =
125 + new CoreButton("Device", Glyphs.SWITCH, false);
126 +
127 + public static final ButtonDescriptor SHOW_FLOW_VIEW =
128 + new CoreButton("Flow", Glyphs.FLOW_TABLE, true);
129 +
130 + public static final ButtonDescriptor SHOW_PORT_VIEW =
131 + new CoreButton("Port", Glyphs.PORT_TABLE, true);
132 +
133 + public static final ButtonDescriptor SHOW_GROUP_VIEW =
134 + new CoreButton("Group", Glyphs.GROUP_TABLE, true);
135 + }
136 +
109 } 137 }
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + *
16 + */
17 +
18 +package org.onosproject.ui.topo;
19 +
20 +import org.junit.Test;
21 +
22 +import static org.junit.Assert.assertEquals;
23 +
24 +/**
25 + * Unit tests for {@link ButtonDescriptor}.
26 + */
27 +public class ButtonDescriptorTest {
28 +
29 + private static final String ID = "my-id";
30 + private static final String GID = "my-glyphId";
31 + private static final String TT = "my-tewltyp";
32 +
33 + private ButtonDescriptor bd;
34 +
35 +
36 + @Test
37 + public void basic() {
38 + bd = new ButtonDescriptor(ID, GID, TT);
39 +
40 + assertEquals("bad id", ID, bd.id());
41 + assertEquals("bad gid", GID, bd.glyphId());
42 + assertEquals("bad tt", TT, bd.tooltip());
43 + }
44 +
45 +}
...@@ -25,9 +25,7 @@ import java.util.HashMap; ...@@ -25,9 +25,7 @@ import java.util.HashMap;
25 import java.util.Iterator; 25 import java.util.Iterator;
26 import java.util.Map; 26 import java.util.Map;
27 27
28 -import static org.junit.Assert.assertEquals; 28 +import static org.junit.Assert.*;
29 -import static org.junit.Assert.assertNull;
30 -import static org.junit.Assert.fail;
31 29
32 /** 30 /**
33 * Unit tests for {@link PropertyPanel}. 31 * Unit tests for {@link PropertyPanel}.
...@@ -43,11 +41,20 @@ public class PropertyPanelTest { ...@@ -43,11 +41,20 @@ public class PropertyPanelTest {
43 private static final String KEY_A = "A"; 41 private static final String KEY_A = "A";
44 private static final String KEY_B = "B"; 42 private static final String KEY_B = "B";
45 private static final String KEY_C = "C"; 43 private static final String KEY_C = "C";
44 + private static final String SEP = "-";
46 private static final String KEY_Z = "Z"; 45 private static final String KEY_Z = "Z";
47 private static final String VALUE_A = "Hay"; 46 private static final String VALUE_A = "Hay";
48 private static final String VALUE_B = "Bee"; 47 private static final String VALUE_B = "Bee";
49 private static final String VALUE_C = "Sea"; 48 private static final String VALUE_C = "Sea";
50 private static final String VALUE_Z = "Zed"; 49 private static final String VALUE_Z = "Zed";
50 + private static final String GID_A = "gid-A";
51 + private static final String GID_B = "gid-B";
52 + private static final String GID_C = "gid-C";
53 + private static final String GID_Z = "gid-Z";
54 + private static final String TT_A = "toolTip-A";
55 + private static final String TT_B = "toolTip-B";
56 + private static final String TT_C = "toolTip-C";
57 + private static final String TT_Z = "toolTip-Z";
51 58
52 private static final Map<String, Prop> PROP_MAP = new HashMap<>(); 59 private static final Map<String, Prop> PROP_MAP = new HashMap<>();
53 60
...@@ -73,6 +80,7 @@ public class PropertyPanelTest { ...@@ -73,6 +80,7 @@ public class PropertyPanelTest {
73 PROP_MAP.put(KEY_B, new Prop(KEY_B, VALUE_B)); 80 PROP_MAP.put(KEY_B, new Prop(KEY_B, VALUE_B));
74 PROP_MAP.put(KEY_C, new Prop(KEY_C, VALUE_C)); 81 PROP_MAP.put(KEY_C, new Prop(KEY_C, VALUE_C));
75 PROP_MAP.put(KEY_Z, new Prop(KEY_Z, VALUE_Z)); 82 PROP_MAP.put(KEY_Z, new Prop(KEY_Z, VALUE_Z));
83 + PROP_MAP.put(SEP, new PropertyPanel.Separator());
76 } 84 }
77 85
78 @Test 86 @Test
...@@ -82,6 +90,7 @@ public class PropertyPanelTest { ...@@ -82,6 +90,7 @@ public class PropertyPanelTest {
82 assertEquals("wrong type", TYPE_ORIG, pp.typeId()); 90 assertEquals("wrong type", TYPE_ORIG, pp.typeId());
83 assertNull("id?", pp.id()); 91 assertNull("id?", pp.id());
84 assertEquals("unexpected props", 0, pp.properties().size()); 92 assertEquals("unexpected props", 0, pp.properties().size());
93 + assertEquals("unexpected buttons", 0, pp.buttons().size());
85 } 94 }
86 95
87 @Test 96 @Test
...@@ -141,6 +150,16 @@ public class PropertyPanelTest { ...@@ -141,6 +150,16 @@ public class PropertyPanelTest {
141 } 150 }
142 151
143 @Test 152 @Test
153 + public void separator() {
154 + props();
155 + pp.addSeparator()
156 + .addProp(KEY_Z, VALUE_Z);
157 +
158 + assertEquals("bad props", 5, pp.properties().size());
159 + validateProps(KEY_A, KEY_B, KEY_C, SEP, KEY_Z);
160 + }
161 +
162 + @Test
144 public void removeAllProps() { 163 public void removeAllProps() {
145 props(); 164 props();
146 assertEquals("wrong props", 3, pp.properties().size()); 165 assertEquals("wrong props", 3, pp.properties().size());
...@@ -192,4 +211,40 @@ public class PropertyPanelTest { ...@@ -192,4 +211,40 @@ public class PropertyPanelTest {
192 validateProp(KEY_B, ">byyy<"); 211 validateProp(KEY_B, ">byyy<");
193 } 212 }
194 213
214 + private static final ButtonDescriptor BD_A =
215 + new ButtonDescriptor(KEY_A, GID_A, TT_A);
216 + private static final ButtonDescriptor BD_B =
217 + new ButtonDescriptor(KEY_B, GID_B, TT_B);
218 + private static final ButtonDescriptor BD_C =
219 + new ButtonDescriptor(KEY_C, GID_C, TT_C);
220 + private static final ButtonDescriptor BD_Z =
221 + new ButtonDescriptor(KEY_Z, GID_Z, TT_Z);
222 +
223 + private void verifyButtons(String... keys) {
224 + Iterator<ButtonDescriptor> iter = pp.buttons().iterator();
225 + for (String k: keys) {
226 + assertEquals("wrong button", k, iter.next().id());
227 + }
228 + assertFalse("too many buttons", iter.hasNext());
229 + }
230 +
231 + @Test
232 + public void buttons() {
233 + basic();
234 + pp.addButton(BD_A)
235 + .addButton(BD_B);
236 + assertEquals("wrong buttons", 2, pp.buttons().size());
237 + verifyButtons(KEY_A, KEY_B);
238 +
239 + pp.removeButtons(BD_B)
240 + .addButton(BD_C)
241 + .addButton(BD_Z);
242 + assertEquals("wrong buttons", 3, pp.buttons().size());
243 + verifyButtons(KEY_A, KEY_C, KEY_Z);
244 +
245 + pp.removeAllButtons()
246 + .addButton(BD_B);
247 + assertEquals("wrong buttons", 1, pp.buttons().size());
248 + verifyButtons(KEY_B);
249 + }
195 } 250 }
......
...@@ -72,6 +72,7 @@ import org.onosproject.net.topology.TopologyService; ...@@ -72,6 +72,7 @@ import org.onosproject.net.topology.TopologyService;
72 import org.onosproject.ui.JsonUtils; 72 import org.onosproject.ui.JsonUtils;
73 import org.onosproject.ui.UiConnection; 73 import org.onosproject.ui.UiConnection;
74 import org.onosproject.ui.UiMessageHandler; 74 import org.onosproject.ui.UiMessageHandler;
75 +import org.onosproject.ui.topo.ButtonDescriptor;
75 import org.onosproject.ui.topo.PropertyPanel; 76 import org.onosproject.ui.topo.PropertyPanel;
76 import org.slf4j.Logger; 77 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory; 78 import org.slf4j.LoggerFactory;
...@@ -107,7 +108,8 @@ import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED; ...@@ -107,7 +108,8 @@ import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
107 import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED; 108 import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
108 import static org.onosproject.ui.impl.TopologyViewMessageHandlerBase.StatsType.FLOW; 109 import static org.onosproject.ui.impl.TopologyViewMessageHandlerBase.StatsType.FLOW;
109 import static org.onosproject.ui.impl.TopologyViewMessageHandlerBase.StatsType.PORT; 110 import static org.onosproject.ui.impl.TopologyViewMessageHandlerBase.StatsType.PORT;
110 -import static org.onosproject.ui.topo.TopoConstants.*; 111 +import static org.onosproject.ui.topo.TopoConstants.CoreButtons;
112 +import static org.onosproject.ui.topo.TopoConstants.Properties;
111 113
112 /** 114 /**
113 * Facility for creating messages bound for the topology viewer. 115 * Facility for creating messages bound for the topology viewer.
...@@ -474,6 +476,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -474,6 +476,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
474 476
475 PropertyPanel pp = new PropertyPanel(title, typeId) 477 PropertyPanel pp = new PropertyPanel(title, typeId)
476 .id(deviceId.toString()) 478 .id(deviceId.toString())
479 +
477 .addProp(Properties.URI, deviceId.toString()) 480 .addProp(Properties.URI, deviceId.toString())
478 .addProp(Properties.VENDOR, device.manufacturer()) 481 .addProp(Properties.VENDOR, device.manufacturer())
479 .addProp(Properties.HW_VERSION, device.hwVersion()) 482 .addProp(Properties.HW_VERSION, device.hwVersion())
...@@ -481,14 +484,19 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -481,14 +484,19 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
481 .addProp(Properties.SERIAL_NUMBER, device.serialNumber()) 484 .addProp(Properties.SERIAL_NUMBER, device.serialNumber())
482 .addProp(Properties.PROTOCOL, annot.value(AnnotationKeys.PROTOCOL)) 485 .addProp(Properties.PROTOCOL, annot.value(AnnotationKeys.PROTOCOL))
483 .addSeparator() 486 .addSeparator()
487 +
484 .addProp(Properties.LATITUDE, annot.value(AnnotationKeys.LATITUDE)) 488 .addProp(Properties.LATITUDE, annot.value(AnnotationKeys.LATITUDE))
485 .addProp(Properties.LONGITUDE, annot.value(AnnotationKeys.LONGITUDE)) 489 .addProp(Properties.LONGITUDE, annot.value(AnnotationKeys.LONGITUDE))
486 .addSeparator() 490 .addSeparator()
491 +
487 .addProp(Properties.PORTS, portCount) 492 .addProp(Properties.PORTS, portCount)
488 .addProp(Properties.FLOWS, flowCount) 493 .addProp(Properties.FLOWS, flowCount)
489 - .addProp(Properties.TUNNELS, tunnelCount); 494 + .addProp(Properties.TUNNELS, tunnelCount)
490 495
491 - // TODO: add button descriptors 496 + .addButton(CoreButtons.SHOW_DEVICE_VIEW)
497 + .addButton(CoreButtons.SHOW_FLOW_VIEW)
498 + .addButton(CoreButtons.SHOW_PORT_VIEW)
499 + .addButton(CoreButtons.SHOW_GROUP_VIEW);
492 500
493 return pp; 501 return pp;
494 } 502 }
...@@ -862,13 +870,22 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -862,13 +870,22 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
862 result.set("props", pnode); 870 result.set("props", pnode);
863 871
864 ArrayNode buttons = arrayNode(); 872 ArrayNode buttons = arrayNode();
865 - for (PropertyPanel.Button b : pp.buttons()) { 873 + for (ButtonDescriptor b : pp.buttons()) {
866 - buttons.add(b.id()); 874 + buttons.add(json(b));
867 } 875 }
868 result.set("buttons", buttons); 876 result.set("buttons", buttons);
869 return result; 877 return result;
870 } 878 }
871 879
880 + // translates the button descriptor into JSON
881 + private ObjectNode json(ButtonDescriptor bdesc) {
882 + return objectNode()
883 + .put("id", bdesc.id())
884 + .put("gid", bdesc.glyphId())
885 + .put("tt", bdesc.tooltip());
886 + }
887 +
888 +
872 // Produces canonical link key, i.e. one that will match link and its inverse. 889 // Produces canonical link key, i.e. one that will match link and its inverse.
873 static LinkKey canonicalLinkKey(Link link) { 890 static LinkKey canonicalLinkKey(Link link) {
874 String sn = link.src().elementId().toString(); 891 String sn = link.src().elementId().toString();
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
30 var tos = 'TopoOverlayService: '; 30 var tos = 'TopoOverlayService: ';
31 31
32 // injected refs 32 // injected refs
33 - var $log, fs, gs, wss; 33 + var $log, fs, gs, wss, ns;
34 34
35 // internal state 35 // internal state
36 var overlays = {}, 36 var overlays = {},
...@@ -142,37 +142,53 @@ ...@@ -142,37 +142,53 @@
142 } 142 }
143 } 143 }
144 144
145 - // install buttons from the current overlay 145 + var coreButtonPath = {
146 - function installButtons(bids, addFn, data) { 146 + showDeviceView: 'device',
147 - if (current) { 147 + showFlowView: 'flow',
148 - bids.forEach(function (bid) { 148 + showPortView: 'port',
149 - var btn = current.buttons[bid], 149 + showGroupView: 'group'
150 - funcWrap = function () { 150 + };
151 - btn.cb(data); 151 +
152 - }; 152 + // install core buttons, and include any additional from the current overlay
153 - 153 + function installButtons(buttons, addFn, data, devId) {
154 - if (btn) { 154 +
155 - addFn({ 155 + angular.forEach(buttons, function (btn) {
156 - id: current.mkId(bid), 156 + var path = coreButtonPath[btn.id],
157 - gid: current.mkGid(btn.gid), 157 + _id,
158 - cb: funcWrap, 158 + _gid,
159 - tt: btn.tt 159 + _cb,
160 - }); 160 + action;
161 - } 161 +
162 - }); 162 + if (path) {
163 - } 163 + // core callback function
164 + _id = btn.id;
165 + _gid = btn.gid;
166 + action = function () {
167 + ns.navTo(path, { devId: devId });
168 + };
169 + } else if (current) {
170 + _id = current.mkId(btn.id);
171 + _gid = current.mkGid(btn.gid);
172 + action = current.buttonActions[btn.id] || function () {};
173 + }
174 +
175 + _cb = function () { action(data); };
176 +
177 + addFn({ id: _id, gid: _gid, cb: _cb, tt: btn.tt});
178 + });
164 179
165 } 180 }
166 181
167 angular.module('ovTopo') 182 angular.module('ovTopo')
168 .factory('TopoOverlayService', 183 .factory('TopoOverlayService',
169 - ['$log', 'FnService', 'GlyphService', 'WebSocketService', 184 + ['$log', 'FnService', 'GlyphService', 'WebSocketService', 'NavService',
170 185
171 - function (_$log_, _fs_, _gs_, _wss_) { 186 + function (_$log_, _fs_, _gs_, _wss_, _ns_) {
172 $log = _$log_; 187 $log = _$log_;
173 fs = _fs_; 188 fs = _fs_;
174 gs = _gs_; 189 gs = _gs_;
175 wss = _wss_; 190 wss = _wss_;
191 + ns = _ns_;
176 192
177 return { 193 return {
178 register: register, 194 register: register,
......
...@@ -272,7 +272,7 @@ ...@@ -272,7 +272,7 @@
272 .select('.actionBtns') 272 .select('.actionBtns')
273 .append('div') 273 .append('div')
274 .classed('actionBtn', true); 274 .classed('actionBtn', true);
275 - bns.button(btnDiv, idDet + o.id, o.gid, o.cb, o.tt); 275 + bns.button(btnDiv, idDet + '-' + o.id, o.gid, o.cb, o.tt);
276 } 276 }
277 277
278 var friendlyIndex = { 278 var friendlyIndex = {
......
...@@ -229,13 +229,14 @@ ...@@ -229,13 +229,14 @@
229 // Event Handlers 229 // Event Handlers
230 230
231 function showDetails(data) { 231 function showDetails(data) {
232 - var buttons = fs.isA(data.buttons); 232 + var buttons = fs.isA(data.buttons) || [];
233 233
234 // display the data for the single selected node 234 // display the data for the single selected node
235 tps.displaySingle(data); 235 tps.displaySingle(data);
236 236
237 - // TODO: use server-side-button-descriptors to add buttons 237 + tov.installButtons(buttons, tps.addAction, data, data.props['URI']);
238 238
239 + // TODO: MOVE traffic buttons to the traffic overlay
239 // always add the 'show traffic' action 240 // always add the 'show traffic' action
240 tps.addAction({ 241 tps.addAction({
241 id: '-sin-rel-traf-btn', 242 id: '-sin-rel-traf-btn',
...@@ -254,49 +255,6 @@ ...@@ -254,49 +255,6 @@
254 }); 255 });
255 } 256 }
256 257
257 - // TODO: for now, install overlay buttons here
258 - if (buttons) {
259 - tov.installButtons(buttons, tps.addAction, data);
260 - }
261 -
262 -
263 - // TODO: have the server return explicit class and ID of each node
264 - // for now, we assume the node is a device if it has a URI
265 - if ((data.props).hasOwnProperty('URI')) {
266 - tps.addAction({
267 - id: 'device-table-btn',
268 - gid: data.type,
269 - cb: function () {
270 - ns.navTo(devPath, { devId: data.props['URI'] });
271 - },
272 - tt: 'Show device view'
273 - });
274 - tps.addAction({
275 - id: 'flows-table-btn',
276 - gid: 'flowTable',
277 - cb: function () {
278 - ns.navTo(flowPath, { devId: data.props['URI'] });
279 - },
280 - tt: 'Show flow view for this device'
281 - });
282 - tps.addAction({
283 - id: 'ports-table-btn',
284 - gid: 'portTable',
285 - cb: function () {
286 - ns.navTo(portPath, { devId: data.props['URI'] });
287 - },
288 - tt: 'Show port view for this device'
289 - });
290 - tps.addAction({
291 - id: 'groups-table-btn',
292 - gid: 'groupTable',
293 - cb: function () {
294 - ns.navTo(groupPath, { devId: data.props['URI'] });
295 - },
296 - tt: 'Show group view for this device'
297 - });
298 - }
299 -
300 tps.displaySomething(); 258 tps.displaySomething();
301 } 259 }
302 260
......