Merge ~ya-bo-ng/maas:kvm-single-pod-view into maas:master

Proposed by Anthony Dillon
Status: Merged
Approved by: Anthony Dillon
Approved revision: 0b4cf94d0d5401f9e008e648b0d9eb3ca17d82a3
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~ya-bo-ng/maas:kvm-single-pod-view
Merge into: maas:master
Diff against target: 934 lines (+611/-87)
16 files modified
src/maasserver/static/js/angular/controllers/pod_details.js (+12/-1)
src/maasserver/static/js/angular/filters/range.js (+14/-0)
src/maasserver/static/js/angular/filters/tests/test_range.js (+28/-0)
src/maasserver/static/partials/nodes-list.html (+0/-1)
src/maasserver/static/partials/pod-details.html (+132/-47)
src/maasserver/static/scss/_base_forms.scss (+5/-0)
src/maasserver/static/scss/_base_typography.scss (+5/-1)
src/maasserver/static/scss/_maas.scss (+2/-0)
src/maasserver/static/scss/_patterns_button.scss (+16/-3)
src/maasserver/static/scss/_patterns_icons.scss (+30/-0)
src/maasserver/static/scss/_patterns_meter.scss (+140/-11)
src/maasserver/static/scss/_patterns_pod-summary.scss (+191/-0)
src/maasserver/static/scss/_patterns_slider.scss (+28/-0)
src/maasserver/static/scss/_utils.scss (+5/-0)
src/maasserver/static/scss/build.scss (+3/-0)
src/maasserver/templates/maasserver/index.html (+0/-23)
Reviewer Review Type Date Requested Status
Blake Rouse (community) Approve
Kit Randel (community) Approve
MAAS Lander Needs Fixing
Review via email: mp+355124@code.launchpad.net

Commit message

Developed the KVM single pod view UI

Description of the change

On the pod details page there is now a pod view section which displays details of the pod.

https://screenshots.firefox.com/McucA7rgOFXY1JgQ/10.54.72.65

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b kvm-single-pod-view lp:~ya-bo-ng/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/3950/console
COMMIT: 1e548afe07ffe9c4202a08cd92589079fdbac008

review: Needs Fixing
Revision history for this message
Kit Randel (blr) wrote :

A few inline comments

Revision history for this message
Kit Randel (blr) wrote :

lgtm. You might want to consider setting:

"files.trimTrailingWhitespace": true

in your vscode user settings.

Revision history for this message
Kit Randel (blr) :
review: Approve
Revision history for this message
Blake Rouse (blake-rouse) :
review: Needs Fixing
Revision history for this message
Anthony Dillon (ya-bo-ng) wrote :

Blake, back now and added copyToClipboard stuff.

Revision history for this message
Blake Rouse (blake-rouse) wrote :

Looks good, other than the comment below. Should think about moving that into a directive. Its okay for now as I think this is the only place it is needed, but should look into cleaning that up in a later branch or when another copy to clipboard is needed.

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
~ya-bo-ng/maas:kvm-single-pod-view updated
0b4cf94... by Anthony Dillon

