ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a.@apache.org
Subject [12/28] ignite git commit: IGNITE-843 Implemented Web Console.
Date Wed, 18 May 2016 09:21:15 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.jade b/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.jade
new file mode 100644
index 0000000..c6c3351
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.jade
@@ -0,0 +1,126 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+include ../../../../../app/helpers/jade/mixins.jade
+
+-var form = 'store'
+-var model = 'backupItem'
+-var keyFields = model + '.keyFields'
+-var valueFields = model + '.valueFields'
+-var keyFieldsForm = 'storeKeyFields'
+-var valueFieldsForm = 'storeValueFields'
+
+//- LEGACY mixin for LEGACY db fields tables.
+mixin table-db-field-edit(tbl, prefix, focusId, index)
+    -var databaseName = prefix + 'DatabaseFieldName'
+    -var databaseType = prefix + 'DatabaseFieldType'
+    -var javaName = prefix + 'JavaFieldName'
+    -var javaType = prefix + 'JavaFieldType'
+
+    -var databaseNameModel = tbl + '.' + databaseName
+    -var databaseTypeModel = tbl + '.' + databaseType
+    -var javaNameModel = tbl + '.' + javaName
+    -var javaTypeModel = tbl + '.' + javaType
+
+    -var databaseNameId = databaseName + focusId
+    -var databaseTypeId = databaseType + focusId
+    -var javaNameId = javaName + focusId
+    -var javaTypeId = javaType + focusId
+
+    .col-xs-3.col-sm-3.col-md-3
+        .fieldSep /
+        .input-tip
+            input.form-control(id=databaseNameId enter-focus-next=databaseTypeId type='text' ng-model=databaseNameModel placeholder='DB name' on-enter='#{javaNameModel} = #{javaNameModel} ? #{javaNameModel} : #{databaseNameModel}' on-escape='tableReset()')
+    .col-xs-3.col-sm-3.col-md-3
+        .fieldSep /
+        .input-tip
+            button.select-toggle.form-control(id=databaseTypeId enter-focus-next=javaNameId ng-model=databaseTypeModel data-placeholder='DB type' ng-class='{placeholder: !#{databaseTypeModel}}' bs-select bs-options='item.value as item.label for item in {{supportedJdbcTypes}}' on-escape='tableReset()' tabindex='0')
+    .col-xs-3.col-sm-3.col-md-3
+        .fieldSep /
+        .input-tip
+            input.form-control(id=javaNameId enter-focus-next=javaTypeId type='text' ng-model=javaNameModel placeholder='Java name' on-escape='tableReset()')
+    .col-xs-3.col-sm-3.col-md-3
+        -var btnVisible = 'tableDbFieldSaveVisible(' + tbl + ', ' + index +')'
+        -var btnSave = 'tableDbFieldSave(' + tbl + ', ' + index +')'
+        -var btnVisibleAndSave = btnVisible + ' && ' + btnSave
+
+        +btn-save(btnVisible, btnSave)
+        .input-tip
+            button.select-toggle.form-control(id=javaTypeId ng-model=javaTypeModel data-placeholder='Java type' ng-class='{placeholder: !#{javaTypeModel}}' bs-select bs-options='item.value as item.label for item in {{supportedJavaTypes}}' on-enter=btnVisibleAndSave on-escape='tableReset()' tabindex='0')
+
+form.panel.panel-default(name=form novalidate)
+    .panel-heading(bs-collapse-toggle='' ng-click='ui.loadPanel("#{form}")')
+        ignite-form-panel-chevron
+        label Domain model for cache store
+        ignite-form-field-tooltip.tipLabel
+            | Domain model properties for fields queries
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=form)
+        .panel-body(ng-if='ui.isPanelLoaded("#{form}")')
+            .col-sm-6
+                .settings-row
+                    +text('Database schema:', model + '.databaseSchema', 'databaseSchema', 'false', 'Input DB schema name', 'Schema name in database')
+                .settings-row
+                    +text('Database table:', model + '.databaseTable', 'databaseTable', 'false', 'Input DB table name', 'Table name in database')
+                .settings-row(ng-init='keysTbl={type: "table-db-fields", model: "keyFields", focusId: "KeyField", ui: "table-db-fields"}')
+                    ignite-form-group(ng-model='#{keyFields}' ng-form='#{keyFieldsForm}')
+                        ignite-form-field-label(id='keyFields')
+                            | Key fields
+                        ignite-form-group-tooltip
+                            | Collection of key fields descriptions for CacheJdbcPojoStore
+                        ignite-form-group-add(ng-click='tableNewItem(keysTbl)')
+                            | Add key field
+                        .group-content-empty(ng-show='!((#{keyFields} && #{keyFields}.length > 0) || tableNewItemActive(keysTbl))') Not defined
+                        .group-content(ng-show='(#{keyFields} && #{keyFields}.length > 0) || tableNewItemActive(keysTbl)')
+                            table.links-edit(st-table=keyFields)
+                                tbody
+                                    tr(ng-repeat='item in #{keyFields}')
+                                        td
+                                            div(ng-show='!tableEditing(keysTbl, $index)')
+                                                a.labelFormField(ng-click='tableStartEdit(backupItem, keysTbl, $index)') {{$index + 1}}) {{item.databaseFieldName}} / {{item.databaseFieldType}} / {{item.javaFieldName}} / {{item.javaFieldType}}
+                                                +btn-remove('tableRemove(backupItem, keysTbl, $index)', '"Remove key field"')
+                                            div(ng-show='tableEditing(keysTbl, $index)')
+                                                +table-db-field-edit('keysTbl', 'cur', '{{::keysTbl.focusId + $index}}', '$index')
+                                tfoot(ng-show='tableNewItemActive(keysTbl)')
+                                    tr
+                                        td
+                                            +table-db-field-edit('keysTbl', 'new', 'KeyField', '-1')
+                .settings-row(ng-init='valuesTbl={type: "table-db-fields", model: "valueFields", focusId: "ValueField", ui: "table-db-fields"}')
+                    ignite-form-group(ng-model='#{valueFields}' ng-form='#{valueFieldsForm}')
+                        ignite-form-field-label(id='valueFields')
+                            | Value fields
+                        ignite-form-group-tooltip
+                            | Collection of value fields descriptions for CacheJdbcPojoStore
+                        ignite-form-group-add(ng-click='tableNewItem(valuesTbl)')
+                            | Add value field
+                        .group-content-empty(ng-show='!((#{valueFields} && #{valueFields}.length > 0) || tableNewItemActive(valuesTbl))') Not defined
+                        .group-content(ng-show='(#{valueFields} && #{valueFields}.length > 0) || tableNewItemActive(valuesTbl)')
+                            table.links-edit(st-table=valueFields)
+                                tbody
+                                    tr(ng-repeat='item in #{valueFields}')
+                                        td
+                                            div(ng-show='!tableEditing(valuesTbl, $index)')
+                                                a.labelFormField(ng-click='tableStartEdit(backupItem, valuesTbl, $index)') {{$index + 1}}) {{item.databaseFieldName}} / {{item.databaseFieldType}} / {{item.javaFieldName}} / {{item.javaFieldType}}
+                                                +btn-remove('tableRemove(backupItem, valuesTbl, $index)', '"Remove key field"')
+                                            div(ng-show='tableEditing(valuesTbl, $index)')
+                                                +table-db-field-edit('valuesTbl', 'cur', '{{::valuesTbl.focusId + $index}}', '$index')
+                                tfoot(ng-show='tableNewItemActive(valuesTbl)')
+                                    tr
+                                        td
+                                            +table-db-field-edit('valuesTbl', 'new', 'ValueField', '-1')
+            .col-sm-6
+                +preview-xml-java(model, 'domainStore')
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.directive.js
new file mode 100644
index 0000000..109fa63
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.directive.js
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import template from './dual.jade!';
+
+export default ['igniteConfigurationIgfsDual', [() => {
+    return {
+        scope: true,
+        restrict: 'E',
+        template,
+        replace: true
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.jade b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.jade
new file mode 100644
index 0000000..ba2e182
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.jade
@@ -0,0 +1,42 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+include ../../../../../app/helpers/jade/mixins.jade
+
+-var form = 'dualMode'
+-var model = 'backupItem'
+
+form.panel.panel-default(name=form novalidate)
+    .panel-heading(bs-collapse-toggle='' ng-click='ui.loadPanel("#{form}")')
+        ignite-form-panel-chevron
+        label Dual mode
+        ignite-form-field-tooltip.tipLabel
+            | IGFS supports dual-mode that allows it to work as either a standalone file system in Hadoop cluster, or work in tandem with HDFS, providing a primary caching layer for the secondary HDFS#[br]
+            | As a caching layer it provides highly configurable read-through and write-through behaviour
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=form)
+        .panel-body(ng-if='ui.isPanelLoaded("#{form}")')
+            .col-sm-6
+                .settings-row
+                    +number('Maximum pending puts size:', model + '.dualModeMaxPendingPutsSize', 'dualModeMaxPendingPutsSize', 'true', '0', 'Number.MIN_SAFE_INTEGER',
+                        'Maximum amount of pending data read from the secondary file system and waiting to be written to data cache\
+                        0 or negative value stands for unlimited size')
+                .settings-row
+                    +java-class('Put executor service:', model + '.dualModePutExecutorService', 'dualModePutExecutorService', 'true', 'false', 'DUAL mode put operation executor service')
+                .settings-row
+                    +checkbox('Put executor service shutdown', model + '.dualModePutExecutorServiceShutdown', 'dualModePutExecutorServiceShutdown', 'DUAL mode put operation executor service shutdown flag')
+            .col-sm-6
+                +preview-xml-java(model, 'igfsDualMode')

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.directive.js
new file mode 100644
index 0000000..f93c76c
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.directive.js
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import template from './fragmentizer.jade!';
+
+export default ['igniteConfigurationIgfsFragmentizer', [() => {
+    return {
+        scope: true,
+        restrict: 'E',
+        template,
+        replace: true
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.jade b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.jade
new file mode 100644
index 0000000..fa8c244
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.jade
@@ -0,0 +1,43 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+include ../../../../../app/helpers/jade/mixins.jade
+
+-var form = 'fragmentizer'
+-var model = 'backupItem'
+
+form.panel.panel-default(name=form novalidate)
+    .panel-heading(bs-collapse-toggle='' ng-click='ui.loadPanel("#{form}")')
+        ignite-form-panel-chevron
+        label Fragmentizer
+        ignite-form-field-tooltip.tipLabel
+            | Fragmentizer settings
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=form)
+        .panel-body(ng-if='ui.isPanelLoaded("#{form}")')
+            .col-sm-6
+                -var enabled = model + '.fragmentizerEnabled'
+
+                .settings-row
+                    +checkbox('Enabled', enabled, 'fragmentizerEnabled', 'Fragmentizer enabled flag')
+                .settings-row
+                    +number('Concurrent files:', model + '.fragmentizerConcurrentFiles', 'fragmentizerConcurrentFiles', enabled, '0', '0', 'Number of files to process concurrently by fragmentizer')
+                .settings-row
+                    +number('Throttling block length:', model + '.fragmentizerThrottlingBlockLength', 'fragmentizerThrottlingBlockLength', enabled, '16777216', '1', 'Length of file chunk to transmit before throttling is delayed')
+                .settings-row
+                    +number('Throttling delay:', model + '.fragmentizerThrottlingDelay', 'fragmentizerThrottlingDelay', enabled, '200', '0', 'Delay in milliseconds for which fragmentizer is paused')
+            .col-sm-6
+                +preview-xml-java(model, 'igfsFragmentizer')

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.directive.js
new file mode 100644
index 0000000..294c3b8
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.directive.js
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import template from './general.jade!';
+
+export default ['igniteConfigurationIgfsGeneral', [() => {
+    return {
+        scope: true,
+        restrict: 'E',
+        template,
+        replace: true
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.jade b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.jade
new file mode 100644
index 0000000..e81dd9b
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.jade
@@ -0,0 +1,53 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+include ../../../../../app/helpers/jade/mixins.jade
+
+-var model = 'backupItem'
+
+form.panel.panel-default(name='general' novalidate)
+    .panel-heading(bs-collapse-toggle)
+        ignite-form-panel-chevron
+        label General
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id='general')
+        .panel-body
+            .col-sm-6
+                .settings-row
+                    +text('Name:', model + '.name', 'igfsName', 'true', 'Input name', 'IGFS name')
+                .settings-row
+                    +clusters(model, 'Associate clusters with the current IGFS')
+                .settings-row
+                    +dropdown('IGFS mode:', model + '.defaultMode', 'defaultMode', 'true', 'DUAL_ASYNC',
+                    '[\
+                        {value: "PRIMARY", label: "PRIMARY"},\
+                        {value: "PROXY", label: "PROXY"},\
+                        {value: "DUAL_SYNC", label: "DUAL_SYNC"},\
+                        {value: "DUAL_ASYNC", label: "DUAL_ASYNC"}\
+                    ]',
+                    'Mode to specify how IGFS interacts with Hadoop file system:\
+                    <ul>\
+                        <li>PRIMARY - in this mode IGFS will not delegate to secondary Hadoop file system and will cache all the files in memory only</li>\
+                        <li>PROXY - in this mode IGFS will not cache any files in memory and will only pass them through to secondary file system</li>\
+                        <li>DUAL_SYNC - in this mode IGFS will cache files locally and also <b>synchronously</b> write them through to secondary file system</li>\
+                        <li>DUAL_ASYNC - in this mode IGFS will cache files locally and also <b> asynchronously </b> write them through to secondary file system</li>\
+                    </ul>')
+                .settings-row
+                    +number('Group size:', model + '.affinnityGroupSize', 'affinnityGroupSize', 'true', '512', '1',
+                        'Size of the group in blocks<br/>\
+                        Required for construction of affinity mapper in IGFS data cache')
+            .col-sm-6
+                +preview-xml-java(model, 'igfsGeneral')

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.directive.js
new file mode 100644
index 0000000..a0bd44c
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.directive.js
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import template from './ipc.jade!';
+
+export default ['igniteConfigurationIgfsIpc', [() => {
+    return {
+        scope: true,
+        restrict: 'E',
+        template,
+        replace: true
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.jade b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.jade
new file mode 100644
index 0000000..361036a
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.jade
@@ -0,0 +1,57 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+include ../../../../../app/helpers/jade/mixins.jade
+
+-var form = 'ipc'
+-var model = 'backupItem'
+
+form.panel.panel-default(name=form novalidate)
+    .panel-heading(bs-collapse-toggle='' ng-click='ui.loadPanel("#{form}")')
+        ignite-form-panel-chevron
+        label IPC
+        ignite-form-field-tooltip.tipLabel
+            | IGFS Inter-process communication properties
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=form)
+        .panel-body(ng-if='ui.isPanelLoaded("#{form}")')
+            .col-sm-6
+                -var ipcEndpointConfiguration = model + '.ipcEndpointConfiguration'
+                -var enabled = model + '.ipcEndpointEnabled'
+
+                .settings-row
+                    +checkbox('Enabled', enabled, 'ipcEndpointEnabled', 'IPC endpoint enabled flag')
+                .settings-row
+                    +dropdown('Type:', ipcEndpointConfiguration + '.type', 'ipcEndpointConfigurationType', enabled, 'TCP',
+                        '[\
+                            {value: "SHMEM", label: "SHMEM"},\
+                            {value: "TCP", label: "TCP"}\
+                        ]',
+                        'IPC endpoint type\
+                        <ul>\
+                            <li>SHMEM - shared memory endpoint</li>\
+                            <li>TCP - TCP endpoint</li>\
+                        </ul>')
+                .settings-row
+                    +text-ip-address('Host:', ipcEndpointConfiguration + '.host', 'ipcEndpointConfigurationHost', enabled, '127.0.0.1', 'Host name')
+                .settings-row
+                    +number-min-max('Port:', ipcEndpointConfiguration + '.port', 'ipcEndpointConfigurationPort', enabled, '10500', '1', '65535', 'Port number')
+                .settings-row
+                    +number('Memory size:', ipcEndpointConfiguration + '.memorySize', 'ipcEndpointConfigurationMemorySize', enabled, '262144', '1', 'Shared memory size in bytes allocated for endpoint communication')
+                .settings-row
+                    +text-enabled('Token directory:', ipcEndpointConfiguration + '.tokenDirectoryPath', 'ipcEndpointConfigurationTokenDirectoryPath', enabled, 'false', 'ipc/shmem', 'Directory where shared memory tokens are stored')
+            .col-sm-6
+                +preview-xml-java(model, 'igfsIPC')

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.directive.js
new file mode 100644
index 0000000..6a6ca12
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.directive.js
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import template from './misc.jade!';
+
+export default ['igniteConfigurationIgfsMisc', [() => {
+    return {
+        scope: true,
+        restrict: 'E',
+        template,
+        replace: true
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.jade b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.jade
new file mode 100644
index 0000000..7cc0354
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.jade
@@ -0,0 +1,108 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+include ../../../../../app/helpers/jade/mixins.jade
+
+-var form = 'misc'
+-var model = 'backupItem'
+-var pathModesForm = 'miscPathModes'
+-var pathModes = model + '.pathModes'
+
+//- LEGACY mixin for LEGACY IGFS path modes table.
+mixin table-igfs-path-mode-edit(prefix, focusId, index)
+    -var keyModel = 'tblPathModes.' + prefix + 'Key'
+    -var valModel = 'tblPathModes.' + prefix + 'Value'
+
+    -var keyFocusId = prefix + 'Key' + focusId
+    -var valFocusId = prefix + 'Value' + focusId
+
+    .col-xs-8.col-sm-8.col-md-8
+        .fieldSep /
+        .input-tip
+            input.form-control(id=keyFocusId enter-focus-next=valFocusId type='text' ng-model=keyModel placeholder='Path' on-escape='tableReset()')
+    .col-xs-4.col-sm-4.col-md-4
+        -var arg = keyModel + ', ' + valModel
+        -var btnVisible = 'tablePairSaveVisible(tblPathModes, ' + index + ')'
+        -var btnSave = 'tablePairSave(tablePairValid, backupItem, tblPathModes, ' + index + ')'
+        -var btnVisibleAndSave = btnVisible + ' && ' + btnSave
+        +btn-save(btnVisible, btnSave)
+        .input-tip
+            button.select-toggle.form-control(id=valFocusId bs-select ng-model=valModel data-placeholder='Mode' bs-options='item.value as item.label for item in igfsModes' tabindex='0' on-enter=btnVisibleAndSave on-escape='tableReset()')
+
+form.panel.panel-default(name=form novalidate)
+    .panel-heading(bs-collapse-toggle='' ng-click='ui.loadPanel("#{form}")')
+        ignite-form-panel-chevron
+        label Miscellaneous
+        ignite-form-field-tooltip.tipLabel
+            | Various miscellaneous IGFS settings
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=form)
+        .panel-body(ng-if='ui.isPanelLoaded("#{form}")')
+            .col-sm-6
+                .settings-row
+                    +number('Block size:', model + '.blockSize', 'blockSize', 'true', '65536', '0', 'File data block size in bytes')
+                .settings-row
+                    +number('Stream buffer size:', model + '.streamBufferSize', 'streamBufferSize', 'true', '65536', '0', 'File data block size in bytes')
+                .settings-row
+                    +number('Maximum space size:', model + '.maxSpaceSize', 'maxSpaceSize', 'true', '0', '0', 'Maximum space available for data cache to store file system entries')
+                .settings-row
+                    +number('Maximum task range length:', model + '.maximumTaskRangeLength', 'maximumTaskRangeLength', 'true', '0', '0', 'Maximum default range size of a file being split during IGFS task execution')
+                .settings-row
+                    +number-min-max('Management port:', model + '.managementPort', 'managementPort', 'true', '11400', '0', '65535', 'Port number for management endpoint')
+                .settings-row
+                    +number('Per node batch size:', model + '.perNodeBatchSize', 'perNodeBatchSize', 'true', '100', '0', 'Number of file blocks collected on local node before sending batch to remote node')
+                .settings-row
+                    +number('Per node parallel batch count:', model + '.perNodeParallelBatchCount', 'perNodeParallelBatchCount', 'true', '8', '0', 'Number of file block batches that can be concurrently sent to remote node')
+                .settings-row
+                    +number('Prefetch blocks:', model + '.prefetchBlocks', 'prefetchBlocks', 'true', '0', '0', 'Number of pre-fetched blocks if specific file chunk is requested')
+                .settings-row
+                    +number('Sequential reads before prefetch:', model + '.sequentialReadsBeforePrefetch', 'sequentialReadsBeforePrefetch', 'true', '0', '0', 'Amount of sequential block reads before prefetch is triggered')
+                .settings-row
+                    +number('Trash purge timeout:', model + '.trashPurgeTimeout', 'trashPurgeTimeout', 'true', '1000', '0', 'Maximum timeout awaiting for trash purging in case data cache oversize is detected')
+                .settings-row
+                    +checkbox('Colocate metadata', model + '.colocateMetadata', 'colocateMetadata', 'Whether to co-locate metadata on a single node')
+                .settings-row
+                    +checkbox('Relaxed consistency ', model + '.relaxedConsistency', 'relaxedConsistency',
+                        'If value of this flag is <b>true</b>, IGFS will skip expensive consistency checks. It is recommended to set\
+                        this flag to <b>false</b>b> if your application has conflicting operations, or you do not how exactly users will\
+                        use your system.')
+                .settings-row(ng-init='tblPathModes={type: "pathModes", model: "pathModes", focusId: "PathMode", ui: "table-pair", keyName: "path", valueName: "mode"}')
+                    ignite-form-group(ng-model=pathModes ng-form=pathModesForm)
+                        ignite-form-field-label
+                            | Path modes
+                        ignite-form-group-tooltip
+                            | Map of path prefixes to IGFS modes used for them
+                        ignite-form-group-add(ng-click='tableNewItem(tblPathModes)')
+                            | Add path mode
+
+                        .group-content-empty(ng-if='!((#{pathModes} && #{pathModes}.length > 0) || tableNewItemActive(tblPathModes))') Not defined
+
+                        .group-content(ng-show='(#{pathModes} && #{pathModes}.length > 0) || tableNewItemActive(tblPathModes)')
+                            table.links-edit(id='pathModes' st-table=pathModes)
+                                tbody
+                                    tr(ng-repeat='item in #{pathModes}')
+                                        td.col-sm-12(ng-show='!tableEditing(tblPathModes, $index)')
+                                            a.labelFormField(ng-click='tableStartEdit(backupItem, tblPathModes, $index)') {{item.path + " [" + item.mode + "]"}}
+                                            +btn-remove('tableRemove(backupItem, tblPathModes, $index)', '"Remove path"')
+                                        td.col-sm-12(ng-show='tableEditing(tblPathModes, $index)')
+                                            +table-igfs-path-mode-edit('cur', '{{::tblPathModes.focusId + $index}}', '$index')
+                                tfoot(ng-show='tableNewItemActive(tblPathModes)')
+                                    tr
+                                        td.col-sm-12
+                                            +table-igfs-path-mode-edit('new', 'PathMode', '-1')
+
+            .col-sm-6
+                +preview-xml-java(model, 'igfsMisc')

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.directive.js
new file mode 100644
index 0000000..8b3b37b
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.directive.js
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import template from './secondary.jade!';
+
+export default ['igniteConfigurationIgfsSecondary', [() => {
+    return {
+        scope: true,
+        restrict: 'E',
+        template,
+        replace: true
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.jade b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.jade
new file mode 100644
index 0000000..333fad9
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.jade
@@ -0,0 +1,44 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+include ../../../../../app/helpers/jade/mixins.jade
+
+-var form = 'secondaryFileSystem'
+-var model = 'backupItem'
+
+form.panel.panel-default(name=form novalidate)
+    .panel-heading(bs-collapse-toggle='' ng-click='ui.loadPanel("#{form}")')
+        ignite-form-panel-chevron
+        label(id="secondaryFileSystem-title") Secondary file system
+        ignite-form-field-tooltip.tipLabel
+            | Secondary file system is provided for pass-through, write-through, and read-through purposes
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=form)
+        .panel-body(ng-if='ui.isPanelLoaded("#{form}")')
+            .col-sm-6
+                -var enabled = model + '.secondaryFileSystemEnabled'
+                -var secondaryFileSystem = model + '.secondaryFileSystem'
+
+                .settings-row
+                    +checkbox('Enabled', enabled, 'secondaryFileSystemEnabled', 'Secondary file system enabled flag')
+                .settings-row
+                    +text-enabled('URI:', secondaryFileSystem + '.uri', 'hadoopURI', enabled, 'false', 'hdfs://[namenodehost]:[port]/[path]', 'URI of file system')
+                .settings-row
+                    +text-enabled('Config path:', secondaryFileSystem + '.cfgPath', 'cfgPath', enabled, 'false', 'Path to additional config', 'Additional path to Hadoop configuration')
+                .settings-row
+                    +text-enabled('User name:', secondaryFileSystem + '.userName', 'userName', enabled, 'false', 'Input user name', 'User name')
+            .col-sm-6
+                +preview-xml-java(model, 'igfsSecondFS')

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/preview-panel.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/preview-panel.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/preview-panel.directive.js
new file mode 100644
index 0000000..fb67326
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/preview-panel.directive.js
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import ace from 'ace';
+
+export default ['previewPanel', ['$interval', '$timeout', ($interval, $timeout) => {
+    let animation = {editor: null, stage: 0, start: 0, stop: 0};
+    let prevContent = [];
+
+    const Range = ace.require('ace/range').Range;
+
+    const _clearSelection = (editor) => {
+        _.forEach(editor.session.getMarkers(false), (marker) => {
+            editor.session.removeMarker(marker.id);
+        });
+    };
+
+    /**
+     * Switch to next stage of animation.
+     */
+    const _animate = () => {
+        animation.stage += animation.step;
+
+        const stage = animation.stage;
+        const editor = animation.editor;
+
+        _clearSelection(editor);
+
+        animation.selections.forEach((selection) => {
+            editor.session.addMarker(new Range(selection.start, 0, selection.stop, 0),
+                'preview-highlight-' + stage, 'line', false);
+        });
+
+        if (stage === animation.finalStage) {
+            editor.animatePromise = null;
+
+            if (animation.clearOnFinal)
+                _clearSelection(editor);
+        }
+    };
+
+    /**
+     * Selection with animation.
+     *
+     * @param editor Editor to show selection animation.
+     * @param selections Array of selection intervals.
+     * @param step Step of animation (1 or -1).
+     * @param stage Start stage of animation.
+     * @param finalStage Final stage of animation.
+     * @param clearOnFinal Boolean flat to clear selection on animation finish.
+     */
+    const _fade = (editor, selections, step, stage, finalStage, clearOnFinal) => {
+        const promise = editor.animatePromise;
+
+        if (promise) {
+            $interval.cancel(promise);
+
+            _clearSelection(editor);
+        }
+
+        animation = {editor, selections, step, stage, finalStage, clearOnFinal};
+
+        editor.animatePromise = $interval(_animate, 100, 10, false);
+    };
+
+    /**
+     * Show selections with animation.
+     *
+     * @param editor Editor to show selection.
+     * @param selections Array of selection intervals.
+     */
+    const _fadeIn = (editor, selections) => {
+        _fade(editor, selections, 1, 0, 10, false);
+    };
+
+    /**
+     * Hide selections with animation.
+     *
+     * @param editor Editor to show selection.
+     * @param selections Array of selection intervals.
+     */
+    const _fadeOut = (editor, selections) => {
+        _fade(editor, selections, -1, 10, 0, true);
+    };
+
+    const onChange = ([content, editor]) => {
+        const {clearPromise} = editor;
+        const {lines} = content;
+
+        if (content.action === 'remove')
+            prevContent = lines;
+        else if (prevContent.length > 0 && lines.length > 0 && editor.attractAttention) {
+            if (clearPromise) {
+                $timeout.cancel(clearPromise);
+
+                _clearSelection(editor);
+            }
+
+            const selections = [];
+
+            let newIx = 0;
+            let prevIx = 0;
+
+            let prevLen = prevContent.length - (prevContent[prevContent.length - 1] === '' ? 1 : 0);
+            let newLen = lines.length - (lines[lines.length - 1] === '' ? 1 : 0);
+
+            const removed = newLen < prevLen;
+
+            let skipEnd = 0;
+
+            let selected = false;
+            let scrollTo = -1;
+
+            while (lines[newLen - 1] === prevContent[prevLen - 1] && newLen > 0 && prevLen > 0) {
+                prevLen -= 1;
+                newLen -= 1;
+
+                skipEnd += 1;
+            }
+
+            while (newIx < newLen || prevIx < prevLen) {
+                let start = -1;
+                let stop = -1;
+
+                // Find an index of a first line with different text.
+                for (; (newIx < newLen || prevIx < prevLen) && start < 0; newIx++, prevIx++) {
+                    if (newIx >= newLen || prevIx >= prevLen || lines[newIx] !== prevContent[prevIx]) {
+                        start = newIx;
+
+                        break;
+                    }
+                }
+
+                if (start >= 0) {
+                    // Find an index of a last line with different text by checking last string of old and new content in reverse order.
+                    for (let i = start; i < newLen && stop < 0; i++) {
+                        for (let j = prevIx; j < prevLen && stop < 0; j++) {
+                            if (lines[i] === prevContent[j] && lines[i] !== '') {
+                                stop = i;
+
+                                newIx = i;
+                                prevIx = j;
+
+                                break;
+                            }
+                        }
+                    }
+
+                    if (stop < 0) {
+                        stop = newLen;
+
+                        newIx = newLen;
+                        prevIx = prevLen;
+                    }
+
+                    if (start === stop) {
+                        if (removed)
+                            start = Math.max(0, start - 1);
+
+                        stop = Math.min(newLen + skipEnd, stop + 1);
+                    }
+
+                    if (start <= stop) {
+                        selections.push({start, stop});
+
+                        if (!selected)
+                            scrollTo = start;
+
+                        selected = true;
+                    }
+                }
+            }
+
+            // Run clear selection one time.
+            if (selected) {
+                _fadeIn(editor, selections);
+
+                editor.clearPromise = $timeout(() => {
+                    _fadeOut(editor, selections);
+
+                    editor.clearPromise = null;
+                }, 2000);
+
+                editor.scrollToRow(scrollTo);
+            }
+
+            prevContent = [];
+        }
+        else
+            editor.attractAttention = true;
+    };
+
+
+    const link = (scope, $element, $attrs, [igniteUiAceTabs1, igniteUiAceTabs2]) => {
+        const igniteUiAceTabs = igniteUiAceTabs1 || igniteUiAceTabs2;
+
+        if (!igniteUiAceTabs)
+            return;
+
+        igniteUiAceTabs.onLoad = (editor) => {
+            editor.setReadOnly(true);
+            editor.setOption('highlightActiveLine', false);
+            editor.setAutoScrollEditorIntoView(true);
+            editor.$blockScrolling = Infinity;
+            editor.attractAttention = false;
+
+            const renderer = editor.renderer;
+
+            renderer.setHighlightGutterLine(false);
+            renderer.setShowPrintMargin(false);
+            renderer.setOption('fontSize', '10px');
+            renderer.setOption('maxLines', '50');
+
+            editor.setTheme('ace/theme/chrome');
+        };
+
+        igniteUiAceTabs.onChange = onChange;
+    };
+
+    return {
+        restrict: 'C',
+        link,
+        require: ['?igniteUiAceTabs', '?^igniteUiAceTabs']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary-tabs.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary-tabs.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary-tabs.directive.js
new file mode 100644
index 0000000..f8094af
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary-tabs.directive.js
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export default ['summaryTabs', [() => {
+    const link = (scope, $element, $attrs, [igniteUiAceTabs1, igniteUiAceTabs2]) => {
+        const igniteUiAceTabs = igniteUiAceTabs1 || igniteUiAceTabs2;
+
+        if (!igniteUiAceTabs)
+            return;
+
+        igniteUiAceTabs.onLoad = (editor) => {
+            editor.setReadOnly(true);
+            editor.setOption('highlightActiveLine', false);
+            editor.setAutoScrollEditorIntoView(true);
+            editor.$blockScrolling = Infinity;
+
+            const renderer = editor.renderer;
+
+            renderer.setHighlightGutterLine(false);
+            renderer.setShowPrintMargin(false);
+            renderer.setOption('fontFamily', 'monospace');
+            renderer.setOption('fontSize', '12px');
+            renderer.setOption('minLines', '25');
+            renderer.setOption('maxLines', '25');
+
+            editor.setTheme('ace/theme/chrome');
+        };
+    };
+
+    return {
+        priority: 1000,
+        restrict: 'C',
+        link,
+        require: ['?igniteUiAceTabs', '?^igniteUiAceTabs']
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.controller.js b/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.controller.js
new file mode 100644
index 0000000..866d97f
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.controller.js
@@ -0,0 +1,360 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import _ from 'lodash';
+import JSZip from 'jszip';
+
+export default [
+    '$rootScope', '$scope', '$http', '$common', '$loading', '$filter', 'ConfigurationSummaryResource', 'JavaTypes', 'IgniteVersion', 'GeneratorDocker', 'GeneratorPom',
+    function($root, $scope, $http, $common, $loading, $filter, Resource, JavaTypes, IgniteVersion, docker, pom) {
+        const ctrl = this;
+
+        $scope.ui = { ready: false };
+
+        $loading.start('summaryPage');
+
+        Resource.read().then(({clusters}) => {
+            $scope.clusters = clusters;
+            $scope.clustersMap = {};
+            $scope.clustersView = _.map(clusters, (item) => {
+                const { _id, name } = item;
+
+                $scope.clustersMap[_id] = item;
+
+                return { _id, name };
+            });
+
+            $loading.finish('summaryPage');
+
+            $scope.ui.ready = true;
+
+            if (!_.isEmpty(clusters)) {
+                const idx = sessionStorage.summarySelectedId || 0;
+
+                $scope.selectItem(clusters[idx]);
+            }
+        });
+
+        $scope.contentVisible = (rows, row) => {
+            return !row || !row._id || _.findIndex(rows, (item) => item._id === row._id) >= 0;
+        };
+
+        $scope.widthIsSufficient = $common.widthIsSufficient;
+        $scope.dialects = {};
+
+        $scope.projectStructureOptions = {
+            nodeChildren: 'children',
+            dirSelectable: false,
+            injectClasses: {
+                iExpanded: 'fa fa-folder-open-o',
+                iCollapsed: 'fa fa-folder-o'
+            },
+            equality: (node1, node2) => {
+                return node1 === node2;
+            }
+        };
+
+        const javaConfigFolder = {
+            type: 'folder',
+            name: 'config',
+            children: [
+                { type: 'file', name: 'ClientConfigurationFactory.java' },
+                { type: 'file', name: 'ServerConfigurationFactory.java' }
+            ]
+        };
+
+        const javaStartupFolder = {
+            type: 'folder',
+            name: 'startup',
+            children: [
+                { type: 'file', name: 'ClientNodeCodeStartup.java' },
+                { type: 'file', name: 'ClientNodeSpringStartup.java' },
+                { type: 'file', name: 'ServerNodeCodeStartup.java' },
+                { type: 'file', name: 'ServerNodeSpringStartup.java' }
+            ]
+        };
+
+        const demoFolder = {
+            type: 'folder',
+            name: 'demo',
+            children: [
+                { type: 'file', name: 'DemoStartup.java' }
+            ]
+        };
+
+        const resourcesFolder = {
+            type: 'folder',
+            name: 'resources',
+            children: [
+                { type: 'file', name: 'secret.properties' }
+            ]
+        };
+
+        const javaFolder = {
+            type: 'folder',
+            name: 'java',
+            children: [
+                {
+                    type: 'folder',
+                    name: 'config',
+                    children: [
+                        javaConfigFolder,
+                        javaStartupFolder
+                    ]
+                }
+            ]
+        };
+
+        const clnCfg = { type: 'file', name: 'client.xml' };
+
+        const srvCfg = { type: 'file', name: 'server.xml' };
+
+        const mainFolder = {
+            type: 'folder',
+            name: 'main',
+            children: [javaFolder]
+        };
+
+        const projectStructureRoot = {
+            type: 'folder',
+            name: 'project.zip',
+            children: [
+                {
+                    type: 'folder',
+                    name: 'config',
+                    children: [clnCfg, srvCfg]
+                },
+                {
+                    type: 'folder',
+                    name: 'jdbc-drivers',
+                    children: [
+                        { type: 'file', name: 'README.txt' }
+                    ]
+                },
+                {
+                    type: 'folder',
+                    name: 'src',
+                    children: [mainFolder]
+                },
+                { type: 'file', name: '.dockerignore' },
+                { type: 'file', name: 'Dockerfile' },
+                { type: 'file', name: 'pom.xml' },
+                { type: 'file', name: 'README.txt' }
+            ]
+        };
+
+        $scope.projectStructure = [projectStructureRoot];
+
+        $scope.projectStructureExpanded = [projectStructureRoot];
+
+        $scope.tabsServer = { activeTab: 0 };
+        $scope.tabsClient = { activeTab: 0 };
+
+        /**
+         *
+         * @param {Object} node - Tree node.
+         * @param {string[]} path - Path to find.
+         * @returns {Object} Tree node.
+         */
+        function getOrCreateFolder(node, path) {
+            if (_.isEmpty(path))
+                return node;
+
+            const leaf = path.shift();
+
+            let children = null;
+
+            if (!_.isEmpty(node.children)) {
+                children = _.find(node.children, {type: 'folder', name: leaf});
+
+                if (children)
+                    return getOrCreateFolder(children, path);
+            }
+
+            children = {type: 'folder', name: leaf, children: []};
+
+            node.children.push(children);
+
+            node.children = _.orderBy(node.children, ['type', 'name'], ['desc', 'asc']);
+
+            return getOrCreateFolder(children, path);
+        }
+
+        function addClass(fullClsName) {
+            const path = fullClsName.split('.');
+            const leaf = {type: 'file', name: path.pop() + '.java'};
+            const folder = getOrCreateFolder(javaFolder, path);
+
+            if (!_.find(folder.children, leaf))
+                folder.children.push(leaf);
+        }
+
+        $scope.selectItem = (cluster) => {
+            delete ctrl.cluster;
+
+            if (!cluster)
+                return;
+
+            cluster = $scope.clustersMap[cluster._id];
+
+            ctrl.cluster = cluster;
+
+            $scope.cluster = cluster;
+            $scope.selectedItem = cluster;
+            $scope.dialects = {};
+
+            sessionStorage.summarySelectedId = $scope.clusters.indexOf(cluster);
+
+            mainFolder.children = [javaFolder];
+            javaFolder.children = [javaConfigFolder, javaStartupFolder];
+
+            if ($generatorCommon.secretPropertiesNeeded(cluster))
+                mainFolder.children.push(resourcesFolder);
+
+            if ($generatorJava.isDemoConfigured(cluster, $root.IgniteDemoMode))
+                javaFolder.children.push(demoFolder);
+
+            _.forEach(cluster.caches, (cache) => {
+                if (cache.cacheStoreFactory) {
+                    const store = cache.cacheStoreFactory[cache.cacheStoreFactory.kind];
+
+                    if (store && store.dialect)
+                        $scope.dialects[store.dialect] = true;
+                }
+
+                _.forEach(cache.domains, (domain) => {
+                    if (!_.isEmpty(domain.keyFields)) {
+                        if (JavaTypes.nonBuiltInClass(domain.keyType))
+                            addClass(domain.keyType);
+
+                        addClass(domain.valueType);
+                    }
+                });
+            });
+
+            projectStructureRoot.name = cluster.name + '-project.zip';
+            clnCfg.name = cluster.name + '-client.xml';
+            srvCfg.name = cluster.name + '-server.xml';
+        };
+
+        $scope.$watch('cluster', (cluster) => {
+            if (!cluster)
+                return;
+
+            if (!$filter('hasPojo')(cluster) && $scope.tabsClient.activeTab === 3)
+                $scope.tabsClient.activeTab = 0;
+        });
+
+        $scope.$watch('cluster._id', () => {
+            $scope.tabsClient.init = [];
+            $scope.tabsServer.init = [];
+        });
+
+        // TODO IGNITE-2114: implemented as independent logic for download.
+        $scope.downloadConfiguration = function() {
+            const cluster = $scope.cluster;
+            const clientNearCfg = cluster.clientNearCfg;
+
+            const zip = new JSZip();
+
+            if (!ctrl.data)
+                ctrl.data = {};
+
+            if (!ctrl.data.docker)
+                ctrl.data.docker = docker.generate(cluster, 'latest');
+
+            zip.file('Dockerfile', ctrl.data.docker);
+            zip.file('.dockerignore', docker.ignoreFile());
+
+            const builder = $generatorProperties.generateProperties(cluster);
+
+            if (builder)
+                zip.file('src/main/resources/secret.properties', builder.asString());
+
+            const srcPath = 'src/main/java/';
+
+            const serverXml = 'config/' + cluster.name + '-server.xml';
+            const clientXml = 'config/' + cluster.name + '-client.xml';
+
+            zip.file(serverXml, $generatorXml.cluster(cluster));
+            zip.file(clientXml, $generatorXml.cluster(cluster, clientNearCfg));
+
+            zip.file(srcPath + 'config/ServerConfigurationFactory.java', $generatorJava.cluster(cluster, 'config', 'ServerConfigurationFactory', null));
+            zip.file(srcPath + 'config/ClientConfigurationFactory.java', $generatorJava.cluster(cluster, 'config', 'ClientConfigurationFactory', clientNearCfg));
+
+            if ($generatorJava.isDemoConfigured(cluster, $root.IgniteDemoMode)) {
+                zip.file(srcPath + 'demo/DemoStartup.java', $generatorJava.nodeStartup(cluster, 'demo', 'DemoStartup',
+                    'ServerConfigurationFactory.createConfiguration()', 'config.ServerConfigurationFactory'));
+            }
+
+            zip.file(srcPath + 'startup/ServerNodeSpringStartup.java', $generatorJava.nodeStartup(cluster, 'startup', 'ServerNodeSpringStartup', '"' + serverXml + '"'));
+            zip.file(srcPath + 'startup/ClientNodeSpringStartup.java', $generatorJava.nodeStartup(cluster, 'startup', 'ClientNodeSpringStartup', '"' + clientXml + '"'));
+
+            zip.file(srcPath + 'startup/ServerNodeCodeStartup.java', $generatorJava.nodeStartup(cluster, 'startup', 'ServerNodeCodeStartup',
+                'ServerConfigurationFactory.createConfiguration()', 'config.ServerConfigurationFactory'));
+            zip.file(srcPath + 'startup/ClientNodeCodeStartup.java', $generatorJava.nodeStartup(cluster, 'startup', 'ClientNodeCodeStartup',
+                'ClientConfigurationFactory.createConfiguration()', 'config.ClientConfigurationFactory', clientNearCfg));
+
+            zip.file('pom.xml', pom.generate(cluster, IgniteVersion.version).asString());
+
+            zip.file('README.txt', $generatorReadme.readme().asString());
+            zip.file('jdbc-drivers/README.txt', $generatorReadme.readmeJdbc().asString());
+
+            if (!ctrl.data.pojos)
+                ctrl.data.pojos = $generatorJava.pojos(cluster.caches);
+
+            for (const pojo of ctrl.data.pojos) {
+                if (pojo.keyClass && JavaTypes.nonBuiltInClass(pojo.keyType))
+                    zip.file(srcPath + pojo.keyType.replace(/\./g, '/') + '.java', pojo.keyClass);
+
+                zip.file(srcPath + pojo.valueType.replace(/\./g, '/') + '.java', pojo.valueClass);
+            }
+
+            $generatorOptional.optionalContent(zip, cluster);
+
+            const blob = zip.generate({type: 'blob', compression: 'DEFLATE', mimeType: 'application/octet-stream'});
+
+            // Download archive.
+            saveAs(blob, cluster.name + '-project.zip');
+        };
+
+        /**
+         * @returns {boolean} 'true' if at least one proprietary JDBC driver is configured for cache store.
+         */
+        $scope.downloadJdbcDriversVisible = function() {
+            const dialects = $scope.dialects;
+
+            return !!(dialects.Oracle || dialects.DB2 || dialects.SQLServer);
+        };
+
+        /**
+         * Open download proprietary JDBC driver pages.
+         */
+        $scope.downloadJdbcDrivers = function() {
+            const dialects = $scope.dialects;
+
+            if (dialects.Oracle)
+                window.open('http://www.oracle.com/technetwork/apps-tech/jdbc-112010-090769.html');
+
+            if (dialects.DB2)
+                window.open('http://www-01.ibm.com/support/docview.wss?uid=swg21363866');
+
+            if (dialects.SQLServer)
+                window.open('https://www.microsoft.com/en-us/download/details.aspx?id=11774');
+        };
+    }
+];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.resource.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.resource.js b/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.resource.js
new file mode 100644
index 0000000..0ef53ac
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.resource.js
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export default ['ConfigurationSummaryResource', ['$q', '$http', ($q, $http) => {
+    const api = '/api/v1/configuration/clusters/list';
+
+    return {
+        read() {
+            return $http
+                .post(api)
+                .then(({data}) => data)
+                .then(({clusters, caches, igfss}) => {
+                    if (!clusters || !clusters.length)
+                        return {};
+
+                    _.forEach(clusters, (cluster) => {
+                        cluster.igfss = _.filter(igfss, ({_id}) => _.includes(cluster.igfss, _id));
+                        cluster.caches = _.filter(caches, ({_id}) => _.includes(cluster.caches, _id));
+                    });
+
+                    return {clusters};
+                })
+                .catch((err) => $q.reject(err));
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/logout.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/logout.state.js b/modules/web-console/src/main/js/app/modules/states/logout.state.js
new file mode 100644
index 0000000..7f24a45
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/logout.state.js
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import angular from 'angular';
+
+angular
+.module('ignite-console.states.logout', [
+    'ui.router'
+])
+.config(['$stateProvider', function($stateProvider) {
+    // set up the states
+    $stateProvider
+    .state('logout', {
+        url: '/logout',
+        controller: ['Auth', function(Auth) {
+            Auth.logout();
+        }],
+        metaTags: {
+            title: 'Logout'
+        }
+    });
+}]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/password.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/password.state.js b/modules/web-console/src/main/js/app/modules/states/password.state.js
new file mode 100644
index 0000000..48d01df
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/password.state.js
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import angular from 'angular';
+
+angular
+.module('ignite-console.states.password', [
+    'ui.router'
+])
+.config(['$stateProvider', function($stateProvider) {
+    // set up the states
+    $stateProvider
+    .state('password', {
+        url: '/password',
+        abstract: true,
+        template: '<ui-view></ui-view>'
+    })
+    .state('password.reset', {
+        url: '/reset?{token}',
+        templateUrl: '/reset.html',
+        metaTags: {
+            title: 'Reset password'
+        }
+    })
+    .state('password.send', {
+        url: '/send',
+        templateUrl: '/reset.html',
+        metaTags: {
+            title: 'Password Send'
+        }
+    });
+}]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/profile.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/profile.state.js b/modules/web-console/src/main/js/app/modules/states/profile.state.js
new file mode 100644
index 0000000..8b6cdfe
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/profile.state.js
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import angular from 'angular';
+
+angular
+.module('ignite-console.states.profile', [
+    'ui.router'
+])
+.config(['$stateProvider', function($stateProvider) {
+    // set up the states
+    $stateProvider
+    .state('settings.profile', {
+        url: '/profile',
+        templateUrl: '/settings/profile.html',
+        metaTags: {
+            title: 'User profile'
+        }
+    });
+}]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/signin.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/signin.state.js b/modules/web-console/src/main/js/app/modules/states/signin.state.js
new file mode 100644
index 0000000..91c84a3
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/signin.state.js
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import angular from 'angular';
+
+angular
+.module('ignite-console.states.login', [
+    'ui.router',
+    // services
+    'ignite-console.user'
+])
+.config(['$stateProvider', function($stateProvider) {
+    // set up the states
+    $stateProvider
+    .state('signin', {
+        url: '/',
+        templateUrl: '/signin.html',
+        metaTags: {
+        }
+    });
+}])
+.run(['$rootScope', '$state', 'Auth', 'IgniteBranding', function($root, $state, Auth, branding) {
+    $root.$on('$stateChangeStart', function(event, toState) {
+        if (toState.name === branding.termsState)
+            return;
+
+        if (!Auth.authorized && (toState.name !== 'signin' && !_.startsWith(toState.name, 'password.'))) {
+            event.preventDefault();
+
+            $state.go('signin');
+        }
+        else if (Auth.authorized && toState.name === 'signin') {
+            event.preventDefault();
+
+            $state.go('base.configuration.clusters');
+        }
+    });
+}]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/states/sql.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/sql.state.js b/modules/web-console/src/main/js/app/modules/states/sql.state.js
new file mode 100644
index 0000000..1aa4f47
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/states/sql.state.js
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import angular from 'angular';
+
+angular
+.module('ignite-console.states.sql', [
+    'ui.router'
+])
+.config(['$stateProvider', function($stateProvider) {
+    // set up the states
+    $stateProvider
+    .state('base.sql', {
+        url: '/sql',
+        abstract: true,
+        template: '<ui-view></ui-view>'
+    })
+    .state('base.sql.notebook', {
+        url: '/notebook/{noteId}',
+        templateUrl: '/sql/sql.html',
+        metaTags: {
+            title: 'Query notebook'
+        }
+    })
+    .state('base.sql.demo', {
+        url: '/demo',
+        templateUrl: '/sql/sql.html',
+        metaTags: {
+            title: 'SQL demo'
+        }
+    });
+}]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/user/Auth.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/user/Auth.service.js b/modules/web-console/src/main/js/app/modules/user/Auth.service.js
new file mode 100644
index 0000000..8ed9f33
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/user/Auth.service.js
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export default ['Auth', ['$http', '$rootScope', '$state', '$window', '$common', 'gettingStarted', 'User', 'IgniteAgentMonitor',
+    ($http, $root, $state, $window, $common, gettingStarted, User, agentMonitor) => {
+        let _auth = false;
+
+        try {
+            _auth = localStorage.authorized === 'true';
+        }
+        catch (ignore) {
+            // No-op.
+        }
+
+        function _authorized(value) {
+            try {
+                return _auth = localStorage.authorized = !!value;
+            } catch (ignore) {
+                return _auth = !!value;
+            }
+        }
+
+        return {
+            get authorized() {
+                return _auth;
+            },
+            set authorized(auth) {
+                _authorized(auth);
+            },
+            auth(action, userInfo) {
+                $http.post('/api/v1/' + action, userInfo)
+                    .then(User.read)
+                    .then((user) => {
+                        if (action !== 'password/forgot') {
+                            _authorized(true);
+
+                            $root.$broadcast('user', user);
+
+                            $state.go('base.configuration.clusters');
+
+                            $root.gettingStarted.tryShow();
+
+                            agentMonitor.init();
+                        } else
+                            $state.go('password.send');
+                    })
+                    .catch((errMsg) => $common.showPopoverMessage(null, null, action === 'signup' ? 'signup_email' : 'signin_email', errMsg.data));
+            },
+            logout() {
+                $http.post('/api/v1/logout')
+                    .then(() => {
+                        User.clean();
+
+                        $window.open($state.href('signin'), '_self');
+                    })
+                    .catch((err) => $common.showError(err));
+            }
+        };
+    }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/user/User.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/user/User.service.js b/modules/web-console/src/main/js/app/modules/user/User.service.js
new file mode 100644
index 0000000..d1f8083
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/user/User.service.js
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export default ['User', ['$q', '$injector', '$rootScope', '$state', '$http', function($q, $injector, $root, $state, $http) {
+    let _user;
+
+    try {
+        _user = JSON.parse(localStorage.user);
+
+        if (_user)
+            $root.user = _user;
+    }
+    catch (ignore) {
+        // No-op.
+    }
+
+    return {
+        read() {
+            return $http.post('/api/v1/user').then(({data}) => {
+                if (_.isEmpty(data)) {
+                    const Auth = $injector.get('Auth');
+
+                    Auth.authorized = false;
+
+                    this.clean();
+
+                    if ($state.current.name !== 'signin')
+                        $state.go('signin');
+                }
+
+                try {
+                    localStorage.user = JSON.stringify(data);
+                }
+                catch (ignore) {
+                    // No-op.
+                }
+
+                return _user = $root.user = data;
+            });
+        },
+        clean() {
+            delete $root.user;
+
+            delete localStorage.user;
+
+            delete $root.IgniteDemoMode;
+
+            sessionStorage.removeItem('IgniteDemoMode');
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/user/user.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/user/user.module.js b/modules/web-console/src/main/js/app/modules/user/user.module.js
new file mode 100644
index 0000000..2387f20
--- /dev/null
+++ b/modules/web-console/src/main/js/app/modules/user/user.module.js
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import angular from 'angular';
+
+import Auth from './Auth.service';
+import User from './User.service';
+
+angular
+.module('ignite-console.user', [
+
+])
+.service(...Auth)
+.service(...User);


Mime
View raw message