Merge lp:~lamont/maas/bug-1660188b into lp:~maas-committers/maas/trunk
- bug-1660188b
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | LaMont Jones | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 5770 | ||||
Proposed branch: | lp:~lamont/maas/bug-1660188b | ||||
Merge into: | lp:~maas-committers/maas/trunk | ||||
Prerequisite: | lp:~lamont/maas/bug-1660188a | ||||
Diff against target: |
968 lines (+347/-160) 7 files modified
src/maasserver/static/js/angular/controllers/node_details.js (+35/-7) src/maasserver/static/js/angular/controllers/node_details_networking.js (+135/-47) src/maasserver/static/js/angular/controllers/tests/test_node_details.js (+5/-3) src/maasserver/static/js/angular/factories/devices.js (+5/-4) src/maasserver/static/js/angular/factories/tests/test_devices.js (+1/-1) src/maasserver/static/partials/node-details.html (+163/-97) src/maasserver/static/partials/nodes-list.html (+3/-1) |
||||
To merge this branch: | bzr merge lp:~lamont/maas/bug-1660188b | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Blake Rouse (community) | Approve | ||
Review via email: mp+318463@code.launchpad.net |
Commit message
Device-details page, with editing.
Description of the change
Device-details page, with editing.
Blake Rouse (blake-rouse) wrote : | # |
Blake Rouse (blake-rouse) wrote : | # |
Couple things I noticed using the branch.
1. The checkbox should be removed on the interfaces table. At the moment you cannot perform and action between two interfaces, so it should be removed because at the moment it does not server a purpose.
2. The add interface MAC address input is miss aligned and does not match how it is show to edit an interface. This should match. Looks like a mark up problem.
Blake Rouse (blake-rouse) wrote : | # |
I also tried to modify an existing interface. It was set to Dynamic, I changed it to External and it failed to save:
TypeError: Cannot read property 'id' of null
at Scope.$
at $$childScopeCla
at http://
at callback (http://
at $$childScopeCla
at $$childScopeCla
at HTMLButtonEleme
at HTMLButtonEleme
at HTMLButtonEleme
Blake Rouse (blake-rouse) wrote : | # |
I then changed an interface from Dynamic to Static, selected a Subnet, did not select an IP address at the interface now shows twice, with two different IP addresses.
Blake Rouse (blake-rouse) wrote : | # |
I am no longer getting two static IP addresses, but some of the other issues still remain.
1. When selecting a Static IP "Unconfigued" subnet is not supported for a device.
2. When adding a new interface the MAC address field is miss aligned.
Blake Rouse (blake-rouse) wrote : | # |
The create interface padding is incorrect:
Blake Rouse (blake-rouse) wrote : | # |
It also should pick a default subnet in the dropdown, it should not be blank. Same goes for editing an interface as well. When I click "static" it should pick the first subnet in the dropdown.
Blake Rouse (blake-rouse) wrote : | # |
Looks good. The only other thing I see is that IP address is not optional when providing an external IP address. In that case the IP address is always required. The form is validated correctly, its just that the placeholder text for that field needs to be updated.
Preview Diff
1 | === modified file 'src/maasserver/static/js/angular/controllers/node_details.js' |
2 | --- src/maasserver/static/js/angular/controllers/node_details.js 2017-02-28 20:57:13 +0000 |
3 | +++ src/maasserver/static/js/angular/controllers/node_details.js 2017-03-02 00:31:00 +0000 |
4 | @@ -6,14 +6,22 @@ |
5 | |
6 | angular.module('MAAS').controller('NodeDetailsController', [ |
7 | '$scope', '$rootScope', '$routeParams', '$location', '$interval', |
8 | + 'DevicesManager', |
9 | 'MachinesManager', 'ControllersManager', 'ZonesManager', 'GeneralManager', |
10 | 'UsersManager', 'TagsManager', 'DomainsManager', 'ManagerHelperService', |
11 | 'ServicesManager', 'ErrorService', 'ValidationService', function( |
12 | - $scope, $rootScope, $routeParams, $location, $interval, |
13 | + $scope, $rootScope, $routeParams, $location, $interval, DevicesManager, |
14 | MachinesManager, ControllersManager, ZonesManager, GeneralManager, |
15 | UsersManager, TagsManager, DomainsManager, ManagerHelperService, |
16 | ServicesManager, ErrorService, ValidationService) { |
17 | |
18 | + // Mapping of device.ip_assignment to viewable text. |
19 | + var DEVICE_IP_ASSIGNMENT = { |
20 | + external: "External", |
21 | + dynamic: "Dynamic", |
22 | + "static": "Static" |
23 | + }; |
24 | + |
25 | // Set title and page. |
26 | $rootScope.title = "Loading..."; |
27 | $rootScope.page = "nodes"; |
28 | @@ -84,6 +92,11 @@ |
29 | parameters: {} |
30 | }; |
31 | |
32 | + // Get the display text for device ip assignment type. |
33 | + $scope.getDeviceIPAssignment = function(ipAssignment) { |
34 | + return DEVICE_IP_ASSIGNMENT[ipAssignment]; |
35 | + }; |
36 | + |
37 | // Events section. |
38 | $scope.events = { |
39 | limit: 10 |
40 | @@ -674,9 +687,10 @@ |
41 | $scope.hasInvalidArchitecture = function() { |
42 | if(angular.isObject($scope.node)) { |
43 | return ( |
44 | - $scope.node.architecture === "" || |
45 | - $scope.summary.architecture.options.indexOf( |
46 | - $scope.node.architecture) === -1); |
47 | + !$scope.isDevice && ( |
48 | + $scope.node.architecture === "" || |
49 | + $scope.summary.architecture.options.indexOf( |
50 | + $scope.node.architecture) === -1)); |
51 | } else { |
52 | return false; |
53 | } |
54 | @@ -685,9 +699,10 @@ |
55 | // Return true if the current architecture selection is invalid. |
56 | $scope.invalidArchitecture = function() { |
57 | return ( |
58 | - $scope.summary.architecture.selected === "" || |
59 | - $scope.summary.architecture.options.indexOf( |
60 | - $scope.summary.architecture.selected) === -1); |
61 | + !$scope.isDevice && ( |
62 | + $scope.summary.architecture.selected === "" || |
63 | + $scope.summary.architecture.options.indexOf( |
64 | + $scope.summary.architecture.selected) === -1)); |
65 | }; |
66 | |
67 | // Return true if at least a rack controller is connected to the |
68 | @@ -1029,6 +1044,7 @@ |
69 | // Load all the required managers. |
70 | ManagerHelperService.loadManagers($scope, [ |
71 | MachinesManager, |
72 | + DevicesManager, |
73 | ControllersManager, |
74 | ZonesManager, |
75 | GeneralManager, |
76 | @@ -1040,11 +1056,19 @@ |
77 | if('controller' === $routeParams.type) { |
78 | $scope.nodesManager = ControllersManager; |
79 | $scope.isController = true; |
80 | + $scope.isDevice = false; |
81 | $scope.type_name = 'controller'; |
82 | $scope.type_name_title = 'Controller'; |
83 | + }else if('device' === $routeParams.type) { |
84 | + $scope.nodesManager = DevicesManager; |
85 | + $scope.isController = false; |
86 | + $scope.isDevice = true; |
87 | + $scope.type_name = 'device'; |
88 | + $scope.type_name_title = 'Device'; |
89 | }else{ |
90 | $scope.nodesManager = MachinesManager; |
91 | $scope.isController = false; |
92 | + $scope.isDevice = false; |
93 | $scope.type_name = 'machine'; |
94 | $scope.type_name_title = 'Machine'; |
95 | } |
96 | @@ -1062,6 +1086,10 @@ |
97 | }, function(error) { |
98 | ErrorService.raiseError(error); |
99 | }); |
100 | + activeNode = $scope.nodesManager.getActiveItem(); |
101 | + } |
102 | + if($scope.isDevice) { |
103 | + $scope.ip_assignment = activeNode.ip_assignment; |
104 | } |
105 | |
106 | // Poll for architectures, hwe_kernels, and osinfo the whole |
107 | |
108 | === modified file 'src/maasserver/static/js/angular/controllers/node_details_networking.js' |
109 | --- src/maasserver/static/js/angular/controllers/node_details_networking.js 2016-10-26 19:05:43 +0000 |
110 | +++ src/maasserver/static/js/angular/controllers/node_details_networking.js 2017-03-02 00:31:00 +0000 |
111 | @@ -171,6 +171,28 @@ |
112 | EDIT: "edit" |
113 | }; |
114 | |
115 | + var IP_ASSIGNMENT = { |
116 | + DYNAMIC: "dynamic", |
117 | + EXTERNAL: "external", |
118 | + STATIC: "static" |
119 | + }; |
120 | + |
121 | + // Device ip assignment options. |
122 | + $scope.ipAssignments = [ |
123 | + { |
124 | + name: IP_ASSIGNMENT.EXTERNAL, |
125 | + text: "External" |
126 | + }, |
127 | + { |
128 | + name: IP_ASSIGNMENT.DYNAMIC, |
129 | + text: "Dynamic" |
130 | + }, |
131 | + { |
132 | + name: IP_ASSIGNMENT.STATIC, |
133 | + text: "Static" |
134 | + } |
135 | + ]; |
136 | + |
137 | // Set the initial values for this scope. |
138 | $scope.loaded = false; |
139 | $scope.nodeHasLoaded = false; |
140 | @@ -542,6 +564,10 @@ |
141 | // If the user is not the superuser, pretend it's not Ready. |
142 | return false; |
143 | } |
144 | + if ($scope.$parent.isDevice) { |
145 | + // Devices are never Ready, for our purposes, for now. |
146 | + return true; |
147 | + } |
148 | if ($scope.$parent.isController) { |
149 | // Controllers are always Ready, for our purposes. |
150 | return true; |
151 | @@ -563,8 +589,8 @@ |
152 | // If the user is not the superuser, pretend it's not Ready. |
153 | return false; |
154 | } |
155 | - if ($scope.$parent.isController) { |
156 | - // Controllers never in limited mode. |
157 | + if ($scope.$parent.isController || $scope.$parent.isDevice) { |
158 | + // Controllers and Devices are never in limited mode. |
159 | return false; |
160 | } |
161 | return ( |
162 | @@ -581,9 +607,9 @@ |
163 | // If the user is not a superuser, disable the networking panel. |
164 | return true; |
165 | } |
166 | - if ($scope.$parent.isController) { |
167 | + if ($scope.$parent.isController || $scope.$parent.isDevice) { |
168 | // Never disable the full networking panel when its a |
169 | - // controller. |
170 | + // Controller or Device. |
171 | return false; |
172 | } |
173 | if (angular.isObject($scope.node) && |
174 | @@ -772,18 +798,29 @@ |
175 | $scope.edit = function(nic) { |
176 | $scope.selectedInterfaces = [$scope.getUniqueKey(nic)]; |
177 | $scope.selectedMode = SELECTION_MODE.EDIT; |
178 | - $scope.editInterface = { |
179 | - id: nic.id, |
180 | - name: nic.name, |
181 | - mac_address: nic.mac_address, |
182 | - tags: angular.copy(nic.tags), |
183 | - fabric: nic.fabric, |
184 | - vlan: nic.vlan, |
185 | - subnet: nic.subnet, |
186 | - mode: nic.mode, |
187 | - ip_address: nic.ip_address, |
188 | - link_id: nic.link_id |
189 | - }; |
190 | + if($scope.$parent.isDevice) { |
191 | + $scope.editInterface = { |
192 | + id: nic.id, |
193 | + name: nic.name, |
194 | + mac_address: nic.mac_address, |
195 | + subnet: nic.subnet, |
196 | + ip_address: nic.ip_address, |
197 | + ip_assignment: nic.ip_assignment |
198 | + }; |
199 | + } else { |
200 | + $scope.editInterface = { |
201 | + id: nic.id, |
202 | + name: nic.name, |
203 | + mac_address: nic.mac_address, |
204 | + tags: angular.copy(nic.tags), |
205 | + fabric: nic.fabric, |
206 | + vlan: nic.vlan, |
207 | + subnet: nic.subnet, |
208 | + mode: nic.mode, |
209 | + ip_address: nic.ip_address, |
210 | + link_id: nic.link_id |
211 | + }; |
212 | + } |
213 | }; |
214 | |
215 | // Called when the fabric is changed. |
216 | @@ -837,13 +874,24 @@ |
217 | |
218 | // Save the following interface on the node. |
219 | $scope.saveInterface = function(nic) { |
220 | - var params = { |
221 | - "name": nic.name, |
222 | - "mac_address": nic.mac_address, |
223 | - "tags": nic.tags.map( |
224 | - function(tag) { return tag.text; }) |
225 | - }; |
226 | - if(nic.vlan !== null) { |
227 | + var params; |
228 | + if($scope.$parent.isDevice) { |
229 | + params = { |
230 | + "name": nic.name, |
231 | + "mac_address": nic.mac_address, |
232 | + "ip_assignment": nic.ip_assignment, |
233 | + "ip_address": nic.ip_address, |
234 | + "subnet": nic.subnet.id |
235 | + }; |
236 | + } else { |
237 | + params = { |
238 | + "name": nic.name, |
239 | + "mac_address": nic.mac_address, |
240 | + "tags": nic.tags.map( |
241 | + function(tag) { return tag.text; }) |
242 | + }; |
243 | + } |
244 | + if(nic.vlan !== undefined && nic.vlan !== null) { |
245 | params.vlan = nic.vlan.id; |
246 | } else { |
247 | params.vlan = null; |
248 | @@ -866,6 +914,9 @@ |
249 | var params = { |
250 | "mode": nic.mode |
251 | }; |
252 | + if($scope.$parent.isDevice) { |
253 | + params.ip_assignment = nic.ip_assignment; |
254 | + } |
255 | if(angular.isObject(nic.subnet)) { |
256 | params.subnet = nic.subnet.id; |
257 | } |
258 | @@ -903,11 +954,17 @@ |
259 | |
260 | // Make a copy so a change after clicking save is not saved. |
261 | var nic = angular.copy($scope.editInterface); |
262 | - $scope.saveInterface(nic).then(function() { |
263 | - $scope.saveInterfaceLink(nic).then(function() { |
264 | + if($scope.$parent.isDevice) { |
265 | + $scope.saveInterface(nic).then(function() { |
266 | $scope.editCancel(); |
267 | }); |
268 | - }); |
269 | + } else { |
270 | + $scope.saveInterface(nic).then(function() { |
271 | + $scope.saveInterfaceLink(nic).then(function() { |
272 | + $scope.editCancel(); |
273 | + }); |
274 | + }); |
275 | + } |
276 | }; |
277 | |
278 | // Return true if the interface delete confirm is being shown. |
279 | @@ -1110,9 +1167,18 @@ |
280 | |
281 | // Perform the add action over the websocket. |
282 | $scope.addInterface = function(type) { |
283 | - if($scope.newInterface.type === INTERFACE_TYPE.ALIAS) { |
284 | + var nic; |
285 | + if($scope.$parent.isDevice) { |
286 | + nic = { |
287 | + id: $scope.newInterface.parent.id, |
288 | + ip_assignment: $scope.newInterface.ip_assignment, |
289 | + subnet: $scope.newInterface.subnet, |
290 | + ip_address: $scope.newInterface.ip_address |
291 | + }; |
292 | + $scope.saveInterfaceLink(nic); |
293 | + } else if($scope.newInterface.type === INTERFACE_TYPE.ALIAS) { |
294 | // Add a link to the current interface. |
295 | - var nic = { |
296 | + nic = { |
297 | id: $scope.newInterface.parent.id, |
298 | mode: $scope.newInterface.mode, |
299 | subnet: $scope.newInterface.subnet, |
300 | @@ -1416,17 +1482,29 @@ |
301 | $scope.showCreatePhysical = function() { |
302 | if($scope.selectedMode === SELECTION_MODE.NONE) { |
303 | $scope.selectedMode = SELECTION_MODE.CREATE_PHYSICAL; |
304 | - $scope.newInterface = { |
305 | - name: getNextName("eth"), |
306 | - macAddress: "", |
307 | - macError: false, |
308 | - tags: [], |
309 | - errorMsg: null, |
310 | - fabric: $scope.fabrics[0], |
311 | - vlan: getDefaultVLAN($scope.fabrics[0]), |
312 | - subnet: null, |
313 | - mode: LINK_MODE.LINK_UP |
314 | - }; |
315 | + if($scope.$parent.isDevice) { |
316 | + $scope.newInterface = { |
317 | + name: getNextName("eth"), |
318 | + macAddress: "", |
319 | + macError: false, |
320 | + tags: [], |
321 | + errorMsg: null, |
322 | + subnet: null, |
323 | + ip_assignment: IP_ASSIGNMENT.DYNAMIC |
324 | + }; |
325 | + } else { |
326 | + $scope.newInterface = { |
327 | + name: getNextName("eth"), |
328 | + macAddress: "", |
329 | + macError: false, |
330 | + tags: [], |
331 | + errorMsg: null, |
332 | + fabric: $scope.fabrics[0], |
333 | + vlan: getDefaultVLAN($scope.fabrics[0]), |
334 | + subnet: null, |
335 | + mode: LINK_MODE.LINK_UP |
336 | + }; |
337 | + } |
338 | } |
339 | }; |
340 | |
341 | @@ -1444,14 +1522,24 @@ |
342 | return; |
343 | } |
344 | |
345 | - var params = { |
346 | - name: $scope.newInterface.name, |
347 | - tags: $scope.newInterface.tags.map( |
348 | - function(tag) { return tag.text; }), |
349 | - mac_address: $scope.newInterface.macAddress, |
350 | - vlan: $scope.newInterface.vlan.id, |
351 | - mode: $scope.newInterface.mode |
352 | - }; |
353 | + var params; |
354 | + if($scope.$parent.isDevice) { |
355 | + params = { |
356 | + name: $scope.newInterface.name, |
357 | + mac_address: $scope.newInterface.macAddress, |
358 | + ip_assignment: $scope.newInterface.ip_assignment, |
359 | + ip_address: $scope.newInterface.ip_address |
360 | + }; |
361 | + } else { |
362 | + params = { |
363 | + name: $scope.newInterface.name, |
364 | + tags: $scope.newInterface.tags.map( |
365 | + function(tag) { return tag.text; }), |
366 | + mac_address: $scope.newInterface.macAddress, |
367 | + vlan: $scope.newInterface.vlan.id, |
368 | + mode: $scope.newInterface.mode |
369 | + }; |
370 | + } |
371 | if(angular.isObject($scope.newInterface.subnet)) { |
372 | params.subnet = $scope.newInterface.subnet.id; |
373 | } |
374 | |
375 | === modified file 'src/maasserver/static/js/angular/controllers/tests/test_node_details.js' |
376 | --- src/maasserver/static/js/angular/controllers/tests/test_node_details.js 2017-02-28 20:57:13 +0000 |
377 | +++ src/maasserver/static/js/angular/controllers/tests/test_node_details.js 2017-03-02 00:31:00 +0000 |
378 | @@ -42,6 +42,7 @@ |
379 | var webSocket; |
380 | beforeEach(inject(function($injector) { |
381 | MachinesManager = $injector.get("MachinesManager"); |
382 | + DevicesManager = $injector.get("DevicesManager"); |
383 | ControllersManager = $injector.get("ControllersManager"); |
384 | ZonesManager = $injector.get("ZonesManager"); |
385 | GeneralManager = $injector.get("GeneralManager"); |
386 | @@ -137,6 +138,7 @@ |
387 | $routeParams: $routeParams, |
388 | $location: $location, |
389 | MachinesManager: MachinesManager, |
390 | + DevicesManager: DevicesManager, |
391 | ControllersManager: ControllersManager, |
392 | ZonesManager: ZonesManager, |
393 | GeneralManager: GeneralManager, |
394 | @@ -261,9 +263,9 @@ |
395 | var controller = makeController(); |
396 | expect(ManagerHelperService.loadManagers).toHaveBeenCalledWith( |
397 | $scope, [ |
398 | - MachinesManager, ControllersManager, ZonesManager, |
399 | - GeneralManager, UsersManager, TagsManager, DomainsManager, |
400 | - ServicesManager]); |
401 | + MachinesManager, DevicesManager, ControllersManager, |
402 | + ZonesManager, GeneralManager, UsersManager, TagsManager, |
403 | + DomainsManager, ServicesManager]); |
404 | }); |
405 | |
406 | it("doesnt call setActiveItem if node is loaded", function() { |
407 | |
408 | === modified file 'src/maasserver/static/js/angular/factories/devices.js' |
409 | --- src/maasserver/static/js/angular/factories/devices.js 2016-09-27 00:47:54 +0000 |
410 | +++ src/maasserver/static/js/angular/factories/devices.js 2017-03-02 00:31:00 +0000 |
411 | @@ -11,16 +11,17 @@ |
412 | |
413 | angular.module('MAAS').factory( |
414 | 'DevicesManager', |
415 | - ['$q', '$rootScope', 'RegionConnection', 'Manager', function( |
416 | - $q, $rootScope, RegionConnection, Manager) { |
417 | + ['$q', '$rootScope', 'RegionConnection', 'NodesManager', function( |
418 | + $q, $rootScope, RegionConnection, NodesManager) { |
419 | |
420 | function DevicesManager() { |
421 | - Manager.call(this); |
422 | + NodesManager.call(this); |
423 | |
424 | this._pk = "system_id"; |
425 | this._handler = "device"; |
426 | this._metadataAttributes = { |
427 | "owner": null, |
428 | + "subnets": null, |
429 | "tags": null, |
430 | "zone": function(device) { |
431 | return device.zone.name; |
432 | @@ -34,7 +35,7 @@ |
433 | }); |
434 | } |
435 | |
436 | - DevicesManager.prototype = new Manager(); |
437 | + DevicesManager.prototype = new NodesManager(); |
438 | |
439 | // Create a device. |
440 | DevicesManager.prototype.create = function(node) { |
441 | |
442 | === modified file 'src/maasserver/static/js/angular/factories/tests/test_devices.js' |
443 | --- src/maasserver/static/js/angular/factories/tests/test_devices.js 2016-09-27 14:24:19 +0000 |
444 | +++ src/maasserver/static/js/angular/factories/tests/test_devices.js 2017-03-02 00:31:00 +0000 |
445 | @@ -46,7 +46,7 @@ |
446 | expect(DevicesManager._pk).toBe("system_id"); |
447 | expect(DevicesManager._handler).toBe("device"); |
448 | expect(Object.keys(DevicesManager._metadataAttributes)).toEqual( |
449 | - ["owner", "tags", "zone"]); |
450 | + ["owner", "subnets", "tags", "zone"]); |
451 | }); |
452 | |
453 | describe("createInferface", function() { |
454 | |
455 | === modified file 'src/maasserver/static/partials/node-details.html' |
456 | --- src/maasserver/static/partials/node-details.html 2017-03-01 07:12:26 +0000 |
457 | +++ src/maasserver/static/partials/node-details.html 2017-03-02 00:31:00 +0000 |
458 | @@ -30,7 +30,7 @@ |
459 | data-ng-click="saveEditHeader()">Save</a> |
460 | |
461 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> |
462 | - <p class="page-header__status" data-ng-hide="isController || header.editing"> |
463 | + <p class="page-header__status" data-ng-if="!isController && !isDevice && !header.editing"> |
464 | {$ node.status $} |
465 | <span class="u-text--{$ getPowerStateClass() $} u-margin--left-small"><i class="icon icon--power-{$ getPowerStateClass() $} u-margin--right-tiny"></i>{$ getPowerStateText() $}</span> |
466 | <a href="" class="page-header__status-check" data-ng-show="canCheckPowerState()" data-ng-click="checkPowerState()">check now</a> |
467 | @@ -47,7 +47,7 @@ |
468 | <!-- XXX blake_r 2015-02-19 - Need to add e2e test. --> |
469 | <div class="page-header__dropdown" data-ng-class="{ 'is-open': actionOption }"> |
470 | |
471 | - <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="!node.dhcp_on"> |
472 | + <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-if="!isDevice && !node.dhcp_on"> |
473 | <p class="page-header__message page-header__message--warning"> |
474 | MAAS is not providing DHCP. |
475 | </p> |
476 | @@ -89,58 +89,20 @@ |
477 | <div class="page-header__controls"> |
478 | <a href="" class="button--base button--inline" data-ng-click="actionCancel()">Cancel</a> |
479 | <button class="button--inline" data-ng-class="actionOption.name === 'delete' ? 'button--destructive' : 'button--positive'" data-ng-click="actionGo('nodes')" data-ng-hide="hasActionsFailed('nodes')"> |
480 | - <span data-ng-if="actionOption.name === 'commission'">Commission |
481 | - <span data-ng-if="!isController">machine</span> |
482 | - <span data-ng-if="isController">controller</span> |
483 | - </span> |
484 | - <span data-ng-if="actionOption.name === 'acquire'">Acquire |
485 | - <span data-ng-if="!isController">machine</span> |
486 | - <span data-ng-if="isController">controller</span> |
487 | - </span> |
488 | - <span data-ng-if="actionOption.name === 'deploy'">Deploy |
489 | - <span data-ng-if="!isController">machine</span> |
490 | - <span data-ng-if="isController">controller</span> |
491 | - </span> |
492 | - <span data-ng-if="actionOption.name === 'release'">Release |
493 | - <span data-ng-if="!isController">machine</span> |
494 | - <span data-ng-if="isController">controller</span> |
495 | - </span> |
496 | - <span data-ng-if="actionOption.name === 'set-zone'">Set zone for |
497 | - <span data-ng-if="!isController">machine</span> |
498 | - <span data-ng-if="isController">controller</span> |
499 | - </span> |
500 | - <span data-ng-if="actionOption.name === 'on'">Power on |
501 | - <span data-ng-if="!isController">machine</span> |
502 | - <span data-ng-if="isController">controller</span> |
503 | - </span> |
504 | - <span data-ng-if="actionOption.name === 'off'">Power off |
505 | - <span data-ng-if="!isController">machine</span> |
506 | - <span data-ng-if="isController">controller</span> |
507 | - </span> |
508 | - <span data-ng-if="actionOption.name === 'abort'">Abort action on |
509 | - <span data-ng-if="!isController">machine</span> |
510 | - <span data-ng-if="isController">controller</span> |
511 | - </span> |
512 | - <span data-ng-if="actionOption.name === 'rescue-mode'">Rescue |
513 | - <span data-ng-if="!isController">machine</span> |
514 | - <span data-ng-if="isController">controller</span> |
515 | - </span> |
516 | - <span data-ng-if="actionOption.name === 'exit-rescue-mode'">Exit rescue mode |
517 | - </span> |
518 | - <span data-ng-if="actionOption.name === 'mark-broken'">Mark |
519 | - <span data-ng-if="!isController">machine</span> |
520 | - <span data-ng-if="isController">controller</span> as broken |
521 | - </span> |
522 | - <span data-ng-if="actionOption.name === 'mark-fixed'">Mark |
523 | - <span data-ng-if="!isController">machine</span> |
524 | - <span data-ng-if="isController">controller</span> as fixed |
525 | - </span> |
526 | - <span data-ng-if="actionOption.name === 'delete'">Delete |
527 | - <span data-ng-if="!isController">machine</span> |
528 | - <span data-ng-if="isController">controller</span> |
529 | - </span> |
530 | - <span data-ng-if="actionOption.name === 'import-images'">Import images |
531 | - </span> |
532 | + <span data-ng-if="actionOption.name === 'commission'">Commission {$ type_name $}</span> |
533 | + <span data-ng-if="actionOption.name === 'acquire'">Acquire {$ type_name $}</span> |
534 | + <span data-ng-if="actionOption.name === 'deploy'">Deploy {$ type_name $}</span> |
535 | + <span data-ng-if="actionOption.name === 'release'">Release {$ type_name $}</span> |
536 | + <span data-ng-if="actionOption.name === 'set-zone'">Set zone for {$ type_name $}</span> |
537 | + <span data-ng-if="actionOption.name === 'on'">Power on {$ type_name $}</span> |
538 | + <span data-ng-if="actionOption.name === 'off'">Power off {$ type_name $}</span> |
539 | + <span data-ng-if="actionOption.name === 'abort'">Abort action on {$ type_name $}</span> |
540 | + <span data-ng-if="actionOption.name === 'rescue-mode'">Rescue {$ type_name $}</span> |
541 | + <span data-ng-if="actionOption.name === 'exit-rescue-mode'">Exit rescue mode</span> |
542 | + <span data-ng-if="actionOption.name === 'mark-broken'">Mark {$ type_name $}</span> |
543 | + <span data-ng-if="actionOption.name === 'mark-fixed'">Mark {$ type_name $}</span> |
544 | + <span data-ng-if="actionOption.name === 'delete'">Delete {$ type_name $}</span> |
545 | + <span data-ng-if="actionOption.name === 'import-images'">Import images</span> |
546 | </button> |
547 | </div> |
548 | </form> |
549 | @@ -201,12 +163,13 @@ |
550 | </nav> --> |
551 | <div class="row" id="summary"> |
552 | <div class="wrapper--inner"> |
553 | - <h2 data-ng-hide="isController" class="eight-col">Machine summary</h2> |
554 | - <h2 data-ng-show="isController" class="eight-col">Controller summary</h2> |
555 | - <div data-ng-hide="isController"> |
556 | + <h2 data-ng-if="!isController && !isDevice" class="eight-col">Machine summary</h2> |
557 | + <h2 data-ng-if="isController" class="eight-col">Controller summary</h2> |
558 | + <h2 data-ng-if="isDevice" class="eight-col">Device summary</h2> |
559 | + <div data-ng-if="!isController"> |
560 | <div class="four-col last-col u-align--right" data-ng-hide="summary.editing"> |
561 | <a href="" class="button--secondary button--inline" |
562 | - data-ng-show="canEdit()" |
563 | + data-ng-if="canEdit()" |
564 | data-ng-click="editSummary()">Edit</a> |
565 | </div> |
566 | <div class="four-col last-col u-align--right ng-hide" data-ng-show="summary.editing"> |
567 | @@ -219,17 +182,17 @@ |
568 | </div> |
569 | <div class="twelve-col" data-ng-if="isSuperUser()"> |
570 | <div class="p-notification--error" |
571 | - data-ng-if="!isController && !isRackControllerConnected()"> |
572 | + data-ng-if="!isController && !isDevice && !isRackControllerConnected()"> |
573 | <p class="p-notification__response"> |
574 | <span class="p-notification__status">Error:</span>Editing is currently disabled because no rack controller is currently connected to the region.</p> |
575 | </div> |
576 | <div class="p-notification--error" |
577 | - data-ng-if="!isController && hasInvalidArchitecture() && isRackControllerConnected() && hasUsableArchitectures()"> |
578 | + data-ng-if="!isController && !isDevice && hasInvalidArchitecture() && isRackControllerConnected() && hasUsableArchitectures()"> |
579 | <p class="p-notification__response"> |
580 | <span class="p-notification__status">Error:</span>This machine currently has an invalid architecture. Update the architecture of this machine to make it deployable.</p> |
581 | </div> |
582 | <div class="p-notification--error" |
583 | - data-ng-if="!isController && hasInvalidArchitecture() && isRackControllerConnected() && !hasUsableArchitectures()"> |
584 | + data-ng-if="!isController && !isDevice && hasInvalidArchitecture() && isRackControllerConnected() && !hasUsableArchitectures()"> |
585 | <p class="p-notification__response"> |
586 | <span class="p-notification__status">Error:</span>No boot images have been imported for a valid architecture to be selected. Visit the <a href="images">images page</a> to start the import process.</p> |
587 | </div> |
588 | @@ -247,7 +210,7 @@ |
589 | </select> |
590 | </div> |
591 | </div> |
592 | - <div class="form__group"> |
593 | + <div class="form__group" data-ng-if="!isDevice"> |
594 | <label for="architecture" class="form__group-label two-col">Architecture</label> |
595 | <div class="form__group-input three-col"> |
596 | <select name="architecture" id="architecture" |
597 | @@ -259,7 +222,7 @@ |
598 | </select> |
599 | </div> |
600 | </div> |
601 | - <div class="form__group"> |
602 | + <div class="form__group" data-ng-if="!isDevice"> |
603 | <label for="min_hwe_kernel" class="form__group-label two-col">Minimum Kernel</label> |
604 | <div class="form__group-input three-col"> |
605 | <select name="min_hwe_kernel" id="min_hwe_kernel" placeholder="No minimum kernel" |
606 | @@ -293,7 +256,7 @@ |
607 | <dd class="four-col last-col"> |
608 | {$ node.zone.name $} |
609 | </dd> |
610 | - <dt class="two-col">Architecture</dt> |
611 | + <dt class="two-col" data-ng-if="!isDevice">Architecture</dt> |
612 | <dd class="four-col last-col"> |
613 | {$ node.architecture || "Missing" $} |
614 | </dd> |
615 | @@ -336,7 +299,7 @@ |
616 | </dd> |
617 | </dl> |
618 | </div> |
619 | - <div class="six-col last-col"> |
620 | + <div class="six-col last-col" data-ng-if="!isDevice"> |
621 | <dl> |
622 | <dt class="two-col">CPU</dt> |
623 | <dd class="four-col last-col"> |
624 | @@ -388,7 +351,7 @@ |
625 | </div> |
626 | </div> |
627 | </div> |
628 | - <div class="row" id="power" data-ng-show="!isController && isSuperUser()"> |
629 | + <div class="row" id="power" data-ng-if="!isController && !isDevice && isSuperUser()"> |
630 | <div class="wrapper--inner"> |
631 | <h2 class="eight-col">Power</h2> |
632 | <div class="four-col last-col u-align--right" data-ng-hide="power.editing"> |
633 | @@ -613,8 +576,8 @@ |
634 | <h2 class="title">Interfaces</h2> |
635 | </div> |
636 | <div class="twelve-col" data-ng-if=" |
637 | - (!isController && isAllNetworkingDisabled() && isSuperUser()) || |
638 | - !node.on_network || (!isController && !isUbuntuOS())"> |
639 | + !isDevice && ((!isController && isAllNetworkingDisabled() && isSuperUser()) || |
640 | + !node.on_network || (!isController && !isUbuntuOS()))"> |
641 | <div class="p-notification--error" data-ng-if="!node.on_network"> |
642 | <p class="p-notification__response"> |
643 | <span class="p-notification__status">Error:</span>Node must be connected to a network.</p> |
644 | @@ -633,8 +596,9 @@ |
645 | <div class="table table--hover u-margin--bottom"> |
646 | <header class="table__head"> |
647 | <div class="table__row"> |
648 | - <div class="table__header table-col--3"></div> |
649 | + <div class="table__header table-col--3" data-ng-if="!isDevice"></div> |
650 | <div class="table__header table-col--12"> |
651 | + <span data-ng-if="!isDevice"> |
652 | <a class="table__header-link is-active" |
653 | data-ng-class="{ 'is-active': column == 'name' }" |
654 | data-ng-click="column = 'name'"> |
655 | @@ -645,11 +609,16 @@ |
656 | data-ng-click="column = 'mac'"> |
657 | MAC |
658 | </a> |
659 | - </div> |
660 | - <div class="table__header table-col--3"><span data-ng-if="!isController">PXE</span></div> |
661 | - <div class="table__header table-col--9">Type</div> |
662 | - <div class="table__header table-col--14">Fabric</div> |
663 | - <div class="table__header table-col--14">VLAN</div> |
664 | + </span> |
665 | + <span data-ng-if="isDevice">MAC</span> |
666 | + </div> |
667 | + <div class="table__header table-col--3"><span data-ng-if="!isController && !isDevice">PXE</span></div> |
668 | + <div class="table__header table-col--9"><span data-ng-if="!isDevice">Type</span></div> |
669 | + <div class="table__header table-col--14"> |
670 | + <span data-ng-if="!isDevice">Fabric</span> |
671 | + <span data-ng-if="isDevice">IP Assignment</span> |
672 | + </div> |
673 | + <div class="table__header table-col--14"><span data-ng-if="!isDevice">VLAN</span></div> |
674 | <div class="table__header table-col--18">Subnet</div> |
675 | <div class="table__header table-col--27">IP Address</div> |
676 | </div> |
677 | @@ -658,7 +627,7 @@ |
678 | <div class="table__row" |
679 | data-ng-class="{ disabled: isDisabled(), 'is-active': isInterfaceSelected(interface) && (isNodeEditingAllowed() || isLimitedEditingAllowed(interface)), noEdit: cannotEditInterface(interface) }" |
680 | data-ng-repeat="interface in interfaces | removeInterfaceParents:newBondInterface:!isNodeEditingAllowed() | removeInterfaceParents:newBridgeInterface:!isNodeEditingAllowed()"> |
681 | - <div class="table__data table-col--3" aria-label="Select"> |
682 | + <div class="table__data table-col--3" data-ng-if="!isDevice" aria-label="Select"> |
683 | <input type="checkbox" class="checkbox" id="{$ getUniqueKey(interface) $}" |
684 | data-ng-hide="isAllNetworkingDisabled()" |
685 | data-ng-checked="isInterfaceSelected(interface)" |
686 | @@ -667,43 +636,48 @@ |
687 | data-ng-if="!isController && isNodeEditingAllowed()"> |
688 | <label for="{$ getUniqueKey(interface) $}"></label> |
689 | </div> |
690 | - <div class="table__data table-col--12" aria-label="Name" data-ng-show="column == 'name'"> |
691 | + <div class="table__data table-col--12" aria-label="Name" data-ng-if="!isDevice" data-ng-show="column == 'name'"> |
692 | <span data-ng-if="!isEditing(interface)">{$ interface.name $}</span> |
693 | <input type="text" class="table__input" |
694 | data-ng-if="isEditing(interface) && interface.type != 'vlan'" |
695 | data-ng-model="editInterface.name" |
696 | data-ng-class="{ 'has-error': isInterfaceNameInvalid(editInterface) }"> |
697 | </div> |
698 | - <div class="table__data table-col--12 ng-hide" data-ng-show="column == 'mac'"> |
699 | + <div class="table__data table-col--12 ng-hide" data-ng-if="!isDevice" data-ng-show="column == 'mac'"> |
700 | {$ interface.mac_address $} |
701 | </div> |
702 | + <div class="table__data table-col--12" data-ng-if="isDevice">{$ interface.mac_address $}</div> |
703 | <div class="table__data table-col--3 u-align--center" aria-label="Boot interface"> |
704 | <input type="radio" name="bootInterface" id="{$ interface.name $}" checked |
705 | - data-ng-if="!isController && isBootInterface(interface)" class="u-display--desktop"> |
706 | + data-ng-if="!isController && !isDevice && isBootInterface(interface)" class="u-display--desktop"> |
707 | <label for="{$ interface.name $}" class="u-display--desktop"></label> |
708 | - <span class="u-display--mobile" data-ng-if="!isController && isBootInterface(interface)">Yes</span> |
709 | - <span class="u-display--mobile" data-ng-if="!isController && !isBootInterface(interface)">No</span> |
710 | + <span class="u-display--mobile" data-ng-if="!isController && !isDevice && isBootInterface(interface)">Yes</span> |
711 | + <span class="u-display--mobile" data-ng-if="!isController && !isDevice && !isBootInterface(interface)">No</span> |
712 | </div> |
713 | <div class="table__data table-col--9" aria-label="Type"> |
714 | - <span data-ng-if="!isEditing(interface)">{$ getInterfaceTypeText(interface) $}</span> |
715 | + <span data-ng-if="!isDevice && !isEditing(interface)">{$ getInterfaceTypeText(interface) $}</span> |
716 | </div> |
717 | <div class="table__data table-col--14" aria-label="Fabric"> |
718 | - <span data-ng-if="!isEditing(interface)">{$ interface.fabric.name || "Disconnected" $}</span> |
719 | + <span data-ng-if="!isDevice && !isEditing(interface)">{$ interface.fabric.name || "Disconnected" $}</span> |
720 | + <span data-ng-if="isDevice && !isEditing(interface)">{$ getDeviceIPAssignment(interface.ip_assignment) $}</span> |
721 | </div> |
722 | <div class="table__data table-col--14" aria-label="VLAN"> |
723 | - <span data-ng-if="!isEditing(interface)">{$ getVLANText(interface.vlan) $}</span> |
724 | + <span data-ng-if="!isDevice && !isEditing(interface)">{$ getVLANText(interface.vlan) $}</span> |
725 | </div> |
726 | <div class="table__data table-col--18" aria-label="Subnet"> |
727 | - <span data-ng-if="!isEditing(interface) && interface.fabric">{$ getSubnetText(interface.subnet) $}</span> |
728 | + <span data-ng-if="!isEditing(interface) && ((isDevice && interface.subnet) || interface.fabric)">{$ getSubnetText(interface.subnet) $}</span> |
729 | <span data-ng-if="isAllNetworkingDisabled() && interface.discovered[0].subnet_id"> |
730 | {$ getSubnetText(getSubnet(interface.discovered[0].subnet_id)) $} |
731 | </span> |
732 | </div> |
733 | <div class="table__data table-col--19" aria-label="IP Address"> |
734 | - <span data-ng-if="!isEditing(interface) && !interface.discovered[0].ip_address && interface.fabric"> |
735 | + <span data-ng-if="isDevice"> |
736 | + {$ interface.ip_address $} |
737 | + </span> |
738 | + <span data-ng-if="!isDevice && !isEditing(interface) && !interface.discovered[0].ip_address && interface.fabric" > |
739 | {$ interface.ip_address $} ({$ getLinkModeText(interface) $}) |
740 | </span> |
741 | - <span data-ng-if="!isEditing(interface) && interface.discovered[0].ip_address && interface.fabric"> |
742 | + <span data-ng-if="!isDevice && !isEditing(interface) && interface.discovered[0].ip_address && interface.fabric"> |
743 | {$ interface.discovered[0].ip_address $} (DHCP) |
744 | </span> |
745 | </div> |
746 | @@ -711,7 +685,7 @@ |
747 | <div class="table__controls u-align--right" data-ng-if="isNodeEditingAllowed() || isLimitedEditingAllowed(interface)"> |
748 | <a class="u-display--desktop icon icon--add tooltip" |
749 | aria-label="Add Alias or VLAN" |
750 | - data-ng-if="canAddAliasOrVLAN(interface)" |
751 | + data-ng-if="!isDevice && canAddAliasOrVLAN(interface)" |
752 | data-ng-click="quickAdd(interface)"></a> |
753 | <a class="u-display--desktop icon icon--edit tooltip" |
754 | data-ng-if="!cannotEditInterface(interface)" |
755 | @@ -723,7 +697,7 @@ |
756 | data-ng-click="quickRemove(interface)"></a> |
757 | <a class="button--secondary u-display--mobile" |
758 | aria-label="Add Alias or VLAN" |
759 | - data-ng-if="canAddAliasOrVLAN(interface)" |
760 | + data-ng-if="!isDevice && canAddAliasOrVLAN(interface)" |
761 | data-ng-click="quickAdd(interface)">Add alias or VLAN</a> |
762 | <a class="button--secondary u-display--mobile" |
763 | data-ng-if="!cannotEditInterface(interface)" |
764 | @@ -837,8 +811,10 @@ |
765 | <div class="table__data table-col--100" data-ng-if="isEditing(interface)"> |
766 | <fieldset class="form__fieldset six-col"> |
767 | <dl> |
768 | + <span data-ng-if="!isDevice"> |
769 | <dt class="two-col">Type</dt> |
770 | <dd class="four-col last-col">{$ getInterfaceTypeText(interface) $}</dd> |
771 | + </span> |
772 | </dl> |
773 | <div class="form__group" data-ng-if="interface.type != 'alias' && interface.type != 'vlan'"> |
774 | <label for="mac" class="two-col">MAC address</label> |
775 | @@ -847,14 +823,14 @@ |
776 | data-ng-model="editInterface.mac_address" |
777 | data-ng-class="{ 'has-error': isMACAddressInvalid(editInterface.mac_address, true) }"> |
778 | </div> |
779 | - <div class="form__group" data-ng-if="!isLimitedEditingAllowed(interface)"> |
780 | + <div class="form__group" data-ng-if="!isDevice && !isLimitedEditingAllowed(interface)"> |
781 | <label class="two-col" data-ng-if="interface.type != 'alias'">Tags</label> |
782 | <div class="form__group-input three-col last-col" data-ng-if="interface.type != 'alias'"> |
783 | <tags-input ng-model="editInterface.tags" allow-tags-pattern="[\w-]+"></tags-input> |
784 | </div> |
785 | </div> |
786 | </fieldset> |
787 | - <fieldset class="form__fieldset six-col last-col" data-ng-if="!isLimitedEditingAllowed(interface)"> |
788 | + <fieldset class="form__fieldset six-col last-col" data-ng-if="!isDevice && !isLimitedEditingAllowed(interface)"> |
789 | <div class="form__group"> |
790 | <label for="fabric" class="two-col">Fabric</label> |
791 | <select name="fabric" class="three-col" |
792 | @@ -904,6 +880,42 @@ |
793 | </div> |
794 | </div> |
795 | </fieldset> |
796 | + <fieldset class="form__fieldset six-col last-col" data-ng-if="isDevice && !isLimitedEditingAllowed(interface)"> |
797 | + <div class="form__group"> |
798 | + <label for="ip-assignment" class="two-col">IP Assignment</label> |
799 | + <select name="ip-assignment" class="three-col" |
800 | + ng-model="editInterface.ip_assignment" |
801 | + data-ng-options="assignment.name as assignment.text for assignment in ipAssignments"> |
802 | + </select> |
803 | + </div> |
804 | + <div class="form__group" data-ng-if="editInterface.ip_assignment === 'static'"> |
805 | + <label for="subnet" class="two-col">Subnet</label> |
806 | + <select name="subnet" class="three-col" |
807 | + ng-init="editInterface.subnet = subnets[0]" |
808 | + ng-model="editInterface.subnet" |
809 | + data-ng-change="subnetChanged(newInterface)" |
810 | + data-ng-options="subnet as getSubnetText(subnet) for subnet in subnets"> |
811 | + </select> |
812 | + </div> |
813 | + <div class="form__group" data-ng-if="editInterface.ip_assignment !== 'dynamic'"> |
814 | + <label for="ip-address" class="two-col">IP address</label> |
815 | + <div class="form__group-input three-col last-col"> |
816 | + <input name="ip-address" type="text" |
817 | + data-ng-if="editInterface.ip_assignment === 'static'" |
818 | + placeholder="IP address (optional)" |
819 | + ng-model="editInterface.ip_address" |
820 | + data-ng-class="{ 'has-error': isIPAddressInvalid(editInterface) }"> |
821 | + <input name="ip-address" type="text" |
822 | + data-ng-if="editInterface.ip_assignment !== 'static'" |
823 | + placeholder="IP address" |
824 | + ng-model="editInterface.ip_address" |
825 | + data-ng-class="{ 'has-error': isIPAddressInvalid(editInterface) }"> |
826 | + <ul class="errors u-margin--bottom-none form__group--errors" data-ng-if="getInterfaceError(editInterface)"> |
827 | + <li>{$ getInterfaceError(editInterface) $}</li> |
828 | + </ul> |
829 | + </div> |
830 | + </div> |
831 | + </fieldset> |
832 | </div> |
833 | </div> |
834 | <div class="table__row is-active" data-ng-if="isShowingDeleteConfirm()"> |
835 | @@ -1120,11 +1132,11 @@ |
836 | </div> |
837 | </div> |
838 | <div class="table__row is-active" data-ng-show="isShowingCreatePhysical()"> |
839 | - <div class="table__data table-col--3"> |
840 | + <div class="table__data table-col--3" data-ng-if="!isDevice"> |
841 | <input type="checkbox" class="checkbox" id="interface-create" disabled="disabled" checked /> |
842 | <label for="interface-create"></label> |
843 | </div> |
844 | - <div class="table__data table-col--12"> |
845 | + <div class="table__data table-col--12" data-ng-if="!isDevice"> |
846 | <input type="text" class="table__input" |
847 | data-ng-class="{ 'has-error': isInterfaceNameInvalid(newInterface) }" |
848 | data-ng-model="newInterface.name"> |
849 | @@ -1136,9 +1148,9 @@ |
850 | </h2> |
851 | <i data-ng-click="cancel()" class="icon icon--remove u-float--right u-margin--top-small u-margin--right-small"></i> |
852 | </div> |
853 | - <div class="table__row form form--stack is-active"> |
854 | + <div class="table__row form form--stack is-active" data-ng-if="!isDevice"> |
855 | <div class="table__data table-col--100"> |
856 | - <div class="form__fieldset six-col"> |
857 | + <div class="form__fieldset six-col" data-ng-if="!isDevice"> |
858 | <div class="form__group u-display--mobile"> |
859 | <label for="new-interface-name" class="two-col">Name</label> |
860 | <input type="text" class="three-col" id="new-interface-name" |
861 | @@ -1206,6 +1218,55 @@ |
862 | </div> |
863 | </div> |
864 | </div> |
865 | + <div class="table__row form form--stack is-active"> |
866 | + <div class="table__data table-col--100" data-ng-if="isDevice"> |
867 | + <fieldset class="form__fieldset six-col"> |
868 | + <div class="form__group"> |
869 | + <label for="mac" class="two-col">MAC address</label> |
870 | + <input name="mac" type="text" class="three-col" |
871 | + placeholder="00:00:00:00:00:00" |
872 | + data-ng-model="newInterface.mac_address" |
873 | + data-ng-class="{ 'has-error': isMACAddressInvalid(newInterface.mac_address, true) }"> |
874 | + </div> |
875 | + </fieldset> |
876 | + <fieldset class="form__fieldset six-col last-col" data-ng-if="!isLimitedEditingAllowed(interface)"> |
877 | + <div class="form__group"> |
878 | + <label for="ip-assignment" class="two-col">IP Assignment</label> |
879 | + <select name="ip-assignment" class="three-col" |
880 | + ng-model="newInterface.ip_assignment" |
881 | + data-ng-options="assignment.name as assignment.text for assignment in ipAssignments"> |
882 | + </select> |
883 | + </div> |
884 | + <div class="form__group" data-ng-if="newInterface.ip_assignment === 'static'"> |
885 | + <label for="subnet" class="two-col">Subnet</label> |
886 | + <select name="subnet" class="three-col" |
887 | + ng-init="newInterface.subnet = subnets[0]" |
888 | + ng-model="newInterface.subnet" |
889 | + data-ng-change="subnetChanged(newInterface)" |
890 | + data-ng-options="subnet as getSubnetText(subnet) for subnet in subnets"> |
891 | + </select> |
892 | + </div> |
893 | + <div class="form__group" data-ng-if="newInterface.ip_assignment !== 'dynamic'"> |
894 | + <label for="ip-address" class="two-col">IP address</label> |
895 | + <div class="form__group-input three-col last-col"> |
896 | + <input name="ip-address" type="text" |
897 | + data-ng-if="editInterface.ip_assignment === 'static'" |
898 | + placeholder="IP address (optional)" |
899 | + ng-model="newInterface.ip_address" |
900 | + data-ng-class="{ 'has-error': isIPAddressInvalid(newInterface) }"> |
901 | + <input name="ip-address" type="text" |
902 | + data-ng-if="editInterface.ip_assignment !== 'static'" |
903 | + placeholder="IP address" |
904 | + ng-model="newInterface.ip_address" |
905 | + data-ng-class="{ 'has-error': isIPAddressInvalid(newInterface) }"> |
906 | + <ul class="errors u-margin--bottom-none form__group--errors" data-ng-if="getInterfaceError(newInterface)"> |
907 | + <li>{$ getInterfaceError(newInterface) $}</li> |
908 | + </ul> |
909 | + </div> |
910 | + </div> |
911 | + </fieldset> |
912 | + </div> |
913 | + </div> |
914 | <div class="table__row is-active"> |
915 | <div class="table__data u-float--left" data-ng-show="newInterface.errorMsg"> |
916 | <span class="icon icon--error u-margin--right-small"></span>{$ newInterface.errorMsg $} |
917 | @@ -1221,7 +1282,7 @@ |
918 | </div> |
919 | </main> |
920 | </div> |
921 | - <div data-ng-if="!isController" data-ng-hide="isAllNetworkingDisabled() || isShowingCreateBond() || isShowingCreatePhysical()"> |
922 | + <div data-ng-if="!isController && !isDevice" data-ng-hide="isAllNetworkingDisabled() || isShowingCreateBond() || isShowingCreatePhysical()"> |
923 | <a class="button--secondary button--inline" |
924 | data-ng-disabled="selectedMode !== null" |
925 | data-ng-click="showCreatePhysical()">Add interface</a> |
926 | @@ -1232,12 +1293,17 @@ |
927 | data-ng-disabled="!canCreateBridge()" |
928 | data-ng-click="showCreateBridge()">Create bridge</a> |
929 | </div> |
930 | + <div data-ng-if="isDevice" data-ng-hide="isAllNetworkingDisabled() || isShowingCreateBond() || isShowingCreatePhysical()"> |
931 | + <a class="button--secondary button--inline" |
932 | + data-ng-disabled="selectedMode !== null" |
933 | + data-ng-click="showCreatePhysical()">Add interface</a> |
934 | + </div> |
935 | </div> |
936 | </form> |
937 | </div> |
938 | </div> |
939 | </div> |
940 | - <div class="row" id="storage" data-ng-hide="isController"> |
941 | + <div class="row" id="storage" data-ng-if="!isController && !isDevice"> |
942 | <div class="wrapper--inner" ng-controller="NodeStorageController"> |
943 | <form> |
944 | <div class="twelve-col"> |
945 | @@ -2223,7 +2289,7 @@ |
946 | </form> |
947 | </div> |
948 | </div> |
949 | - <div class="row" id="events"> |
950 | + <div class="row" id="events" data-ng-if="!isDevice"> |
951 | <div class="wrapper--inner"> |
952 | <div class="eight-col"> |
953 | <h2 class="title">Latest {$ type_name $} events</h2> |
954 | |
955 | === modified file 'src/maasserver/static/partials/nodes-list.html' |
956 | --- src/maasserver/static/partials/nodes-list.html 2017-02-17 14:23:04 +0000 |
957 | +++ src/maasserver/static/partials/nodes-list.html 2017-03-02 00:31:00 +0000 |
958 | @@ -902,7 +902,9 @@ |
959 | <input type="checkbox" class="checkbox" data-ng-click="toggleChecked(device, 'devices')" data-ng-checked="device.$selected" id="{$ device.fqdn $}" data-ng-disabled="hasActionsInProgress('devices')"/> |
960 | <label for="{$ device.fqdn $}" class="checkbox-label"></label> |
961 | </td> |
962 | - <td class="table-col--24" aria-label="FQDN">{$ device.fqdn $}</td> |
963 | + <td class="table-col--24" aria-label="FQDN"> |
964 | + <a href="#/node/device/{$ device.system_id $}">{$ device.fqdn $}</a> |
965 | + </td> |
966 | <td class="table-col--25" aria-label="MAC"> |
967 | {$ device.primary_mac $} |
968 | <span class="extra-macs" data-ng-show="device.extra_macs.length">(+{$ device.extra_macs.length $})</span> |
Just some comments on the code. I am pulling it now to test it locally.