You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2017/03/13 08:45:44 UTC

[23/50] [abbrv] ignite git commit: IGNITE-4659 Migration to Webpack 2. Upgrade template engine from jade to pug.

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/helpers/jade/mixins.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/helpers/jade/mixins.pug b/modules/web-console/frontend/app/helpers/jade/mixins.pug
new file mode 100644
index 0000000..db175a2
--- /dev/null
+++ b/modules/web-console/frontend/app/helpers/jade/mixins.pug
@@ -0,0 +1,609 @@
+//-
+    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 ./form
+
+//- Mixin for advanced options toggle.
+mixin advanced-options-toggle(click, cond, showMessage, hideMessage)
+    .advanced-options
+        i.fa(ng-click=`${click}` ng-class=`${cond} ? 'fa-chevron-circle-down' : 'fa-chevron-circle-right'`)
+        a(ng-click=click) {{ #{cond} ? '#{hideMessage}' : '#{showMessage}' }}
+
+//- Mixin for advanced options toggle with default settings.
+mixin advanced-options-toggle-default
+    +advanced-options-toggle('toggleExpanded()', 'ui.expanded', 'Show advanced settings...', 'Hide advanced settings...')
+
+//- Mixin for main table on screen with list of items.
+mixin main-table(title, rows, focusId, click, rowTemplate, searchField)
+    .padding-bottom-dflt(ng-show=`${rows} && ${rows}.length > 0`)
+        table.links(st-table='displayedRows' st-safe-src=`${rows}`)
+            thead
+                tr
+                    th
+                        lable.labelHeader.labelFormField #{title}:
+                        .col-sm-3.pull-right(style='padding: 0')
+                            input.form-control(type='text' st-search=`${searchField}` placeholder=`Filter ${title}...`)
+            tbody
+                tr
+                    td
+                        .scrollable-y(ng-show='displayedRows.length > 0' style='max-height: 200px')
+                            table
+                                tbody
+                                    tr(ng-repeat='row in displayedRows track by row._id' ignite-bs-affix-update)
+                                        td
+                                            a(ng-class='{active: row._id == selectedItem._id}' ignite-on-click-focus=focusId ng-click=click) #{rowTemplate}
+                        label.placeholder(ng-show='displayedRows.length == 0') No #{title} found
+
+//- Mixin with save, remove, clone and undo buttons.
+mixin save-remove-clone-undo-buttons(objectName)
+    -var removeTip = '"Remove current ' + objectName + '"'
+    -var cloneTip = '"Clone current ' + objectName + '"'
+    -var undoTip = '"Undo all changes for current ' + objectName + '"'
+
+    div(ng-show='contentVisible()' style='display: inline-block;')
+        .panel-tip-container(ng-hide='!backupItem || backupItem._id')
+            a.btn.btn-primary(ng-disabled='!ui.inputForm.$dirty' ng-click='ui.inputForm.$dirty && saveItem()' bs-tooltip='' data-title=`{{saveBtnTipText(ui.inputForm.$dirty, '${objectName}')}}` data-placement='bottom' data-trigger='hover') Save
+        .panel-tip-container(ng-show='backupItem._id')
+            a.btn.btn-primary(id='save-item' ng-disabled='!ui.inputForm.$dirty' ng-click='ui.inputForm.$dirty && saveItem()' bs-tooltip='' data-title=`{{saveBtnTipText(ui.inputForm.$dirty, '${objectName}')}}` data-placement='bottom' data-trigger='hover') Save
+        .panel-tip-container(ng-show='backupItem._id')
+            a.btn.btn-primary(id='clone-item' ng-click='cloneItem()' bs-tooltip=cloneTip data-placement='bottom' data-trigger='hover') Clone
+        .btn-group.panel-tip-container(ng-show='backupItem._id')
+            button.btn.btn-primary(id='remove-item' ng-click='removeItem()' bs-tooltip=removeTip data-placement='bottom' data-trigger='hover') Remove
+            button.btn.dropdown-toggle.btn-primary(id='remove-item-dropdown' data-toggle='dropdown' data-container='body' bs-dropdown='[{ text: "Remove All", click: "removeAllItems()" }]' data-placement='bottom-right')
+                span.caret
+        .panel-tip-container(ng-show='backupItem')
+            i.btn.btn-primary.fa.fa-undo(id='undo-item' ng-disabled='!ui.inputForm.$dirty' ng-click='ui.inputForm.$dirty && resetAll()' bs-tooltip=undoTip data-placement='bottom' data-trigger='hover')
+
+//- Mixin for feedback on specified error.
+mixin error-feedback(visible, error, errorMessage, name)
+    i.fa.fa-exclamation-triangle.form-control-feedback(
+        ng-if=visible
+        bs-tooltip=`'${errorMessage}'`
+        ignite-error=error
+        ignite-error-message=errorMessage
+        name=name
+    )
+
+//- Mixin for feedback on unique violation.
+mixin unique-feedback(name, errorMessage)
+    +form-field-feedback(name, 'igniteUnique', errorMessage)
+
+//- Mixin for feedback on IP address violation.
+mixin ipaddress-feedback(name)
+    +form-field-feedback(name, 'ipaddress', 'Invalid address!')
+
+//- Mixin for feedback on port of IP address violation.
+mixin ipaddress-port-feedback(name)
+    +form-field-feedback(name, 'ipaddressPort', 'Invalid port!')
+
+//- Mixin for feedback on port range violation.
+mixin ipaddress-port-range-feedback(name)
+    +form-field-feedback(name, 'ipaddressPortRange', 'Invalid port range!')
+
+//- Mixin for feedback on UUID violation.
+mixin uuid-feedback(name)
+    +form-field-feedback(name, 'uuid', 'Invalid node ID!')
+
+//- Function that convert enabled state to corresponding disabled state.
+-var enabledToDisabled = function (enabled) {
+-    return (enabled === false || enabled === true) ? !enabled : '!(' + enabled + ')';
+-}
+
+//- Mixin for checkbox.
+mixin checkbox(lbl, model, name, tip)
+    +form-field-checkbox(lbl, model, name, false, false, tip)
+
+//- Mixin for checkbox with enabled condition.
+mixin checkbox-enabled(lbl, model, name, enabled, tip)
+    +form-field-checkbox(lbl, model, name, enabledToDisabled(enabled), false, tip)
+
+//- Mixin for Java class name field with auto focus condition.
+mixin java-class-autofocus-placholder(lbl, model, name, enabled, required, autofocus, placeholder, tip, validationActive)
+    -var errLbl = lbl.substring(0, lbl.length - 1)
+
+    +ignite-form-field-text(lbl, model, name, enabledToDisabled(enabled), required, placeholder, tip)(
+        data-java-identifier='true'
+        data-java-package-specified='true'
+        data-java-keywords='true'
+        data-java-built-in-class='true'
+        data-ignite-form-field-input-autofocus=autofocus
+        data-validation-active=validationActive ? `{{ ${validationActive} }}` : `'always'`
+    )
+        if  block
+            block
+
+        +form-field-feedback(name, 'javaBuiltInClass', errLbl + ' should not be the Java built-in class!')
+        +form-field-feedback(name, 'javaKeywords', errLbl + ' could not contains reserved Java keyword!')
+        +form-field-feedback(name, 'javaPackageSpecified', errLbl + ' does not have package specified!')
+        +form-field-feedback(name, 'javaIdentifier', errLbl + ' is invalid Java identifier!')
+
+//- Mixin for Java class name field with auto focus condition.
+mixin java-class-autofocus(lbl, model, name, enabled, required, autofocus, tip, validationActive)
+    +java-class-autofocus-placholder(lbl, model, name, enabled, required, autofocus, 'Enter fully qualified class name', tip, validationActive)
+        if  block
+            block
+
+//- Mixin for Java class name field.
+mixin java-class(lbl, model, name, enabled, required, tip, validationActive)
+    +java-class-autofocus(lbl, model, name, enabled, required, 'false', tip, validationActive)
+        if  block
+            block
+
+//- Mixin for text field with enabled condition with options.
+mixin java-class-typeahead(lbl, model, name, options, enabled, required, placeholder, tip, validationActive)
+    -var errLbl = lbl.substring(0, lbl.length - 1)
+
+    +form-field-datalist(lbl, model, name, enabledToDisabled(enabled), required, placeholder, options, tip)(
+        data-java-identifier='true'
+        data-java-package-specified='allow-built-in'
+        data-java-keywords='true'
+        data-validation-active=validationActive ? `{{ ${validationActive} }}` : `'always'`
+    )
+        +form-field-feedback(name, 'javaKeywords', errLbl + ' could not contains reserved Java keyword!')
+        +form-field-feedback(name, 'javaPackageSpecified', errLbl + ' does not have package specified!')
+        +form-field-feedback(name, 'javaIdentifier', errLbl + ' is invalid Java identifier!')
+
+//- Mixin for java package field with enabled condition.
+mixin java-package(lbl, model, name, enabled, required, tip)
+    +ignite-form-field-text(lbl, model, name, enabledToDisabled(enabled), required, 'Enter package name', tip)(
+        data-java-keywords='true'
+        data-java-package-name='package-only'
+    )
+        +form-field-feedback(name, 'javaPackageName', 'Package name is invalid')
+        +form-field-feedback(name, 'javaKeywords', 'Package name could not contains reserved java keyword')
+
+//- Mixin for text field with IP address check.
+mixin text-ip-address(lbl, model, name, enabled, placeholder, tip)
+    +ignite-form-field-text(lbl, model, name, enabledToDisabled(enabled), false, placeholder, tip)(data-ipaddress='true')
+        +ipaddress-feedback(name)
+
+//- Mixin for text field with IP address and port range check.
+mixin text-ip-address-with-port-range(lbl, model, name, enabled, placeholder, tip)
+    +ignite-form-field-text(lbl, model, name, enabledToDisabled(enabled), false, placeholder, tip)(data-ipaddress='true' data-ipaddress-with-port='true' data-ipaddress-with-port-range='true')
+        +ipaddress-feedback(name)
+        +ipaddress-port-feedback(name)
+        +ipaddress-port-range-feedback(name)
+
+//- Mixin for text field.
+mixin text-enabled(lbl, model, name, enabled, required, placeholder, tip)
+    +ignite-form-field-text(lbl, model, name, enabledToDisabled(enabled), required, placeholder, tip)
+        if  block
+            block
+
+//- Mixin for text field with autofocus.
+mixin text-enabled-autofocus(lbl, model, name, enabled, required, placeholder, tip)
+    +ignite-form-field-text(lbl, model, name, enabledToDisabled(enabled), required, placeholder, tip)(
+        data-ignite-form-field-input-autofocus='true'
+    )
+        if  block
+            block
+
+//- Mixin for text field.
+mixin text(lbl, model, name, required, placeholder, tip)
+    +ignite-form-field-text(lbl, model, name, false, required, placeholder, tip)
+        if  block
+            block
+
+//- Mixin for password field.
+mixin password(lbl, model, name, required, placeholder, tip)
+    +ignite-form-field-password(lbl, model, name, false, required, placeholder, tip)
+        if  block
+            block
+
+//- Mixin for text field with enabled condition with options.
+mixin text-options(lbl, model, name, options, enabled, required, placeholder, tip)
+    +form-field-datalist(lbl, model, name, enabledToDisabled(enabled), required, placeholder, options, tip)
+
+//- Mixin for required numeric field.
+mixin number-required(lbl, model, name, enabled, required, placeholder, min, tip)
+    +ignite-form-field-number(lbl, model, name, enabledToDisabled(enabled), required, placeholder, min, false, false, tip)
+
+//- Mixin for required numeric field with maximum and minimum limit.
+mixin number-min-max(lbl, model, name, enabled, placeholder, min, max, tip)
+    +ignite-form-field-number(lbl, model, name, enabledToDisabled(enabled), false, placeholder, min, max, '1', tip)
+
+//- Mixin for required numeric field with maximum and minimum limit.
+mixin number-min-max-step(lbl, model, name, enabled, placeholder, min, max, step, tip)
+    +ignite-form-field-number(lbl, model, name, enabledToDisabled(enabled), false, placeholder, min, max, step, tip)
+
+//- Mixin for numeric field.
+mixin number(lbl, model, name, enabled, placeholder, min, tip)
+    +ignite-form-field-number(lbl, model, name, enabledToDisabled(enabled), false, placeholder, min, false, false, tip)
+
+//- Mixin for required dropdown field.
+mixin dropdown-required-empty(lbl, model, name, enabled, required, placeholder, placeholderEmpty, options, tip)
+    +ignite-form-field-dropdown(lbl, model, name, enabledToDisabled(enabled), required, false, placeholder, placeholderEmpty, options, tip)
+        if  block
+            block
+
+//- Mixin for required dropdown field with autofocus.
+mixin dropdown-required-empty-autofocus(lbl, model, name, enabled, required, placeholder, placeholderEmpty, options, tip)
+    +ignite-form-field-dropdown(lbl, model, name, enabledToDisabled(enabled), required, false, placeholder, placeholderEmpty, options, tip)(
+        data-ignite-form-field-input-autofocus='true'
+    )
+        if  block
+            block
+
+//- Mixin for required dropdown field.
+mixin dropdown-required(lbl, model, name, enabled, required, placeholder, options, tip)
+    +ignite-form-field-dropdown(lbl, model, name, enabledToDisabled(enabled), required, false, placeholder, '', options, tip)
+        if  block
+            block
+
+//- Mixin for required dropdown field with autofocus.
+mixin dropdown-required-autofocus(lbl, model, name, enabled, required, placeholder, options, tip)
+    +ignite-form-field-dropdown(lbl, model, name, enabledToDisabled(enabled), required, false, placeholder, '', options, tip)(
+        data-ignite-form-field-input-autofocus='true'
+    )
+        if  block
+            block
+
+//- Mixin for dropdown field.
+mixin dropdown(lbl, model, name, enabled, placeholder, options, tip)
+    +ignite-form-field-dropdown(lbl, model, name, enabledToDisabled(enabled), false, false, placeholder, '', options, tip)
+        if  block
+            block
+
+//- Mixin for dropdown-multiple field.
+mixin dropdown-multiple(lbl, model, name, enabled, placeholder, placeholderEmpty, options, tip)
+    +ignite-form-field-dropdown(lbl, model, name, enabledToDisabled(enabled), false, true, placeholder, placeholderEmpty, options, tip)
+        if  block
+            block
+
+//- Mixin for table text field.
+mixin table-text-field(name, model, items, valid, save, placeholder, newItem)
+    -var resetOnEnter = newItem ? '(stopblur = true) && (group.add = [{}])' : '(field.edit = false)'
+    -var onEnter = `${valid} && (${save}); ${valid} && ${resetOnEnter};`
+
+    -var onEscape = newItem ? 'group.add = []' : 'field.edit = false'
+
+    -var resetOnBlur = newItem ? '!stopblur && (group.add = [])' : 'field.edit = false'
+    -var onBlur = `${valid} && (${save}); ${resetOnBlur};`
+
+    div(ignite-on-focus-out=onBlur)
+        if block
+            block
+
+        .input-tip
+            +ignite-form-field-input(name, model, false, 'true', placeholder)(
+                data-ignite-unique=items
+                data-ignite-form-field-input-autofocus='true'
+
+                ignite-on-enter=onEnter
+                ignite-on-escape=onEscape
+            )
+
+//- Mixin for table java class field.
+mixin table-java-class-field(lbl, name, model, items, valid, save, newItem)
+    -var resetOnEnter = newItem ? '(stopblur = true) && (group.add = [{}])' : '(field.edit = false)'
+    -var onEnter = `${valid} && (${save}); ${valid} && ${resetOnEnter};`
+
+    -var onEscape = newItem ? 'group.add = []' : 'field.edit = false'
+
+    -var resetOnBlur = newItem ? '!stopblur && (group.add = [])' : 'field.edit = false'
+    -var onBlur = `${valid} && (${save}); ${resetOnBlur};`
+
+    div(ignite-on-focus-out=onBlur)
+        +form-field-feedback(name, 'javaBuiltInClass', lbl + ' should not be the Java built-in class!')
+        +form-field-feedback(name, 'javaKeywords', lbl + ' could not contains reserved Java keyword!')
+        +form-field-feedback(name, 'javaPackageSpecified', lbl + ' does not have package specified!')
+        +form-field-feedback(name, 'javaIdentifier', lbl + ' is invalid Java identifier!')
+
+        if block
+            block
+
+        .input-tip
+            +ignite-form-field-input(name, model, false, 'true', 'Enter fully qualified class name')(
+                data-java-identifier='true'
+                data-java-package-specified='true'
+                data-java-keywords='true'
+                data-java-built-in-class='true'
+
+                data-ignite-unique=items
+                data-ignite-form-field-input-autofocus='true'
+
+                ignite-on-enter=onEnter
+                ignite-on-escape=onEscape
+            )
+
+//- Mixin for table java package field.
+mixin table-java-package-field(name, model, items, valid, save, newItem)
+    -var resetOnEnter = newItem ? '(stopblur = true) && (group.add = [{}])' : '(field.edit = false)'
+    -var onEnter = `${valid} && (${save}); ${valid} && ${resetOnEnter};`
+
+    -var onEscape = newItem ? 'group.add = []' : 'field.edit = false'
+
+    -var resetOnBlur = newItem ? '!stopblur && (group.add = [])' : 'field.edit = false'
+    -var onBlur = `${valid} && (${save}); ${resetOnBlur};`
+
+    div(ignite-on-focus-out=onBlur)
+        +form-field-feedback(name, 'javaKeywords', 'Package name could not contains reserved Java keyword!')
+        +form-field-feedback(name, 'javaPackageName', 'Package name is invalid!')
+
+        if block
+            block
+
+        .input-tip
+            +ignite-form-field-input(name, model, false, 'true', 'Enter package name')(
+                data-java-keywords='true'
+                data-java-package-name='package-only'
+
+                data-ignite-unique=items
+                data-ignite-form-field-input-autofocus='true'
+
+                ignite-on-enter=onEnter
+                ignite-on-escape=onEscape
+            )
+
+//- Mixin for table java package field.
+mixin table-url-field(name, model, items, valid, save, newItem)
+    -var resetOnEnter = newItem ? '(stopblur = true) && (group.add = [{}])' : '(field.edit = false)'
+    -var onEnter = `${valid} && (${save}); ${valid} && ${resetOnEnter};`
+
+    -var onEscape = newItem ? 'group.add = []' : 'field.edit = false'
+
+    -var resetOnBlur = newItem ? '!stopblur && (group.add = [])' : 'field.edit = false'
+    -var onBlur = `${valid} && (${save}); ${resetOnBlur};`
+
+    div(ignite-on-focus-out=onBlur)
+        if block
+            block
+
+        .input-tip
+            +ignite-form-field-url-input(name, model, false, 'true', 'Enter URL')(
+                data-ignite-unique=items
+                data-ignite-form-field-input-autofocus='true'
+
+                ignite-on-enter=onEnter
+                ignite-on-escape=onEscape
+            )
+
+//- Mixin for table address field.
+mixin table-address-field(name, model, items, valid, save, newItem, portRange)
+    -var resetOnEnter = newItem ? '(stopblur = true) && (group.add = [{}])' : '(field.edit = false)'
+    -var onEnter = `${valid} && (${save}); ${valid} && ${resetOnEnter};`
+
+    -var onEscape = newItem ? 'group.add = []' : 'field.edit = false'
+
+    -var resetOnBlur = newItem ? '!stopblur && (group.add = [])' : 'field.edit = false'
+    -var onBlur = `${valid} && (${save}); ${resetOnBlur};`
+
+    div(ignite-on-focus-out=onBlur)
+        +ipaddress-feedback(name)
+        +ipaddress-port-feedback(name)
+        +ipaddress-port-range-feedback(name)
+        +form-field-feedback(name, 'required', 'IP address:port could not be empty!')
+
+        if block
+            block
+
+        .input-tip
+            +ignite-form-field-input(name, model, false, 'true', 'IP address:port')(
+                data-ipaddress='true'
+                data-ipaddress-with-port='true'
+                data-ipaddress-with-port-range=portRange ? 'true' : null
+                data-ignite-unique=items
+                data-ignite-form-field-input-autofocus='true'
+
+                ignite-on-enter=onEnter
+                ignite-on-escape=onEscape
+            )
+
+//- Mixin for table UUID field.
+mixin table-uuid-field(name, model, items, valid, save, newItem)
+    -var resetOnEnter = newItem ? '(stopblur = true) && (group.add = [{}])' : '(field.edit = false)'
+    -var onEnter = `${valid} && (${save}); ${valid} && ${resetOnEnter};`
+
+    -var onEscape = newItem ? 'group.add = []' : 'field.edit = false'
+
+    -var resetOnBlur = newItem ? '!stopblur && (group.add = [])' : 'field.edit = false'
+    -var onBlur = `${valid} && (${save}); ${resetOnBlur};`
+
+    div(ignite-on-focus-out=onBlur)
+        if block
+            block
+
+        .input-tip
+            +ignite-form-field-input(name, model, false, 'true', 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx')(
+                data-uuid='true'
+                data-ignite-unique=items
+                data-ignite-form-field-input-autofocus='true'
+
+                ignite-on-enter=onEnter
+                ignite-on-escape=onEscape
+            )
+
+//- Mixin for table save button.
+   "||" used instead of "&&" to workaround escaping of "&&" to "&&"
+mixin table-save-button(valid, save, newItem)
+    -var reset = newItem ? 'group.add = []' : 'field.edit = false'
+
+    i.fa.fa-floppy-o.form-field-save(
+        ng-show=valid
+        ng-click=`!(${valid}) || (${save}); !(${valid}) || (${reset});`
+        bs-tooltip
+        data-title='Click icon or press [Enter] to save item'
+    )
+
+//- Mixin for table remove button.
+mixin table-remove-conditional-button(items, show, tip, row)
+    i.tipField.fa.fa-remove(
+        ng-hide=`!${show} || field.edit`
+        bs-tooltip
+        data-title=tip
+        ng-click=`${items}.splice(${items}.indexOf(${row}), 1)`
+    )
+
+//- Mixin for table remove button.
+mixin table-remove-button(items, tip)
+    +table-remove-conditional-button(items, 'true', tip, 'model')
+
+//- Mixin for cache mode.
+mixin cacheMode(lbl, model, name, placeholder)
+    +dropdown(lbl, model, name, 'true', placeholder,
+        '[\
+            {value: "LOCAL", label: "LOCAL"},\
+            {value: "REPLICATED", label: "REPLICATED"},\
+            {value: "PARTITIONED", label: "PARTITIONED"}\
+        ]',
+        'Cache modes:\
+        <ul>\
+            <li>PARTITIONED - in this mode the overall key set will be divided into partitions and all partitions will be split equally between participating nodes</li>\
+            <li>REPLICATED - in this mode all the keys are distributed to all participating nodes</li>\
+            <li>LOCAL - in this mode caches residing on different grid nodes will not know about each other</li>\
+        </ul>'
+    )
+
+//- Mixin for eviction policy.
+mixin evictionPolicy(model, name, enabled, required, tip)
+    -var kind = model + '.kind'
+    -var policy = model + '[' + kind + ']'
+
+    +dropdown-required('Eviction policy:', kind, name + '+ "Kind"', enabled, required, 'Not set',
+        '[\
+            {value: "LRU", label: "LRU"},\
+            {value: "FIFO", label: "FIFO"},\
+            {value: "SORTED", label: "Sorted"},\
+            {value: undefined, label: "Not set"}\
+        ]', tip)
+    span(ng-show=kind)
+        +showHideLink('expanded', 'settings')
+            .details-row
+                +number('Batch size', policy + '.batchSize', name + '+ "batchSize"', enabled, '1', '1',
+                    'Number of entries to remove on shrink')
+            .details-row
+                +number('Max memory size', policy + '.maxMemorySize', name + '+ "maxMemorySize"', enabled, '0', '0',
+                    'Maximum allowed cache size in bytes')
+            .details-row
+                +number('Max size', policy + '.maxSize', name + '+ "maxSize"', enabled, '100000', '0',
+                    'Maximum allowed size of cache before entry will start getting evicted')
+
+//- Mixin for clusters dropdown.
+mixin clusters(model, tip)
+    +dropdown-multiple('<span>Clusters:</span>' + '<a ui-sref="base.configuration.clusters({linkId: linkId()})"> (add)</a>',
+        model + '.clusters', '"clusters"', true, 'Choose clusters', 'No clusters configured', 'clusters', tip)
+
+//- Mixin for caches dropdown.
+mixin caches(model, tip)
+    +dropdown-multiple('<span>Caches:</span>' + '<a ui-sref="base.configuration.caches({linkId: linkId()})"> (add)</a>',
+        model + '.caches', '"caches"', true, 'Choose caches', 'No caches configured', 'caches', tip)
+
+//- Mixin for XML, Java, .Net preview.
+mixin preview(master, generator, detail)
+    ignite-ui-ace-tabs
+        .preview-panel(ng-init='mode = "spring"')
+            .preview-legend
+                a(ng-class='{active: mode === "spring"}' ng-click='mode = "spring"') Spring
+                a(ng-class='{active: mode === "java"}' ng-click='mode = "java"') Java
+                a(ng-class='{active: mode === "csharp"}' ng-click='mode = "csharp"') C#
+                //a(ng-class='{active: mode === "app.config"}' ng-click='mode = "app.config"') app.config
+            .preview-content(ng-switch='mode')
+                ignite-ui-ace-spring(ng-switch-when="spring" data-master=master data-generator=generator ng-model='$parent.data' data-detail=detail)
+                ignite-ui-ace-java(ng-switch-when="java" data-master=master data-generator=generator ng-model='$parent.data' data-detail=detail)
+                ignite-ui-ace-sharp(ng-switch-when="csharp" data-master=master data-generator=generator ng-model='$parent.data' data-detail=detail)
+            .preview-content-empty(ng-if='!data')
+                label All Defaults
+
+//- Mixin for XML and Java preview.
+mixin preview-xml-java(master, generator, detail)
+    ignite-ui-ace-tabs
+        .preview-panel(ng-init='mode = "spring"')
+            .preview-legend
+                a(ng-class='{active: mode === "spring"}' ng-click='mode = "spring"') Spring
+                a(ng-class='{active: mode === "java"}' ng-click='mode = "java"') Java
+                //a(ng-class='{active: mode === "csharp"}' ng-click='mode = "csharp"') C#
+                //a(ng-class='{active: mode === "app.config"}' ng-click='mode = "app.config"') app.config
+            .preview-content(ng-switch='mode')
+                ignite-ui-ace-spring(ng-switch-when="spring" data-master=master data-generator=generator ng-model='$parent.data' data-detail=detail)
+                ignite-ui-ace-java(ng-switch-when="java" data-master=master data-generator=generator ng-model='$parent.data' data-detail=detail)
+                //ignite-ui-ace-sharp(ng-switch-when="csharp" data-master=master data-generator=generator ng-model='$parent.data' data-detail=detail)
+            .preview-content-empty(ng-if='!data')
+                label All Defaults
+
+//- LEGACY mixin for LEGACY tables.
+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')
+
+//- LEGACY mixin for LEGACY tables.
+mixin btn-add(click, tip)
+    i.tipField.fa.fa-plus(ng-click=click bs-tooltip=tip data-trigger = 'hover')
+
+//- LEGACY mixin for LEGACY tables.
+mixin btn-remove(click, tip)
+    i.tipField.fa.fa-remove(ng-click=click bs-tooltip=tip data-trigger='hover')
+
+//- LEGACY mixin for LEGACY tables.
+mixin btn-remove-cond(cond, click, tip)
+    i.tipField.fa.fa-remove(ng-show=cond ng-click=click bs-tooltip=tip data-trigger='hover')
+
+//- LEGACY mixin for LEGACY pair values tables.
+mixin table-pair-edit(tbl, prefix, keyPlaceholder, valPlaceholder, keyJavaBuiltInTypes, valueJavaBuiltInTypes, focusId, index, divider)
+    -var keyModel = `${tbl}.${prefix}Key`
+    -var valModel = `${tbl}.${prefix}Value`
+
+    -var keyFocusId = `${prefix}Key${focusId}`
+    -var valFocusId = `${prefix}Value${focusId}`
+
+    .col-xs-6.col-sm-6.col-md-6
+        .fieldSep !{divider}
+        .input-tip
+            if keyJavaBuiltInTypes
+                input.form-control(id=keyFocusId ignite-on-enter-focus-move=valFocusId type='text' ng-model=keyModel placeholder=keyPlaceholder bs-typeahead container='body' ignite-retain-selection data-min-length='1' bs-options='javaClass for javaClass in javaBuiltInClasses' ignite-on-escape='tableReset(false)')
+            else
+                input.form-control(id=keyFocusId ignite-on-enter-focus-move=valFocusId type='text' ng-model=keyModel placeholder=keyPlaceholder ignite-on-escape='tableReset(false)')
+    .col-xs-6.col-sm-6.col-md-6
+        -var btnVisible = 'tablePairSaveVisible(' + tbl + ', ' + index + ')'
+        -var btnSave = 'tablePairSave(tablePairValid, backupItem, ' + tbl + ', ' + index + ')'
+        -var btnVisibleAndSave = btnVisible + ' && ' + btnSave
+
+        +btn-save(btnVisible, btnSave)
+        .input-tip
+            if valueJavaBuiltInTypes
+                input.form-control(id=valFocusId type='text' ng-model=valModel placeholder=valPlaceholder bs-typeahead container='body' ignite-retain-selection data-min-length='1' bs-options='javaClass for javaClass in javaBuiltInClasses' ignite-on-enter=btnVisibleAndSave ignite-on-escape='tableReset(false)')
+            else
+                input.form-control(id=valFocusId type='text' ng-model=valModel placeholder=valPlaceholder ignite-on-enter=btnVisibleAndSave ignite-on-escape='tableReset(false)')
+
+//- Mixin for DB dialect.
+mixin dialect(lbl, model, name, required, tipTitle, genericDialectName, placeholder)
+    +dropdown-required(lbl, model, name, 'true', required, placeholder, '[\
+                {value: "Generic", label: "' + genericDialectName + '"},\
+                {value: "Oracle", label: "Oracle"},\
+                {value: "DB2", label: "IBM DB2"},\
+                {value: "SQLServer", label: "Microsoft SQL Server"},\
+                {value: "MySQL", label: "MySQL"},\
+                {value: "PostgreSQL", label: "PostgreSQL"},\
+                {value: "H2", label: "H2 database"}\
+        ]',
+        tipTitle +
+        '<ul>\
+            <li>' + genericDialectName + '</li>\
+            <li>Oracle database</li>\
+            <li>IBM DB2</li>\
+            <li>Microsoft SQL Server</li>\
+            <li>MySQL</li>\
+            <li>PostgreSQL</li>\
+            <li>H2 database</li>\
+        </ul>')
+
+//- Mixin for show/hide links.
+mixin showHideLink(name, text)
+    span(ng-init='__ = {};')
+        a.customize(ng-show=`__.${name}` ng-click=`__.${name} = false`) Hide #{text}
+        a.customize(ng-hide=`__.${name}` ng-click=`__.${name} = true; ui.loadPanel('${name}');`) Show #{text}
+        div(ng-if=`ui.isPanelLoaded('${name}')`)
+            .panel-details(ng-show=`__.${name}`)
+                if block
+                    block

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/agent/agent.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/agent/agent.module.js b/modules/web-console/frontend/app/modules/agent/agent.module.js
index 7ac39d1..c0e92d5 100644
--- a/modules/web-console/frontend/app/modules/agent/agent.module.js
+++ b/modules/web-console/frontend/app/modules/agent/agent.module.js
@@ -18,6 +18,8 @@
 import angular from 'angular';
 import io from 'socket.io-client'; // eslint-disable-line no-unused-vars
 
+import templateUrl from 'views/templates/agent-download.tpl.pug';
+
 const maskNull = (val) => _.isEmpty(val) ? 'null' : val;
 
 class IgniteAgentMonitor {
@@ -35,7 +37,7 @@ class IgniteAgentMonitor {
         // Pre-fetch modal dialogs.
         this._downloadAgentModal = $modal({
             scope: this._scope,
-            templateUrl: '/templates/agent-download.html',
+            templateUrl,
             show: false,
             backdrop: 'static',
             keyboard: false

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/branding/header-logo.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/branding/header-logo.directive.js b/modules/web-console/frontend/app/modules/branding/header-logo.directive.js
index 423de9c..231411b 100644
--- a/modules/web-console/frontend/app/modules/branding/header-logo.directive.js
+++ b/modules/web-console/frontend/app/modules/branding/header-logo.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import templateUrl from './header-logo.jade';
+import template from './header-logo.pug';
 
 export default ['igniteHeaderLogo', ['IgniteBranding', (branding) => {
     function controller() {
@@ -26,7 +26,7 @@ export default ['igniteHeaderLogo', ['IgniteBranding', (branding) => {
 
     return {
         restrict: 'E',
-        templateUrl,
+        template,
         controller,
         controllerAs: 'logo',
         replace: true

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/branding/header-logo.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/branding/header-logo.jade b/modules/web-console/frontend/app/modules/branding/header-logo.jade
deleted file mode 100644
index b58f670..0000000
--- a/modules/web-console/frontend/app/modules/branding/header-logo.jade
+++ /dev/null
@@ -1,18 +0,0 @@
-//-
-    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.
-
-a(ui-sref='signin')
-    img.navbar-brand(ng-src='{{logo.url}}' height='40')

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/branding/header-logo.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/branding/header-logo.pug b/modules/web-console/frontend/app/modules/branding/header-logo.pug
new file mode 100644
index 0000000..b58f670
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/branding/header-logo.pug
@@ -0,0 +1,18 @@
+//-
+    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.
+
+a(ui-sref='signin')
+    img.navbar-brand(ng-src='{{logo.url}}' height='40')

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/branding/powered-by-apache.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/branding/powered-by-apache.directive.js b/modules/web-console/frontend/app/modules/branding/powered-by-apache.directive.js
index 2f02446..dce7d55 100644
--- a/modules/web-console/frontend/app/modules/branding/powered-by-apache.directive.js
+++ b/modules/web-console/frontend/app/modules/branding/powered-by-apache.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import templateUrl from './powered-by-apache.jade';
+import template from './powered-by-apache.pug';
 
 export default ['ignitePoweredByApache', ['IgniteBranding', (branding) => {
     function controller() {
@@ -26,7 +26,7 @@ export default ['ignitePoweredByApache', ['IgniteBranding', (branding) => {
 
     return {
         restrict: 'E',
-        templateUrl,
+        template,
         controller,
         controllerAs: 'poweredBy',
         replace: true

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/branding/powered-by-apache.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/branding/powered-by-apache.jade b/modules/web-console/frontend/app/modules/branding/powered-by-apache.jade
deleted file mode 100644
index af9aadf..0000000
--- a/modules/web-console/frontend/app/modules/branding/powered-by-apache.jade
+++ /dev/null
@@ -1,18 +0,0 @@
-//-
-    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.
-
-a(ng-if='poweredBy.show' href='//ignite.apache.org' target='_blank')
-    img(ng-src='/images/pb-ignite.png' height='65')

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/branding/powered-by-apache.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/branding/powered-by-apache.pug b/modules/web-console/frontend/app/modules/branding/powered-by-apache.pug
new file mode 100644
index 0000000..af9aadf
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/branding/powered-by-apache.pug
@@ -0,0 +1,18 @@
+//-
+    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.
+
+a(ng-if='poweredBy.show' href='//ignite.apache.org' target='_blank')
+    img(ng-src='/images/pb-ignite.png' height='65')

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/demo/Demo.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/demo/Demo.module.js b/modules/web-console/frontend/app/modules/demo/Demo.module.js
index bd759df..740ab30 100644
--- a/modules/web-console/frontend/app/modules/demo/Demo.module.js
+++ b/modules/web-console/frontend/app/modules/demo/Demo.module.js
@@ -18,6 +18,7 @@
 import angular from 'angular';
 
 import DEMO_INFO from 'app/data/demo-info.json';
+import templateUrl from 'views/templates/demo-info.tpl.pug';
 
 angular
 .module('ignite-console.demo', [
@@ -129,7 +130,7 @@ angular
     }
 
     const dialog = $modal({
-        templateUrl: '/templates/demo-info.html',
+        templateUrl,
         scope,
         placement: 'center',
         show: false,

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/dialog/dialog.factory.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/dialog/dialog.factory.js b/modules/web-console/frontend/app/modules/dialog/dialog.factory.js
index e15891f..2ac8917 100644
--- a/modules/web-console/frontend/app/modules/dialog/dialog.factory.js
+++ b/modules/web-console/frontend/app/modules/dialog/dialog.factory.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import templateUrl from './dialog.jade';
+import templateUrl from './dialog.tpl.pug';
 
 export default ['IgniteDialog', ['$modal', ($modal) => {
     const defaults = {

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/dialog/dialog.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/dialog/dialog.jade b/modules/web-console/frontend/app/modules/dialog/dialog.jade
deleted file mode 100644
index 0043709..0000000
--- a/modules/web-console/frontend/app/modules/dialog/dialog.jade
+++ /dev/null
@@ -1,26 +0,0 @@
-//-
-    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.
-
-.modal(tabindex='-1' role='dialog')
-    .modal-dialog
-        .modal-content
-            .modal-header
-                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' ng-click='$hide()') Ok

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/dialog/dialog.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/dialog/dialog.tpl.pug b/modules/web-console/frontend/app/modules/dialog/dialog.tpl.pug
new file mode 100644
index 0000000..0043709
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/dialog/dialog.tpl.pug
@@ -0,0 +1,26 @@
+//-
+    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.
+
+.modal(tabindex='-1' role='dialog')
+    .modal-dialog
+        .modal-content
+            .modal-header
+                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' ng-click='$hide()') Ok

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/getting-started/GettingStarted.provider.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/getting-started/GettingStarted.provider.js b/modules/web-console/frontend/app/modules/getting-started/GettingStarted.provider.js
index cf9f561..f4c834c 100644
--- a/modules/web-console/frontend/app/modules/getting-started/GettingStarted.provider.js
+++ b/modules/web-console/frontend/app/modules/getting-started/GettingStarted.provider.js
@@ -19,6 +19,7 @@ import angular from 'angular';
 
 // Getting started pages.
 import PAGES from 'app/data/getting-started.json';
+import templateUrl from 'views/templates/getting-started.tpl.pug';
 
 angular
     .module('ignite-console.getting-started', [])
@@ -77,7 +78,7 @@ angular
             _fillPage();
         };
 
-        const dialog = $modal({templateUrl: '/templates/getting-started.html', scope, placement: 'center', show: false, backdrop: 'static'});
+        const dialog = $modal({ templateUrl, scope, placement: 'center', show: false, backdrop: 'static'});
 
         scope.close = () => {
             try {

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/loading/loading.css
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/loading/loading.css b/modules/web-console/frontend/app/modules/loading/loading.css
deleted file mode 100644
index 87bbc6a..0000000
--- a/modules/web-console/frontend/app/modules/loading/loading.css
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.
- */
-
-[ignite-loading] {
-    position: relative;
-}
-
-.loading {
-    position: absolute;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    top: 0;
-    z-index: 1001;
-    opacity: 0;
-    visibility: hidden;
-    background-color: white;
-    transition: visibility 0s 0.5s, opacity 0.5s linear;
-}
-
-.loading-active {
-    opacity: 1;
-    visibility: visible;
-    transition: opacity 0.5s linear;
-}
-
-.loading:before {
-    content: '';
-    display: inline-block;
-    height: 100%;
-    vertical-align: middle;
-}
-
-.loading .loading-wrapper {
-    display: inline-block;
-    vertical-align: middle;
-    position: relative;
-    width: 100%;
-}
-
-.loading.loading-top .loading-wrapper {
-    position: absolute;
-    top: 100px;
-    display: block;
-}
-
-.loading .loading-text {
-    font-size: 18px;
-    margin: 20px 0;
-    text-align: center;
-}
-
-.loading-opacity-80 {
-    opacity: 0.8;
-}
-
-.loading-max-foreground {
-    z-index: 99999;
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/loading/loading.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/loading/loading.directive.js b/modules/web-console/frontend/app/modules/loading/loading.directive.js
index 064b4c2..8a4ca9f 100644
--- a/modules/web-console/frontend/app/modules/loading/loading.directive.js
+++ b/modules/web-console/frontend/app/modules/loading/loading.directive.js
@@ -15,12 +15,12 @@
  * limitations under the License.
  */
 
-import templateUrl from './loading.jade';
-import './loading.css';
+import template from './loading.pug';
+import './loading.scss';
 
-export default ['igniteLoading', ['IgniteLoading', '$templateCache', '$compile', (Loading, $templateCache, $compile) => {
+export default ['igniteLoading', ['IgniteLoading', '$compile', (Loading, $compile) => {
     const link = (scope, element) => {
-        const compiledTemplate = $compile($templateCache.get(templateUrl));
+        const compiledTemplate = $compile(template);
 
         const build = () => {
             scope.position = scope.position || 'middle';

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/loading/loading.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/loading/loading.jade b/modules/web-console/frontend/app/modules/loading/loading.jade
deleted file mode 100644
index cc6cf45..0000000
--- a/modules/web-console/frontend/app/modules/loading/loading.jade
+++ /dev/null
@@ -1,23 +0,0 @@
-//-
-    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.
-
-.loading.loading-opacity-80(ng-class='[class, "loading-" + position]')
-    .loading-wrapper
-        .spinner
-            .bounce1
-            .bounce2
-            .bounce3
-        .loading-text {{ text }}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/loading/loading.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/loading/loading.pug b/modules/web-console/frontend/app/modules/loading/loading.pug
new file mode 100644
index 0000000..cc6cf45
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/loading/loading.pug
@@ -0,0 +1,23 @@
+//-
+    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.
+
+.loading.loading-opacity-80(ng-class='[class, "loading-" + position]')
+    .loading-wrapper
+        .spinner
+            .bounce1
+            .bounce2
+            .bounce3
+        .loading-text {{ text }}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/loading/loading.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/loading/loading.scss b/modules/web-console/frontend/app/modules/loading/loading.scss
new file mode 100644
index 0000000..87bbc6a
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/loading/loading.scss
@@ -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.
+ */
+
+[ignite-loading] {
+    position: relative;
+}
+
+.loading {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    top: 0;
+    z-index: 1001;
+    opacity: 0;
+    visibility: hidden;
+    background-color: white;
+    transition: visibility 0s 0.5s, opacity 0.5s linear;
+}
+
+.loading-active {
+    opacity: 1;
+    visibility: visible;
+    transition: opacity 0.5s linear;
+}
+
+.loading:before {
+    content: '';
+    display: inline-block;
+    height: 100%;
+    vertical-align: middle;
+}
+
+.loading .loading-wrapper {
+    display: inline-block;
+    vertical-align: middle;
+    position: relative;
+    width: 100%;
+}
+
+.loading.loading-top .loading-wrapper {
+    position: absolute;
+    top: 100px;
+    display: block;
+}
+
+.loading .loading-text {
+    font-size: 18px;
+    margin: 20px 0;
+    text-align: center;
+}
+
+.loading-opacity-80 {
+    opacity: 0.8;
+}
+
+.loading-max-foreground {
+    z-index: 99999;
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/nodes/Nodes.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/nodes/Nodes.service.js b/modules/web-console/frontend/app/modules/nodes/Nodes.service.js
index b320ae4..4ca1d45 100644
--- a/modules/web-console/frontend/app/modules/nodes/Nodes.service.js
+++ b/modules/web-console/frontend/app/modules/nodes/Nodes.service.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import nodesDialogTemplate from './nodes-dialog.jade';
+import nodesDialogTplUrl from './nodes-dialog.tpl.pug';
 
 const DEFAULT_OPTIONS = {
     grid: {
@@ -41,7 +41,7 @@ class Nodes {
         options.target = cacheName;
 
         const modalInstance = $modal({
-            templateUrl: nodesDialogTemplate,
+            templateUrl: nodesDialogTplUrl,
             show: true,
             resolve: {
                 nodes: () => nodes || [],

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/nodes/nodes-dialog.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/nodes/nodes-dialog.jade b/modules/web-console/frontend/app/modules/nodes/nodes-dialog.jade
deleted file mode 100644
index d9ea68c..0000000
--- a/modules/web-console/frontend/app/modules/nodes/nodes-dialog.jade
+++ /dev/null
@@ -1,35 +0,0 @@
-//-
-    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.
-
-.modal.ignite-nodes-dialog(tabindex='-1' role='dialog')
-    .modal-dialog
-        .modal-content
-            .modal-header
-                button.close(ng-click='$cancel()' aria-hidden='true') &times;
-                h4.modal-title Select Node
-            .modal-body.modal-body-with-scroll
-                p Choose node to execute query for cache: #[strong {{ $ctrl.options.target }}]
-
-                .panel.panel-default.nodes-grid
-                    .panel-heading
-                        label Cache Nodes: {{ $ctrl.nodes.length }}
-
-                    .panel-body.panel-body_collapse
-                        .grid(ui-grid='$ctrl.gridOptions' ui-grid-resize-columns ui-grid-selection ui-grid-pinning)
-
-            .modal-footer
-                button.btn.btn-primary(id='confirm-btn-confirm' ng-click='$ok($ctrl.selected)' ng-disabled='$ctrl.selected.length === 0') Select node
-                button.btn.btn-default(id='confirm-btn-close' ng-click='$cancel()') Cancel

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/nodes/nodes-dialog.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/nodes/nodes-dialog.tpl.pug b/modules/web-console/frontend/app/modules/nodes/nodes-dialog.tpl.pug
new file mode 100644
index 0000000..d9ea68c
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/nodes/nodes-dialog.tpl.pug
@@ -0,0 +1,35 @@
+//-
+    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.
+
+.modal.ignite-nodes-dialog(tabindex='-1' role='dialog')
+    .modal-dialog
+        .modal-content
+            .modal-header
+                button.close(ng-click='$cancel()' aria-hidden='true') &times;
+                h4.modal-title Select Node
+            .modal-body.modal-body-with-scroll
+                p Choose node to execute query for cache: #[strong {{ $ctrl.options.target }}]
+
+                .panel.panel-default.nodes-grid
+                    .panel-heading
+                        label Cache Nodes: {{ $ctrl.nodes.length }}
+
+                    .panel-body.panel-body_collapse
+                        .grid(ui-grid='$ctrl.gridOptions' ui-grid-resize-columns ui-grid-selection ui-grid-pinning)
+
+            .modal-footer
+                button.btn.btn-primary(id='confirm-btn-confirm' ng-click='$ok($ctrl.selected)' ng-disabled='$ctrl.selected.length === 0') Select node
+                button.btn.btn-default(id='confirm-btn-close' ng-click='$cancel()') Cancel

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/sql/notebook.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/notebook.controller.js b/modules/web-console/frontend/app/modules/sql/notebook.controller.js
index f10a4d0..252dee6 100644
--- a/modules/web-console/frontend/app/modules/sql/notebook.controller.js
+++ b/modules/web-console/frontend/app/modules/sql/notebook.controller.js
@@ -15,11 +15,13 @@
  * limitations under the License.
  */
 
+import templateUrl from 'views/sql/notebook-new.tpl.pug';
+
 // Controller that load notebooks in navigation bar .
 export default ['$scope', '$modal', '$state', 'IgniteMessages', 'IgniteNotebook',
     (scope, $modal, $state, Messages, Notebook) => {
         // Pre-fetch modal dialogs.
-        const nameModal = $modal({scope, templateUrl: '/sql/notebook-new.html', show: false});
+        const nameModal = $modal({scope, templateUrl, show: false});
 
         scope.create = (name) => {
             return Notebook.create(name)

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/sql/sql.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.controller.js b/modules/web-console/frontend/app/modules/sql/sql.controller.js
index 4e972ef..e2ead13 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.controller.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.controller.js
@@ -15,6 +15,12 @@
  * limitations under the License.
  */
 
+import paragraphRateTemplateUrl from 'views/sql/paragraph-rate.tpl.pug';
+import cacheMetadataTemplateUrl from 'views/sql/cache-metadata.tpl.pug';
+import chartSettingsTemplateUrl from 'views/sql/chart-settings.tpl.pug';
+import showQueryTemplateUrl from 'views/templates/message.tpl.pug';
+
+
 // Time line X axis descriptor.
 const TIME_LINE = {value: -1, type: 'java.sql.Date', label: 'TIME_LINE'};
 
@@ -188,6 +194,13 @@ class Paragraph {
 // Controller for SQL notebook screen.
 export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$filter', '$modal', '$popover', 'IgniteLoading', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteAgentMonitor', 'IgniteChartColors', 'IgniteNotebook', 'IgniteNodes', 'uiGridExporterConstants', 'IgniteVersion', 'IgniteActivitiesData',
     function($root, $scope, $http, $q, $timeout, $interval, $animate, $location, $anchorScroll, $state, $filter, $modal, $popover, Loading, LegacyUtils, Messages, Confirm, agentMonitor, IgniteChartColors, Notebook, Nodes, uiGridExporterConstants, Version, ActivitiesData) {
+        const $ctrl = this;
+
+        // Define template urls.
+        $ctrl.paragraphRateTemplateUrl = paragraphRateTemplateUrl;
+        $ctrl.cacheMetadataTemplateUrl = cacheMetadataTemplateUrl;
+        $ctrl.chartSettingsTemplateUrl = chartSettingsTemplateUrl;
+
         let stopTopology = null;
 
         const _tryStopRefresh = function(paragraph) {
@@ -1737,7 +1750,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 }
 
                 // Show a basic modal from a controller
-                $modal({scope, template: '/templates/message.html', placement: 'center', show: true});
+                $modal({scope, templateUrl: showQueryTemplateUrl, placement: 'center', show: true});
             }
         };
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/sql/sql.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.module.js b/modules/web-console/frontend/app/modules/sql/sql.module.js
index 5875961..670e4f4 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.module.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.module.js
@@ -20,7 +20,9 @@ import angular from 'angular';
 import NotebookData from './Notebook.data';
 import Notebook from './Notebook.service';
 import notebook from './notebook.controller';
-import sql from './sql.controller';
+import controller from './sql.controller';
+
+import sqlTplUrl from 'app/../views/sql/sql.tpl.pug';
 
 angular.module('ignite-console.sql', [
     'ui.router'
@@ -32,11 +34,13 @@ angular.module('ignite-console.sql', [
                 .state('base.sql', {
                     url: '/queries',
                     abstract: true,
-                    template: '<ui-view></ui-view>'
+                    template: '<ui-view></ui-view>',
+                    controller,
+                    controllerAs: '$ctrl'
                 })
                 .state('base.sql.notebook', {
                     url: '/notebook/{noteId}',
-                    templateUrl: '/sql/sql.html',
+                    templateUrl: sqlTplUrl,
                     onEnter: AclRoute.checkAccess('query'),
                     metaTags: {
                         title: 'Query notebook'
@@ -44,7 +48,7 @@ angular.module('ignite-console.sql', [
                 })
                 .state('base.sql.demo', {
                     url: '/demo',
-                    templateUrl: '/sql/sql.html',
+                    templateUrl: sqlTplUrl,
                     onEnter: AclRoute.checkAccess('query'),
                     metaTags: {
                         title: 'SQL demo'
@@ -54,5 +58,4 @@ angular.module('ignite-console.sql', [
     )
     .service('IgniteNotebookData', NotebookData)
     .service('IgniteNotebook', Notebook)
-    .controller('notebookController', notebook)
-    .controller('sqlController', sql);
+    .controller('notebookController', notebook);

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/states/admin.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/admin.state.js b/modules/web-console/frontend/app/modules/states/admin.state.js
index 35c6fbb..93a38dd 100644
--- a/modules/web-console/frontend/app/modules/states/admin.state.js
+++ b/modules/web-console/frontend/app/modules/states/admin.state.js
@@ -17,6 +17,8 @@
 
 import angular from 'angular';
 
+import templateUrl from 'views/settings/admin.tpl.pug';
+
 angular
 .module('ignite-console.states.admin', [
     'ui.router'
@@ -26,7 +28,7 @@ angular
     $stateProvider
     .state('settings.admin', {
         url: '/admin',
-        templateUrl: '/settings/admin.html',
+        templateUrl,
         onEnter: AclRoute.checkAccess('admin_page'),
         metaTags: {
             title: 'Admin panel'

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/states/configuration.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration.state.js b/modules/web-console/frontend/app/modules/states/configuration.state.js
index 61dca13..a609d3a 100644
--- a/modules/web-console/frontend/app/modules/states/configuration.state.js
+++ b/modules/web-console/frontend/app/modules/states/configuration.state.js
@@ -26,6 +26,14 @@ import ConfigurationResource from './configuration/Configuration.resource';
 import summaryTabs from './configuration/summary/summary-tabs.directive';
 import IgniteSummaryZipper from './configuration/summary/summary-zipper.service';
 
+import sidebarTpl from 'views/configuration/sidebar.tpl.pug';
+import clustersTpl from 'views/configuration/clusters.tpl.pug';
+import cachesTpl from 'views/configuration/caches.tpl.pug';
+import domainsTpl from 'views/configuration/domains.tpl.pug';
+import igfsTpl from 'views/configuration/igfs.tpl.pug';
+import summaryTpl from 'views/configuration/summary.tpl.pug';
+import summaryTabsTemplateUrl from 'views/configuration/summary-tabs.pug';
+
 angular.module('ignite-console.states.configuration', ['ui.router'])
     .directive(...previewPanel)
     // Summary screen
@@ -33,18 +41,21 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
     // Services.
     .service('IgniteSummaryZipper', IgniteSummaryZipper)
     .service('IgniteConfigurationResource', ConfigurationResource)
+    .run(['$templateCache', ($templateCache) => {
+        $templateCache.put('summary-tabs.html', summaryTabsTemplateUrl);
+    }])
     // Configure state provider.
     .config(['$stateProvider', 'AclRouteProvider', ($stateProvider, AclRoute) => {
         // Setup the states.
         $stateProvider
             .state('base.configuration', {
                 url: '/configuration',
-                templateUrl: '/configuration/sidebar.html',
+                templateUrl: sidebarTpl,
                 abstract: true
             })
             .state('base.configuration.clusters', {
                 url: '/clusters',
-                templateUrl: '/configuration/clusters.html',
+                templateUrl: clustersTpl,
                 onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
@@ -55,7 +66,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             })
             .state('base.configuration.caches', {
                 url: '/caches',
-                templateUrl: '/configuration/caches.html',
+                templateUrl: cachesTpl,
                 onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
@@ -66,7 +77,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             })
             .state('base.configuration.domains', {
                 url: '/domains',
-                templateUrl: '/configuration/domains.html',
+                templateUrl: domainsTpl,
                 onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
@@ -77,7 +88,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             })
             .state('base.configuration.igfs', {
                 url: '/igfs',
-                templateUrl: '/configuration/igfs.html',
+                templateUrl: igfsTpl,
                 onEnter: AclRoute.checkAccess('configuration'),
                 params: {
                     linkId: null
@@ -88,7 +99,7 @@ angular.module('ignite-console.states.configuration', ['ui.router'])
             })
             .state('base.configuration.summary', {
                 url: '/summary',
-                templateUrl: '/configuration/summary.html',
+                templateUrl: summaryTpl,
                 onEnter: AclRoute.checkAccess('configuration'),
                 controller: ConfigurationSummaryCtrl,
                 controllerAs: 'ctrl',

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.jade b/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.jade
deleted file mode 100644
index 3c4746b..0000000
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.jade
+++ /dev/null
@@ -1,82 +0,0 @@
-//-
-    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 = 'affinity'
--var model = 'backupItem'
--var affModel = model + '.affinity'
--var affMapModel = model + '.affinityMapper'
--var rendezvousAff = affModel + '.kind === "Rendezvous"'
--var fairAff = affModel + '.kind === "Fair"'
--var customAff = affModel + '.kind === "Custom"'
--var customAffMapper = affMapModel + '.kind === "Custom"'
--var rendPartitionsRequired = rendezvousAff + ' && ' + affModel + '.Rendezvous.affinityBackupFilter'
--var fairPartitionsRequired = fairAff + ' && ' + affModel + '.Fair.affinityBackupFilter'
-
-.panel.panel-default(ng-form=form novalidate)
-    .panel-heading(bs-collapse-toggle='' ng-click='ui.loadPanel("#{form}")')
-        ignite-form-panel-chevron
-        label Affinity Collocation
-        ignite-form-field-tooltip.tipLabel
-            | Collocate data with data to improve performance and scalability of your application#[br]
-            | #[a(href="http://apacheignite.gridgain.org/docs/affinity-collocation" target="_blank") More info]
-        ignite-form-revert
-    .panel-collapse(role='tabpanel' bs-collapse-target id=form)
-        .panel-body(ng-if='ui.isPanelLoaded("#{form}")')
-            .col-sm-6
-                .settings-row
-                    +dropdown('Function:', affModel + '.kind', '"AffinityKind"', 'true', 'Default',
-                        '[\
-                            {value: "Rendezvous", label: "Rendezvous"},\
-                            {value: "Fair", label: "Fair"},\
-                            {value: "Custom", label: "Custom"},\
-                            {value: undefined, label: "Default"}\
-                        ]',
-                        'Key topology resolver to provide mapping from keys to nodes\
-                        <ul>\
-                            <li>Rendezvous - Based on Highest Random Weight algorithm<br/></li>\
-                            <li>Fair - Tries to ensure that all nodes get equal number of partitions with minimum amount of reassignments between existing nodes<br/></li>\
-                            <li>Custom - Custom implementation of key affinity fynction<br/></li>\
-                            <li>Default - By default rendezvous affinity function  with 1024 partitions is used<br/></li>\
-                        </ul>')
-                .panel-details(ng-if=rendezvousAff)
-                    .details-row
-                        +number-required('Partitions', affModel + '.Rendezvous.partitions', '"RendPartitions"', 'true', rendPartitionsRequired, '1024', '1', 'Number of partitions')
-                    .details-row
-                        +java-class('Backup filter', affModel + '.Rendezvous.affinityBackupFilter', '"RendAffinityBackupFilter"', 'true', 'false',
-                            'Backups will be selected from all nodes that pass this filter')
-                    .details-row
-                        +checkbox('Exclude neighbors', affModel + '.Rendezvous.excludeNeighbors', '"RendExcludeNeighbors"',
-                            'Exclude same - host - neighbors from being backups of each other and specified number of backups')
-                .panel-details(ng-if=fairAff)
-                    .details-row
-                        +number-required('Partitions', affModel + '.Fair.partitions', '"FairPartitions"', 'true', fairPartitionsRequired, '256', '1', 'Number of partitions')
-                    .details-row
-                        +java-class('Backup filter', affModel + '.Fair.affinityBackupFilter', '"FairAffinityBackupFilter"', 'true', 'false',
-                            'Backups will be selected from all nodes that pass this filter')
-                    .details-row
-                        +checkbox('Exclude neighbors', affModel + '.Fair.excludeNeighbors', '"FairExcludeNeighbors"',
-                            'Exclude same - host - neighbors from being backups of each other and specified number of backups')
-                .panel-details(ng-if=customAff)
-                    .details-row
-                        +java-class('Class name:', affModel + '.Custom.className', '"AffCustomClassName"', 'true', customAff,
-                            'Custom key affinity function implementation class name')
-                .settings-row
-                    +java-class('Mapper:', model + '.affinityMapper', '"AffMapCustomClassName"', 'true', 'false',
-                        'Provide custom affinity key for any given key')
-            .col-sm-6
-                +preview-xml-java(model, 'cacheAffinity')

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.pug b/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.pug
new file mode 100644
index 0000000..70b90bd
--- /dev/null
+++ b/modules/web-console/frontend/app/modules/states/configuration/caches/affinity.pug
@@ -0,0 +1,82 @@
+//-
+    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
+
+-var form = 'affinity'
+-var model = 'backupItem'
+-var affModel = model + '.affinity'
+-var affMapModel = model + '.affinityMapper'
+-var rendezvousAff = affModel + '.kind === "Rendezvous"'
+-var fairAff = affModel + '.kind === "Fair"'
+-var customAff = affModel + '.kind === "Custom"'
+-var customAffMapper = affMapModel + '.kind === "Custom"'
+-var rendPartitionsRequired = rendezvousAff + ' && ' + affModel + '.Rendezvous.affinityBackupFilter'
+-var fairPartitionsRequired = fairAff + ' && ' + affModel + '.Fair.affinityBackupFilter'
+
+.panel.panel-default(ng-form=form novalidate)
+    .panel-heading(bs-collapse-toggle='' ng-click=`ui.loadPanel('${form}')`)
+        ignite-form-panel-chevron
+        label Affinity Collocation
+        ignite-form-field-tooltip.tipLabel
+            | Collocate data with data to improve performance and scalability of your application#[br]
+            | #[a(href="http://apacheignite.gridgain.org/docs/affinity-collocation" target="_blank") More info]
+        ignite-form-revert
+    .panel-collapse(role='tabpanel' bs-collapse-target id=`${form}`)
+        .panel-body(ng-if=`ui.isPanelLoaded('${form}')`)
+            .col-sm-6
+                .settings-row
+                    +dropdown('Function:', `${affModel}.kind`, '"AffinityKind"', 'true', 'Default',
+                        '[\
+                            {value: "Rendezvous", label: "Rendezvous"},\
+                            {value: "Fair", label: "Fair"},\
+                            {value: "Custom", label: "Custom"},\
+                            {value: undefined, label: "Default"}\
+                        ]',
+                        'Key topology resolver to provide mapping from keys to nodes\
+                        <ul>\
+                            <li>Rendezvous - Based on Highest Random Weight algorithm<br/></li>\
+                            <li>Fair - Tries to ensure that all nodes get equal number of partitions with minimum amount of reassignments between existing nodes<br/></li>\
+                            <li>Custom - Custom implementation of key affinity fynction<br/></li>\
+                            <li>Default - By default rendezvous affinity function  with 1024 partitions is used<br/></li>\
+                        </ul>')
+                .panel-details(ng-if=rendezvousAff)
+                    .details-row
+                        +number-required('Partitions', `${affModel}.Rendezvous.partitions`, '"RendPartitions"', 'true', rendPartitionsRequired, '1024', '1', 'Number of partitions')
+                    .details-row
+                        +java-class('Backup filter', `${affModel}.Rendezvous.affinityBackupFilter`, '"RendAffinityBackupFilter"', 'true', 'false',
+                            'Backups will be selected from all nodes that pass this filter')
+                    .details-row
+                        +checkbox('Exclude neighbors', `${affModel}.Rendezvous.excludeNeighbors`, '"RendExcludeNeighbors"',
+                            'Exclude same - host - neighbors from being backups of each other and specified number of backups')
+                .panel-details(ng-if=fairAff)
+                    .details-row
+                        +number-required('Partitions', `${affModel}.Fair.partitions`, '"FairPartitions"', 'true', fairPartitionsRequired, '256', '1', 'Number of partitions')
+                    .details-row
+                        +java-class('Backup filter', `${affModel}.Fair.affinityBackupFilter`, '"FairAffinityBackupFilter"', 'true', 'false',
+                            'Backups will be selected from all nodes that pass this filter')
+                    .details-row
+                        +checkbox('Exclude neighbors', `${affModel}.Fair.excludeNeighbors`, '"FairExcludeNeighbors"',
+                            'Exclude same - host - neighbors from being backups of each other and specified number of backups')
+                .panel-details(ng-if=customAff)
+                    .details-row
+                        +java-class('Class name:', `${affModel}.Custom.className`, '"AffCustomClassName"', 'true', customAff,
+                            'Custom key affinity function implementation class name')
+                .settings-row
+                    +java-class('Mapper:', model + '.affinityMapper', '"AffMapCustomClassName"', 'true', 'false',
+                        'Provide custom affinity key for any given key')
+            .col-sm-6
+                +preview-xml-java(model, 'cacheAffinity')

http://git-wip-us.apache.org/repos/asf/ignite/blob/1080e686/modules/web-console/frontend/app/modules/states/configuration/caches/client-near-cache.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/states/configuration/caches/client-near-cache.jade b/modules/web-console/frontend/app/modules/states/configuration/caches/client-near-cache.jade
deleted file mode 100644
index e3d1a81..0000000
--- a/modules/web-console/frontend/app/modules/states/configuration/caches/client-near-cache.jade
+++ /dev/null
@@ -1,50 +0,0 @@
-//-
-    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 = 'clientNearCache'
--var model = 'backupItem.clientNearConfiguration'
-
-.panel.panel-default(ng-form=form novalidate ng-show='backupItem.cacheMode === "PARTITIONED"')
-    .panel-heading(bs-collapse-toggle='' ng-click='ui.loadPanel("#{form}")')
-        ignite-form-panel-chevron
-        label Client near cache
-        ignite-form-field-tooltip.tipLabel
-            | Near cache settings for client nodes#[br]
-            | Near cache is a small local cache that stores most recently or most frequently accessed data#[br]
-            | Should be used in case when it is impossible to send computations to remote nodes
-        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 + '.clientNearCacheEnabled'
-
-                .settings-row
-                    +checkbox('Enabled', enabled, '"clientNacheEnabled"', 'Flag indicating whether to configure near cache')
-                .settings-row
-                    +number('Start size:', model + '.nearStartSize', '"clientNearStartSize"', enabled, '375000', '0',
-                        'Initial cache size for near cache which will be used to pre-create internal hash table after start')
-                .settings-row
-                    +evictionPolicy(model + '.nearEvictionPolicy', '"clientNearCacheEvictionPolicy"', enabled, 'false',
-                        'Near cache eviction policy\
-                        <ul>\
-                            <li>Least Recently Used (LRU) - Eviction policy based on LRU algorithm and supports batch eviction</li>\
-                            <li>First In First Out (FIFO) - Eviction policy based on FIFO algorithm and supports batch eviction</li>\
-                            <li>SORTED - Eviction policy which will select the minimum cache entry for eviction</li>\
-                        </ul>')
-            .col-sm-6
-                +preview-xml-java('backupItem', 'cacheClientNearCache')