Committed by
Gerrit Code Review
GUI -- WIP Device View details panel. Egress Links backend added, updated FnServ…
…ice, added CSS for panel, populates panel with properties and a close button. Change-Id: Ia510b1e47fecc9140adcb1596c365a4114784b88
Showing
7 changed files
with
384 additions
and
46 deletions
| ... | @@ -15,12 +15,15 @@ | ... | @@ -15,12 +15,15 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.ui.impl; | 16 | package org.onosproject.ui.impl; |
| 17 | 17 | ||
| 18 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 18 | import com.fasterxml.jackson.databind.node.ArrayNode; | 19 | import com.fasterxml.jackson.databind.node.ArrayNode; |
| 19 | import com.fasterxml.jackson.databind.node.ObjectNode; | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 20 | import com.google.common.collect.ImmutableSet; | 21 | import com.google.common.collect.ImmutableSet; |
| 21 | import org.onosproject.mastership.MastershipService; | 22 | import org.onosproject.mastership.MastershipService; |
| 23 | +import org.onosproject.net.ConnectPoint; | ||
| 22 | import org.onosproject.net.Device; | 24 | import org.onosproject.net.Device; |
| 23 | import org.onosproject.net.DeviceId; | 25 | import org.onosproject.net.DeviceId; |
| 26 | +import org.onosproject.net.Link; | ||
| 24 | import org.onosproject.net.Port; | 27 | import org.onosproject.net.Port; |
| 25 | import org.onosproject.net.device.DeviceService; | 28 | import org.onosproject.net.device.DeviceService; |
| 26 | import org.onosproject.net.link.LinkService; | 29 | import org.onosproject.net.link.LinkService; |
| ... | @@ -28,31 +31,61 @@ import org.onosproject.net.link.LinkService; | ... | @@ -28,31 +31,61 @@ import org.onosproject.net.link.LinkService; |
| 28 | import java.util.ArrayList; | 31 | import java.util.ArrayList; |
| 29 | import java.util.Arrays; | 32 | import java.util.Arrays; |
| 30 | import java.util.List; | 33 | import java.util.List; |
| 31 | - | 34 | +import java.util.Set; |
| 32 | -//import org.onosproject.net.Link; | ||
| 33 | -//import java.util.Set; | ||
| 34 | 35 | ||
| 35 | /** | 36 | /** |
| 36 | * Message handler for device view related messages. | 37 | * Message handler for device view related messages. |
| 37 | */ | 38 | */ |
| 38 | public class DeviceViewMessageHandler extends AbstractTabularViewMessageHandler { | 39 | public class DeviceViewMessageHandler extends AbstractTabularViewMessageHandler { |
| 39 | 40 | ||
| 41 | + private static final String ID = "id"; | ||
| 42 | + private static final String TYPE = "type"; | ||
| 43 | + private static final String AVAILABLE = "available"; | ||
| 44 | + private static final String AVAILABLE_IID = "_iconid_available"; | ||
| 45 | + private static final String TYPE_IID = "_iconid_type"; | ||
| 46 | + private static final String DEV_ICON_PREFIX = "devIcon_"; | ||
| 47 | + private static final String NUM_PORTS = "num_ports"; | ||
| 48 | + private static final String LINK_DEST = "elinks_dest"; | ||
| 49 | + private static final String MFR = "mfr"; | ||
| 50 | + private static final String HW = "hw"; | ||
| 51 | + private static final String SW = "sw"; | ||
| 52 | + private static final String PROTOCOL = "protocol"; | ||
| 53 | + private static final String MASTER_ID = "masterid"; | ||
| 54 | + private static final String CHASSIS_ID = "chassisid"; | ||
| 55 | + private static final String SERIAL = "serial"; | ||
| 56 | + private static final String PORTS = "ports"; | ||
| 57 | + private static final String ENABLED = "enabled"; | ||
| 58 | + private static final String SPEED = "speed"; | ||
| 59 | + | ||
| 60 | + private static final ObjectMapper MAPPER = new ObjectMapper(); | ||
| 61 | + | ||
| 62 | + | ||
| 40 | /** | 63 | /** |
| 41 | * Creates a new message handler for the device messages. | 64 | * Creates a new message handler for the device messages. |
| 42 | */ | 65 | */ |
| 43 | protected DeviceViewMessageHandler() { | 66 | protected DeviceViewMessageHandler() { |
| 44 | - super(ImmutableSet.of("deviceDataRequest")); | 67 | + super(ImmutableSet.of("deviceDataRequest", "deviceDetailsRequest")); |
| 45 | } | 68 | } |
| 46 | 69 | ||
| 47 | @Override | 70 | @Override |
| 48 | - public void process(ObjectNode message) { | 71 | + public void process(ObjectNode event) { |
| 49 | - ObjectNode payload = payload(message); | 72 | + String type = string(event, "event", "unknown"); |
| 73 | + if (type.equals("deviceDataRequest")) { | ||
| 74 | + dataRequest(event); | ||
| 75 | + } else if (type.equals("deviceDetailsRequest")) { | ||
| 76 | + detailsRequest(event); | ||
| 77 | + } | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + private void dataRequest(ObjectNode event) { | ||
| 81 | + ObjectNode payload = payload(event); | ||
| 50 | String sortCol = string(payload, "sortCol", "id"); | 82 | String sortCol = string(payload, "sortCol", "id"); |
| 51 | String sortDir = string(payload, "sortDir", "asc"); | 83 | String sortDir = string(payload, "sortDir", "asc"); |
| 52 | 84 | ||
| 53 | DeviceService service = get(DeviceService.class); | 85 | DeviceService service = get(DeviceService.class); |
| 54 | MastershipService mastershipService = get(MastershipService.class); | 86 | MastershipService mastershipService = get(MastershipService.class); |
| 55 | LinkService linkService = get(LinkService.class); | 87 | LinkService linkService = get(LinkService.class); |
| 88 | + | ||
| 56 | TableRow[] rows = generateTableRows(service, | 89 | TableRow[] rows = generateTableRows(service, |
| 57 | mastershipService, | 90 | mastershipService, |
| 58 | linkService); | 91 | linkService); |
| ... | @@ -66,6 +99,37 @@ public class DeviceViewMessageHandler extends AbstractTabularViewMessageHandler | ... | @@ -66,6 +99,37 @@ public class DeviceViewMessageHandler extends AbstractTabularViewMessageHandler |
| 66 | connection().sendMessage("deviceDataResponse", 0, rootNode); | 99 | connection().sendMessage("deviceDataResponse", 0, rootNode); |
| 67 | } | 100 | } |
| 68 | 101 | ||
| 102 | + private void detailsRequest(ObjectNode event) { | ||
| 103 | + ObjectNode payload = payload(event); | ||
| 104 | + String id = string(payload, "id", "of:0000000000000000"); | ||
| 105 | + | ||
| 106 | + DeviceId deviceId = DeviceId.deviceId(id); | ||
| 107 | + DeviceService service = get(DeviceService.class); | ||
| 108 | + MastershipService ms = get(MastershipService.class); | ||
| 109 | + Device device = service.getDevice(deviceId); | ||
| 110 | + ObjectNode data = MAPPER.createObjectNode(); | ||
| 111 | + | ||
| 112 | + data.put(ID, deviceId.toString()); | ||
| 113 | + data.put(TYPE, device.type().toString()); | ||
| 114 | + data.put(MFR, device.manufacturer()); | ||
| 115 | + data.put(HW, device.hwVersion()); | ||
| 116 | + data.put(SW, device.swVersion()); | ||
| 117 | + data.put(SERIAL, device.serialNumber()); | ||
| 118 | + data.put(CHASSIS_ID, device.chassisId().toString()); | ||
| 119 | + data.put(MASTER_ID, ms.getMasterFor(deviceId).toString()); | ||
| 120 | + data.put(PROTOCOL, device.annotations().value(PROTOCOL)); | ||
| 121 | + | ||
| 122 | + ArrayNode ports = MAPPER.createArrayNode(); | ||
| 123 | + for (Port p : service.getPorts(deviceId)) { | ||
| 124 | + ports.add(portData(p, deviceId)); | ||
| 125 | + } | ||
| 126 | + data.set(PORTS, ports); | ||
| 127 | + | ||
| 128 | + ObjectNode rootNode = mapper.createObjectNode(); | ||
| 129 | + rootNode.set("details", data); | ||
| 130 | + connection().sendMessage("deviceDetailsResponse", 0, rootNode); | ||
| 131 | + } | ||
| 132 | + | ||
| 69 | private TableRow[] generateTableRows(DeviceService service, | 133 | private TableRow[] generateTableRows(DeviceService service, |
| 70 | MastershipService mastershipService, | 134 | MastershipService mastershipService, |
| 71 | LinkService linkService) { | 135 | LinkService linkService) { |
| ... | @@ -79,48 +143,44 @@ public class DeviceViewMessageHandler extends AbstractTabularViewMessageHandler | ... | @@ -79,48 +143,44 @@ public class DeviceViewMessageHandler extends AbstractTabularViewMessageHandler |
| 79 | return list.toArray(new TableRow[list.size()]); | 143 | return list.toArray(new TableRow[list.size()]); |
| 80 | } | 144 | } |
| 81 | 145 | ||
| 146 | + private ObjectNode portData(Port p, DeviceId id) { | ||
| 147 | + ObjectNode port = MAPPER.createObjectNode(); | ||
| 148 | + LinkService ls = get(LinkService.class); | ||
| 149 | + | ||
| 150 | + port.put(ID, p.number().toString()); | ||
| 151 | + port.put(TYPE, p.type().toString()); | ||
| 152 | + port.put(SPEED, p.portSpeed()); | ||
| 153 | + port.put(ENABLED, p.isEnabled()); | ||
| 154 | + | ||
| 155 | + Set<Link> links = ls.getEgressLinks(new ConnectPoint(id, p.number())); | ||
| 156 | + if (!links.isEmpty()) { | ||
| 157 | + String egressLinks = ""; | ||
| 158 | + for (Link l : links) { | ||
| 159 | + ConnectPoint dest = l.dst(); | ||
| 160 | + egressLinks += dest.elementId().toString() | ||
| 161 | + + "/" + dest.port().toString() + " "; | ||
| 162 | + } | ||
| 163 | + port.put(LINK_DEST, egressLinks); | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | + return port; | ||
| 167 | + } | ||
| 168 | + | ||
| 82 | /** | 169 | /** |
| 83 | * TableRow implementation for {@link Device devices}. | 170 | * TableRow implementation for {@link Device devices}. |
| 84 | */ | 171 | */ |
| 85 | private static class DeviceTableRow extends AbstractTableRow { | 172 | private static class DeviceTableRow extends AbstractTableRow { |
| 86 | 173 | ||
| 87 | - private static final String ID = "id"; | ||
| 88 | - private static final String AVAILABLE = "available"; | ||
| 89 | - private static final String AVAILABLE_IID = "_iconid_available"; | ||
| 90 | - private static final String TYPE_IID = "_iconid_type"; | ||
| 91 | - private static final String DEV_ICON_PREFIX = "devIcon_"; | ||
| 92 | - private static final String NUM_PORTS = "num_ports"; | ||
| 93 | - private static final String NUM_EGRESS_LINKS = "num_elinks"; | ||
| 94 | - private static final String MFR = "mfr"; | ||
| 95 | - private static final String HW = "hw"; | ||
| 96 | - private static final String SW = "sw"; | ||
| 97 | - private static final String PROTOCOL = "protocol"; | ||
| 98 | - private static final String MASTERID = "masterid"; | ||
| 99 | - private static final String CHASSISID = "chassisid"; | ||
| 100 | - private static final String SERIAL = "serial"; | ||
| 101 | - | ||
| 102 | private static final String[] COL_IDS = { | 174 | private static final String[] COL_IDS = { |
| 103 | AVAILABLE, AVAILABLE_IID, TYPE_IID, ID, | 175 | AVAILABLE, AVAILABLE_IID, TYPE_IID, ID, |
| 104 | - NUM_PORTS, NUM_EGRESS_LINKS, MASTERID, MFR, HW, SW, | 176 | + NUM_PORTS, MASTER_ID, MFR, HW, SW, |
| 105 | - PROTOCOL, CHASSISID, SERIAL | 177 | + PROTOCOL, CHASSIS_ID, SERIAL |
| 106 | }; | 178 | }; |
| 107 | 179 | ||
| 108 | private static final String ICON_ID_ONLINE = "deviceOnline"; | 180 | private static final String ICON_ID_ONLINE = "deviceOnline"; |
| 109 | private static final String ICON_ID_OFFLINE = "deviceOffline"; | 181 | private static final String ICON_ID_OFFLINE = "deviceOffline"; |
| 110 | 182 | ||
| 111 | // TODO: use in details pane | 183 | // TODO: use in details pane |
| 112 | -// private String getPorts(List<Port> ports) { | ||
| 113 | -// String formattedString = ""; | ||
| 114 | -// int numPorts = 0; | ||
| 115 | -// | ||
| 116 | -// for (Port p : ports) { | ||
| 117 | -// numPorts++; | ||
| 118 | -// formattedString += p.number().toString() + ", "; | ||
| 119 | -// } | ||
| 120 | -// return formattedString + "Total: " + numPorts; | ||
| 121 | -// } | ||
| 122 | - | ||
| 123 | - // TODO: use in details pane | ||
| 124 | // private String getEgressLinks(Set<Link> links) { | 184 | // private String getEgressLinks(Set<Link> links) { |
| 125 | // String formattedString = ""; | 185 | // String formattedString = ""; |
| 126 | // | 186 | // |
| ... | @@ -139,7 +199,6 @@ public class DeviceViewMessageHandler extends AbstractTabularViewMessageHandler | ... | @@ -139,7 +199,6 @@ public class DeviceViewMessageHandler extends AbstractTabularViewMessageHandler |
| 139 | String iconId = available ? ICON_ID_ONLINE : ICON_ID_OFFLINE; | 199 | String iconId = available ? ICON_ID_ONLINE : ICON_ID_OFFLINE; |
| 140 | DeviceId id = d.id(); | 200 | DeviceId id = d.id(); |
| 141 | List<Port> ports = service.getPorts(id); | 201 | List<Port> ports = service.getPorts(id); |
| 142 | -// Set<Link> links = ls.getDeviceEgressLinks(id); | ||
| 143 | 202 | ||
| 144 | add(ID, id.toString()); | 203 | add(ID, id.toString()); |
| 145 | add(AVAILABLE, Boolean.toString(available)); | 204 | add(AVAILABLE, Boolean.toString(available)); |
| ... | @@ -148,12 +207,9 @@ public class DeviceViewMessageHandler extends AbstractTabularViewMessageHandler | ... | @@ -148,12 +207,9 @@ public class DeviceViewMessageHandler extends AbstractTabularViewMessageHandler |
| 148 | add(MFR, d.manufacturer()); | 207 | add(MFR, d.manufacturer()); |
| 149 | add(HW, d.hwVersion()); | 208 | add(HW, d.hwVersion()); |
| 150 | add(SW, d.swVersion()); | 209 | add(SW, d.swVersion()); |
| 151 | -// add(SERIAL, d.serialNumber()); | ||
| 152 | add(PROTOCOL, d.annotations().value(PROTOCOL)); | 210 | add(PROTOCOL, d.annotations().value(PROTOCOL)); |
| 153 | add(NUM_PORTS, Integer.toString(ports.size())); | 211 | add(NUM_PORTS, Integer.toString(ports.size())); |
| 154 | -// add(NUM_EGRESS_LINKS, Integer.toString(links.size())); | 212 | + add(MASTER_ID, ms.getMasterFor(d.id()).toString()); |
| 155 | -// add(CHASSISID, d.chassisId().toString()); | ||
| 156 | - add(MASTERID, ms.getMasterFor(d.id()).toString()); | ||
| 157 | } | 213 | } |
| 158 | 214 | ||
| 159 | private String getTypeIconId(Device d) { | 215 | private String getTypeIconId(Device d) { | ... | ... |
| ... | @@ -5,6 +5,7 @@ | ... | @@ -5,6 +5,7 @@ |
| 5 | - Key Handler | 5 | - Key Handler |
| 6 | - Theme Service | 6 | - Theme Service |
| 7 | - Alert Service | 7 | - Alert Service |
| 8 | + - Preference Service | ||
| 8 | 9 | ||
| 9 | - Mast | 10 | - Mast |
| 10 | - Masthead | 11 | - Masthead |
| ... | @@ -27,4 +28,6 @@ | ... | @@ -27,4 +28,6 @@ |
| 27 | 28 | ||
| 28 | - Widget | 29 | - Widget |
| 29 | - Table Styling Directives | 30 | - Table Styling Directives |
| 31 | + - Table Builder Service | ||
| 30 | - Toolbar Service | 32 | - Toolbar Service |
| 33 | + - Button Service | ... | ... |
| ... | @@ -161,7 +161,7 @@ | ... | @@ -161,7 +161,7 @@ |
| 161 | 161 | ||
| 162 | // return the given string with the first character capitalized. | 162 | // return the given string with the first character capitalized. |
| 163 | function cap(s) { | 163 | function cap(s) { |
| 164 | - return s.replace(/^[a-z]/, function (m) { | 164 | + return s.toLowerCase().replace(/^[a-z]/, function (m) { |
| 165 | return m.toUpperCase(); | 165 | return m.toUpperCase(); |
| 166 | }); | 166 | }); |
| 167 | } | 167 | } | ... | ... |
| ... | @@ -18,5 +18,86 @@ | ... | @@ -18,5 +18,86 @@ |
| 18 | ONOS GUI -- Device View -- CSS file | 18 | ONOS GUI -- Device View -- CSS file |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | -#ov-device td { | 21 | +/* More in generic panel.css */ |
| 22 | + | ||
| 23 | +#device-details-panel.floatpanel { | ||
| 24 | + -moz-border-radius: 0; | ||
| 25 | + border-radius: 0; | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +.light #device-details-panel.floatpanel { | ||
| 29 | + background-color: rgb(226, 248, 255); | ||
| 30 | +} | ||
| 31 | +.dark #device-details-panel.floatpanel { | ||
| 32 | + background-color: #444; | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +#device-details-panel .container { | ||
| 36 | + padding: 0 12px; | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +#device-details-panel .close-btn { | ||
| 40 | + position: absolute; | ||
| 41 | + right: 10px; | ||
| 42 | + top: 0; | ||
| 43 | +} | ||
| 44 | +.close-btn svg.embeddedIcon .icon.appPlus .glyph { | ||
| 45 | + /* works for both dark and light themes */ | ||
| 46 | + fill: #ccc; | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +#device-details-panel h2 { | ||
| 50 | + margin: 8px 0; | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +#device-details-panel td.label { | ||
| 54 | + font-style: italic; | ||
| 55 | + padding-right: 12px; | ||
| 56 | + /* works for both light and dark themes ... */ | ||
| 57 | + color: #777; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +#device-details-panel hr { | ||
| 61 | + margin: 12px 0; | ||
| 62 | +} | ||
| 63 | + | ||
| 64 | +.light #device-details-panel hr { | ||
| 65 | + opacity: .5; | ||
| 66 | + border-color: #FFF; | ||
| 67 | +} | ||
| 68 | +.dark #device-details-panel hr { | ||
| 69 | + border-color: #666; | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +#device-details-panel .bottom table { | ||
| 73 | + border-spacing: 0; | ||
| 74 | +} | ||
| 75 | + | ||
| 76 | +#device-details-panel .bottom th { | ||
| 77 | + letter-spacing: 0.02em; | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +.light #device-details-panel .bottom th { | ||
| 81 | + background-color: #D0E1ED; | ||
| 82 | + /* default text color */ | ||
| 83 | +} | ||
| 84 | +.dark #device-details-panel .bottom th { | ||
| 85 | + background-color: #2b2b2b; | ||
| 86 | + color: #ccc; | ||
| 87 | +} | ||
| 88 | + | ||
| 89 | +#device-details-panel .bottom th, | ||
| 90 | +#device-details-panel .bottom td { | ||
| 91 | + padding: 6px 12px; | ||
| 92 | + text-align: center; | ||
| 93 | +} | ||
| 94 | + | ||
| 95 | +.light #device-details-panel .bottom tr:nth-child(odd) { | ||
| 96 | + background-color: #f9f9f9; | ||
| 97 | +} | ||
| 98 | +.light #device-details-panel .bottom tr:nth-child(even) { | ||
| 99 | + background-color: #EBEDF2; | ||
| 100 | +} | ||
| 101 | +.dark #device-details-panel .bottom tr:nth-child(odd) { | ||
| 102 | + background-color: #333; | ||
| 22 | } | 103 | } | ... | ... |
| ... | @@ -27,6 +27,8 @@ | ... | @@ -27,6 +27,8 @@ |
| 27 | </tr> | 27 | </tr> |
| 28 | 28 | ||
| 29 | <tr ng-repeat="dev in ctrl.tableData" | 29 | <tr ng-repeat="dev in ctrl.tableData" |
| 30 | + ng-click="selectCallback(dev)" | ||
| 31 | + ng-class="{selected: dev === sel}" | ||
| 30 | ng-repeat-done> | 32 | ng-repeat-done> |
| 31 | <td class="table-icon"> | 33 | <td class="table-icon"> |
| 32 | <div icon icon-id="{{dev._iconid_available}}"></div> | 34 | <div icon icon-id="{{dev._iconid_available}}"></div> | ... | ... |
| ... | @@ -21,15 +21,209 @@ | ... | @@ -21,15 +21,209 @@ |
| 21 | (function () { | 21 | (function () { |
| 22 | 'use strict'; | 22 | 'use strict'; |
| 23 | 23 | ||
| 24 | + // injected refs | ||
| 25 | + var $log, $scope, fs, mast, ps, wss, is; | ||
| 26 | + | ||
| 27 | + // internal state | ||
| 28 | + var self, | ||
| 29 | + detailsPane, | ||
| 30 | + container, top, bottom, closeBtn; | ||
| 31 | + | ||
| 32 | + // constants | ||
| 33 | + // TODO: consider having a set y height that all tables start at | ||
| 34 | + var h2Pdg = 40, | ||
| 35 | + mastPdg = 8, | ||
| 36 | + tbodyPdg = 5, | ||
| 37 | + cntrPdg = 24, | ||
| 38 | + pName = 'device-details-panel', | ||
| 39 | + detailsReq = 'deviceDetailsRequest', | ||
| 40 | + detailsResp = 'deviceDetailsResponse', | ||
| 41 | + propOrder = [ | ||
| 42 | + 'type', 'masterid', 'chassisid', | ||
| 43 | + 'mfr', 'hw', 'sw', 'protocol', 'serial' | ||
| 44 | + ], | ||
| 45 | + friendlyProps = [ | ||
| 46 | + 'Type', 'Master ID', 'Chassis ID', | ||
| 47 | + 'Vendor', 'H/W Version', 'S/W Version', 'Protocol', 'Serial #' | ||
| 48 | + ], | ||
| 49 | + portCols = [ | ||
| 50 | + 'enabled', 'id', 'speed', 'type', 'elinks_dest' | ||
| 51 | + ], | ||
| 52 | + friendlyPortCols = [ | ||
| 53 | + 'Enabled', 'ID', 'Speed', 'Type', 'Egress Links' | ||
| 54 | + ]; | ||
| 55 | + | ||
| 56 | + function setUpPanel() { | ||
| 57 | + detailsPane.empty(); | ||
| 58 | + | ||
| 59 | + container = detailsPane.append('div').classed('container', true); | ||
| 60 | + | ||
| 61 | + top = container.append('div').classed('top', true); | ||
| 62 | + closeBtn = top.append('div').classed('close-btn', true); | ||
| 63 | + addCloseBtn(closeBtn); | ||
| 64 | + top.append('h2'); | ||
| 65 | + top.append('table'); | ||
| 66 | + | ||
| 67 | + container.append('hr'); | ||
| 68 | + | ||
| 69 | + bottom = container.append('div').classed('bottom', true); | ||
| 70 | + bottom.append('h2').text('Ports'); | ||
| 71 | + bottom.append('table'); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + function createDetailsPane() { | ||
| 75 | + var headerHeight = h2Pdg + fs.noPxStyle(d3.select('h2'), 'height'), | ||
| 76 | + panelTop = headerHeight + tbodyPdg + mast.mastHeight() + mastPdg, | ||
| 77 | + wSize = fs.windowSize(panelTop); | ||
| 78 | + | ||
| 79 | + detailsPane = ps.createPanel(pName, { | ||
| 80 | + height: wSize.height, | ||
| 81 | + width: wSize.width / 2, | ||
| 82 | + margin: 0, | ||
| 83 | + hideMargin: 0 | ||
| 84 | + }); | ||
| 85 | + | ||
| 86 | + detailsPane.el().style({ | ||
| 87 | + position: 'absolute', | ||
| 88 | + top: panelTop + 'px' | ||
| 89 | + }); | ||
| 90 | + | ||
| 91 | + setUpPanel(); | ||
| 92 | + | ||
| 93 | + detailsPane.hide(); | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + function addCloseBtn(div) { | ||
| 97 | + is.loadEmbeddedIcon(div, 'appPlus', 30); | ||
| 98 | + div.select('g').attr('transform', 'translate(25, 0) rotate(45)'); | ||
| 99 | + div.on('click', function () { | ||
| 100 | + detailsPane.hide(); | ||
| 101 | + // TODO: deselect the table row when button is clicked | ||
| 102 | + //$scope.sel = null; | ||
| 103 | + }); | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + function populateTopHalf(tbody, details) { | ||
| 107 | + top.select('h2').text(details['id']); | ||
| 108 | + | ||
| 109 | + propOrder.forEach(function (prop, i) { | ||
| 110 | + addProp(tbody, i, details[prop]); | ||
| 111 | + }); | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + function populateBottomHalf(table, ports) { | ||
| 115 | + var theader = table.append('thead').append('tr'), | ||
| 116 | + tbody = table.append('tbody'), | ||
| 117 | + tbWidth, tbHeight, | ||
| 118 | + scrollSize = 20, | ||
| 119 | + btmPdg = 50; | ||
| 120 | + | ||
| 121 | + friendlyPortCols.forEach(function (header) { | ||
| 122 | + theader.append('th').html(header); | ||
| 123 | + }); | ||
| 124 | + ports.forEach(function (port) { | ||
| 125 | + addPortRow(tbody, port); | ||
| 126 | + }); | ||
| 127 | + | ||
| 128 | + tbWidth = fs.noPxStyle(tbody, 'width') + scrollSize; | ||
| 129 | + tbHeight = detailsPane.height() | ||
| 130 | + - (fs.noPxStyle(detailsPane.el().select('.top'), 'height') | ||
| 131 | + + fs.noPxStyle(detailsPane.el().select('hr'), 'height') | ||
| 132 | + + fs.noPxStyle(detailsPane.el().select('h2'), 'height') | ||
| 133 | + + btmPdg); | ||
| 134 | + | ||
| 135 | + table.style({ | ||
| 136 | + height: tbHeight + 'px', | ||
| 137 | + width: tbWidth + 'px', | ||
| 138 | + overflow: 'auto', | ||
| 139 | + display: 'block' | ||
| 140 | + }); | ||
| 141 | + | ||
| 142 | + detailsPane.width(tbWidth + cntrPdg); | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + function addProp(tbody, index, value) { | ||
| 146 | + var tr = tbody.append('tr'); | ||
| 147 | + | ||
| 148 | + function addCell(cls, txt) { | ||
| 149 | + tr.append('td').attr('class', cls).html(txt); | ||
| 150 | + } | ||
| 151 | + addCell('label', friendlyProps[index] + ' :'); | ||
| 152 | + addCell('value', value); | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + function addPortRow(tbody, port) { | ||
| 156 | + var tr = tbody.append('tr'); | ||
| 157 | + | ||
| 158 | + portCols.forEach(function (col) { | ||
| 159 | + if (col === 'type' || col === 'id') { | ||
| 160 | + port[col] = fs.cap(port[col]); | ||
| 161 | + } | ||
| 162 | + tr.append('td').html(port[col]); | ||
| 163 | + }); | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | + function populateDetails(details) { | ||
| 167 | + setUpPanel(); | ||
| 168 | + | ||
| 169 | + var toptbody = top.select('table').append('tbody'), | ||
| 170 | + btmTable = bottom.select('table'), | ||
| 171 | + ports = details.ports; | ||
| 172 | + | ||
| 173 | + populateTopHalf(toptbody, details); | ||
| 174 | + populateBottomHalf(btmTable, ports); | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + function respDetailsCb(data) { | ||
| 178 | + self.panelData = data['details']; | ||
| 179 | + populateDetails(self.panelData); | ||
| 180 | + detailsPane.show(); | ||
| 181 | + } | ||
| 182 | + | ||
| 24 | angular.module('ovDevice', []) | 183 | angular.module('ovDevice', []) |
| 25 | .controller('OvDeviceCtrl', | 184 | .controller('OvDeviceCtrl', |
| 26 | - ['$log', '$scope', 'TableBuilderService', | 185 | + ['$log', '$scope', 'TableBuilderService', 'FnService', |
| 186 | + 'MastService', 'PanelService', 'WebSocketService', 'IconService', | ||
| 187 | + | ||
| 188 | + function (_$log_, _$scope_, tbs, _fs_, _mast_, _ps_, _wss_, _is_) { | ||
| 189 | + $log = _$log_; | ||
| 190 | + $scope = _$scope_; | ||
| 191 | + fs = _fs_; | ||
| 192 | + mast = _mast_; | ||
| 193 | + ps = _ps_; | ||
| 194 | + wss = _wss_; | ||
| 195 | + is = _is_; | ||
| 196 | + self = this; | ||
| 197 | + var handlers = {}; | ||
| 198 | + self.panelData = []; | ||
| 199 | + | ||
| 200 | + function selCb(row) { | ||
| 201 | + // request the server for more information | ||
| 202 | + // get the id from the row to request details with | ||
| 203 | + if ($scope.sel) { | ||
| 204 | + wss.sendEvent(detailsReq, { id: row.id }); | ||
| 205 | + } else { | ||
| 206 | + detailsPane.hide(); | ||
| 207 | + } | ||
| 208 | + $log.debug('Got a click on:', row); | ||
| 209 | + } | ||
| 27 | 210 | ||
| 28 | - function ($log, $scope, tbs) { | ||
| 29 | tbs.buildTable({ | 211 | tbs.buildTable({ |
| 30 | - self: this, | 212 | + self: self, |
| 31 | scope: $scope, | 213 | scope: $scope, |
| 32 | - tag: 'device' | 214 | + tag: 'device', |
| 215 | + selCb: selCb | ||
| 216 | + }); | ||
| 217 | + | ||
| 218 | + createDetailsPane(); | ||
| 219 | + | ||
| 220 | + // bind websocket handlers | ||
| 221 | + handlers[detailsResp] = respDetailsCb; | ||
| 222 | + wss.bindHandlers(handlers); | ||
| 223 | + | ||
| 224 | + $scope.$on('$destroy', function () { | ||
| 225 | + ps.destroyPanel(pName); | ||
| 226 | + wss.unbindHandlers(handlers); | ||
| 33 | }); | 227 | }); |
| 34 | 228 | ||
| 35 | $log.log('OvDeviceCtrl has been created'); | 229 | $log.log('OvDeviceCtrl has been created'); | ... | ... |
| ... | @@ -386,6 +386,8 @@ describe('factory: fw/util/fn.js', function() { | ... | @@ -386,6 +386,8 @@ describe('factory: fw/util/fn.js', function() { |
| 386 | expect(fs.cap('Foo')).toEqual('Foo'); | 386 | expect(fs.cap('Foo')).toEqual('Foo'); |
| 387 | expect(fs.cap('foo')).toEqual('Foo'); | 387 | expect(fs.cap('foo')).toEqual('Foo'); |
| 388 | expect(fs.cap('foo bar')).toEqual('Foo bar'); | 388 | expect(fs.cap('foo bar')).toEqual('Foo bar'); |
| 389 | + expect(fs.cap('FOO BAR')).toEqual('Foo bar'); | ||
| 390 | + expect(fs.cap('foo Bar')).toEqual('Foo bar'); | ||
| 389 | }); | 391 | }); |
| 390 | 392 | ||
| 391 | // === Tests for noPx() | 393 | // === Tests for noPx() | ... | ... |
-
Please register or login to post a comment