You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by an...@apache.org on 2015/07/23 10:41:10 UTC
[39/50] [abbrv] incubator-ignite git commit: # ignite-843 moved
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/includes/controls.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/includes/controls.jade b/modules/web-control-center/nodejs/views/includes/controls.jade
deleted file mode 100644
index 4a618fa..0000000
--- a/modules/web-control-center/nodejs/views/includes/controls.jade
+++ /dev/null
@@ -1,322 +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.
-
-mixin block-callout(titleWorkflow, contentWorkflow, whatsNextWorkflow, whatsNextContent)
- .block-callout-parent.block-callout-border.margin-bottom-dflt
- .block-callout
- i.fa.fa-check-square
- label #{titleWorkflow}
- p(ng-bind-html=contentWorkflow)
- .block-callout
- i.fa.fa-check-square
- label #{whatsNextWorkflow}
- p(ng-bind-html=whatsNextContent)
-
-
-mixin tipField(lines)
- i.tipField.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
- i.tipField.fa.fa-question-circle.blank(ng-if='!#{lines}')
-
-mixin tipLabel(lines)
- i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='joinTip(#{lines})' type='button')
- i.tipLabel.fa.fa-question-circle.blank(ng-if='!#{lines}')
-
-mixin ico-exclamation(mdl, err, msg)
- i.fa.fa-exclamation-triangle.form-control-feedback(ng-show='inputForm["#{mdl}"].$error.#{err}' bs-tooltip data-title='#{msg}' type='button')
-
-mixin btn-save(show, click)
- i.tipField.fa.fa-floppy-o(ng-show=show ng-click=click)
-
-mixin btn-add(click)
- i.tipField.fa.fa-plus(ng-click=click)
-
-mixin btn-remove(click)
- i.tipField.fa.fa-remove(ng-click=click)
-
-mixin btn-up(show, click)
- i.tipField.fa.fa-arrow-up(ng-show=show ng-click=click)
-
-mixin btn-down(show, click)
- i.tipField.fa.fa-arrow-down(ng-show=show ng-click=click)
-
-mixin table-pair-edit(keyModel, valModel, keyPlaceholder, valPlaceholder)
- .col-sm-6(style='float: right')
- input.form-control(type='text' ng-model=valModel placeholder=valPlaceholder)
- label.fieldSep /
- .input-tip
- input.form-control(type='text' ng-model=keyModel placeholder=keyPlaceholder)
-
-mixin table-pair(header, tblMdl, keyFld, valFld, keyPlaceholder, valPlaceholder)
- .col-sm-6
- label.table-header #{header}:
- +tipLabel('field.tip')
- button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
- table.links-edit.col-sm-12(st-table=tblMdl)
- tbody
- tr.col-sm-12(ng-repeat='item in #{tblMdl}')
- td.col-sm-6
- div(ng-show='!tableEditing(field, $index)')
- a.labelFormField(ng-click='curPair = tableStartEdit(backupItem, field, $index); curKey = curPair.#{keyFld}; curValue = curPair.#{valFld}') {{$index + 1}}) {{item.#{keyFld}}} / {{item.#{valFld}}}
- +btn-remove('tableRemove(backupItem, field, $index)')
- div(ng-show='tableEditing(field, $index)')
- label.labelField {{$index + 1}})
- +btn-save('tablePairSaveVisible(curKey, curValue)', 'tablePairSave(tablePairValid, backupItem, field, curKey, curValue, $index)')
- +table-pair-edit('curKey', 'curValue', keyPlaceholder, valPlaceholder)
- tr.col-sm-12(ng-show='tableNewItemActive(field)')
- td.col-sm-6
- +btn-save('tablePairSaveVisible(newKey, newValue)', 'tablePairSave(tablePairValid, backupItem, field, newKey, newValue, -1)')
- +table-pair-edit('newKey', 'newValue', keyPlaceholder, valPlaceholder)
-
-mixin details-row
- - var lblDetailClasses = ['col-sm-4', 'details-label']
-
- - var detailMdl = 'getModel(backupItem, detail)[detail.model]';
- - var detailCommon = {'ng-model': detailMdl, 'ng-required': 'detail.required'};
-
- - var customValidators = {'ng-attr-ipaddress': '{{detail.ipaddress}}'}
-
- div(ng-switch='detail.type')
- div(ng-switch-when='label')
- label {{detail.label}}
- div.checkbox(ng-switch-when='check')
- label
- input(type='checkbox')&attributes(detailCommon)
- |{{detail.label}}
- +tipLabel('detail.tip')
- div(ng-switch-when='text')
- label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
- .col-sm-8
- +tipField('detail.tip')
- .input-tip
- input.form-control(type='text' placeholder='{{detail.placeholder}}')&attributes(detailCommon)
- div(ng-switch-when='number' )
- label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
- .col-sm-8
- +tipField('detail.tip')
- .input-tip
- input.form-control(name='{{detail.model}}' type='number' placeholder='{{detail.placeholder}}' min='{{detail.min ? detail.min : 0}}' max='{{detail.max ? detail.max : Number.MAX_VALUE}}')&attributes(detailCommon)
- +ico-exclamation('{{detail.model}}', 'min', 'Value is less than allowable minimum.')
- +ico-exclamation('{{detail.model}}', 'max', 'Value is more than allowable maximum.')
- +ico-exclamation('{{detail.model}}', 'number', 'Invalid value. Only numbers allowed.')
- div(ng-switch-when='dropdown')
- label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
- .col-sm-8
- +tipField('detail.tip')
- .input-tip
- button.form-control(bs-select data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in {{detail.items}}')&attributes(detailCommon)
- div(ng-switch-when='dropdown-multiple')
- label(class=lblDetailClasses ng-class='{required: detail.required}') {{detail.label}}:
- .col-sm-8
- button.form-control(bs-select data-multiple='1' data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label for item in {{detail.items}}')&attributes(detailCommon)
- +tipField('detail.tip')
- div(ng-switch-when='table-simple')&attributes(detailCommon)
- div(ng-if='detail.label')
- label.table-header {{detail.label}}:
- +tipLabel('detail.tableTip')
- table.col-sm-12.links-edit-details(st-table='#{detailMdl}')
- tbody
- tr(ng-repeat='item in #{detailMdl} track by $index')
- td
- div(ng-show='!tableEditing(detail, $index)')
- a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, detail, $index)') {{$index + 1}}) {{item}}
- +btn-remove('tableRemove(backupItem, detail, $index)')
- +btn-down('detail.reordering && tableSimpleDownVisible(backupItem, detail, $index)', 'tableSimpleDown(backupItem, detail, $index)')
- +btn-up('detail.reordering && $index > 0', 'tableSimpleUp(backupItem, detail, $index)')
- div(ng-show='tableEditing(detail, $index)')
- label.labelField {{$index + 1}})
- +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, detail, curValue, $index)')
- .input-tip.form-group.has-feedback
- input.form-control(name='{{detail.model}}.edit' type='text' ng-model='curValue' placeholder='{{detail.placeholder}}')&attributes(customValidators)
- +ico-exclamation('{{detail.model}}.edit', 'ipaddress', 'Invalid address, see help for format description.')
- button.btn.btn-primary.fieldButton(ng-disabled='!newValue' ng-click='tableSimpleSave(tableSimpleValid, backupItem, detail, newValue, -1)') Add
- +tipField('detail.tip')
- .input-tip.form-group.has-feedback
- input.form-control(name='{{detail.model}}' type='text' ng-model='newValue' ng-focus='tableNewItem(detail)' placeholder='{{detail.placeholder}}')&attributes(customValidators)
- +ico-exclamation('{{detail.model}}', 'ipaddress', 'Invalid address, see help for format description.')
-
-mixin table-db-field-edit(dbName, dbType, javaName, javaType)
- div(style='width: 22%; float: right')
- button.form-control(ng-model=javaType bs-select data-placeholder='Java type' bs-options='item.value as item.label for item in {{javaTypes}}')
- label.fieldSep /
- div(style='width: 20%; float: right')
- input.form-control(type='text' ng-model=javaName placeholder='Java name')
- label.fieldSep /
- div(style='width: 22%; float: right')
- button.form-control(ng-model=dbType bs-select data-placeholder='JDBC type' bs-options='item.value as item.label for item in {{jdbcTypes}}')
- label.fieldSep /
- .input-tip
- input.form-control(type='text' ng-model=dbName placeholder='DB name')
-
-mixin table-group-item-edit(fieldName, className, direction)
- div(style='width: 15%; float: right')
- button.form-control(ng-model=direction bs-select data-placeholder='Sort' bs-options='item.value as item.label for item in {{sortDirections}}')
- label.fieldSep /
- div(style='width: 38%; float: right')
- input.form-control(type='text' ng-model=className placeholder='Class name')
- label.fieldSep /
- .input-tip
- input.form-control(type='text' ng-model=fieldName placeholder='Field name')
-
-mixin form-row
- +form-row-custom(['col-sm-2'], ['col-sm-4'])
-
-mixin form-row-custom(lblClasses, fieldClasses)
- - var fieldMdl = 'getModel(backupItem, field)[field.model]';
- - var fieldCommon = {'ng-model': fieldMdl, 'ng-required': 'field.required || required(field)'};
- - var fieldRequiredClass = '{true: "required"}[field.required || required(field)]'
- - var fieldHide = '{{field.hide}}'
-
- div(ng-switch='field.type')
- div.col-sm-6(ng-switch-when='label')
- label {{field.label}}
- div.checkbox.col-sm-6(ng-switch-when='check' ng-hide=fieldHide)
- label
- input(type='checkbox')&attributes(fieldCommon)
- | {{field.label}}
- +tipLabel('field.tip')
- div(ng-switch-when='text' ng-hide=fieldHide)
- label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
- div(class=fieldClasses)
- +tipField('field.tip')
- .input-tip
- input.form-control(type='text' placeholder='{{field.placeholder}}')&attributes(fieldCommon)
- div(ng-switch-when='password' ng-hide=fieldHide)
- label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
- div(class=fieldClasses)
- +tipField('field.tip')
- .input-tip
- input.form-control(type='password' placeholder='{{field.placeholder}}')&attributes(fieldCommon)
- div(ng-switch-when='number' ng-hide=fieldHide)
- label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
- div(class=fieldClasses)
- +tipField('field.tip')
- .input-tip
- input.form-control(name='{{field.model}}' type='number' placeholder='{{field.placeholder}}' min='{{field.min ? field.min : 0}}' max='{{field.max ? field.max : Number.MAX_VALUE}}')&attributes(fieldCommon)
- +ico-exclamation('{{field.model}}', 'min', 'Value is less than allowable minimum.')
- +ico-exclamation('{{field.model}}', 'max', 'Value is more than allowable maximum.')
- +ico-exclamation('{{field.model}}', 'number', 'Invalid value. Only numbers allowed.')
- div(ng-switch-when='dropdown' ng-hide=fieldHide)
- label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
- div(class=fieldClasses)
- +tipField('field.tip')
- .input-tip
- button.form-control(bs-select data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
- div(ng-switch-when='dropdown-multiple' ng-hide=fieldHide)
- label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
- div(class=fieldClasses)
- +tipField('field.tip')
- .input-tip
- button.form-control(bs-select ng-disabled='{{field.items}}.length == 0' data-multiple='1' data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
- a.customize(ng-show='field.addLink' ng-href='{{field.addLink.ref}}') {{field.addLink.label}}
- div(ng-switch-when='dropdown-details' ng-hide=fieldHide)
- - var expanded = 'field.details[' + fieldMdl + '].expanded'
-
- label(class=lblClasses ng-class=fieldRequiredClass) {{field.label}}:
- div(class=fieldClasses)
- +tipField('field.tip')
- .input-tip
- button.form-control(bs-select data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label for item in {{field.items}}')&attributes(fieldCommon)
- a.customize(ng-show='#{fieldMdl} && field.details[#{fieldMdl}].fields' ng-click='#{expanded} = !#{expanded}') {{#{expanded} ? "Hide settings" : "Show settings"}}
- .col-sm-6.panel-details(ng-show='#{expanded} && #{fieldMdl}')
- .details-row(ng-repeat='detail in field.details[#{fieldMdl}].fields')
- +details-row
- div(ng-switch-when='table-simple' ng-hide=fieldHide)&attributes(fieldCommon)
- .col-sm-6
- label.table-header {{field.label}}:
- +tipLabel('field.tableTip')
- button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
- table.links-edit.col-sm-12(st-table='#{fieldMdl}')
- tbody
- tr.col-sm-12(ng-repeat='item in #{fieldMdl} track by $index')
- td.col-sm-6
- div(ng-show='!tableEditing(field, $index)')
- a.labelFormField(ng-click='curValue = tableStartEdit(backupItem, field, $index)') {{$index + 1}}) {{item | compact}}
- +btn-remove('tableRemove(backupItem, field, $index)')
- +btn-down('field.reordering && tableSimpleDownVisible(backupItem, field, $index)', 'tableSimpleDown(backupItem, field, $index)')
- +btn-up('field.reordering && $index > 0', 'tableSimpleUp(backupItem, field, $index)')
- div(ng-show='tableEditing(field, $index)')
- label.labelField {{$index + 1}})
- +btn-save('tableSimpleSaveVisible(curValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, curValue, $index)')
- .input-tip
- input.form-control(type='text' ng-model='curValue' placeholder='{{field.placeholder}}')
- tr.col-sm-12(ng-show='tableNewItemActive(field)')
- td.col-sm-6
- +btn-save('tableSimpleSaveVisible(newValue)', 'tableSimpleSave(tableSimpleValid, backupItem, field, newValue, -1)')
- .input-tip
- input.form-control(type='text' ng-model='newValue' placeholder='{{field.placeholder}}')
- div(ng-switch-when='indexedTypes')
- +table-pair('Index key-value type pairs', fieldMdl, 'keyClass', 'valueClass', 'Key class full name', 'Value class full name')
- div(ng-switch-when='queryFields' ng-hide=fieldHide)
- +table-pair('{{field.label}}', fieldMdl, 'name', 'className', 'Field name', 'Field class full name')
- div(ng-switch-when='dbFields' ng-hide=fieldHide)
- .col-sm-6
- label.table-header {{field.label}}:
- +tipLabel('field.tip')
- button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
- table.links-edit.col-sm-12(st-table=fieldMdl)
- tbody
- tr.col-sm-12(ng-repeat='item in #{fieldMdl}')
- td.col-sm-6
- div(ng-show='!tableEditing(field, $index)')
- a.labelFormField(ng-click='curField = tableStartEdit(backupItem, field, $index); curDbName = curField.dbName; curDbType = curField.dbType; curJavaName = curField.javaName; curJavaType = curField.javaType') {{$index + 1}}) {{item.dbName}} / {{item.dbType}} / {{item.javaName}} / {{item.javaType}}
- +btn-remove('tableRemove(backupItem, field, $index)')
- div(ng-if='tableEditing(field, $index)')
- label.labelField {{$index + 1}})
- +btn-save('tableDbFieldSaveVisible(curDbName, curDbType, curJavaName, curJavaType)', 'tableDbFieldSave(field, curDbName, curDbType, curJavaName, curJavaType, $index)')
- +table-db-field-edit('curDbName', 'curDbType', 'curJavaName', 'curJavaType')
- tr(ng-show='tableNewItemActive(field)')
- td.col-sm-6
- +btn-save('tableDbFieldSaveVisible(newDbName, newDbType, newJavaName, newJavaType)', 'tableDbFieldSave(field, newDbName, newDbType, newJavaName, newJavaType, -1)')
- +table-db-field-edit('newDbName', 'newDbType', 'newJavaName', 'newJavaType')
- div(ng-switch-when='queryGroups' ng-hide=fieldHide)
- .col-sm-6
- label.table-header {{field.label}}:
- +tipLabel('field.tip')
- button.btn.btn-primary.fieldButton(ng-click='tableNewItem(field)') Add
- table.links-edit.col-sm-12(st-table=fieldMdl)
- tbody
- tr.col-sm-12(ng-repeat='group in #{fieldMdl}')
- td.col-sm-6
- div
- .col-sm-12(ng-show='!tableEditing(field, $index)')
- a.labelFormField(ng-click='curGroup = tableStartEdit(backupItem, field, $index); curGroupName = curGroup.name; curFields = curGroup.fields') {{$index + 1}}) {{group.name}}
- +btn-remove('tableRemove(backupItem, field, $index)')
- +btn-add('tableGroupNewItem($index); newDirection = "ASC"')
- div(ng-show='tableEditing(field, $index)')
- label.labelField {{$index + 1}})
- +btn-save('tableGroupSaveVisible(curGroupName)', 'tableGroupSave(curGroupName, $index)')
- .input-tip
- input.form-control(type='text' ng-model='curGroupName' placeholder='Index name')
- div
- table.links-edit.col-sm-12(st-table='group.fields' ng-init='groupIndex = $index')
- tr(ng-repeat='groupItem in group.fields')
- td
- div(ng-show='!tableGroupItemEditing(groupIndex, $index)')
- a.labelFormField(ng-click='curGroupItem = tableGroupItemStartEdit(groupIndex, $index); curFieldName = curGroupItem.name; curClassName = curGroupItem.className; curDirection = curGroupItem.direction') {{$index + 1}}) {{groupItem.name}} / {{groupItem.className}} / {{groupItem.direction}}
- +btn-remove('tableRemoveGroupItem(group, $index)')
- div(ng-show='tableGroupItemEditing(groupIndex, $index)')
- label.labelField {{$index + 1}})
- +btn-save('tableGroupItemSaveVisible(curFieldName, curClassName)', 'tableGroupItemSave(curFieldName, curClassName, curDirection, groupIndex, $index)')
- +table-group-item-edit('curFieldName', 'curClassName', 'curDirection')
- tr.col-sm-12(style='padding-left: 18px' ng-show='tableGroupNewItemActive(groupIndex)')
- td
- +btn-save('tableGroupItemSaveVisible(newFieldName, newClassName)', 'tableGroupItemSave(newFieldName, newClassName, newDirection, groupIndex, -1)')
- +table-group-item-edit('newFieldName', 'newClassName', 'newDirection')
- tr.col-sm-12(ng-show='tableNewItemActive(field)')
- td.col-sm-6
- +btn-save('tableGroupSaveVisible(newGroupName)', 'tableGroupSave(newGroupName, -1)')
- .input-tip
- input.form-control(type='text' ng-model='newGroupName' placeholder='Group name')
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/includes/footer.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/includes/footer.jade b/modules/web-control-center/nodejs/views/includes/footer.jade
deleted file mode 100644
index d8ff5d7..0000000
--- a/modules/web-control-center/nodejs/views/includes/footer.jade
+++ /dev/null
@@ -1,22 +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.
-
-.container.container-footer
- footer
- center
- p Apache Ignite Control Center, version 1.0.0
- p © 2015 The Apache Software Foundation.
- p Apache, Apache Ignite, the Apache feather and the Apache Ignite logo are trademarks of The Apache Software Foundation.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/includes/header.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/includes/header.jade b/modules/web-control-center/nodejs/views/includes/header.jade
deleted file mode 100644
index ab2d31e..0000000
--- a/modules/web-control-center/nodejs/views/includes/header.jade
+++ /dev/null
@@ -1,39 +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.
-mixin header-item(active, ref, txt)
- li
- a(ng-class='{active: isActive("#{active}")}' href='#{ref}') #{txt}
-
-header.header(id='header')
- .viewedUser(ng-show='becomeUsed') Currently assuming "
- strong {{user.username}}
- | ",
- a(href='/admin/become') revert to your identity.
- .container
- h1.navbar-brand
- a(href='/') Apache Ignite Web Configurator
- .navbar-collapse.collapse(ng-controller='auth')
- ul.nav.navbar-nav(ng-controller='activeLink' ng-show='user')
- +header-item('/configuration', '/configuration/clusters', 'Configuration')
- //+header-item('/monitoring', '/monitoring', 'Monitoring')
- //+header-item('/sql', '/sql', 'SQL')
- //+header-item('/deploy', '/deploy', 'Deploy')
- ul.nav.navbar-nav.pull-right
- li(ng-if='user')
- a.dropdown-toggle(data-toggle='dropdown' bs-dropdown='userDropdown' data-placement='bottom-right') {{user.username}}
- span.caret
- li.nav-login(ng-if='!user')
- a(ng-click='login()' href='#') Log In
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/index.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/index.jade b/modules/web-control-center/nodejs/views/index.jade
deleted file mode 100644
index 999c4f8..0000000
--- a/modules/web-control-center/nodejs/views/index.jade
+++ /dev/null
@@ -1,30 +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.
-
-extends templates/layout
-
-block container
- .row
- .docs-content
- div
- p
- | Apache Ignite<sup>tm</sup> In-Memory Data Fabric is a high-performance,
- | integrated and distributed in-memory platform for computing and transacting on large-scale data
- | sets in real-time, orders of magnitude faster than possible with traditional disk-based or flash technologies.
- .block-image.block-display-image
- img(ng-src='https://www.filepicker.io/api/file/lydEeGB6Rs9hwbpcQxiw' alt='Apache Ignite stack')
- .text-center(ng-controller='auth')
- button.btn.btn-primary(ng-click='login()' href='#') Configure Now
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/login.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/login.jade b/modules/web-control-center/nodejs/views/login.jade
deleted file mode 100644
index 5bb39dd..0000000
--- a/modules/web-control-center/nodejs/views/login.jade
+++ /dev/null
@@ -1,55 +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.
-
-mixin lbl(txt)
- label.col-sm-3.required #{txt}
-
-.modal.center(role='dialog')
- .modal-dialog
- .modal-content
- .modal-header.header
- div(id='errors-container')
- button.close(type='button', ng-click='$hide()', aria-hidden='true') ×
- h1.navbar-brand
- a(href='/') Apache Ignite Web Configurator
- h4.modal-title(style='padding-right: 55px') Authentication
- p(style='padding-right: 55px') Log in or register in order to collaborate
- form.form-horizontal(name='loginForm')
- .modal-body.row
- .col-sm-9.login.col-sm-offset-1
- .details-row(ng-show='action == "register"')
- +lbl('Full Name:')
- .col-sm-9
- input.form-control(type='text', ng-model='user_info.username', placeholder='John Smith', focus-me='action=="register"', ng-required='action=="register"')
- .details-row
- +lbl('Email:')
- .col-sm-9
- input.form-control(type='email', ng-model='user_info.email', placeholder='you@domain.com', focus-me='action=="login"', required)
- .details-row
- +lbl('Password:')
- .col-sm-9
- input.form-control(type='password', ng-model='user_info.password', placeholder='Password', required, ng-keyup='action == "login" && $event.keyCode == 13 ? auth(action, user_info) : null')
- .details-row(ng-show='action == "register"')
- +lbl('Confirm:')
- .col-sm-9.input-tip.has-feedback
- input.form-control(type='password', ng-model='user_info.confirm', match="user_info.password" placeholder='Confirm password', required, ng-keyup='$event.keyCode == 13 ? auth(action, user_info) : null')
-
- .modal-footer
- a.show-signup.ng-hide(ng-show='action != "login"', ng-click='action = "login";') log in
- a.show-signup(ng-show="action != 'register'", ng-click='action = "register";') sign up
- | or
- button.btn.btn-primary(ng-show='action == "login"' ng-click='auth(action, user_info)') Log In
- button.btn.btn-primary(ng-show='action == "register"' ng-disabled='loginForm.$invalid || user_info.password != user_info.confirm' ng-click='auth(action, user_info)') Sign Up
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/settings/admin.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/settings/admin.jade b/modules/web-control-center/nodejs/views/settings/admin.jade
deleted file mode 100644
index 4d50631..0000000
--- a/modules/web-control-center/nodejs/views/settings/admin.jade
+++ /dev/null
@@ -1,58 +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.
-
-extends ../templates/layout
-
-append scripts
- script(src='/admin-controller.js')
-
-block container
- .row(ng-controller='adminController')
- .docs-content
- .docs-header
- h1 List of registered users
- hr
- .docs-body
- table.table.table-striped.admin(st-table='displayedUsers' st-safe-src='users')
- thead
- tr
- th.header(colspan='5')
- .col-sm-2.pull-right
- input.form-control(type='text' st-search='' placeholder='Filter users...')
- tr
- th(st-sort='username') User name
- th(st-sort='email') Email
- th.col-sm-2(st-sort='lastLogin') Last login
- th(width='1%' st-sort='admin') Admin
- th(width='1%') Actions
- tbody
- tr(ng-repeat='row in displayedUsers')
- td {{row.username}}
- td
- a(ng-href='mailto:{{row.email}}') {{row.email}}
- td
- span {{row.lastLogin | date:'medium'}}
- td(style='text-align: center;')
- input(type='checkbox' ng-disabled='row.adminChanging || row._id == user._id'
- ng-model='row.admin' ng-change='toggleAdmin(row)')
- td(style='text-align: center;')
- a(ng-click='removeUser(row)' ng-show='row._id != user._id' bs-tooltip data-title='Remove user')
- i.fa.fa-remove
- a(style='margin-left: 5px' ng-href='admin/become?viewedUserId={{row._id}}' ng-show='row._id != user._id' bs-tooltip data-title='Become this user')
- i.fa.fa-eye
- tfoot
- tr
- td(colspan='5' class="text-right")
- div(st-pagination st-items-by-page='15' st-displayed-pages='5')
-
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/settings/profile.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/settings/profile.jade b/modules/web-control-center/nodejs/views/settings/profile.jade
deleted file mode 100644
index dbc6dea..0000000
--- a/modules/web-control-center/nodejs/views/settings/profile.jade
+++ /dev/null
@@ -1,58 +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.
-
-extends ../templates/layout
-
-mixin lbl(txt)
- label.col-sm-2.required.labelFormField #{txt}
-
-append scripts
- script(src='/profile-controller.js')
-
-block container
- .row(ng-controller='profileController')
- .docs-content
- .docs-header
- h1 User profile
- hr
- .docs-body
- form.form-horizontal(name='profileForm' novalidate)
- .col-sm-10(style='padding: 0')
- .details-row
- +lbl('User name:')
- .col-sm-4
- input.form-control(type='text' ng-model='profileUser.username' placeholder='Input name' required)
- .details-row
- +lbl('Email:')
- .col-sm-4
- input.form-control(type='email' ng-model='profileUser.email' placeholder='you@domain.com' required)
- .details-row
- .checkbox
- label
- input(type="checkbox" ng-model='profileUser.changePassword')
- | Change password
- div(ng-show='profileUser.changePassword')
- .details-row
- +lbl('New password:')
- .col-sm-4
- input.form-control(type='password', ng-model='profileUser.newPassword' placeholder='New password' ng-required='profileUser.changePassword')
- .details-row
- +lbl('Confirm:')
- .col-sm-4
- input.form-control(type='password', ng-model='profileUser.confirmPassword' match='profileUser.newPassword' placeholder='Confirm new password' ng-required='profileUser.changePassword')
- .col-sm-12.details-row
- button.btn.btn-primary(ng-disabled='profileForm.$invalid' ng-click='saveUser()') Save
-
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/templates/confirm.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/confirm.jade b/modules/web-control-center/nodejs/views/templates/confirm.jade
deleted file mode 100644
index bdaf9bf..0000000
--- a/modules/web-control-center/nodejs/views/templates/confirm.jade
+++ /dev/null
@@ -1,27 +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(type="button" ng-click="$hide()") ×
- h4.modal-title Confirmation
- .modal-body(ng-show='content')
- p(ng-bind-html='content' style='text-align: center;')
- .modal-footer
- button.btn.btn-default(type="button" ng-click="$hide()") Cancel
- button.btn.btn-primary(type="button" ng-click="ok()") Confirm
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/templates/copy.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/copy.jade b/modules/web-control-center/nodejs/views/templates/copy.jade
deleted file mode 100644
index 22cc64c..0000000
--- a/modules/web-control-center/nodejs/views/templates/copy.jade
+++ /dev/null
@@ -1,31 +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(type="button" ng-click="$hide()") ×
- h4.modal-title Copy
- form.form-horizontal(name='inputForm' novalidate)
- .modal-body.row
- .col-sm-9.login.col-sm-offset-1
- label.required.labelFormField() New name:
- .col-sm-9
- input.form-control(type="text" ng-model='newName' required)
- .modal-footer
- button.btn.btn-default(type="button" ng-click="$hide()") Cancel
- button.btn.btn-primary(type="button" ng-disabled='inputForm.$invalid' ng-click="ok(newName)") Confirm
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/templates/layout.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/layout.jade b/modules/web-control-center/nodejs/views/templates/layout.jade
deleted file mode 100644
index a4191ae..0000000
--- a/modules/web-control-center/nodejs/views/templates/layout.jade
+++ /dev/null
@@ -1,61 +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.
-
-doctype html
-html(ng-app='ignite-web-control-center', ng-init='user = #{JSON.stringify(user)}; becomeUsed = #{becomeUsed}')
- head
- title= title
-
- block css
- // Bootstrap
- link(rel='stylesheet', href='//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.css')
-
- // Font Awesome Icons
- link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.css')
-
- // Font
- link(rel='stylesheet', href='//fonts.googleapis.com/css?family=Roboto+Slab:700:serif|Roboto+Slab:400:serif')
-
- link(rel='stylesheet', href='/stylesheets/style.css')
-
- block scripts
- script(src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js')
-
- script(src='//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js')
-
- script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.js')
- script(src='//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular-sanitize.js')
- script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.js')
- script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.tpl.min.js')
-
- script(src='//cdnjs.cloudflare.com/ajax/libs/angular-smart-table/2.0.3/smart-table.js')
-
- script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js')
- script(src='//angular-ui.github.io/ui-ace/dist/ui-ace.min.js')
-
- script(src='/common-module.js')
- script(src='/data-structures.js')
-
- body.theme-line.body-overlap
- .wrapper
- include ../includes/header
-
- block main-container
- .container.body-container
- .main-content
- block container
-
- include ../includes/footer
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/nodejs/views/templates/select.jade
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/views/templates/select.jade b/modules/web-control-center/nodejs/views/templates/select.jade
deleted file mode 100644
index 10c1946..0000000
--- a/modules/web-control-center/nodejs/views/templates/select.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.
-
-ul.select.dropdown-menu(tabindex='-1', ng-show='$isVisible()', role='select')
- li(role='presentation', ng-repeat='match in $matches')
- hr(ng-if='match.value == undefined' style='margin: 5px 0')
- a(style='cursor: default; padding: 3px 6px;', role='menuitem', tabindex='-1', ng-class='{active: $isActive($index)}' ng-click='$select($index, $event)')
- i(class='{{$iconCheckmark}}', ng-if='$isActive($index)' ng-class='{active: $isActive($index)}' style='color: #ec1c24; margin-left: 15px; line-height: 20px; float: right;background-color: transparent;')
- span(ng-bind='match.label')
- li(ng-if='$showAllNoneButtons || ($isMultiple && $matches.length > 5)')
- hr(style='margin: 5px 0')
- a(ng-click='$selectAll()') {{$allText}}
- a(ng-click='$selectNone()') {{$noneText}}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/.gitignore
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/.gitignore b/modules/web-control-center/src/main/js/.gitignore
new file mode 100644
index 0000000..65f2596
--- /dev/null
+++ b/modules/web-control-center/src/main/js/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+*.idea
+*.log
+*.css
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/DEVNOTES.txt b/modules/web-control-center/src/main/js/DEVNOTES.txt
new file mode 100644
index 0000000..aa56011
--- /dev/null
+++ b/modules/web-control-center/src/main/js/DEVNOTES.txt
@@ -0,0 +1,21 @@
+Ignite Web Control Center Instructions
+======================================
+
+How to deploy:
+
+1. Install locally NodeJS using installer from site https://nodejs.org for your OS.
+2. Install locally MongoDB folow instructions from site http://docs.mongodb.org/manual/installation
+3. Checkout ignite-843 branch.
+4. Change directory '$IGNITE_HOME/modules/web-control-center/nodejs'.
+5. Run "npm install" in terminal for download all dependencies.
+
+Steps 1 - 5 should be executed once.
+
+How to run:
+
+1. Run MongoDB.
+ 1.1 In terminal change dir to $MONGO_ISNTALL_DIR/server/3.0/bin.
+ 1.2 Run "mongod".
+2. In new terminal change directory '$IGNITE_HOME/modules/web-control-center/nodejs'.
+3. Start application by executing "npm start".
+4. In browser open: http://localhost:3000
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/app.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/app.js b/modules/web-control-center/src/main/js/app.js
new file mode 100644
index 0000000..8c347db
--- /dev/null
+++ b/modules/web-control-center/src/main/js/app.js
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+var flash = require('connect-flash');
+var express = require('express');
+var path = require('path');
+var favicon = require('serve-favicon');
+var logger = require('morgan');
+var cookieParser = require('cookie-parser');
+var bodyParser = require('body-parser');
+var session = require('express-session');
+var mongoStore = require('connect-mongo')(session);
+
+var publicRoutes = require('./routes/public');
+var clustersRouter = require('./routes/clusters');
+var cachesRouter = require('./routes/caches');
+var metadataRouter = require('./routes/metadata');
+var summary = require('./routes/summary');
+var adminRouter = require('./routes/admin');
+var profileRouter = require('./routes/profile');
+var sqlRouter = require('./routes/sql');
+
+var passport = require('passport');
+
+var db = require('./db');
+
+var app = express();
+
+// Views engine setup.
+app.set('views', path.join(__dirname, 'views'));
+app.set('view engine', 'jade');
+
+// Site favicon.
+app.use(favicon(__dirname + '/public/favicon.ico'));
+
+app.use(logger('dev'));
+
+app.use(bodyParser.json());
+app.use(bodyParser.urlencoded({extended: false}));
+
+app.use(require('less-middleware')(path.join(__dirname, 'public'), {
+ render: {
+ compress: false
+ }
+}));
+
+app.use(express.static(path.join(__dirname, 'public')));
+app.use(express.static(path.join(__dirname, 'controllers')));
+app.use(express.static(path.join(__dirname, 'helpers')));
+
+app.use(cookieParser('keyboard cat'));
+
+app.use(session({
+ secret: 'keyboard cat',
+ resave: false,
+ saveUninitialized: true,
+ store: new mongoStore({
+ mongooseConnection: db.mongoose.connection
+ })
+}));
+
+app.use(flash());
+
+app.use(passport.initialize());
+app.use(passport.session());
+
+passport.serializeUser(db.Account.serializeUser());
+passport.deserializeUser(db.Account.deserializeUser());
+
+passport.use(db.Account.createStrategy());
+
+var mustAuthenticated = function (req, res, next) {
+ req.isAuthenticated() ? next() : res.redirect('/');
+};
+
+var adminOnly = function(req, res, next) {
+ req.isAuthenticated() && req.user.admin ? next() : res.sendStatus(403);
+};
+
+app.all('/configuration/*', mustAuthenticated);
+
+app.all('*', function(req, res, next) {
+ var becomeUsed = req.session.viewedUser && req.user.admin;
+
+ res.locals.user = becomeUsed ? req.session.viewedUser : req.user;
+ res.locals.becomeUsed = becomeUsed;
+
+ req.currentUserId = function() {
+ if (!req.user)
+ return null;
+
+ if (req.session.viewedUser && req.user.admin)
+ return req.session.viewedUser._id;
+
+ return req.user._id;
+ };
+
+ next();
+});
+
+app.use('/', publicRoutes);
+app.use('/admin', mustAuthenticated, adminOnly, adminRouter);
+app.use('/profile', mustAuthenticated, profileRouter);
+
+app.use('/configuration/clusters', clustersRouter);
+app.use('/configuration/caches', cachesRouter);
+app.use('/configuration/metadata', metadataRouter);
+app.use('/configuration/summary', summary);
+app.use('/sql', sqlRouter);
+
+// Catch 404 and forward to error handler.
+app.use(function (req, res, next) {
+ var err = new Error('Not Found: ' + req.originalUrl);
+ err.status = 404;
+ next(err);
+});
+
+// Error handlers.
+
+// Development error handler: will print stacktrace.
+if (app.get('env') === 'development') {
+ app.use(function (err, req, res) {
+ res.status(err.status || 500);
+ res.render('error', {
+ message: err.message,
+ error: err
+ });
+ });
+}
+
+// Production error handler: no stacktraces leaked to user.
+app.use(function (err, req, res) {
+ res.status(err.status || 500);
+ res.render('error', {
+ message: err.message,
+ error: {}
+ });
+});
+
+module.exports = app;
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/bin/www
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/bin/www b/modules/web-control-center/src/main/js/bin/www
new file mode 100644
index 0000000..4cf0583
--- /dev/null
+++ b/modules/web-control-center/src/main/js/bin/www
@@ -0,0 +1,85 @@
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+var app = require('../app');
+var config = require('../helpers/configuration-loader.js');
+var debug = require('debug')('ignite-web-control-center:server');
+var http = require('http');
+
+/**
+ * Get port from environment and store in Express.
+ */
+var port = normalizePort(process.env.PORT || config.get('express:port'));
+app.set('port', port);
+
+/**
+ * Create HTTP server.
+ */
+var server = http.createServer(app);
+
+/**
+ * Listen on provided port, on all network interfaces.
+ */
+server.listen(port);
+server.on('error', onError);
+server.on('listening', onListening);
+
+/**
+ * Normalize a port into a number, string, or false.
+ */
+function normalizePort(val) {
+ var port = parseInt(val, 10);
+
+ if (isNaN(port)) {
+ // named pipe
+ return val;
+ }
+
+ if (port >= 0) {
+ // port number
+ return port;
+ }
+
+ return false;
+}
+
+/**
+ * Event listener for HTTP server "error" event.
+ */
+function onError(error) {
+ if (error.syscall !== 'listen') {
+ throw error;
+ }
+
+ var bind = typeof port === 'string'
+ ? 'Pipe ' + port
+ : 'Port ' + port;
+
+ // handle specific listen errors with friendly messages
+ switch (error.code) {
+ case 'EACCES':
+ console.error(bind + ' requires elevated privileges');
+ process.exit(1);
+ break;
+ case 'EADDRINUSE':
+ console.error(bind + ' is already in use');
+ process.exit(1);
+ break;
+ default:
+ throw error;
+ }
+}
+
+/**
+ * Event listener for HTTP server "listening" event.
+ */
+function onListening() {
+ var addr = server.address();
+ var bind = typeof addr === 'string'
+ ? 'pipe ' + addr
+ : 'port ' + addr.port;
+
+ debug('Listening on ' + bind);
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/config/default.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/config/default.json b/modules/web-control-center/src/main/js/config/default.json
new file mode 100644
index 0000000..72dbd4e
--- /dev/null
+++ b/modules/web-control-center/src/main/js/config/default.json
@@ -0,0 +1,8 @@
+{
+ "express": {
+ "port": 3000
+ },
+ "mongoDB": {
+ "url": "mongodb://localhost/web-control-center"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/admin-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/admin-controller.js b/modules/web-control-center/src/main/js/controllers/admin-controller.js
new file mode 100644
index 0000000..09490fe
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/admin-controller.js
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+controlCenterModule.controller('adminController', ['$scope', '$http', '$common', '$confirm', function ($scope, $http, $common, $confirm) {
+ $scope.users = null;
+
+ function reload() {
+ $http.post('admin/list')
+ .success(function (data) {
+ $scope.users = data;
+ })
+ .error(function (errMsg) {
+ $common.showError($common.errorMessage(errMsg));
+ });
+ }
+
+ reload();
+
+ $scope.removeUser = function (user) {
+ $confirm.show('Are you sure you want to remove user: "' + user.username + '"?').then(function () {
+ $http.post('admin/remove', {userId: user._id}).success(
+ function () {
+ var i = _.findIndex($scope.users, function (u) {
+ return u._id == user._id;
+ });
+
+ if (i >= 0)
+ $scope.users.splice(i, 1);
+
+ $common.showInfo('User has been removed: "' + user.username + '"');
+ }).error(function (errMsg) {
+ $common.showError('Failed to remove user: "' + $common.errorMessage(errMsg) + '"');
+ });
+ });
+ };
+
+ $scope.toggleAdmin = function (user) {
+ if (user.adminChanging)
+ return;
+
+ user.adminChanging = true;
+
+ $http.post('admin/save', {userId: user._id, adminFlag: user.admin}).success(
+ function () {
+ $common.showInfo('Admin right was successfully toggled for user: "' + user.username + '"');
+
+ user.adminChanging = false;
+ }).error(function (errMsg) {
+ $common.showError('Failed to toggle admin right for user: "' + $common.errorMessage(errMsg) + '"');
+
+ user.adminChanging = false;
+ });
+ }
+}]);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/cache-viewer-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/cache-viewer-controller.js b/modules/web-control-center/src/main/js/controllers/cache-viewer-controller.js
new file mode 100644
index 0000000..6e0c130
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/cache-viewer-controller.js
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+var demoResults = [
+ {
+ id: 256,
+ s: 'com.foo.User@3213',
+ fields: {
+ id: 256,
+ firstName: 'Ivan',
+ lastName: 'Ivanov',
+ old: 23
+ }
+ },
+
+ {
+ id: 384,
+ s: 'com.foo.User@23214',
+ fields: {
+ id: 384,
+ firstName: 'Sergey',
+ lastName: 'Petrov',
+ old: 28
+ }
+ },
+
+ {
+ id: 923,
+ s: 'com.foo.User@93494',
+ fields: {
+ id: 923,
+ firstName: 'Andrey',
+ lastName: 'Sidorov',
+ old: 28
+ }
+ }
+];
+
+var demoCaches = ['Users', 'Organizations', 'Cities'];
+
+controlCenterModule.controller('cacheViewerController', ['$scope', '$http', '$common', function ($scope, $http, $common) {
+ $scope.results = demoResults;
+
+ $scope.caches = demoCaches;
+
+ $scope.defCache = $scope.caches.length > 0 ? $scope.caches[0] : null;
+
+ var sqlEditor = ace.edit('querySql');
+
+ sqlEditor.setOptions({
+ highlightActiveLine: false,
+ showPrintMargin: false,
+ showGutter: true,
+ theme: "ace/theme/chrome",
+ mode: "ace/mode/sql",
+ fontSize: 14
+ });
+
+ sqlEditor.setValue("select u.id from User u where u.name like 'aaaa';");
+
+ sqlEditor.selection.clearSelection()
+
+}]);
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/caches-controller.js b/modules/web-control-center/src/main/js/controllers/caches-controller.js
new file mode 100644
index 0000000..0c23e3b
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/caches-controller.js
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ */
+
+controlCenterModule.controller('cachesController', ['$scope', '$http', '$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, $confirm, $copy, $table) {
+ $scope.joinTip = $common.joinTip;
+ $scope.getModel = $common.getModel;
+
+ $scope.tableNewItem = $table.tableNewItem;
+ $scope.tableNewItemActive = $table.tableNewItemActive;
+ $scope.tableEditing = $table.tableEditing;
+ $scope.tableStartEdit = $table.tableStartEdit;
+ $scope.tableRemove = $table.tableRemove;
+
+ $scope.tableSimpleSave = $table.tableSimpleSave;
+ $scope.tableSimpleSaveVisible = $table.tableSimpleSaveVisible;
+ $scope.tableSimpleUp = $table.tableSimpleUp;
+ $scope.tableSimpleDown = $table.tableSimpleDown;
+ $scope.tableSimpleDownVisible = $table.tableSimpleDownVisible;
+
+ $scope.tablePairSave = $table.tablePairSave;
+ $scope.tablePairSaveVisible = $table.tablePairSaveVisible;
+
+ $scope.atomicities = [
+ {value: 'ATOMIC', label: 'ATOMIC'},
+ {value: 'TRANSACTIONAL', label: 'TRANSACTIONAL'}
+ ];
+
+ $scope.modes = [
+ {value: 'PARTITIONED', label: 'PARTITIONED'},
+ {value: 'REPLICATED', label: 'REPLICATED'},
+ {value: 'LOCAL', label: 'LOCAL'}
+ ];
+
+ $scope.atomicWriteOrderModes = [
+ {value: 'CLOCK', label: 'CLOCK'},
+ {value: 'PRIMARY', label: 'PRIMARY'}
+ ];
+
+ $scope.memoryModes = [
+ {value: 'ONHEAP_TIERED', label: 'ONHEAP_TIERED'},
+ {value: 'OFFHEAP_TIERED', label: 'OFFHEAP_TIERED'},
+ {value: 'OFFHEAP_VALUES', label: 'OFFHEAP_VALUES'}
+ ];
+
+ $scope.evictionPolicies = [
+ {value: 'LRU', label: 'LRU'},
+ {value: 'RND', label: 'Random'},
+ {value: 'FIFO', label: 'FIFO'},
+ {value: 'SORTED', label: 'Sorted'},
+ {value: undefined, label: 'Not set'}
+ ];
+
+ $scope.rebalanceModes = [
+ {value: 'SYNC', label: 'SYNC'},
+ {value: 'ASYNC', label: 'ASYNC'},
+ {value: 'NONE', label: 'NONE'}
+ ];
+
+ $scope.cacheStoreFactories = [
+ {value: 'CacheJdbcPojoStoreFactory', label: 'JDBC POJO store factory'},
+ {value: 'CacheJdbcBlobStoreFactory', label: 'JDBC BLOB store factory'},
+ {value: 'CacheHibernateBlobStoreFactory', label: 'Hibernate BLOB store factory'},
+ {value: undefined, label: 'Not set'}
+ ];
+
+ $scope.cacheStoreJdbcDialects = [
+ {value: 'Oracle', label: 'Oracle'},
+ {value: 'DB2', label: 'IBM DB2'},
+ {value: 'SQLServer', label: 'Microsoft SQL Server'},
+ {value: 'MySQL', label: 'My SQL'},
+ {value: 'PostgreSQL', label: 'Postgre SQL'},
+ {value: 'H2', label: 'H2 database'}
+ ];
+
+ $scope.general = [];
+ $scope.advanced = [];
+
+ $http.get('/models/caches.json')
+ .success(function (data) {
+ $scope.screenTip = data.screenTip;
+ $scope.general = data.general;
+ $scope.advanced = data.advanced;
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+
+ $scope.caches = [];
+
+ $scope.required = function (field) {
+ var model = $common.isDefined(field.path) ? field.path + '.' + field.model : field.model;
+
+ var backupItem = $scope.backupItem;
+
+ var memoryMode = backupItem.memoryMode;
+
+ var onHeapTired = memoryMode == 'ONHEAP_TIERED';
+ var offHeapTired = memoryMode == 'OFFHEAP_TIERED';
+
+ var offHeapMaxMemory = backupItem.offHeapMaxMemory;
+
+ if (model == 'offHeapMaxMemory' && offHeapTired)
+ return true;
+
+ if (model == 'evictionPolicy.kind' && onHeapTired)
+ return backupItem.swapEnabled || ($common.isDefined(offHeapMaxMemory) && offHeapMaxMemory >= 0);
+
+ return false;
+ };
+
+ $scope.tableSimpleValid = function (item, field, fx, index) {
+ var model = item[field.model];
+
+ if ($common.isDefined(model)) {
+ var idx = _.indexOf(model, fx);
+
+ // Found itself.
+ if (index >= 0 && index == idx)
+ return true;
+
+ // Found duplicate.
+ if (idx >= 0) {
+ $common.showError('SQL function such class name already exists!');
+
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ $scope.tablePairValid = function (item, field, keyCls, valCls, index) {
+ var model = item[field.model];
+
+ if ($common.isDefined(model)) {
+ var idx = _.findIndex(model, function (pair) {
+ return pair.keyClass == keyCls
+ });
+
+ // Found itself.
+ if (index >= 0 && index == idx)
+ return true;
+
+ // Found duplicate.
+ if (idx >= 0) {
+ $common.showError('Indexed type with such key class already exists!');
+
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ // When landing on the page, get caches and show them.
+ $http.post('caches/list')
+ .success(function (data) {
+ $scope.spaces = data.spaces;
+ $scope.caches = data.caches;
+
+ var restoredItem = angular.fromJson(sessionStorage.cacheBackupItem);
+
+ if (restoredItem) {
+ if (restoredItem._id) {
+ var idx = _.findIndex($scope.caches, function (cache) {
+ return cache._id == restoredItem._id;
+ });
+
+ if (idx >= 0) {
+ $scope.selectedItem = $scope.caches[idx];
+ $scope.backupItem = restoredItem;
+ }
+ else
+ sessionStorage.removeItem('cacheBackupItem');
+ }
+ else
+ $scope.backupItem = restoredItem;
+ }
+ else if ($scope.caches.length > 0)
+ $scope.selectItem($scope.caches[0]);
+
+ $scope.$watch('backupItem', function (val) {
+ if (val)
+ sessionStorage.cacheBackupItem = angular.toJson(val);
+ }, true);
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+
+ $scope.selectItem = function (item) {
+ $table.tableReset();
+
+ $scope.selectedItem = item;
+ $scope.backupItem = angular.copy(item);
+ };
+
+ // Add new cache.
+ $scope.createItem = function () {
+ $table.tableReset();
+
+ $scope.backupItem = {mode: 'PARTITIONED', atomicityMode: 'ATOMIC', readFromBackup: true, copyOnRead: true};
+ $scope.backupItem.space = $scope.spaces[0]._id;
+ };
+
+ // Check cache logical consistency.
+ function validate(item) {
+ var cacheStoreFactorySelected = item.cacheStoreFactory && item.cacheStoreFactory.kind;
+
+ if (cacheStoreFactorySelected && !(item.readThrough || item.writeThrough)) {
+ $common.showError('Store is configured but read/write through are not enabled!');
+
+ return false;
+ }
+
+ if ((item.readThrough || item.writeThrough) && !cacheStoreFactorySelected) {
+ $common.showError('Read / write through are enabled but store is not configured!');
+
+ return false;
+ }
+
+ if (item.writeBehindEnabled && !cacheStoreFactorySelected) {
+ $common.showError('Write behind enabled but store is not configured!');
+
+ return false;
+ }
+
+ return true;
+ }
+
+ // Save cache into database.
+ function save(item) {
+ $http.post('caches/save', item)
+ .success(function (_id) {
+ var idx = _.findIndex($scope.caches, function (cache) {
+ return cache._id == _id;
+ });
+
+ if (idx >= 0)
+ angular.extend($scope.caches[idx], item);
+ else {
+ item._id = _id;
+
+ $scope.caches.push(item);
+ }
+
+ $scope.selectItem(item);
+
+ $common.showInfo('Cache "' + item.name + '" saved.');
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+ }
+
+ // Save cache.
+ $scope.saveItem = function () {
+ $table.tableReset();
+
+ var item = $scope.backupItem;
+
+ if (validate(item))
+ save(item);
+ };
+
+ // Save cache with new name.
+ $scope.saveItemAs = function () {
+ $table.tableReset();
+
+ if (validate($scope.backupItem))
+ $copy.show($scope.backupItem.name).then(function (newName) {
+ var item = angular.copy($scope.backupItem);
+
+ item._id = undefined;
+ item.name = newName;
+
+ save(item);
+ });
+ };
+
+ // Remove cache from db.
+ $scope.removeItem = function () {
+ $table.tableReset();
+
+ var selectedItem = $scope.selectedItem;
+
+ $confirm.show('Are you sure you want to remove cache: "' + selectedItem.name + '"?').then(
+ function () {
+ var _id = selectedItem._id;
+
+ $http.post('caches/remove', {_id: _id})
+ .success(function () {
+ $common.showInfo('Cache has been removed: ' + selectedItem.name);
+
+ var caches = $scope.caches;
+
+ var idx = _.findIndex(caches, function (cache) {
+ return cache._id == _id;
+ });
+
+ if (idx >= 0) {
+ caches.splice(idx, 1);
+
+ if (caches.length > 0)
+ $scope.selectItem(caches[0]);
+ else {
+ $scope.selectedItem = undefined;
+ $scope.backupItem = undefined;
+ }
+ }
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+ }
+ );
+ };
+ }]
+);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/controllers/clusters-controller.js b/modules/web-control-center/src/main/js/controllers/clusters-controller.js
new file mode 100644
index 0000000..1ec78a1
--- /dev/null
+++ b/modules/web-control-center/src/main/js/controllers/clusters-controller.js
@@ -0,0 +1,309 @@
+/*
+ * 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.
+ */
+
+controlCenterModule.controller('clustersController', ['$scope', '$http', '$common', '$confirm', '$copy', '$table', function ($scope, $http, $common, $confirm, $copy, $table) {
+ $scope.joinTip = $common.joinTip;
+ $scope.getModel = $common.getModel;
+
+ $scope.tableNewItem = $table.tableNewItem;
+ $scope.tableNewItemActive = $table.tableNewItemActive;
+ $scope.tableEditing = $table.tableEditing;
+ $scope.tableStartEdit = $table.tableStartEdit;
+ $scope.tableRemove = $table.tableRemove;
+
+ $scope.tableSimpleSave = $table.tableSimpleSave;
+ $scope.tableSimpleSaveVisible = $table.tableSimpleSaveVisible;
+ $scope.tableSimpleUp = $table.tableSimpleUp;
+ $scope.tableSimpleDown = $table.tableSimpleDown;
+ $scope.tableSimpleDownVisible = $table.tableSimpleDownVisible;
+
+ $scope.templates = [
+ {
+ value: {discovery: {kind: 'Multicast', Vm: {addresses: ['127.0.0.1:47500..47510']}, Multicast: {}}},
+ label: 'multicast'
+ },
+ {value: {discovery: {kind: 'Vm', Vm: {addresses: ['127.0.0.1:47500..47510']}}}, label: 'local'}
+ ];
+
+ $scope.discoveries = [
+ {value: 'Vm', label: 'static IPs'},
+ {value: 'Multicast', label: 'multicast'},
+ {value: 'S3', label: 'AWS S3'},
+ {value: 'Cloud', label: 'apache jclouds'},
+ {value: 'GoogleStorage', label: 'google cloud storage'},
+ {value: 'Jdbc', label: 'JDBC'},
+ {value: 'SharedFs', label: 'shared filesystem'}
+ ];
+
+ $scope.swapSpaceSpis = [
+ {value: 'FileSwapSpaceSpi', label: 'File-based swap'},
+ {value: undefined, label: 'Not set'}
+ ];
+
+ $scope.events = [];
+
+ for (var eventGroupName in eventGroups) {
+ if (eventGroups.hasOwnProperty(eventGroupName)) {
+ $scope.events.push({value: eventGroupName, label: eventGroupName});
+ }
+ }
+
+ $scope.cacheModes = [
+ {value: 'LOCAL', label: 'LOCAL'},
+ {value: 'REPLICATED', label: 'REPLICATED'},
+ {value: 'PARTITIONED', label: 'PARTITIONED'}
+ ];
+
+ $scope.deploymentModes = [
+ {value: 'PRIVATE', label: 'PRIVATE'},
+ {value: 'ISOLATED', label: 'ISOLATED'},
+ {value: 'SHARED', label: 'SHARED'},
+ {value: 'CONTINUOUS', label: 'CONTINUOUS'}
+ ];
+
+ $scope.transactionConcurrency = [
+ {value: 'OPTIMISTIC', label: 'OPTIMISTIC'},
+ {value: 'PESSIMISTIC', label: 'PESSIMISTIC'}
+ ];
+
+ $scope.transactionIsolation = [
+ {value: 'READ_COMMITTED', label: 'READ_COMMITTED'},
+ {value: 'REPEATABLE_READ', label: 'REPEATABLE_READ'},
+ {value: 'SERIALIZABLE', label: 'SERIALIZABLE'}
+ ];
+
+ $scope.segmentationPolicy = [
+ {value: 'RESTART_JVM', label: 'RESTART_JVM'},
+ {value: 'STOP', label: 'STOP'},
+ {value: 'NOOP', label: 'NOOP'}
+ ];
+
+ $scope.marshallers = [
+ {value: 'OptimizedMarshaller', label: 'OptimizedMarshaller'},
+ {value: 'JdkMarshaller', label: 'JdkMarshaller'}
+ ];
+
+ $scope.tableSimpleValid = function (item, field, val, index) {
+ var model = $common.getModel(item, field)[field.model];
+
+ if ($common.isDefined(model)) {
+ var idx = _.indexOf(model, val);
+
+ // Found itself.
+ if (index >= 0 && index == idx)
+ return true;
+
+ // Found duplicate.
+ if (idx >= 0) {
+ var msg = 'Such IP address already exists!';
+
+ if (field.model == 'regions')
+ msg = 'Such region already exists!';
+ if (field.model == 'zones')
+ msg = 'Such zone already exists!';
+
+ $common.showError(msg);
+
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ $scope.clusters = [];
+
+ $http.get('/models/clusters.json')
+ .success(function (data) {
+ $scope.screenTip = data.screenTip;
+ $scope.templateTip = data.templateTip;
+
+ $scope.general = data.general;
+ $scope.advanced = data.advanced;
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+
+ // When landing on the page, get clusters and show them.
+ $http.post('clusters/list')
+ .success(function (data) {
+ $scope.caches = data.caches;
+ $scope.spaces = data.spaces;
+ $scope.clusters = data.clusters;
+
+ var restoredItem = angular.fromJson(sessionStorage.clusterBackupItem);
+
+ if (restoredItem) {
+ if (restoredItem._id) {
+ var idx = _.findIndex($scope.clusters, function (cluster) {
+ return cluster._id == restoredItem._id;
+ });
+
+ if (idx >= 0) {
+ $scope.selectedItem = $scope.clusters[idx];
+ $scope.backupItem = restoredItem;
+ }
+ else
+ sessionStorage.removeItem('clusterBackupItem');
+ }
+ else
+ $scope.backupItem = restoredItem;
+ }
+ else if ($scope.clusters.length > 0)
+ $scope.selectItem($scope.clusters[0]);
+
+ $scope.$watch('backupItem', function (val) {
+ if (val)
+ sessionStorage.clusterBackupItem = angular.toJson(val);
+ }, true);
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+
+ $scope.selectItem = function (item) {
+ $table.tableReset();
+
+ $scope.selectedItem = item;
+ $scope.backupItem = angular.copy(item);
+ };
+
+ // Add new cluster.
+ $scope.createItem = function () {
+ $table.tableReset();
+
+ $scope.backupItem = angular.copy($scope.create.template);
+ $scope.backupItem.space = $scope.spaces[0]._id;
+ };
+
+ $scope.indexOfCache = function (cacheId) {
+ return _.findIndex($scope.caches, function (cache) {
+ return cache.value == cacheId;
+ });
+ };
+
+ // Check cluster logical consistency.
+ function validate(item) {
+ if (!item.swapSpaceSpi || !item.swapSpaceSpi.kind && item.caches) {
+ for (var i = 0; i < item.caches.length; i++) {
+ var idx = $scope.indexOfCache(item.caches[i]);
+
+ if (idx >= 0) {
+ var cache = $scope.caches[idx];
+
+ if (cache.swapEnabled) {
+ $common.showError('Swap space SPI is not configured, but cache "' + cache.label + '" configured to use swap!');
+
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ // Save cluster in database.
+ function save(item) {
+ $http.post('clusters/save', item)
+ .success(function (_id) {
+ var idx = _.findIndex($scope.clusters, function (cluster) {
+ return cluster._id == _id;
+ });
+
+ if (idx >= 0)
+ angular.extend($scope.clusters[idx], item);
+ else {
+ item._id = _id;
+
+ $scope.clusters.push(item);
+ }
+
+ $scope.selectItem(item);
+
+ $common.showInfo('Cluster "' + item.name + '" saved.');
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+ }
+
+ // Save cluster.
+ $scope.saveItem = function () {
+ $table.tableReset();
+
+ var item = $scope.backupItem;
+
+ if (validate(item))
+ save(item);
+ };
+
+ // Save cluster with new name.
+ $scope.saveItemAs = function () {
+ $table.tableReset();
+
+ if (validate($scope.backupItem))
+ $copy.show($scope.backupItem.name).then(function (newName) {
+ var item = angular.copy($scope.backupItem);
+
+ item._id = undefined;
+ item.name = newName;
+
+ save(item);
+ });
+ };
+
+ // Remove cluster from db.
+ $scope.removeItem = function () {
+ $table.tableReset();
+
+ var selectedItem = $scope.selectedItem;
+
+ $confirm.show('Are you sure you want to remove cluster: "' + selectedItem.name + '"?').then(
+ function () {
+ var _id = selectedItem._id;
+
+ $http.post('clusters/remove', {_id: _id})
+ .success(function () {
+ $common.showInfo('Cluster has been removed: ' + selectedItem.name);
+
+ var clusters = $scope.clusters;
+
+ var idx = _.findIndex(clusters, function (cluster) {
+ return cluster._id == _id;
+ });
+
+ if (idx >= 0) {
+ clusters.splice(idx, 1);
+
+ if (clusters.length > 0)
+ $scope.selectItem(clusters[0]);
+ else {
+ $scope.selectedItem = undefined;
+ $scope.backupItem = undefined;
+ }
+ }
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+ }
+ );
+ };
+ }]
+);
\ No newline at end of file