You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2015/09/24 20:00:15 UTC

ignite git commit: IGNITE-843 WIP multi columns support.

Repository: ignite
Updated Branches:
  refs/heads/ignite-843 7c60be0d2 -> a9c59f408


IGNITE-843 WIP multi columns support.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a9c59f40
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a9c59f40
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a9c59f40

Branch: refs/heads/ignite-843
Commit: a9c59f4082d4bc1508bd657a01aab6a2e0cbad6d
Parents: 7c60be0
Author: AKuznetsov <ak...@gridgain.com>
Authored: Fri Sep 25 01:00:06 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Fri Sep 25 01:00:06 2015 +0700

----------------------------------------------------------------------
 .../src/main/js/controllers/common-module.js    |   2 +-
 .../main/js/controllers/metadata-controller.js  |   4 +-
 .../src/main/js/controllers/sql-controller.js   | 141 ++++++++++++++-----
 .../control-center-web/src/main/js/package.json |   2 +-
 .../src/main/js/public/stylesheets/style.scss   |  37 +++++
 .../js/views/configuration/metadata-load.jade   |   2 +-
 .../main/js/views/configuration/summary.jade    |   4 +-
 .../src/main/js/views/includes/controls.jade    |  10 +-
 .../src/main/js/views/settings/profile.jade     |   2 +-
 .../src/main/js/views/sql/cache-metadata.jade   |   2 +-
 .../src/main/js/views/sql/chart-settings.jade   |  32 +++--
 .../src/main/js/views/sql/notebook-new.jade     |   6 +-
 .../src/main/js/views/sql/paragraph-rate.jade   |   6 +-
 .../src/main/js/views/sql/sql.jade              |   3 +-
 .../main/js/views/templates/agent-download.jade |   4 +-
 .../main/js/views/templates/batch-confirm.jade  |   8 +-
 .../src/main/js/views/templates/clone.jade      |   6 +-
 .../src/main/js/views/templates/confirm.jade    |   6 +-
 .../src/main/js/views/templates/layout.jade     |   2 +
 .../src/main/js/views/templates/message.jade    |   4 +-
 .../js/views/templates/validation-error.jade    |   2 +-
 21 files changed, 199 insertions(+), 86 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/controllers/common-module.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/controllers/common-module.js b/modules/control-center-web/src/main/js/controllers/common-module.js
