Merge lp:~gary/juju-gui/fixsavetext into lp:juju-gui/experimental

Proposed by Gary Poster
Status: Needs review
Proposed branch: lp:~gary/juju-gui/fixsavetext
Merge into: lp:juju-gui/experimental
Diff against target: 234 lines (+109/-15)
5 files modified
app/templates/service-configuration.partial (+1/-1)
app/templates/service-constraints-viewlet.handlebars (+2/-2)
app/views/databinding.js (+3/-3)
app/views/inspector.js (+31/-5)
lib/views/juju-inspector.less (+72/-4)
To merge this branch: bzr merge lp:~gary/juju-gui/fixsavetext
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+183996@code.launchpad.net

Description of the change

Fix constraints save and add save confirmation

To QA, deploy a service with the inspector, and then reopen deployed inspector. In configuration and constraints, make changes and click save. The save button should now not change text when you click on it in the constraints tab. The save (and cancel) buttons only appear when there are changes to be saved. The fields correctly recognize when changes are reverted. When changes are saved, the field flashes green to show success.

checkboxes do not work properly in this branch: Rick is working on that. The cancel button does not work: that will be a separate branch.

For comment and discussion, code and UX. The green flash for fields on save is not as described by UX, but the desired display will be a lot more time consuming--and fragile, I am afraid--than what I have here. I am hoping this is a reasonable compromise.

I hope discussion will answer UX issues, as well as resolve what is appropriate for testing. I am a bit too focused on getting this out the door, so need some outside perspective.

https://codereview.appspot.com/13505044/

To post a comment you must log in.
Revision history for this message
Gary Poster (gary) wrote :

A code review. Reviewers: mp+183996_code.launchpad.net,

Message:
Please take a look.

Description:
Fix constraints save and add save confirmation

To QA, deploy a service with the inspector, and then reopen deployed
inspector. In configuration and constraints, make changes and click
save. The save button should now not change text when you click on it
in the constraints tab. The save (and cancel) buttons only appear when
there are changes to be saved. The fields correctly recognize when
changes are reverted. When changes are saved, the field flashes green
to show success.

checkboxes do not work properly in this branch: Rick is working on that.
  The cancel button does not work: that will be a separate branch.

For comment and discussion, code and UX. The green flash for fields on
save is not as described by UX, but the desired display will be a lot
more time consuming--and fragile, I am afraid--than what I have here. I
am hoping this is a reasonable compromise.

I hope discussion will answer UX issues, as well as resolve what is
appropriate for testing. I am a bit too focused on getting this out the
door, so need some outside perspective.

https://code.launchpad.net/~gary/juju-gui/fixsavetext/+merge/183996

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/13505044/

Affected files +111, -15:
   A [revision details]
   M app/templates/service-configuration.partial
   M app/templates/service-constraints-viewlet.handlebars
   M app/views/databinding.js
   M app/views/inspector.js
   M lib/views/juju-inspector.less

Revision history for this message
Jeff Pihach (hatch) wrote :

Looking good but there is some duplication of work, plz see below.

https://codereview.appspot.com/13505044/diff/1/app/views/inspector.js
File app/views/inspector.js (right):

