Merge lp:~frankban/juju-gui/bug-1075679-charm-config-panel into lp:juju-gui/experimental

Proposed by Francesco Banconi
Status: Merged
Merged at revision: 234
Proposed branch: lp:~frankban/juju-gui/bug-1075679-charm-config-panel
Merge into: lp:juju-gui/experimental
Diff against target: 409 lines (+119/-68)
4 files modified
app/templates/charm-pre-configuration.handlebars (+9/-9)
app/views/charm-panel.js (+44/-3)
lib/views/stylesheet.less (+66/-52)
undocumented (+0/-4)
To merge this branch: bzr merge lp:~frankban/juju-gui/bug-1075679-charm-config-panel
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+133657@code.launchpad.net

Description of the change

Charm config panel visual design fixes.

The charm configuration panel now should match UX wireframe.
This branch also contains fixes to the configuration
section hiding when a config file is uploaded.
Also introduced LESS mixins for border radii and box shadows.
Added "docstrings" to relevant charm panel methods.

https://codereview.appspot.com/6827066/

To post a comment you must log in.
Revision history for this message
Francesco Banconi (frankban) wrote :

Reviewers: mp+133657_code.launchpad.net,

Message:
Please take a look.

Description:
Charm config panel visual design fixes.

The charm configuration panel now should match UX wireframe.
This branch also contains fixes to the configuration
section hiding when a config file is uploaded.
Also introduced LESS mixins for border radii and box shadows.
Added "docstrings" to relevant charm panel methods.

https://code.launchpad.net/~frankban/juju-gui/bug-1075679-charm-config-panel/+merge/133657

(do not edit description out of merge proposal)

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

Affected files:
   A [revision details]
   M app/templates/charm-pre-configuration.handlebars
   M app/views/charm-panel.js
   M lib/views/stylesheet.less
   M undocumented

Revision history for this message
Brad Crittenden (bac) wrote :

Nice changes Francesco.

I think the config file button still needs some attention. I find it
odd that it isn't part of the collapsible div and remains visible when
Service Settings is collapsed. Did you discuss that UX with Matt or
Jovan? Of course I defer to them but think it currently looks funny.

Also, when a file is chosen, Service Settings collapses but the chevron
still points down. Further you can click on it and the chevron changes
but nothing else happens. I guess it'd be nice to collapse, set the
chevron to up, and lock it in place.

https://codereview.appspot.com/6827066/diff/1/app/views/charm-panel.js
File app/views/charm-panel.js (right):

https://codereview.appspot.com/6827066/diff/1/app/views/charm-panel.js#newcode601
app/views/charm-panel.js:601: */
Nice, thanks.

https://codereview.appspot.com/6827066/diff/1/lib/views/stylesheet.less
File lib/views/stylesheet.less (right):

https://codereview.appspot.com/6827066/diff/1/lib/views/stylesheet.less#newcode43
lib/views/stylesheet.less:43:
Thanks! Maybe 'set-' instead of 'create-' for both?

https://codereview.appspot.com/6827066/diff/1/lib/views/stylesheet.less#newcode987
lib/views/stylesheet.less:987: padding-left: 5px;
The vis design shows this lined up with the other elements and the charm
icon up top. I think the padding-left should be 11px.

Good to see you and Matt discussing it.

And as I mentioned in IRC we should decide on one value and apply it to
all charm panels, abstracting it into a LESS variable.

https://codereview.appspot.com/6827066/diff/1/undocumented
File undocumented (left):

https://codereview.appspot.com/6827066/diff/1/undocumented#oldcode82
undocumented:82: app/views/charm-panel.js render
yay

https://codereview.appspot.com/6827066/

237. By Francesco Banconi

Fixes per review.

Revision history for this message
Francesco Banconi (frankban) wrote :
Revision history for this message
Gary Poster (gary) wrote :

Great changes, Francesco! No suggestions or requests. Thanks!

Gary

https://codereview.appspot.com/6827066/diff/2002/app/views/charm-panel.js
File app/views/charm-panel.js (right):

https://codereview.appspot.com/6827066/diff/2002/app/views/charm-panel.js#newcode600
app/views/charm-panel.js:600: * @return {undefined} Dispatches only.
Awesome. Thank you for this and the other docs