Lint the copytoclipboard functions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/static/js/angular/controllers/pod_details.js b/src/maasserver/static/js/angular/controllers/pod_details.js
2index 8f015cc..50ff985 100644
3--- a/src/maasserver/static/js/angular/controllers/pod_details.js
4+++ b/src/maasserver/static/js/angular/controllers/pod_details.js
5@@ -267,6 +267,17 @@ angular.module('MAAS').controller('PodDetailsController', [
6 return params;
7 };
8
9+ $scope.copyToClipboard = function($event) {
10+ var clipboardParent = $event.currentTarget.previousSibling;
11+ var clipboardValue = clipboardParent.previousSibling.value;
12+ var el = document.createElement('textarea');
13+ el.value = clipboardValue;
14+ document.body.appendChild(el);
15+ el.select();
16+ document.execCommand('copy');
17+ document.body.removeChild(el);
18+ };
19+
20 // Called to cancel composition.
21 $scope.cancelCompose = function() {
22 $scope.compose.obj = {
23@@ -374,4 +385,4 @@ angular.module('MAAS').controller('PodDetailsController', [
24 });
25 }
26 });
27- }]);
28+ }]);
29\ No newline at end of file
30diff --git a/src/maasserver/static/js/angular/filters/range.js b/src/maasserver/static/js/angular/filters/range.js
31new file mode 100644
32index 0000000..76126ef
33--- /dev/null
34+++ b/src/maasserver/static/js/angular/filters/range.js
35@@ -0,0 +1,14 @@
36+
37+
38+angular.module('MAAS').filter('range', function() {
39+ return function(n) {
40+ var res = [];
41+ if (typeof n != 'number') {
42+ return res;
43+ }
44+ for (var i = 0; i < n; i++) {
45+ res.push(i);
46+ }
47+ return res;
48+ };
49+});
50\ No newline at end of file
51diff --git a/src/maasserver/static/js/angular/filters/tests/test_range.js b/src/maasserver/static/js/angular/filters/tests/test_range.js
52new file mode 100644
53index 0000000..ba44e8e
54--- /dev/null
55+++ b/src/maasserver/static/js/angular/filters/tests/test_range.js
56@@ -0,0 +1,28 @@
57+/* Copyright 2018 Canonical Ltd. This software is licensed under the
58+ * GNU Affero General Public License version 3 (see the file LICENSE).
59+ *
60+ * Unit tests for filterRange.
61+ */
62+
63+describe("filterRange", function() {
64+
65+ // Load the MAAS module.
66+ beforeEach(module("MAAS"));
67+
68+ // Load the filterRange.
69+ var filterRange;
70+ beforeEach(inject(function($filter) {
71+ filterRange = $filter("range");
72+ }));
73+
74+ it("returns empty if invalid range", function() {
75+ var array = undefined;
76+ expect(filterRange(array)).toEqual([]);
77+ });
78+
79+ it("returns correct length array", function() {
80+ var i = 3;
81+ var len = filterRange(i).length;
82+ expect(len).toEqual(i);
83+ });
84+});
85\ No newline at end of file
86diff --git a/src/maasserver/static/partials/nodes-list.html b/src/maasserver/static/partials/nodes-list.html
87index 4df56df..699765f 100644
88--- a/src/maasserver/static/partials/nodes-list.html
89+++ b/src/maasserver/static/partials/nodes-list.html
90@@ -525,7 +525,6 @@
91 </div>
92 </div>
93 </div>
94-
95 <div class="ng-hide" data-ng-show="tabs.controllers.actionOption.name === 'test'">
96 <div class="p-form__group">
97 <input id="enable_SSH" type="checkbox"
98diff --git a/src/maasserver/static/partials/pod-details.html b/src/maasserver/static/partials/pod-details.html
99index 1b41b4d..4908ef6 100644
100--- a/src/maasserver/static/partials/pod-details.html
101+++ b/src/maasserver/static/partials/pod-details.html
102@@ -5,8 +5,8 @@
103 </div>
104 </header>
105 </div>
106-<div class="ng-hide u-no-margin--top" data-ng-show="loaded" data-window-width>
107- <header class="p-strip--light is-shallow u-no-padding--bottom page-header u-no-padding--bottom" media-query="min-width: 769px">
108+<div class="ng-hide" data-ng-show="loaded" data-window-width>
109+ <header class="p-strip--light is-shallow page-header u-no-padding--bottom" media-query="min-width: 769px">
110 <div class="row">
111 <div class="tablet-col-4 col-8">
112 <h1 class="page-header__title">
113@@ -16,7 +16,7 @@
114 data-ng-model="name.value"
115 data-ng-disabled="!canEdit()"
116 data-ng-click="editName()"></span>
117- </h1>
118+ </h1>
119 <button class="p-button--base u-no-margin--top ng-hide"
120 data-ng-show="name.editing"
121 data-ng-click="cancelEditName()">Cancel</button>
122@@ -26,7 +26,7 @@
123 data-ng-click="saveEditName()">Save</button>
124 </div>
125 <div class="tablet-col-2 col-4">
126- <div class="page-header__controls " data-ng-if="isSuperUser()">
127+ <div class="page-header__controls" data-ng-if="isSuperUser()">
128 <div data-maas-cta="action.options"
129 data-ng-model="action.option"
130 data-ng-change="actionOptionChanged()">
131@@ -183,55 +183,138 @@
132 </div>
133 </header>
134
135- <section class="p-strip" data-ng-if="section.area === 'summary'">
136+ <section data-ng-if="section.area === 'summary'">
137 <div class="row">
138- <aside class="col-3">
139- <div class="p-card">
140- <h3 class="p-heading--four">CPU ({$ pod.total.cores $} cores)</h3>
141- <meter class="p-meter" max="{$ pod.total.cores $}" value="{$ pod.used.cores $}"></meter>
142- <p>
143- <span>{$ pod.available.cores $} cores available</span>
144- <span class="u-float--right u-no-margin--top" data-ng-if="windowWidth >= 1180">{$ pod.used.cores $} cores used</span>
145- </p>
146- </div>
147- <div class="p-card">
148- <h3 class="p-heading--four">RAM ({$ pod.total.memory_gb $}&nbsp;GiB)</h3>
149- <meter class="p-meter" max="{$ pod.total.memory $}" value="{$ pod.used.memory $}"></meter>
150- <p>
151- <span>{$ pod.available.memory_gb $} GiB available</span>
152- <span class="u-float--right u-no-margin--top" data-ng-if="windowWidth >= 1180">{$ pod.used.memory_gb $} GiB used</span>
153- </p>
154+ <section class="p-strip">
155+ <div class="p-pod-edit">
156+ <label class="p-pod-edit__label" for="virsh">Virsh:</label>
157+ <div class="p-code-snippet-wrapper">
158+ <div class="p-code-snippet">
159+ <input class="p-code-snippet__input" value="{$ pod.power_address $}" readonly="readonly">
160+ <button class="p-code-snippet__action" data-ng-click="copyToClipboard($event)">Copy to clipboard</button>
161+ </div>
162+ </div>
163 </div>
164- <div class="p-card">
165- <h3 class="p-heading--four">Local storage ({$ pod.total.local_storage_gb $}&nbsp;GiB)</h3>
166- <meter class="p-meter" max="{$ pod.total.local_storage $}" value="{$ pod.used.local_storage $}"></meter>
167- <p>
168- <span>{$ pod.available.local_storage_gb $} GiB available</span>
169- <span class="u-float--right u-no-margin--top" data-ng-if="windowWidth >= 1180">{$ pod.used.local_storage_gb $} GiB used</span>
170- </p>
171+ </section>
172+ <div class="p-card--highlighted">
173+ <div class="p-pod-summary">
174+ <div class="p-pod-summary__aside">
175+ <div class="p-pod-summary__cpu">
176+ <div class="row">
177+ <h4>CPU cores: {$ pod.total.cores $}</h4>
178+ </div>
179+ <div class="p-meter--cpu-cores">
180+ <div class="p-meter--cpu-cores__container">
181+ <span class="p-meter--cpu-cores__core--used" ng-repeat="i in pod.used.cores | range"></span>
182+ <span class="p-meter--cpu-cores__core--available" ng-repeat="i in pod.available.cores | range"></span>
183+ </div>
184+ </div>
185+ <p class="u-no-max-width">
186+ <span>{$ pod.used.cores $} used</span>
187+ <span class="u-float--right">{$ pod.available.cores $} available</span>
188+ </p>
189+ </div>
190+ <div class="p-pod-summary__ram">
191+ <div class="row">
192+ <h4>RAM: {$ pod.total.memory_gb $} (GiB)</h4>
193+ </div>
194+ <div class="p-meter__container">
195+ <meter class="p-meter" max="{$ pod.total.memory $}" value="{$ pod.used.memory $}"></meter>
196+ </div>
197+ <p class="u-no-max-width">
198+ <span>{$ pod.used.memory_gb $} GiB used</span>
199+ <span class="u-float--right">{$ pod.available.memory_gb $} GiB available</span>
200+ </p>
201+ </div>
202+ </div>
203+ <div class="p-pod-summary__storage">
204+ <div class="row u-hide--large">
205+ <hr>
206+ </div>
207+ <div class="row">
208+ <div class="mobile-col-2 tablet-col-3 col-4">
209+ <h3 class="p-heading--four">Storage</h3>
210+ </div>
211+ </div>
212+ <ul class="p-list--divided">
213+ <li class="p-list__item u-no-padding" data-ng-repeat="storage in pod.storage_pools">
214+ <div class="p-storage row u-no-padding--top">
215+ <div class="p-storage__name tablet-col-3 col-4 u-clearfix">
216+ <p class="p-storage__disk-name">
217+ <strong>{$ storage.name $}</strong>
218+ <span class="p-storage__path">
219+ {$ storage.path $}
220+ </span>
221+ </p>
222+ <div class="p-storage__info">
223+ <p class="p-storage__type">{$ storage.type $}<br>
224+ <span class="p-storage__size">{$ storage.total $}</span>
225+ </p>
226+ </div>
227+ </div>
228+ <div class="p-storage__meter tablet-col-3 col-4">
229+ <div class="p-meter__container">
230+ <meter class="p-meter p-meter--kvm" max="{$ storage.total $}" value="{$ storage.used $}">
231+ <div class="p-meter__graph">
232+ <span class="p-meter__graph-content" style="width: calc(65600%/1024);">Disk Usage - {$ storage.used $} out of {$ storage.total $}</span>
233+ </div>
234+ </meter>
235+ </div>
236+ <div class="p-legend--numbers u-clearfix">
237+ <span class="p-legend__text default-text u-float--left">
238+ {$ storage.available $}
239+ </span>
240+ <span class="p-legend__text default-text u-float--right">
241+ {$ storage.used $}
242+ </span>
243+ </div>
244+ </div>
245+ </div>
246+ </li>
247+ </ul>
248+ <div class="row">
249+ <ul class="p-legend mobile-col-2 tablet-col-3 col-4 push-4">
250+ <li class="p-legend__item p-legend__item--used">
251+ <span class="p-legend__text default-text">
252+ Used
253+ </span>
254+ </li>
255+ <li class="p-legend__item p-legend__item--free">
256+ <span class="p-legend__text default-text">
257+ Free
258+ </span>
259+ </li>
260+ </ul>
261+ </div>
262+ </div>
263+ <div class="col-6"
264+ data-ng-if="pod.capabilities.indexOf('iscsi_storage') >= 0">
265+ <h3 class="p-heading--four">iSCSI storage ({$ pod.total.iscsi_storage_gb $}&nbsp;GiB)</h3>
266+ <div class="p-meter__container">
267+ <meter class="p-meter" max="{$ pod.total.iscsi_storage $}" value="{$ pod.used.iscsi_storage $}"></meter>
268+ </div>
269+ <p class="u-no-max-width">
270+ <span>{$ pod.used.iscsi_storage_gb $} GiB used</span>
271+ <span class="u-float--right">{$ pod.available.iscsi_storage_gb $} GiB available</span>
272+ </p>
273+ </div>
274 </div>
275- <div class="p-card" data-ng-if="pod.capabilities.indexOf('iscsi_storage') >= 0">
276- <h3 class="p-heading--four">iSCSI storage ({$ pod.total.iscsi_storage_gb $}&nbsp;GiB)</h3>
277- <meter class="p-meter" max="{$ pod.total.iscsi_storage $}" value="{$ pod.used.iscsi_storage $}"></meter>
278- <p>
279- <span>{$ pod.available.iscsi_storage_gb $} GiB available</span>
280- <span class="u-float--right u-no-margin--top" data-ng-if="windowWidth >= 1180">{$ pod.used.iscsi_storage_gb $} GiB used</span>
281- </p>
282+ </div>
283+ </div>
284+ <section class="p-strip">
285+ <div class="row">
286+ <div class="col-12" data-ng-if="pod.composed_machines_count">
287+ <maas-machines-table search="machinesSearch" hide-checkboxes="true"></maas-machines-table>
288 </div>
289- </aside>
290-
291- <div class="col-9" data-ng-if="pod.composed_machines_count">
292- <maas-machines-table search="machinesSearch" hide-checkboxes="true"></maas-machines-table>
293 </div>
294-
295- <div class="col-9" data-ng-if="!pod.composed_machines_count">
296- <div class="u-align--center u-vertical--align u-align--center">
297- <i class="p-icon--compose-machine" style="width: 128px; height: 128px;"></i>
298- <h3 class="p-heading--four">You have not composed any machines yet.</h3>
299- <button class="p-button--positive is-inline" data-ng-if="canCompose()" data-ng-click="composeMachine()">Compose machine</button>
300+ <div class="row">
301+ <div class="col-12 u-align--center" data-ng-if="!pod.composed_machines_count">
302+ <i class="p-icon--compose-machine u-no-margin" style="width: 128px; height: 128px;"></i>
303+ <h3 class="p-heading--four u-no-max-width">You have not composed any machines yet.</h3>
304+ <button class="p-button--positive is-inline u-no-margin" data-ng-if="canCompose()" data-ng-click="composeMachine()">Compose machine</button>
305 </div>
306 </div>
307- </div>
308+ </section>
309 </section>
310 <section class="p-strip" data-ng-if="pod && section.area === 'configuration'">
311 <div class="row">
312@@ -291,7 +374,9 @@
313 <h3 class="p-heading--four">Total local storage ({$ pod.total.local_storage_gb $} GiB)</h3>
314 <div class="action-card u-margin--bottom">
315 <h3 class="p-heading--four">0 drives</h3>
316- <meter max="{$ pod.total.local_storage $}" value="{$ pod.used.local_storage $}">{$ pod.used.local_storage $} Mb</meter>
317+ <div class="p-meter__container">
318+ <meter max="{$ pod.total.local_storage $}" value="{$ pod.used.local_storage $}">{$ pod.used.local_storage $} Mb</meter>
319+ </div>
320 <p>
321 <span>0 GiB used</span>
322 <span class="u-float--right">{$ pod.total.local_storage_gb $} GiB available</span>
323diff --git a/src/maasserver/static/scss/_base_forms.scss b/src/maasserver/static/scss/_base_forms.scss
324index 519b689..deeae7f 100644
325--- a/src/maasserver/static/scss/_base_forms.scss
326+++ b/src/maasserver/static/scss/_base_forms.scss
327@@ -26,6 +26,11 @@
328 padding-bottom: $spv-nudge - $px;
329 padding-top: $spv-nudge - $px;
330 }
331+ .is-small & {
332+ margin-bottom: $spv-nudge-compensation;
333+ padding-bottom: $spv-nudge - $sp-unit * .5 - $px;
334+ padding-top: $spv-nudge - $sp-unit * .5 - $px;
335+ }
336
337 &.u-min-margin--bottom {
338 margin-bottom: $spv-nudge-compensation * 2;
339diff --git a/src/maasserver/static/scss/_base_typography.scss b/src/maasserver/static/scss/_base_typography.scss
340index 749fd61..7fd8d78 100644
341--- a/src/maasserver/static/scss/_base_typography.scss
342+++ b/src/maasserver/static/scss/_base_typography.scss
343@@ -9,7 +9,7 @@ $nudge--smallest: .15rem;
344 font-size: pow($ms-ratio, -2) * 1rem;
345 font-weight: 400;
346 line-height: map-get($line-heights, smallest);
347- margin-bottom: map-get($sp-after, small) + map-get($line-heights, default-text) - $line-height--smallest - $nudge--smallest;
348+ margin-bottom: map-get($sp-after, default-text) - map-get($nudges, nudge--p);
349 padding-top: $nudge--smallest;
350 }
351
352@@ -23,4 +23,8 @@ h4,
353 .default-text {
354 @extend %default-text;
355 display: block;
356+}
357+
358+.u-no-max-width {
359+ max-width: unset;
360 }
361\ No newline at end of file
362diff --git a/src/maasserver/static/scss/_maas.scss b/src/maasserver/static/scss/_maas.scss
363index c7293c0..d890f5e 100644
364--- a/src/maasserver/static/scss/_maas.scss
365+++ b/src/maasserver/static/scss/_maas.scss
366@@ -254,3 +254,5 @@
367 }
368 }
369 }
370+
371+
372diff --git a/src/maasserver/static/scss/_patterns_button.scss b/src/maasserver/static/scss/_patterns_button.scss
373index 9a52376..f90ed33 100644
374--- a/src/maasserver/static/scss/_patterns_button.scss
375+++ b/src/maasserver/static/scss/_patterns_button.scss
376@@ -1,19 +1,32 @@
377 @mixin maas-p-buttons {
378- .p-button--min-margin-bottom {
379+ %p-button--min-margin-bottom {
380 margin-bottom: $spv-nudge-compensation;
381 }
382
383+ .p-button--min-margin-bottom {
384+ @extend %p-button--min-margin-bottom;
385+ }
386+
387 .p-button--base.is-small {
388 padding: $sp-unit;
389 margin: 0;
390 }
391
392 %icon-button-padding {
393- padding: $spv-intra--condensed $spv-intra--expanded;
394+ padding: $spv-nudge - $px $sph-intra--condensed;
395+ }
396+
397+ .p-button--lock {
398+ margin-left: -.5rem;
399 }
400
401 .p-button--icon {
402- @extend %icon-button-padding;
403+ input + & {
404+ margin-left: $sph-inter;
405+ }
406+
407+ @extend %p-button--min-margin-bottom;
408+ padding: $spv-intra $sph-intra--condensed;
409 }
410
411 .p-button--close {
412diff --git a/src/maasserver/static/scss/_patterns_icons.scss b/src/maasserver/static/scss/_patterns_icons.scss
413index f588902..8667a18 100644
414--- a/src/maasserver/static/scss/_patterns_icons.scss
415+++ b/src/maasserver/static/scss/_patterns_icons.scss
416@@ -212,6 +212,36 @@
417 }
418 }
419
420+ .p-icon--lock {
421+ @extend %icon;
422+ background-image: url("https://assets.ubuntu.com/v1/5d2e0e21-padlock.svg");
423+ background-size: 1rem 1rem;
424+ display: block;
425+ position: relative;
426+ margin-right: $sph-intra;
427+ top: 0 !important;
428+
429+ &.is-open {
430+ background-image: url("https://assets.ubuntu.com/v1/a6c61cd6-padlock_open.svg");
431+ }
432+ }
433+
434+ .p-icon--x {
435+ @extend %icon;
436+ background-size: 1rem 1rem;
437+ display: block;
438+ position: relative;
439+ }
440+
441+ .p-icon--tick {
442+ @extend %icon;
443+ background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg width='22px' height='16px' viewBox='0 0 22 16' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3C/defs%3E%3Cg id='Page-1' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cg id='confirm-tick' transform='translate(-1.000000, -1.000000)'%3E%3Cpolygon id='Shape' points='0 0 24 0 24 24 0 24'%3E%3C/polygon%3E%3Cpolygon id='Shape' fill-opacity='0.999998987' fill='%23666666' fill-rule='nonzero' points='3.872 6.93333333 1.6 9.20533333 9.33333333 16.9386667 22.4 3.872 20.128 1.6 9.33333333 12.3973333'%3E%3C/polygon%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
444+ background-size: 1rem 1rem;
445+
446+ display: block;
447+ position: relative;
448+ }
449+
450 // XXX Use ems rather than rems for icon sizing
451 // Issue: https://github.com/vanilla-framework/vanilla-framework/issues/1599
452 [class^="p-icon"] {
453diff --git a/src/maasserver/static/scss/_patterns_meter.scss b/src/maasserver/static/scss/_patterns_meter.scss
454index 04c8402..5276838 100644
455--- a/src/maasserver/static/scss/_patterns_meter.scss
456+++ b/src/maasserver/static/scss/_patterns_meter.scss
457@@ -1,31 +1,160 @@
458 @mixin maas-meter {
459+ $color--used: #1f78b4;
460+ $color--free: #a6cee3;
461+
462+ %align-with-p {
463+ padding-top: .2rem; // to align it vertically with h5,p etc
464+ margin-bottom: -.2rem;
465+ }
466+
467 .p-meter {
468- -webkit-appearance: none;
469- -moz-appearance: none;
470- width: 100%;
471- height: 20px;
472- border-radius: 10px;
473+ &__container {
474+ position: relative;
475+ @extend %align-with-p;
476+ }
477+
478+ border-radius: $sp-unit;
479+ display: block;
480+ height: $sp-unit * 2;
481+ position: relative;
482 overflow: hidden;
483+ width: 100%;
484+ -moz-appearance: none;
485+ -webkit-appearance: none;
486
487 // Firefox
488 background: none; // Required to get rid of the default background prop.
489- background-color: $color-mid-light;
490- box-shadow: none;
491+ background-color: $color--free;
492
493 &::-webkit-meter-inner-element {
494 display: block;
495 }
496
497 &::-webkit-meter-bar {
498- background: $color-mid-light;
499+ background: $color--free;
500 }
501
502 &::-webkit-meter-optimum-value {
503- background: $color-link;
504+ background: $color--used;
505 }
506
507 &::-moz-meter-bar {
508- background: $color-link;
509+ background: $color--used;
510+ }
511+
512+ &--kvm {
513+ &::-webkit-meter-bar {
514+ background-color: transparent;
515+ }
516+
517+ &::-webkit-meter-optimum-value {
518+ background-color: transparent;
519+ }
520+
521+ &::-moz-meter-bar {
522+ background: $color--used;
523+ }
524+ }
525+
526+ &--cpu-cores {
527+ @extend %align-with-p;
528+
529+ &__container {
530+ @extend %vf-clearfix;
531+ border-radius: $sp-unit;
532+ display: flex;
533+ position: relative;
534+ overflow: hidden;
535+ width: 100%;
536+ }
537+
538+ %cpu-core {
539+ border-right: 1px solid $color-x-light;
540+ display: block;
541+ float: left;
542+ height: $sp-unit * 2;
543+ position: relative;
544+ flex: 1;
545+ }
546+
547+ &__core--used {
548+ @extend %cpu-core;
549+ background: $color--used;
550+ }
551+
552+ &__core--available {
553+ @extend %cpu-core;
554+ background: $color--free;
555+ }
556+ }
557+
558+ &__graph {
559+ position: absolute;
560+ top: 0;
561+ width: 100%;
562+ }
563+
564+ &__graph-content {
565+ background-image: linear-gradient( 90deg,
566+ $color--used 0%,
567+ $color--used 100%,
568+ transparent 100%,
569+ transparent 100%);
570+ background-size: 100% 100%;
571+ display: block;
572+ text-indent: -9999px;
573+ height: inherit;
574 }
575 }
576-}
577+
578+ .p-legend {
579+ @extend %vf-clearfix;
580+ list-style: none;
581+ margin-bottom: 0;
582+ padding: 0;
583+
584+ &--numbers {
585+ margin-left: 0;
586+ padding-left: 0;
587+ }
588+
589+ &::after {content: unset}
590+
591+ &__item {
592+ display: block;
593+ @extend %vf-clearfix;
594+ float: left;
595+
596+ &:not(:first-child) {
597+ margin-left: $sph-intra;
598+ float: right;
599+ }
600+
601+ &::before {
602+ content: "•";
603+
604+ padding-top: map-get($nudges, nudge--p);
605+ float: left;
606+ font-size: 2rem;
607+ line-height: map-get($line-heights, default-text);
608+ display: inline-block;
609+ margin-right: $sph-intra--condensed;
610+ width: $sp-unit;
611+ }
612+
613+ &--used::before {
614+ color: $color--used;
615+ }
616+
617+ &--free::before {
618+ color: $color--free;
619+ }
620+ }
621+
622+ &__text {
623+ float: left;
624+ margin-bottom: $sp-unit * 2 - map-get($nudges, nudge--p);
625+ }
626+ }
627+
628+}
629\ No newline at end of file
630diff --git a/src/maasserver/static/scss/_patterns_pod-summary.scss b/src/maasserver/static/scss/_patterns_pod-summary.scss
631new file mode 100644
632index 0000000..6b94c4f
633--- /dev/null
634+++ b/src/maasserver/static/scss/_patterns_pod-summary.scss
635@@ -0,0 +1,191 @@
636+@mixin maas-p-pod-summary {
637+ .p-input--overcommit {
638+ float: left;
639+ width: 3rem;
640+ max-width: 3rem !important;
641+ min-width: 3rem;
642+ }
643+
644+ .p-pod-summary {
645+ display: flex;
646+ @media (max-width: $breakpoint-large) {
647+ flex-direction: column;
648+ }
649+
650+ @media (min-width: $breakpoint-large) {
651+ flex-direction: row;
652+ flex-wrap: wrap;
653+ }
654+
655+ &__cpu,
656+ &__ram,
657+ &__aside,
658+ &__storage {
659+ flex: 0 0 auto;
660+ }
661+
662+ &__cpu,
663+ &__ram {
664+ @media (min-width: $breakpoint-large) {
665+ margin-bottom: $spv-inter--shallow-scaleable;
666+ }
667+ }
668+
669+ &__ram {
670+ position: relative;
671+
672+ @media (min-width: $breakpoint-small) and (max-width: $breakpoint-large) {
673+ &::after {
674+ content: unset;
675+ }
676+ }
677+ }
678+
679+ &__storage {
680+ @extend .col-8;
681+
682+ position: relative;
683+
684+ @media (max-width: $breakpoint-large) {
685+ width: 100%;
686+ margin-left: 0;
687+ }
688+
689+ @media (min-width: $breakpoint-large) {
690+ &::after {
691+ content: unset;
692+ }
693+
694+ &::before {
695+ background-color: $color-mid-light;
696+ content: '';
697+ height: 100%;
698+ $factor: 100 / 65.47483;
699+ $gutter-width--inside-8-col-nested: 3.57551%;
700+ $offset: $gutter-width--inside-8-col-nested * .5 * $factor;
701+ left: - $offset;
702+ position: absolute;
703+ width: 1px;
704+ }
705+ }
706+ }
707+
708+ &__aside {
709+ @extend .col-4;
710+
711+ @media (max-width: $breakpoint-large - 1px) {
712+ width: 100%;
713+ }
714+ }
715+
716+ &__cpu,
717+ &__ram {
718+ @extend .tablet-col-3;
719+
720+ @media (min-width: $breakpoint-large) {
721+ width: 100%;
722+ margin-left: 0; //clear .tablet-* class as it leaks outside its intended breakpoint
723+ }
724+ }
725+ }
726+
727+ .p-storage {
728+ $p-storage-info-width: 5rem;
729+ margin-bottom: $px;
730+ padding-top: $spv-intra;
731+
732+ @media (max-width: $breakpoint-large - 1px) {
733+ &::after {
734+ background: transparent;
735+ }
736+ }
737+
738+ &__name {
739+ @extend .col-4;
740+
741+ margin-top: - $sp-unit;
742+ }
743+
744+ &__meter {
745+ @extend .col-3;
746+
747+ @media (max-width: $breakpoint-large) {
748+ float: left;
749+ }
750+
751+ @media (max-width: $breakpoint-small) {
752+ width: 100%;
753+ }
754+
755+ }
756+
757+ &__disk-name {
758+ float: left;
759+ margin-bottom: map-get($sp-after, default-text) - map-get($nudges, nudge--p);
760+ margin-right: - $p-storage-info-width;
761+ width: calc(100% - #{$p-storage-info-width});
762+ }
763+
764+ &__info {
765+ float: right;
766+ text-align: right;
767+ width: $p-storage-info-width;
768+ }
769+
770+ &__path {
771+ display: block;
772+ color: $color-mid-dark;
773+ overflow: hidden;
774+ white-space: nowrap;
775+ text-overflow: ellipsis;
776+ }
777+
778+ &__type {
779+ @extend %default-text;
780+ }
781+ }
782+
783+ .p-list--divided .p-list__item {
784+ &::after {
785+ border-bottom-style: solid;
786+ border-bottom-color: $color-light-new;
787+ }
788+ }
789+
790+ .faded {
791+ opacity: .5
792+ }
793+
794+ .p-overcommit-switch {
795+ float: left;
796+ width: 100%;
797+ }
798+
799+ .p-pod-edit {
800+ align-items: flex-start;
801+ display: flex;
802+ justify-content: space-between;
803+
804+ &__label {
805+ @media (max-width: $breakpoint-small) {
806+ display: none;
807+ }
808+ }
809+
810+ &__label,
811+ & .p-button {
812+ flex: 0 0 auto;
813+ }
814+
815+ * + * {
816+ margin-left: $sph-inter;
817+ }
818+
819+ & .p-code-snippet-wrapper {
820+ flex: 1 0 auto;
821+ @media (max-width: $breakpoint-small) {
822+ margin-left: 0; // the label is hidden on small, so margin not needed
823+ }
824+ }
825+ }
826+}
827\ No newline at end of file
828diff --git a/src/maasserver/static/scss/_patterns_slider.scss b/src/maasserver/static/scss/_patterns_slider.scss
829new file mode 100644
830index 0000000..b806a75
831--- /dev/null
832+++ b/src/maasserver/static/scss/_patterns_slider.scss
833@@ -0,0 +1,28 @@
834+//XXX: patch - add missing autoprefixed rules; remove once an autoprefixer has been added to maas
835+.p-slider {
836+ -webkit-appearance: none;
837+ -moz-appearance: none;
838+}
839+.p-slider::-webkit-slider-thumb {
840+ -webkit-appearance: none;
841+ -webkit-box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.2);
842+}
843+.p-slider__wrapper {
844+ -webkit-box-align: center;
845+ -ms-flex-align: center;
846+}
847+
848+.p-slider {
849+ margin: 0 0 1rem 0;
850+
851+ &__wrapper {
852+ margin-top: -1rem;//XXX
853+ }
854+
855+ &__input {
856+ height: inherit !important;
857+ }
858+ & + button {
859+ margin-left: $sph-inter;
860+ }
861+}
862diff --git a/src/maasserver/static/scss/_utils.scss b/src/maasserver/static/scss/_utils.scss
863index 2587691..11bb5c6 100644
864--- a/src/maasserver/static/scss/_utils.scss
865+++ b/src/maasserver/static/scss/_utils.scss
866@@ -19,3 +19,8 @@
867 .u-flex--no-wrap {
868 display: flex;
869 }
870+
871+.u-flex--no-wrap {
872+ display: flex;
873+ flex-wrap: wrap;
874+}
875diff --git a/src/maasserver/static/scss/build.scss b/src/maasserver/static/scss/build.scss
876index 0846e1a..d37a3a8 100644
877--- a/src/maasserver/static/scss/build.scss
878+++ b/src/maasserver/static/scss/build.scss
879@@ -27,12 +27,14 @@
880 @import 'patterns_forms';
881 @import 'patterns_hr';
882 @import 'patterns_notification';
883+@import 'patterns_pod-summary';
884 @import 'patterns_footer';
885 @import 'patterns_search-box';
886 @import 'patterns_table-sortable';
887 @import 'tables';
888 @import 'patterns_space-between';
889 @import 'patterns_filter';
890+@import 'patterns_slider';
891
892 // Include local patterns
893 @include maas;
894@@ -55,6 +57,7 @@
895 @include maas-p-forms;
896 @include maas-p-hr;
897 @include maas-p-notifications;
898+@include maas-p-pod-summary;
899 @include maas-p-search-box;
900 @include maas-p-sticky-footer;
901 @include maas-p-filter;
902diff --git a/src/maasserver/templates/maasserver/index.html b/src/maasserver/templates/maasserver/index.html
903index 804f3bf..1a5cc32 100644
904--- a/src/maasserver/templates/maasserver/index.html
905+++ b/src/maasserver/templates/maasserver/index.html
906@@ -129,28 +129,5 @@
907 </main>
908 {% include "maasserver/footer.html" %}
909 {% include "maasserver/js-conf.html" %}
910-
911- <script>
912- // enable show/hide with an env variable, so this doesn't need to be removed / readed on every branch
913- var ENV = '';
914- if(ENV === 'DEBUG') {
915- function fragmentFromString(htmlString) {
916- var temp = document.createElement('template');
917- temp.innerHTML = htmlString;
918- return temp.content;
919- }
920-
921- document.addEventListener('DOMContentLoaded', function() {
922- var body = document.body;
923- var controls = fragmentFromString('<div class="u-baseline-grid__toggle"><label>Toggle baseline grid<input type="checkbox" class="p-switch js-baseline-toggle" /><div class="p-switch__slider"></div></label></div>');
924- body.appendChild(controls);
925-
926- var toggle = document.querySelector('.js-baseline-toggle');
927- toggle.addEventListener('click', function (event) {
928- body.classList.toggle('u-baseline-grid');
929- });
930- });
931- }
932- </script>
933 </body>
934 </html>

Subscribers

People subscribed via source and target branches