https://codereview.appspot.com/13505044/diff/1/app/views/inspector.js#newcode1047
app/views/inspector.js:1047: if (!this.modifiedKeys) {
When a user changes the value of an input the databinding engine keeps
track of these changes via it's _storeChanged method on line 609 of
databinding.js. This method keeps track of these changes in each
viewlets _changedvalues method. It would be nice if you could use this
data set instead of trying to keep track of it yourself. If you need
reference to these values in this changed method you may need to pass it
into the method call on line 622.

https://codereview.appspot.com/13505044/

Unmerged revisions

1005. By Gary Poster

lint

1004. By Gary Poster

fix constraint save text; add confirmation of changes for constraints and config

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'app/templates/service-configuration.partial'
--- app/templates/service-configuration.partial 2013-09-04 10:44:34 +0000
+++ app/templates/service-configuration.partial 2013-09-05 00:44:43 +0000
@@ -48,7 +48,7 @@
48 </div>48 </div>
49{{/settings}}49{{/settings}}
50{{#unless ghost}}50{{#unless ghost}}
51<div class="yui3-g controls configuration-buttons">51<div class="yui3-g controls closed configuration-buttons">
52 <div class="yui3-u-1-2">52 <div class="yui3-u-1-2">
53 <button class="cancel">Cancel</button>53 <button class="cancel">Cancel</button>
54 </div>54 </div>
5555
=== modified file 'app/templates/service-constraints-viewlet.handlebars'
--- app/templates/service-constraints-viewlet.handlebars 2013-08-06 20:49:47 +0000
+++ app/templates/service-constraints-viewlet.handlebars 2013-09-05 00:44:43 +0000
@@ -1,7 +1,7 @@
1<div class="view-container">1<div class="view-container">
2 <legend>{{service.displayName}} constraints</legend>2 <legend>Constraints for New Units</legend>
3 {{> service-constraints-viewlet}}3 {{> service-constraints-viewlet}}
4 <div class="controls">4 <div class="controls closed">
5 <button type="button" class="save-constraints confirm">Confirm</button>5 <button type="button" class="save-constraints confirm">Confirm</button>
6 </div>6 </div>
7</div>7</div>
88
=== modified file 'app/views/databinding.js'
--- app/views/databinding.js 2013-09-04 15:26:55 +0000
+++ app/views/databinding.js 2013-09-05 00:44:43 +0000
@@ -49,11 +49,11 @@
49 },49 },
50 input: {50 input: {
51 'get': function(node) { return node.get('value');},51 'get': function(node) { return node.get('value');},
52 'set': function(node, value) { node.set('value', value);}52 'set': function(node, value) { node.set('value', value || '');}
53 },53 },
54 textarea: {54 textarea: {
55 'get': function(node) { return node.get('value');},55 'get': function(node) { return node.get('value');},
56 'set': function(node, value) { node.set('value', value);}56 'set': function(node, value) { node.set('value', value || '');}
57 },57 },
58 'default': {58 'default': {
59 'get': function(node) { return node.get('text');},59 'get': function(node) { return node.get('text');},
@@ -607,7 +607,7 @@
607 @param {Object} viewlet reference.607 @param {Object} viewlet reference.
608 */608 */
609 BindingEngine.prototype._storeChanged = function(e, viewlet) {609 BindingEngine.prototype._storeChanged = function(e, viewlet) {
610 var key = e.currentTarget.getData('bind'),610 var key = e.target.getData('bind'),
611 save = true;611 save = true;
612612
613 viewlet._changedValues.forEach(function(value) {613 viewlet._changedValues.forEach(function(value) {
614614
=== modified file 'app/views/inspector.js'
--- app/views/inspector.js 2013-09-04 15:08:24 +0000
+++ app/views/inspector.js 2013-09-05 00:44:43 +0000
@@ -1065,12 +1065,22 @@
10651065
1066 var ConflictMixin = {1066 var ConflictMixin = {
1067 'changed': function(node, key, field) {1067 'changed': function(node, key, field) {
1068 var modelValue = this.model.get(key);1068 if (!this.modifiedKeys) {
1069 this.modifiedKeys = {};
1070 }
1071 var modelValue = this.model.get(key) || '';
1069 var fieldValue = field.get(node);1072 var fieldValue = field.get(node);
1073 var controls = this.container.one('.controls');
1070 if (modelValue !== fieldValue) {1074 if (modelValue !== fieldValue) {
1071 node.addClass('modified');1075 node.replaceClass('change-saved', 'modified');
1076 this.modifiedKeys[key] = true;
1077 controls.removeClass('closed');
1072 } else {1078 } else {
1073 node.removeClass('modified');1079 node.removeClass('modified');
1080 delete this.modifiedKeys[key];
1081 if (Object.keys(this.modifiedKeys).length === 0) {
1082 controls.addClass('closed');
1083 }
1074 }1084 }
1075 },1085 },
1076 'conflict': function(node, model, viewletName, resolve, binding) {1086 'conflict': function(node, model, viewletName, resolve, binding) {
@@ -1131,11 +1141,27 @@
1131 '.conflict', this));1141 '.conflict', this));
1132 },1142 },
1133 'unsyncedFields': function(dirtyFields) {1143 'unsyncedFields': function(dirtyFields) {
1134 this.container.one('.controls .confirm').setHTML('Overwrite');1144 var node = this.container.one('.controls .confirm');
1145 if (!node.getData('originalText')) {
1146 node.setData('originalText', node.getHTML());
1147 }
1148 node.setHTML('Overwrite');
1135 },1149 },
1136 'syncedFields': function() {1150 'syncedFields': function() {
1137 this.container.one('.controls .confirm').setHTML('Save Changes');1151 var controls = this.container.one('.controls');
1138 this.container.all('.modified').removeClass('modified');1152 var node = controls.one('.confirm');
1153 var title = node.getData('originalText');
1154 var modified = this.container.all('.modified');
1155 if (title) {
1156 node.setHTML(title);
1157 }
1158 modified.replaceClass('modified', 'change-saved');
1159 // animationend handlers don't work reliably, once you hook them up
1160 // with the associated custom browser names (e.g. webkitAnimationEnd)
1161 // on the raw DOM node, so don't even bother with them.
1162 Y.later(1000, modified, function() {
1163 this.removeClass('change-saved');});
1164 controls.addClass('closed');
1139 }1165 }
1140 };1166 };
11411167
11421168
=== modified file 'lib/views/juju-inspector.less'
--- lib/views/juju-inspector.less 2013-09-04 10:53:54 +0000
+++ lib/views/juju-inspector.less 2013-09-05 00:44:43 +0000
@@ -1,4 +1,5 @@
1@inspector-background-color: #221e1c;1@inspector-background-color: #221e1c;
2@inspector-changed-field: #dedede;
2@inspector-controls-height: 67px;3@inspector-controls-height: 67px;
3@inspector-divider-bottom: rgba(0, 0, 0, 0.3);4@inspector-divider-bottom: rgba(0, 0, 0, 0.3);
4@inspector-divider-top: rgba(255, 255, 255, 0.05);5@inspector-divider-top: rgba(255, 255, 255, 0.05);
@@ -11,6 +12,54 @@
11@disabled-input-background-color: #727272;12@disabled-input-background-color: #727272;
12@disabled-input-text-color: #252525;13@disabled-input-text-color: #252525;
1314
15@-webkit-keyframes pulse-green {
16 0% {
17 background-color: @inspector-changed-field;
18 }
19 10% {
20 background-color: #38b44a;
21 }
22 100% {
23 background-color: white;
24 }
25}
26
27@-moz-keyframes pulse-green {
28 0% {
29 background-color: @inspector-changed-field;
30 }
31 10% {
32 background-color: #38b44a;
33 }
34 100% {
35 background-color: white;
36 }
37}
38
39@-o-keyframes pulse-green {
40 0% {
41 background-color: @inspector-changed-field;
42 }
43 10% {
44 background-color: #38b44a;
45 }
46 100% {
47 background-color: white;
48 }
49}
50
51@keyframes pulse-green {
52 0% {
53 background-color: @inspector-changed-field;
54 }
55 10% {
56 background-color: #38b44a;
57 }
58 100% {
59 background-color: white;
60 }
61}
62
14.yui3-juju-inspector {63.yui3-juju-inspector {
15 input[type=text]::-ms-clear { display: none; }64 input[type=text]::-ms-clear { display: none; }
1665
@@ -208,6 +257,15 @@
208 margin-top: 20px;257 margin-top: 20px;
209 border-top: 1px solid @inspector-divider-top;258 border-top: 1px solid @inspector-divider-top;
210 border-bottom: 1px solid @inspector-divider-bottom;259 border-bottom: 1px solid @inspector-divider-bottom;
260 overflow: hidden;
261 height: 70px;
262 -moz-transition: .3s, height .3s;
263 -webkit-transition: .25s, height .3s;
264 transition: .3s, height .3s;
265
266 &.closed {
267 height: 0;
268 }
211269
212 button {270 button {
213 .create-border-radius(@border-radius);271 .create-border-radius(@border-radius);
@@ -661,7 +719,7 @@
661 .resolver {719 .resolver {
662 color: black;720 color: black;
663 background-color: white;721 background-color: white;
664 border: 1px solid #dedede;722 border: 1px solid @inspector-changed-field;
665 border-radius: 1px;723 border-radius: 1px;
666724
667 div {725 div {
@@ -669,17 +727,27 @@
669 }727 }
670 }728 }
671 .modified {729 .modified {
672 background-color: #dedede;730 background-color: @inspector-changed-field;
673 background-image: url(/juju-ui/assets/images/field-changed.png);731 background-image: url(/juju-ui/assets/images/field-changed.png);
674 }732 }
675 .conflict-pending {733 .conflict-pending {
676 background-color: #dedede;734 background-color: @inspector-changed-field;
677 background-image: url(/juju-ui/assets/images/field-conflict.png);735 background-image: url(/juju-ui/assets/images/field-conflict.png);
678 }736 }
679 .conflict {737 .conflict {
680 background-color: #dedede;738 background-color: @inspector-changed-field;
681 background-image: url(/juju-ui/assets/images/field-resolved.png);739 background-image: url(/juju-ui/assets/images/field-resolved.png);
682 }740 }
741 .change-saved {
742 -webkit-animation: pulse-green 1s;
743 -moz-animation: pulse-green 1s;
744 -o-animation: pulse-green 1s;
745 animation: pulse-green 1s;
746 -webkit-animation-fill-mode: forwards;
747 -moz-animation-fill-mode: forwards;
748 -o-animation-fill-mode: forwards;
749 animation-fill-mode: forwards;
750 }
683 }751 }
684 .toggle {752 .toggle {
685 padding: 10px @inspector-main-padding;753 padding: 10px @inspector-main-padding;

Subscribers

People subscribed via source and target branches