https://codereview.appspot.com/6827066/diff/2002/lib/views/stylesheet.less
File lib/views/stylesheet.less (right):

https://codereview.appspot.com/6827066/diff/2002/lib/views/stylesheet.less#newcode1
lib/views/stylesheet.less:1: /* Processed with LESS from
lib/views/stylesheet.less */
Great changes here, Francesco.

https://codereview.appspot.com/6827066/diff/2002/undocumented
File undocumented (left):

https://codereview.appspot.com/6827066/diff/2002/undocumented#oldcode81
undocumented:81: app/views/charm-panel.js onFileRemove
Thank you!

https://codereview.appspot.com/6827066/

Revision history for this message
Francesco Banconi (frankban) wrote :

*** Submitted:

Charm config panel visual design fixes.

The charm configuration panel now should match UX wireframe.
This branch also contains fixes to the configuration
section hiding when a config file is uploaded.
Also introduced LESS mixins for border radii and box shadows.
Added "docstrings" to relevant charm panel methods.

R=bac, gary.poster
CC=
https://codereview.appspot.com/6827066

https://codereview.appspot.com/6827066/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'app/templates/charm-pre-configuration.handlebars'
--- app/templates/charm-pre-configuration.handlebars 2012-11-07 14:40:38 +0000
+++ app/templates/charm-pre-configuration.handlebars 2012-11-09 14:33:29 +0000
@@ -44,16 +44,16 @@
44 <!-- Service configuration form -->44 <!-- Service configuration form -->
45 <div class="charm-section">45 <div class="charm-section">
46 <h4>Service Settings<i class="icon-chevron-down"></i></h4>46 <h4>Service Settings<i class="icon-chevron-down"></i></h4>
47 <div class="config-file-upload control-group">47 <div class="collapsible">
48 <input class="config-file-upload-widget" type="file">48 <div class="config-file-upload control-group">
49 <div>49 <input class="config-file-upload-widget" type="file">
50 <span class="config-file-upload-overlay">Use configuration file</span>50 <div>
51 <span class="config-file-name"></span>51 <span class="config-file-upload-overlay">Use configuration file</span>
52 <span class="config-file-name"></span>
53 </div>
52 </div>54 </div>
53 </div>55 <form class="charm-settings">
54 <div class="charm-settings">56 <div id="service-config">
55 <form>
56 <div id="service-config" class="collapsible">
57 {{> service-config}}57 {{> service-config}}
58 </div>58 </div>
59 </form>59 </form>
6060
=== modified file 'app/views/charm-panel.js'
--- app/views/charm-panel.js 2012-11-07 13:12:18 +0000
+++ app/views/charm-panel.js 2012-11-09 14:33:29 +0000
@@ -591,7 +591,14 @@
591 this.tooltip.hide();591 this.tooltip.hide();
592 delete this.tooltip.field;592 delete this.tooltip.field;
593 },593 },
594 /** Pass clicks on the overlay on to the correct recipient. */594 /**
595 * Pass clicks on the overlay on to the correct recipient.
596 * The recipient can be the upload widget or the file remove one.
597 *
598 * @method onOverlayClick
599 * @param {Object} evt An event object.
600 * @return {undefined} Dispatches only.
601 */
595 onOverlayClick: function(evt) {602 onOverlayClick: function(evt) {
596 var container = this.get('container');603 var container = this.get('container');
597 if (this.configFileContent) {604 if (this.configFileContent) {
@@ -600,6 +607,14 @@
600 container.one('.config-file-upload-widget').getDOMNode().click();607 container.one('.config-file-upload-widget').getDOMNode().click();
601 }608 }
602 },609 },
610 /**
611 * Handle the file upload click event.
612 * Call onFileLoaded or onFileError if an error occurs during upload.
613 *
614 * @method onFileChange
615 * @param {Object} evt An event object.
616 * @return {undefined} Mutates only.
617 */
603 onFileChange: function(evt) {618 onFileChange: function(evt) {
604 var container = this.get('container');619 var container = this.get('container');
605 console.log('onFileChange:', evt);620 console.log('onFileChange:', evt);
@@ -613,6 +628,13 @@
613 container.one('.config-file-upload-overlay')628 container.one('.config-file-upload-overlay')
614 .setContent('Remove file');629 .setContent('Remove file');
615 },630 },
631 /**
632 * Handle the file remove click event.
633 * Restore the file upload widget on click.
634 *
635 * @method onFileRemove
636 * @return {undefined} Mutates only.
637 */
616 onFileRemove: function() {638 onFileRemove: function() {
617 var container = this.get('container');639 var container = this.get('container');
618 this.configFileContent = null;640 this.configFileContent = null;
@@ -624,9 +646,20 @@
624 this.fileInput.replace(Y.Node.create('<input type="file"/>')646 this.fileInput.replace(Y.Node.create('<input type="file"/>')
625 .addClass('config-file-upload-widget'));647 .addClass('config-file-upload-widget'));
626 this.fileInput = container.one('.config-file-upload-widget');648 this.fileInput = container.one('.config-file-upload-widget');
627 container.one('.config-file-upload-overlay')649 var overlay = container.one('.config-file-upload-overlay');
628 .setContent('Use configuration file');650 overlay.setContent('Use configuration file');
651 // Ensure the charm section height is correctly restored.
652 overlay.ancestor('.collapsible')
653 .show('sizeIn', {duration: 0.25, width: null});
629 },654 },
655 /**
656 * Callback called when a file is correctly uploaded.
657 * Hide the charm configuration section.
658 *
659 * @method onFileLoaded
660 * @param {Object} evt An event object.
661 * @return {undefined} Mutates only.
662 */
630 onFileLoaded: function(evt) {663 onFileLoaded: function(evt) {
631 this.configFileContent = evt.target.result;664 this.configFileContent = evt.target.result;
632665
@@ -645,6 +678,14 @@
645 }678 }
646 this.get('container').one('.charm-settings').hide();679 this.get('container').one('.charm-settings').hide();
647 },680 },
681 /**
682 * Callback called when an error occurs during file upload.
683 * Hide the charm configuration section.
684 *
685 * @method onFileError
686 * @param {Object} evt An event object (with a "target.error" attr).
687 * @return {undefined} Mutates only.
688 */
648 onFileError: function(evt) {689 onFileError: function(evt) {
649 console.log('onFileError:', evt);690 console.log('onFileError:', evt);
650 var msg;691 var msg;
651692
=== modified file 'lib/views/stylesheet.less'
--- lib/views/stylesheet.less 2012-11-08 15:50:13 +0000
+++ lib/views/stylesheet.less 2012-11-09 14:33:29 +0000
@@ -17,6 +17,7 @@
17@charm-panel-background-color: #eeeeee;17@charm-panel-background-color: #eeeeee;
18@charm-panel-border-color: #BEBEBE;18@charm-panel-border-color: #BEBEBE;
19@charm-paneel-border-top-color: #E0DEDE;19@charm-paneel-border-top-color: #E0DEDE;
20@charm-panel-padding-left: 10px;
20@navbar-color: #2D2D2D!important;21@navbar-color: #2D2D2D!important;
2122
22body {23body {
@@ -29,6 +30,18 @@
29 font-family: @font-family;30 font-family: @font-family;
30}31}
3132
33.create-border-radius(@radius) {
34 -moz-border-radius: @radius;
35 -webkit-border-radius: @radius;
36 border-radius: @radius;
37}
38
39.create-box-shadow(@arguments) {
40 -moz-box-shadow: @arguments;
41 -webkit-box-shadow: @arguments;
42 box-shadow: @arguments;
43}
44
32.create-button(@gradient-start, @gradient-end, @shadow-color, @v-pos) {45.create-button(@gradient-start, @gradient-end, @shadow-color, @v-pos) {
33 @blur: 2px;46 @blur: 2px;
34 background-image: -ms-linear-gradient(top, @gradient-start, @gradient-end);47 background-image: -ms-linear-gradient(top, @gradient-start, @gradient-end);
@@ -38,21 +51,15 @@
38 background-image: -moz-linear-gradient(top, @gradient-start, @gradient-end);51 background-image: -moz-linear-gradient(top, @gradient-start, @gradient-end);
39 background-image: linear-gradient(top, @gradient-start, @gradient-end);52 background-image: linear-gradient(top, @gradient-start, @gradient-end);
40 background-repeat: repeat-x;53 background-repeat: repeat-x;
41 -moz-box-shadow: 0 (@v-pos + 3) @blur -@blur @shadow-color inset,54 // Using a variable here because LESS strips commas in mixin args.
42 2px 0 3px -2px @shadow-color inset, -2px 0 3px -2px @shadow-color inset;55 @box-shadow: 0 (@v-pos + 3) @blur -@blur @shadow-color inset,
43 -webkit-box-shadow: 0 (@v-pos + 3) @blur -@blur @shadow-color inset,56 2px 0 3px -2px @shadow-color inset,
44 2px 0 3px -2px @shadow-color inset, -2px 0 3px -2px @shadow-color inset;57 -2px 0 3px -2px @shadow-color inset;
45 box-shadow: 0 (@v-pos + 3) @blur -@blur @shadow-color inset,58 .create-box-shadow(@box-shadow);
46 2px 0 3px -2px @shadow-color inset, -2px 0 3px -2px @shadow-color inset;59 .create-border-radius(~"6px / 7px");
47 @border-radii: ~"6px / 7px";
48 -moz-border-radius: @border-radii;
49 -webkit-border-radius: @border-radii;
50 border-radius: @border-radii;
51 border: none;60 border: none;
52}61}
5362
54
55
56i.sprite {63i.sprite {
57 display: inline-block;64 display: inline-block;
58 vertical-align: middle;65 vertical-align: middle;
@@ -219,15 +226,8 @@
219 display: none;226 display: none;
220 background-color: @background_color;227 background-color: @background_color;
221 color: #fdf6e3;228 color: #fdf6e3;
222229 .create-border-radius(@border_radius);
223 border-radius: @border_radius;230 .create-box-shadow(-2px 4px 4px 0 rgba(0, 0, 0, 0.5));
224 -moz-border-radius: @border_radius;
225 -webkit-border-radius: @border_radius;
226
227 box-shadow: -2px 4px 4px 0 rgba(0, 0, 0, 0.5);
228 -moz-box-shadow: -2px 4px 4px 0 rgba(0, 0, 0, 0.5);
229 -webkit-box-shadow: -2px 4px 4px 0 rgba(0, 0, 0, 0.5);
230
231 top: 0;231 top: 0;
232 left: 0;232 left: 0;
233 position: absolute;233 position: absolute;
@@ -271,9 +271,7 @@
271 cursor: pointer;271 cursor: pointer;
272 line-height: 32px;272 line-height: 32px;
273 padding: 5px 5px 5px 5px;273 padding: 5px 5px 5px 5px;
274 border-radius: @border_radius;274 .create-border-radius(@border_radius);
275 -moz-border-radius: @border_radius;
276 -webkit-border-radius: @border_radius;
277275
278 &.view-service {276 &.view-service {
279 background-image: url(/juju-ui/assets/images/icons/icon_noshadow_view.png);277 background-image: url(/juju-ui/assets/images/icons/icon_noshadow_view.png);
@@ -379,9 +377,7 @@
379377
380.unit (@min_height: 20px, @border_radius:3px) {378.unit (@min_height: 20px, @border_radius:3px) {
381 padding: 5px;379 padding: 5px;
382 -webkit-border-radius: @border_radius;380 .create-border-radius(@border_radius);
383 -moz-border-radius: @border_radius;
384 border-radius: @border_radius;
385 margin-bottom: 0px;381 margin-bottom: 0px;
386 min-height: @min_height;382 min-height: @min_height;
387 cursor: pointer;383 cursor: pointer;
@@ -731,12 +727,8 @@
731 background: white;727 background: white;
732 padding: 1.6em;728 padding: 1.6em;
733 border: solid black 2px;729 border: solid black 2px;
734 -webkit-border-radius: 6px;730 .create-border-radius(6px);
735 -moz-border-radius: 6px;731 .create-box-shadow(0 3px 7px rgba(0, 0, 0, 0.3));
736 border-radius: 6px;
737 -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
738 -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
739 box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
740 -webkit-background-clip: padding-box;732 -webkit-background-clip: padding-box;
741 -moz-background-clip: padding-box;733 -moz-background-clip: padding-box;
742 background-clip: padding-box;734 background-clip: padding-box;
@@ -844,9 +836,10 @@
844 background-color: #FFFFFF;836 background-color: #FFFFFF;
845 border-bottom: 1px solid @charm-panel-border-color;837 border-bottom: 1px solid @charm-panel-border-color;
846 height: 52px;838 height: 52px;
847 padding-left: 8px;839 padding-left: @charm-panel-padding-left;
848 .btn {840 .btn {
849 margin-top: 12px;841 margin-top: 12px;
842 width: 67px;
850 }843 }
851 }844 }
852 .search-charm-inner {845 .search-charm-inner {
@@ -879,7 +872,7 @@
879 border-bottom: 1px solid @charm-panel-border-color;872 border-bottom: 1px solid @charm-panel-border-color;
880 font-family: @font-family-medium;873 font-family: @font-family-medium;
881 font-weight: normal;874 font-weight: normal;
882 padding: 8px 12px;875 padding: 8px @charm-panel-padding-left;
883 i {876 i {
884 float: right;877 float: right;
885 }878 }
@@ -896,13 +889,13 @@
896 #charm-panel-head {889 #charm-panel-head {
897 border-top: 1px solid #FFFFFF;890 border-top: 1px solid #FFFFFF;
898 border-bottom: 1px solid @charm-panel-border-color;891 border-bottom: 1px solid @charm-panel-border-color;
899 padding: 1ex 12px 10px 12px;892 padding: 1ex 10px 10px @charm-panel-padding-left;
900 }893 }
901 .collapsible {894 .collapsible {
902 background-color: #E7E7E7;895 background-color: #E7E7E7;
903 line-height: 16px;896 line-height: 16px;
904 overflow: hidden;897 overflow: hidden;
905 padding: 0px 12px;898 padding: 0px @charm-panel-padding-left;
906 :last-child {899 :last-child {
907 margin-bottom: 11px;900 margin-bottom: 11px;
908 }901 }
@@ -910,6 +903,9 @@
910 &.charm-description {903 &.charm-description {
911 color: #58595B;904 color: #58595B;
912 font-size: 12px;905 font-size: 12px;
906 .btn.deploy {
907 margin-left: 0;
908 }
913 .charm-section {909 .charm-section {
914 .commitmessage {910 .commitmessage {
915 padding: 0.8ex 0 1ex 1em;911 padding: 0.8ex 0 1ex 1em;
@@ -926,11 +922,16 @@
926 &.config-variant {922 &.config-variant {
927 font-size: 14px;923 font-size: 14px;
928 border-top: 1px solid @charm-paneel-border-top-color;924 border-top: 1px solid @charm-paneel-border-top-color;
925 .charm-entry {
926 padding: 5px @charm-panel-padding-left;
927 &:nth-of-type(2) {
928 margin-bottom: 15px;
929 }
930 }
929 .control-group {931 .control-group {
930 width: auto;932 width: auto;
931 margin-bottom: 0;933 margin-bottom: 0;
932 margin-top: 1ex;934 margin-top: 1ex;
933 padding: 0px 12px;
934 clear: both;935 clear: both;
935 }936 }
936 .control-description {937 .control-description {
@@ -946,6 +947,23 @@
946 .controls {947 .controls {
947 margin-left: auto;948 margin-left: auto;
948 margin-right: 0;949 margin-right: 0;
950 input[type=text] {
951 color: @text-entry-color;
952 font-style: italic;
953 font-size: 12px;
954 height: 15px;
955 width: 250px;
956 margin: 0;
957 .create-border-radius(6px);
958 // Using a variable here because LESS strips commas in
959 // mixin args.
960 @box-shadow: 0 1px 3px #959595 inset, 0 1px 0 white;
961 .create-box-shadow(@box-shadow);
962 }
963 input[type=checkbox] {
964 margin-left: 1ex;
965 margin-top: 0.7ex;
966 }
949 }967 }
950 .config-field {968 .config-field {
951 font-size: 16px;969 font-size: 16px;
@@ -955,6 +973,8 @@
955 position: relative;973 position: relative;
956 width: 252px;974 width: 252px;
957 height: 25px;975 height: 25px;
976 margin-bottom: 20px;
977 margin-top: 20px;
958 }978 }
959 .config-file-upload-widget {979 .config-file-upload-widget {
960 position: absolute;980 position: absolute;
@@ -965,6 +985,8 @@
965 }985 }
966 .config-file-upload-overlay {986 .config-file-upload-overlay {
967 background: url(/juju-ui/assets/images/getfile_button.png) no-repeat;987 background: url(/juju-ui/assets/images/getfile_button.png) no-repeat;
988 color: #4c4c4c;
989 font-family: @font-family-medium;
968 position: absolute;990 position: absolute;
969 top: 0;991 top: 0;
970 left: 0;992 left: 0;
@@ -985,12 +1007,6 @@
985 width: auto;1007 width: auto;
986 z-index: 2;1008 z-index: 2;
987 }1009 }
988 .controls.boolean {
989 input {
990 margin-left: 1ex;
991 margin-top: 0.7ex;
992 }
993 }
994 .btn {1010 .btn {
995 margin-top: 5px;1011 margin-top: 5px;
996 }1012 }
@@ -1005,7 +1021,7 @@
1005 font-weight: normal;1021 font-weight: normal;
1006 font-size: 16px;1022 font-size: 16px;
1007 text-transform: capitalize;1023 text-transform: capitalize;
1008 padding-left: 11px;1024 padding-left: @charm-panel-padding-left;
1009 background-color: #CBCBCB;1025 background-color: #CBCBCB;
1010 border-top: 1px solid #989898;1026 border-top: 1px solid #989898;
1011 }1027 }
@@ -1013,7 +1029,7 @@
1013 margin-bottom: 0;1029 margin-bottom: 0;
1014 }1030 }
1015 .charm-entry {1031 .charm-entry {
1016 padding: 11px;1032 padding: 11px @charm-panel-padding-left;
1017 border-top: 1px solid #FFFFFF;1033 border-top: 1px solid #FFFFFF;
1018 border-bottom: 1px solid #BDBDBD;1034 border-bottom: 1px solid #BDBDBD;
1019 &:first-child {1035 &:first-child {
@@ -1271,9 +1287,7 @@
1271 background-color: white;1287 background-color: white;
1272 border: solid 1px black;1288 border: solid 1px black;
1273 padding: 0.2em 0.5em 0.3em;1289 padding: 0.2em 0.5em 0.3em;
1274 -webkit-border-radius: 3px;1290 .create-border-radius(3px);
1275 -moz-border-radius: 3px;
1276 border-radius: 3px;
1277 min-width: 20px;1291 min-width: 20px;
1278 max-width: 400px;1292 max-width: 400px;
1279}1293}
@@ -1281,11 +1295,11 @@
1281.charm-panel-configure {1295.charm-panel-configure {
1282 background-image: url(/juju-ui/assets/images/configure-cog.png);1296 background-image: url(/juju-ui/assets/images/configure-cog.png);
1283 background-repeat: no-repeat;1297 background-repeat: no-repeat;
1284 background-position: 230px 42px;1298 background-position: 230px 38px;
1285 border-top: 2px solid #dd4814;1299 border-top: 2px solid #dd4814;
1286 background-color: #2F2A27;1300 background-color: #2F2A27;
1287 height: 93px;1301 height: 90px;
1288 padding-left: 8px;1302 padding-left: @charm-panel-padding-left;
1289 .title {1303 .title {
1290 font-weight: lighter;1304 font-weight: lighter;
1291 font-size: 22px;1305 font-size: 22px;
12921306
=== modified file 'undocumented'
--- undocumented 2012-11-08 20:11:46 +0000
+++ undocumented 2012-11-09 14:33:29 +0000
@@ -75,10 +75,6 @@
75app/views/charm-panel.js mouseenter75app/views/charm-panel.js mouseenter
76app/views/charm-panel.js mouseleave76app/views/charm-panel.js mouseleave
77app/views/charm-panel.js onCharmDeployClicked77app/views/charm-panel.js onCharmDeployClicked
78app/views/charm-panel.js onFileChange
79app/views/charm-panel.js onFileError
80app/views/charm-panel.js onFileLoaded
81app/views/charm-panel.js onFileRemove
82app/views/charm-panel.js render78app/views/charm-panel.js render
83app/views/charm-panel.js setDefaultSeries79app/views/charm-panel.js setDefaultSeries
84app/views/charm-panel.js setPanel80app/views/charm-panel.js setPanel

Subscribers

People subscribed via source and target branches