index 2b5dc10..6ae751b 100644
--- a/modules/control-center-web/src/main/js/controllers/common-module.js
+++ b/modules/control-center-web/src/main/js/controllers/common-module.js
@@ -16,7 +16,7 @@
  */
 
 var controlCenterModule = angular.module('ignite-web-control-center',
-    ['ngAnimate', 'smart-table', 'mgcrea.ngStrap', 'ui.ace', 'ngSanitize', 'treeControl', 'darthwade.loading', 'agGrid']);
+    ['ngAnimate', 'smart-table', 'mgcrea.ngStrap', 'ui.ace', 'ngSanitize', 'treeControl', 'darthwade.loading', 'agGrid', 'dndLists']);
 
 // Modal popup configuration.
 controlCenterModule.config(function ($modalProvider) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/controllers/metadata-controller.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/controllers/metadata-controller.js b/modules/control-center-web/src/main/js/controllers/metadata-controller.js
index b1ed91a..16d9ca3 100644
--- a/modules/control-center-web/src/main/js/controllers/metadata-controller.js
+++ b/modules/control-center-web/src/main/js/controllers/metadata-controller.js
@@ -710,9 +710,9 @@ controlCenterModule.controller('metadataController', [
                     : 'New metadata';
             };
 
-            $scope.prepareNewItem = function () {
+            function prepareNewItem() {
                 return {space: $scope.spaces[0]._id, caches: []};
-            };
+            }
 
             // Add new metadata.
             $scope.createItem = function () {

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/controllers/sql-controller.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/controllers/sql-controller.js b/modules/control-center-web/src/main/js/controllers/sql-controller.js
index 45eeb99..25cbe8e 100644
--- a/modules/control-center-web/src/main/js/controllers/sql-controller.js
+++ b/modules/control-center-web/src/main/js/controllers/sql-controller.js
@@ -24,6 +24,45 @@ controlCenterModule.controller('sqlController',
     $scope.agentGoal = 'execute sql statements';
     $scope.agentTestDriveOption = '--test-drive-sql';
 
+    var chartSettingsParagraph = null;
+
+    $scope.chartSettingsDragStart = function (paragraph) {
+        chartSettingsParagraph = paragraph;
+    };
+
+    $scope.removeKeyColumn = function (paragraph, index) {
+        paragraph.chartKeyCols.splice(index, 1);
+
+        $scope.applyChartSettings(paragraph);
+    };
+
+    $scope.removeValColumn = function (paragraph, index) {
+        paragraph.chartValCols.splice(index, 1);
+
+        $scope.applyChartSettings(paragraph);
+    };
+
+    function acceptColumn(cols, droppedCol) {
+        var accepted = _.findIndex(cols, function (col) {
+                return col.label == droppedCol.label;
+            }) < 0;
+
+        if (accepted)
+            $timeout(function () {
+                $scope.applyChartSettings(chartSettingsParagraph);
+            });
+
+        return accepted ? droppedCol : false;
+    }
+
+    $scope.acceptKeyColumn = function(event, index, item, external, type, allowedType) {
+        return acceptColumn(chartSettingsParagraph.chartKeyCols, item);
+    };
+
+    $scope.acceptValColumn = function(event, index, item, external, type, allowedType) {
+        return acceptColumn(chartSettingsParagraph.chartValCols, item);
+    };
+
     $scope.joinTip = $common.joinTip;
 
     $scope.caches = [];
@@ -68,6 +107,10 @@ controlCenterModule.controller('sqlController',
             return this.rows && this.rows.length > 0;
         };
 
+        paragraph.hasChartColumns = function () {
+            return !$common.isEmptyArray(this.chartKeyCols) && !$common.isEmptyArray(this.chartValCols);
+        };
+
         Object.defineProperty(paragraph, 'gridOptions', { value: {
             enableColResize: true,
             columnDefs: [
@@ -288,24 +331,39 @@ controlCenterModule.controller('sqlController',
         paragraph.columnFilter = _columnFilter(paragraph);
     };
 
-    var _selectAxis = function (cols, col, dfltIdx) {
-        if (col) {
-            var idx = _.findIndex(cols, function (item) {
-                return item.label == col.label;
+    function _retainColumns(allCols, curCols, dfltIdx) {
+        var retainedCols = [];
+
+        var allColsLen = allCols.length;
+
+        if (allColsLen > 0) {
+            curCols.forEach(function (curCol) {
+                var idx = _.findIndex(allCols, function (allCol) {
+                    return allCol.label == curCol.label;
+                });
+
+                if (idx >= 0)
+                    retainedCols.push(allCols[idx]);
             });
 
-            if (idx >= 0)
-                return cols[idx];
+            if ($common.isEmptyArray(retainedCols))
+                retainedCols.push(allCols[dfltIdx < allColsLen ? dfltIdx : 0]);
         }
 
-        return cols.length >= dfltIdx ? cols[dfltIdx] : null;
-    };
+        return retainedCols;
+    }
 
     var _processQueryResult = function (paragraph) {
         return function (res) {
             paragraph.meta = [];
             paragraph.chartColumns = [];
 
+            if (!$common.isDefined(paragraph.chartKeyCols))
+                paragraph.chartKeyCols = [];
+
+            if (!$common.isDefined(paragraph.chartValCols ))
+                paragraph.chartValCols = [];
+
             if (res.meta) {
                 paragraph.disabledSystemColumns = res.meta.length == 2 &&
                     res.meta[0].fieldName === "_KEY" && res.meta[1].fieldName === "_VAL";
@@ -332,8 +390,8 @@ controlCenterModule.controller('sqlController',
 
                 paragraph.gridOptions.api.setColumnDefs(columnDefs);
 
-                paragraph.chartColX = _selectAxis(paragraph.chartColumns, paragraph.chartColX, 0);
-                paragraph.chartColY = _selectAxis(paragraph.chartColumns, paragraph.chartColY, 1);
+                paragraph.chartKeyCols = _retainColumns(paragraph.chartColumns, paragraph.chartKeyCols, 0);
+                paragraph.chartValCols = _retainColumns(paragraph.chartColumns, paragraph.chartValCols, 1);
             }
 
             paragraph.page = 1;
@@ -581,33 +639,41 @@ controlCenterModule.controller('sqlController',
     }
 
     function _chartDatum(key, paragraph) {
-        var index = 0;
+        var values = [];
 
-        var values = _.map(paragraph.rows, function (row) {
-            return {
-                x: _chartNumber(row, paragraph.chartColX.value, index++),
-                y: _chartNumber(row, paragraph.chartColY.value, 0)
-            }
-        });
+         if (paragraph.hasChartColumns()) {
+             var index = 0;
+
+             values = _.map(paragraph.rows, function (row) {
+                 return {
+                     x: _chartNumber(row, paragraph.chartKeyCols[0].value, index++),
+                     y: _chartNumber(row, paragraph.chartValCols[0].value, 0)
+                 }
+             });
+         }
 
         return [{key: key, values: values}];
     }
 
+    function _colLabel(col) {
+        return col.label;
+    }
+
     function _insertChart(paragraph, datum, chart) {
         var chartId = 'chart-' + paragraph.id;
 
         var xAxisLabel = 'X';
         var yAxisLabel = 'Y';
 
-        _.forEach(paragraph.chartColumns, function (col) {
-            if (col == paragraph.chartColX)
-                xAxisLabel = col.label;
-
-            if (col == paragraph.chartColY)
-                yAxisLabel = col.label;
-        });
+        if (paragraph.hasChartColumns()) {
+            xAxisLabel = _.map(paragraph.chartKeyCols, _colLabel).join(', ');
+            yAxisLabel = _.map(paragraph.chartValCols, _colLabel).join(', ');
+        }
 
         $timeout(function() {
+            // Remove previous chart.
+            d3.selectAll('#' + chartId + ' svg > *').remove();
+
             chart.height(400);
 
             if (chart.xAxis)
@@ -616,9 +682,6 @@ controlCenterModule.controller('sqlController',
             if (chart.yAxis)
                 chart.yAxis.axisLabel(yAxisLabel);
 
-            // Remove previous chart.
-            d3.selectAll('#' + chartId + ' svg > *').remove();
-
             // Insert new chart.
             d3.select('#' + chartId + ' svg')
                 .datum(datum)
@@ -660,11 +723,14 @@ controlCenterModule.controller('sqlController',
                 .y(function (d) { return d.value;})
                 .margin({left: 70});
 
-            var values = _.map(paragraph.rows, function (row) {
-                return {
-                    label: _chartLabel(row, paragraph.chartColX.value, index++),
-                    value: _chartNumber(row, paragraph.chartColY.value, 0)
-                }
+            var values = [];
+
+            if (paragraph.hasChartColumns())
+                values = _.map(paragraph.rows, function (row) {
+                    return {
+                        label: _chartLabel(row, paragraph.chartKeyCols[0].value, index++),
+                        value: _chartNumber(row, paragraph.chartValCols[0].value, 0)
+                    };
             });
 
             _insertChart(paragraph, [{key: 'bar', values: values}], chart);
@@ -677,10 +743,10 @@ controlCenterModule.controller('sqlController',
         nv.addGraph(function() {
             var chart = nv.models.pieChart()
                     .x(function (row) {
-                        return _chartLabel(row, paragraph.chartColX.value, index++);
+                        return _chartLabel(row, paragraph.chartKeyCols[0].value, index++);
                     })
                     .y(function (row) {
-                        return _chartNumber(row, paragraph.chartColY.value, 0);
+                        return _chartNumber(row, paragraph.chartValCols[0].value, 0);
                     })
                 .showLabels(true)
                 .labelThreshold(.05)
@@ -688,7 +754,12 @@ controlCenterModule.controller('sqlController',
                 .donut(true)
                 .donutRatio(0.35);
 
-            _insertChart(paragraph, paragraph.rows, chart);
+            var datum = [];
+
+            if (paragraph.hasChartColumns())
+                datum = paragraph.rows;
+
+            _insertChart(paragraph, datum, chart);
         });
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/package.json
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/package.json b/modules/control-center-web/src/main/js/package.json
index eed30d8..9e88a0d 100644
--- a/modules/control-center-web/src/main/js/package.json
+++ b/modules/control-center-web/src/main/js/package.json
@@ -37,7 +37,7 @@
     "mongoose-deep-populate": "2.0.1",
     "nconf": "^0.8.0",
     "node-sass-middleware": "0.9.6",
-    "nodemailer": "1.4.0",
+    "nodemailer": "1.5.0",
     "passport": "^0.3.0",
     "passport-local": "^1.0.0",
     "passport-local-mongoose": "3.0.0",

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/public/stylesheets/style.scss
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/public/stylesheets/style.scss b/modules/control-center-web/src/main/js/public/stylesheets/style.scss
index 7a8b393..ab8ed1c 100644
--- a/modules/control-center-web/src/main/js/public/stylesheets/style.scss
+++ b/modules/control-center-web/src/main/js/public/stylesheets/style.scss
@@ -1484,7 +1484,44 @@ a {
 }
 
 .chart-settings {
+    margin: 10px 5px 5px 5px !important;
+}
+
+.chart-settings-columns-list {
+    border: 1px solid $ignite-border-color;
+    list-style: none;
+    margin-bottom: 10px;
+    min-height: 30px;
+    max-height: 200px;
     padding: 5px;
+
+    overflow: auto;
+
+    li {
+        float: left;
+    }
+
+    li:nth-child(even) {
+        margin-right: 0;
+    }
+
+    .fa-close {
+        margin-left: 10px;
+    }
+}
+
+.btn-chart-column {
+    border-radius: 3px;
+    font-size: 12px;
+    margin: 3px 3px;
+    padding: 1px 5px;
+    line-height: 1.5;
+    cursor: default;
+}
+
+.btn-chart-column-movable {
+    @extend .btn-chart-column;
+    cursor: move;
 }
 
 .page-loading-overlay {

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/configuration/metadata-load.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/configuration/metadata-load.jade b/modules/control-center-web/src/main/js/views/configuration/metadata-load.jade
index 7d6c1b0..42e7798 100644
--- a/modules/control-center-web/src/main/js/views/configuration/metadata-load.jade
+++ b/modules/control-center-web/src/main/js/views/configuration/metadata-load.jade
@@ -23,7 +23,7 @@ mixin chk(mdl, change, tip)
     .modal-dialog
         .modal-content(dw-loading='loadingMetadataFromDb' dw-loading-options='{text: ""}')
             #errors-container.modal-header.header
-                button.close(type='button' ng-click='$hide()' aria-hidden='true') &times;
+                button.close(ng-click='$hide()' aria-hidden='true') &times;
                 h4.modal-title Load metadata from database
             .metadata-content(ng-show='loadMeta.action == "connect"' style='margin-bottom: 60px')
                 form.form-horizontal(name='loadForm' novalidate)

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/configuration/summary.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/configuration/summary.jade b/modules/control-center-web/src/main/js/views/configuration/summary.jade
index cb9c645..524bdda 100644
--- a/modules/control-center-web/src/main/js/views/configuration/summary.jade
+++ b/modules/control-center-web/src/main/js/views/configuration/summary.jade
@@ -65,7 +65,7 @@ block content
                                     .col-xs-2.col-sm-2.col-md-1
                                         label Generate:
                                     .col-xs-4.col-sm-3.col-md-3
-                                        button.select-toggle.form-control(type='button' ng-model='configServer.javaClassServer' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
+                                        button.select-toggle.form-control(ng-model='configServer.javaClassServer' bs-select bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
                                 div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaServer')
                             div(bs-pane title='POJO' ng-show='pojoAvailable()')
                                 .details-row
@@ -121,5 +121,5 @@ block content
                                         .col-xs-2.col-sm-2.col-md-1
                                             label Generate:
                                         .col-xs-4.col-sm-3.col-md-3
-                                            button.form-control(type='button' ng-model='backupItem.javaClassClient' bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
+                                            button.form-control(ng-model='backupItem.javaClassClient' bs-select bs-options='item.value as item.label for item in javaClassItems' data-sort='false')
                                     div(ui-ace='{ onLoad: aceInit, mode: "java" }' ng-model='javaClient')

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/includes/controls.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/includes/controls.jade b/modules/control-center-web/src/main/js/views/includes/controls.jade
index 095c9f4..3136542 100644
--- a/modules/control-center-web/src/main/js/views/includes/controls.jade
+++ b/modules/control-center-web/src/main/js/views/includes/controls.jade
@@ -35,21 +35,21 @@ mixin block-callout(workflowTitle, workflowContent, whatsNextTitle, whatsNextCon
                             li(ng-repeat='item in #{whatsNextContent}' ng-bind-html='item')
 
 mixin tipField(lines)
-    i.tipField.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
+    i.tipField.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})')
     i.tipField.fa.fa-question-circle.blank(ng-if='!#{lines}')
 
 mixin tipLabel(lines)
-    i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
+    i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})')
     i.tipLabel.fa.fa-question-circle.blank(ng-if='!#{lines}')
 
 mixin ico-exclamation(mdl, err, msg)
-    i.fa.fa-exclamation-triangle.form-control-feedback(ng-show='ui.inputForm["#{mdl}"].$error.#{err}' bs-tooltip data-title='#{msg}' type='button')
+    i.fa.fa-exclamation-triangle.form-control-feedback(ng-show='ui.inputForm["#{mdl}"].$error.#{err}' bs-tooltip data-title='#{msg}')
 
 mixin btn-save(show, click)
     i.tipField.fa.fa-floppy-o(ng-show=show ng-click=click bs-tooltip data-title='Click icon or press [Enter] to save item' data-trigger='hover')
 
 mixin group-tip(lines)
-    i.group-legend-btn.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
+    i.group-legend-btn.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})')
 
 mixin group-btn-add(click, tip)
     i.group-legend-btn.fa.fa-plus(ng-click=click bs-tooltip=tip)
@@ -465,7 +465,7 @@ mixin groups(groups, dataSource)
     .panel.panel-default(ng-repeat='group in #{groups}' ng-click='triggerDigest=true' ng-hide='{{group.hide}}')
         .panel-heading(bs-collapse-toggle ng-click='hidePopover()') {{::group.label}}
             label(id='{{::group.group + "-title"}}')
-            i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)' type='button')
+            i.tipLabel.fa.fa-question-circle(ng-if='group.tip' bs-tooltip='joinTip(group.tip)')
             i.tipLabel.fa.fa-question-circle.blank(ng-if='!group.tip')
             i.pull-right.fa.fa-undo(ng-show='group.dirty' ng-click='resetItem(group.group); $event.stopPropagation()' bs-tooltip data-title='Undo unsaved changes')
         .panel-collapse(role='tabpanel' bs-collapse-target id='{{::group.group}}' number='{{::group.number}}')

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/settings/profile.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/settings/profile.jade b/modules/control-center-web/src/main/js/views/settings/profile.jade
index deaef77..d45f52f 100644
--- a/modules/control-center-web/src/main/js/views/settings/profile.jade
+++ b/modules/control-center-web/src/main/js/views/settings/profile.jade
@@ -49,7 +49,7 @@ block container
                             label {{profileUser.token}}
                             i.tipLabel.fa.fa-refresh(ng-click='generateToken()' bs-tooltip data-title='Generate random security token')
                             i.tipLabel.fa.fa-clipboard(ng-click-copy='{{profileUser.token}}' bs-tooltip data-title='Copy security token to clipboard')
-                            i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='' data-title='The security token is used for authorization of web agent' type='button')
+                            i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='' data-title='The security token is used for authorization of web agent')
                         .details-row
                             .advanced-options
                                 i.fa.fa-chevron-circle-up(ng-show='profileUser.changePassword' ng-click='profileUser.changePassword = ! profileUser.changePassword')

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/sql/cache-metadata.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/sql/cache-metadata.jade b/modules/control-center-web/src/main/js/views/sql/cache-metadata.jade
index 9d1bbe2..2d79249 100644
--- a/modules/control-center-web/src/main/js/views/sql/cache-metadata.jade
+++ b/modules/control-center-web/src/main/js/views/sql/cache-metadata.jade
@@ -13,7 +13,7 @@
     limitations under the License.
 .popover.cache-metadata(tabindex='-1' dw-loading='loadingCacheMetadata' dw-loading-options='{text: ""}' ng-init='tryLoadMetadata(cache)')
     h3.popover-title Metadata for: <b>{{cache.name}}</b></br>Cache mode: <b>{{cache.mode}}</b>
-    button.close(id='cache-metadata-close' type='button' ng-click='$hide()') &times;
+    button.close(id='cache-metadata-close' ng-click='$hide()') &times;
     .popover-content(ng-if='cache.metadata && cache.metadata.length > 0')
         treecontrol.tree-classic(tree-model='cache.metadata' options='treeOptions')
             label.clickable(ng-if='node.type == "type"' ng-dblclick='dblclickMetadata(paragraph, node)') {{node.name}}

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/sql/chart-settings.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/sql/chart-settings.jade b/modules/control-center-web/src/main/js/views/sql/chart-settings.jade
index 02bae96..708bff6 100644
--- a/modules/control-center-web/src/main/js/views/sql/chart-settings.jade
+++ b/modules/control-center-web/src/main/js/views/sql/chart-settings.jade
@@ -17,21 +17,23 @@
 .popover.settings(tabindex='-1' style='width: 250px')
     .arrow
     h3.popover-title(style='color: black') Chart settings
-    button.close(id='chart-settings-close' type='button' ng-click='$hide()') &times;
+    button.close(id='chart-settings-close' ng-click='$hide()') &times;
     .popover-content
         form.form-horizontal.chart-settings(name='chartSettingsForm' novalidate)
-            .form-group
-                .settings-row
-                    .col-sm-2
-                        label X:
-                    .col-sm-10
-                        button.form-control(id='chart-settings-X' ng-model='paragraph.chartColX' data-placeholder='Col X' bs-select bs-options='item as item.label for item in paragraph.chartColumns' data-container='false' tabindex='0')
-                .settings-row
-                    .col-sm-2
-                        label Y:
-                    .col-sm-10
-                        button.form-control(id='chart-settings-Y' ng-model='paragraph.chartColY' data-placeholder='Col Y' bs-select bs-options='item as item.label for item in paragraph.chartColumns' data-container='false' tabindex='1')
-            .form-actions
-                button.btn.btn-primary(id='chart-settings-apply' ng-disabled='chartSettingsForm.$invalid' type='button' ng-click='applyChartSettings(paragraph); $hide()') Apply
-                button.btn.btn-primary(id='chart-settings-cancel' type='button' ng-click='$hide()') Cancel
+            .form-group.chart-settings
+                label All columns
+                ul.chart-settings-columns-list( dnd-list='paragraph.chartColumns' dnd-allowed-types='[]')
+                    li(ng-repeat='col in paragraph.chartColumns track by $index')
+                        .btn.btn-default.btn-chart-column-movable(dnd-draggable='col' dnd-effect-allowed='copy' dnd-dragstart='chartSettingsDragStart(paragraph)') {{col.label}}
+                label X axis
+                ul.chart-settings-columns-list(id='chart-settings-keys' dnd-list='paragraph.chartKeyCols' dnd-drop='acceptKeyColumn(event, index, item, external, type, allowedType)')
+                    li(ng-repeat='col in paragraph.chartKeyCols track by $index')
+                        .btn.btn-info.btn-chart-column {{col.label}}
+                            i.fa.fa-close(ng-click='removeKeyColumn(paragraph, $index)')
+                label Y axis
+                ul.chart-settings-columns-list(id='chart-settings-vals' dnd-list='paragraph.chartValCols' dnd-drop='acceptValColumn(event, index, item, external, type, allowedType)')
+                    li(ng-repeat='col in paragraph.chartValCols track by $index')
+                        .btn.btn-success.btn-chart-column {{col.label}}
+                            i.fa.fa-close(ng-click='removeValColumn(paragraph, $index)')
+    h3.popover-footer Drag columns to axis
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/sql/notebook-new.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/sql/notebook-new.jade b/modules/control-center-web/src/main/js/views/sql/notebook-new.jade
index c0f2d54..15db4dc 100644
--- a/modules/control-center-web/src/main/js/views/sql/notebook-new.jade
+++ b/modules/control-center-web/src/main/js/views/sql/notebook-new.jade
@@ -18,7 +18,7 @@
     .modal-dialog
         .modal-content
             .modal-header
-                button.close(type='button' ng-click='$hide()') &times;
+                button.close(ng-click='$hide()') &times;
                 h4.modal-title New SQL notebook
             form.form-horizontal(name='ui.inputForm' novalidate)
                 .modal-body.row
@@ -27,5 +27,5 @@
                         .col-sm-9
                             input.form-control(id='create-notebook' type='text' ng-model='name' required on-enter='ui.inputForm.$valid && createNewNotebook(name)' auto-focus)
             .modal-footer
-                button.btn.btn-default(id='copy-btn-cancel' type='button' ng-click='$hide()') Cancel
-                button.btn.btn-primary(id='copy-btn-confirm' type='button' ng-disabled='ui.inputForm.$invalid' ng-click='createNewNotebook(name)') Create
+                button.btn.btn-default(id='copy-btn-cancel' ng-click='$hide()') Cancel
+                button.btn.btn-primary(id='copy-btn-confirm' ng-disabled='ui.inputForm.$invalid' ng-click='createNewNotebook(name)') Create

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/sql/paragraph-rate.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/sql/paragraph-rate.jade b/modules/control-center-web/src/main/js/views/sql/paragraph-rate.jade
index de9c172..689fd24 100644
--- a/modules/control-center-web/src/main/js/views/sql/paragraph-rate.jade
+++ b/modules/control-center-web/src/main/js/views/sql/paragraph-rate.jade
@@ -17,7 +17,7 @@
 .popover.settings(tabindex='-1' style='width: 200px')
     .arrow
     h3.popover-title(style='color: black') Refresh rate
-    button.close(id='paragraph-rate-close' type='button' ng-click='$hide()') &times;
+    button.close(id='paragraph-rate-close' ng-click='$hide()') &times;
     .popover-content
         form(name='popoverForm')
             .form-group(style='padding: 5px')
@@ -26,6 +26,6 @@
                 .col-sm-8(style='padding-left: 5px')
                     button.form-control.select-toggle(id='paragraph-unit' ng-init='unit = paragraph.rate.unit' ng-model='unit' required placeholder='Time unit' bs-select bs-options='item.value as item.label for item in timeUnit' data-container='false' tabindex='0')
             .form-actions(style='margin-top: 30px; padding: 5px')
-                button.btn.btn-primary(id='paragraph-rate-start' ng-disabled='popoverForm.$invalid' type='button' ng-click='startRefresh(paragraph, value, unit); $hide()') Start
-                button.btn.btn-primary.btn-default(id='paragraph-rate-stop' type='button' ng-click='stopRefresh(paragraph); $hide()' ng-disabled='!paragraph.rate.installed') Stop
+                button.btn.btn-primary(id='paragraph-rate-start' ng-disabled='popoverForm.$invalid' ng-click='startRefresh(paragraph, value, unit); $hide()') Start
+                button.btn.btn-primary.btn-default(id='paragraph-rate-stop' ng-click='stopRefresh(paragraph); $hide()' ng-disabled='!paragraph.rate.installed') Stop
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/sql/sql.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/sql/sql.jade b/modules/control-center-web/src/main/js/views/sql/sql.jade
index 1a61aa5..ee6a4e6 100644
--- a/modules/control-center-web/src/main/js/views/sql/sql.jade
+++ b/modules/control-center-web/src/main/js/views/sql/sql.jade
@@ -14,6 +14,8 @@
 
 extends ../templates/layout
 
+append css
+    link(rel='stylesheet', href='//cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.css')
 append scripts
     script(src='/sql-controller.js')
 
@@ -22,7 +24,6 @@ append scripts
     script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ext-language_tools.js')
     script(src='//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js')
     script(src='//cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.js')
-    link(rel='stylesheet', href='//cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.css')
 
 mixin btn-toolbar(btn, click, tip)
     i.btn.btn-default.fa(class=btn ng-click=click bs-tooltip='' data-title=tip data-trigger='hover' data-placement='bottom')

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/templates/agent-download.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/templates/agent-download.jade b/modules/control-center-web/src/main/js/views/templates/agent-download.jade
index 082c551..cfd404b 100644
--- a/modules/control-center-web/src/main/js/views/templates/agent-download.jade
+++ b/modules/control-center-web/src/main/js/views/templates/agent-download.jade
@@ -16,7 +16,7 @@
     .modal-dialog
         .modal-content
             #errors-container.modal-header.header
-                button.close(type='button' ng-click='$hide()') &times;
+                button.close(ng-click='$hide()') &times;
                 h4.modal-title Connection to Ignite Web Agent is not established
             .agent-download
                 p Please download and run&nbsp;
@@ -43,6 +43,6 @@
                 .details-row(ng-show='agentLoad.showToken')
                     label.labelField Security token: {{user.token}}
                     i.tipLabel.fa.fa-clipboard(ng-click-copy='{{user.token}}' bs-tooltip='' data-title='Copy security token to clipboard')
-                    i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='' data-title='The security token is used for authorization of web agent' type='button')
+                    i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='' data-title='The security token is used for authorization of web agent')
             .modal-footer
                 button.btn.btn-primary(ng-click='downloadAgent()') Download zip

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/templates/batch-confirm.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/templates/batch-confirm.jade b/modules/control-center-web/src/main/js/views/templates/batch-confirm.jade
index 0beb67f..a4d7681 100644
--- a/modules/control-center-web/src/main/js/views/templates/batch-confirm.jade
+++ b/modules/control-center-web/src/main/js/views/templates/batch-confirm.jade
@@ -18,7 +18,7 @@
     .modal-dialog
         .modal-content
             .modal-header
-                button.close(type='button' ng-click='cancel()' aria-hidden='true') &times;
+                button.close(ng-click='cancel()' aria-hidden='true') &times;
                 h4.modal-title Confirmation
             .modal-body(ng-show='batchConfirm.content')
                 p(ng-bind-html='batchConfirm.content' style='text-align: center')
@@ -27,6 +27,6 @@
                     label
                         input(type='checkbox' ng-model='batchConfirm.applyToAll')
                         | Apply to all
-                button.btn.btn-default(id='batch-confirm-btn-cancel' type='button' ng-click='batchConfirm.cancel()') Cancel
-                button.btn.btn-default(id='batch-confirm-btn-cancel' type='button' ng-click='batchConfirm.skip()') Skip
-                button.btn.btn-primary(id='batch-confirm-btn-overwrite' type='button' ng-click='batchConfirm.overwrite()') Overwrite
+                button.btn.btn-default(id='batch-confirm-btn-cancel' ng-click='batchConfirm.cancel()') Cancel
+                button.btn.btn-default(id='batch-confirm-btn-cancel' ng-click='batchConfirm.skip()') Skip
+                button.btn.btn-primary(id='batch-confirm-btn-overwrite' ng-click='batchConfirm.overwrite()') Overwrite

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/templates/clone.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/templates/clone.jade b/modules/control-center-web/src/main/js/views/templates/clone.jade
index 52b06ee..be33821 100644
--- a/modules/control-center-web/src/main/js/views/templates/clone.jade
+++ b/modules/control-center-web/src/main/js/views/templates/clone.jade
@@ -18,7 +18,7 @@
     .modal-dialog
         .modal-content
             .modal-header
-                button.close(type='button' ng-click='$hide()') &times;
+                button.close(ng-click='$hide()') &times;
                 h4.modal-title Clone
             form.form-horizontal(name='ui.inputForm' novalidate)
                 .modal-body.row
@@ -28,5 +28,5 @@
                         .col-sm-9
                             input.form-control(id='copy-new-name' type='text' ng-model='newName' required auto-focus)
             .modal-footer
-                button.btn.btn-default(id='copy-btn-cancel' type='button' ng-click='$hide()') Cancel
-                button.btn.btn-primary(id='copy-btn-confirm' type='button' ng-disabled='ui.inputForm.$invalid' ng-click='ok(newName)') Confirm
+                button.btn.btn-default(id='copy-btn-cancel' ng-click='$hide()') Cancel
+                button.btn.btn-primary(id='copy-btn-confirm' ng-disabled='ui.inputForm.$invalid' ng-click='ok(newName)') Confirm

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/templates/confirm.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/templates/confirm.jade b/modules/control-center-web/src/main/js/views/templates/confirm.jade
index bb68a04..b0acc1d 100644
--- a/modules/control-center-web/src/main/js/views/templates/confirm.jade
+++ b/modules/control-center-web/src/main/js/views/templates/confirm.jade
@@ -18,10 +18,10 @@
     .modal-dialog
         .modal-content
             .modal-header
-                button.close(type='button' ng-click='confirmCancel()' aria-hidden='true') &times;
+                button.close(ng-click='confirmCancel()' aria-hidden='true') &times;
                 h4.modal-title Confirmation
             .modal-body(ng-show='content')
                 p(ng-bind-html='content' style='text-align: center;')
             .modal-footer
-                button.btn.btn-default(id='confirm-btn-cancel' type='button' ng-click='confirmCancel()') Cancel
-                button.btn.btn-primary(id='confirm-btn-confirm' type='button' ng-click='confirmOk()') Confirm
+                button.btn.btn-default(id='confirm-btn-cancel' ng-click='confirmCancel()') Cancel
+                button.btn.btn-primary(id='confirm-btn-confirm' ng-click='confirmOk()') Confirm

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/templates/layout.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/templates/layout.jade b/modules/control-center-web/src/main/js/views/templates/layout.jade
index 30af808..a864270 100644
--- a/modules/control-center-web/src/main/js/views/templates/layout.jade
+++ b/modules/control-center-web/src/main/js/views/templates/layout.jade
@@ -61,6 +61,8 @@ html(ng-app='ignite-web-control-center' ng-init='user = #{JSON.stringify(user)};
 
             script(src='//cdn.rawgit.com/ceolter/ag-grid/master/dist/ag-grid.js')
 
+            script(src='//cdnjs.cloudflare.com/ajax/libs/angular-drag-and-drop-lists/1.3.0/angular-drag-and-drop-lists.min.js')
+
             script(src='/common-module.js')
             script(src='/data-structures.js')
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/templates/message.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/templates/message.jade b/modules/control-center-web/src/main/js/views/templates/message.jade
index c5ad288..0043709 100644
--- a/modules/control-center-web/src/main/js/views/templates/message.jade
+++ b/modules/control-center-web/src/main/js/views/templates/message.jade
@@ -18,9 +18,9 @@
     .modal-dialog
         .modal-content
             .modal-header
-                button.close(type='button' ng-click='$hide()' aria-hidden='true') &times;
+                button.close(ng-click='$hide()' aria-hidden='true') &times;
                 h4.modal-title {{title}}
             .modal-body(ng-show='content')
                 p(ng-bind-html='content' style='text-align: left;')
             .modal-footer
-                button.btn.btn-primary(id='confirm-btn-confirm' type='button' ng-click='$hide()') Ok
+                button.btn.btn-primary(id='confirm-btn-confirm' ng-click='$hide()') Ok

http://git-wip-us.apache.org/repos/asf/ignite/blob/a9c59f40/modules/control-center-web/src/main/js/views/templates/validation-error.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/templates/validation-error.jade b/modules/control-center-web/src/main/js/views/templates/validation-error.jade
index 8b483fb..13deb9b 100644
--- a/modules/control-center-web/src/main/js/views/templates/validation-error.jade
+++ b/modules/control-center-web/src/main/js/views/templates/validation-error.jade
@@ -22,4 +22,4 @@
                 td
                     label {{content}}&nbsp&nbsp
                 td
-                    button.close(id='popover-btn-close' type='button' ng-click='$hide()') &times;
+                    button.close(id='popover-btn-close' ng-click='$hide()') &times;