http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.directive.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.directive.js b/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.directive.js new file mode 100644 index 0000000..79787a2 --- /dev/null +++ b/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.directive.js @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import template from './ui-ace-xml.jade!'; +import controller from './ui-ace-xml.controller'; + +export default ['igniteUiAceXml', ['GeneratorXml', (generator) => { + const link = (scope, $el, attrs, [ctrl, igniteUiAceTabs, formCtrl, ngModelCtrl]) => { + if (formCtrl && ngModelCtrl) + formCtrl.$removeControl(ngModelCtrl); + + if (igniteUiAceTabs && igniteUiAceTabs.onLoad) { + scope.onLoad = (editor) => { + igniteUiAceTabs.onLoad(editor); + + scope.$watch('master', () => editor.attractAttention = false); + }; + } + + if (igniteUiAceTabs && igniteUiAceTabs.onChange) + scope.onChange = igniteUiAceTabs.onChange; + + const render = (data) => { + delete ctrl.data; + + if (!data) + return; + + return ctrl.generator(scope.master); + }; + + // Setup generator. + if (scope.generator) { + const method = scope.generator; + + switch (method) { + case 'clusterCaches': + ctrl.generator = (cluster) => { + const caches = _.reduce(scope.detail, (acc, cache) => { + if (_.includes(cluster.caches, cache.value)) + acc.push(cache.cache); + + return acc; + }, []); + + return generator.clusterCaches(caches, null, true, generator.clusterGeneral(cluster)).asString(); + }; + + break; + + case 'igfss': + ctrl.generator = (cluster) => { + const igfss = _.reduce(scope.detail, (acc, igfs) => { + if (_.includes(cluster.igfss, igfs.value)) + acc.push(igfs.igfs); + + return acc; + }, []); + + return generator.igfss(igfss).asString(); + }; + + break; + + case 'cacheStore': + ctrl.generator = (cache) => { + const domains = _.reduce(scope.detail, (acc, domain) => { + if (_.includes(cache.domains, domain.value)) + acc.push(domain.meta); + + return acc; + }, []); + + return generator.cacheStore(cache, domains).asString(); + }; + + break; + + default: + ctrl.generator = (data) => generator[method](data).asString(); + } + } + + if (typeof attrs.clusterCfg !== 'undefined') { + scope.$watch('cfg', (cfg) => { + if (typeof cfg !== 'undefined') + return; + + scope.cfg = {}; + }); + + scope.$watch('cfg', (data) => ctrl.data = render(data), true); + } + + const noDeepWatch = !(typeof attrs.noDeepWatch !== 'undefined'); + + // Setup watchers. + scope.$watch('master', (data) => ctrl.data = render(data), noDeepWatch); + }; + + return { + priority: 1, + restrict: 'E', + scope: { + master: '=', + detail: '=', + generator: '@', + cfg: '=?clusterCfg' + }, + bindToController: { + data: '=?ngModel' + }, + link, + template, + controller, + controllerAs: 'ctrl', + require: ['igniteUiAceXml', '?^igniteUiAceTabs', '?^form', '?ngModel'] + }; +}]];
http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.jade b/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.jade new file mode 100644 index 0000000..0dd627a --- /dev/null +++ b/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.jade @@ -0,0 +1,17 @@ +//- + 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. + +div(ng-if='ctrl.data' ignite-ace='{onLoad: onLoad, onChange: onChange, mode: "xml"}' ng-model='ctrl.data') http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/filters/byName.filter.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/filters/byName.filter.js b/modules/web-console/src/main/js/app/filters/byName.filter.js new file mode 100644 index 0000000..3b0746f --- /dev/null +++ b/modules/web-console/src/main/js/app/filters/byName.filter.js @@ -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. + */ + +export default ['byName', [() => (arr, search) => { + if (!(arr && arr.length) || !search) + return arr; + + return _.filter(arr, ({ name }) => name.indexOf(search) >= 0); +}]]; http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/filters/hasPojo.filter.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/filters/hasPojo.filter.js b/modules/web-console/src/main/js/app/filters/hasPojo.filter.js new file mode 100644 index 0000000..a179423 --- /dev/null +++ b/modules/web-console/src/main/js/app/filters/hasPojo.filter.js @@ -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. + */ + +export default ['hasPojo', [() => ({caches} = []) => _.find(caches, (cache) => cache.domains && cache.domains.length)]]; http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/helpers/jade/mixins.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/helpers/jade/mixins.jade b/modules/web-console/src/main/js/app/helpers/jade/mixins.jade new file mode 100644 index 0000000..341d351 --- /dev/null +++ b/modules/web-console/src/main/js/app/helpers/jade/mixins.jade @@ -0,0 +1,587 @@ +//- + 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 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}' 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(visible, errorMessage) + +error-feedback(visible, 'igniteUnique', errorMessage) + +//- Mixin for feedback on IP address violation. +mixin ipaddress-feedback(visible, name) + +error-feedback(visible, 'ipaddress', 'Invalid address!', name) + +//- Mixin for feedback on port of IP address violation. +mixin ipaddress-port-feedback(visible, name) + +error-feedback(visible, 'ipaddressPort', 'Invalid port!', name) + +//- Mixin for feedback on port range violation. +mixin ipaddress-port-range-feedback(visible, name) + +error-feedback(visible, 'ipaddressPortRange', 'Invalid port range!', name) + +//- Mixin for checkbox. +mixin checkbox(lbl, model, name, tip) + ignite-form-field.checkbox + ignite-form-field-input-checkbox( + data-id=name + data-name=name + data-ng-model=model + ) + | #{lbl} + ignite-form-field-tooltip + | !{tip} + +//- Mixin for checkbox with enabled condition. +mixin checkbox-enabled(lbl, model, name, enabled, tip) + ignite-form-field.checkbox + ignite-form-field-input-checkbox( + data-id=name + data-name=name + data-ng-model=model + data-ng-disabled='!(#{enabled})' + ) + | #{lbl} + ignite-form-field-tooltip + | !{tip} + +//- Mixin for java name field with enabled condition. +mixin java-class(lbl, model, name, enabled, required, tip) + -var errLbl = lbl.substring(0, lbl.length - 1) + + ignite-form-field + ignite-form-field-label + | #{lbl} + ignite-form-field-tooltip + | !{tip} + ignite-form-field-input-text( + data-id=name + data-name=name + data-ng-model=model + data-ng-disabled='!(#{enabled})' + data-ng-required=required + data-placeholder='Enter fully qualified class name' + + data-java-identifier='true' + data-java-package-specified='true' + data-java-keywords='true' + data-java-built-in-class='true' + ) + +error-feedback('form[ngModelName].$error.javaBuiltInClass', 'javaBuiltInClass', errLbl + ' should not be the Java built-in class!', name) + +error-feedback('form[ngModelName].$error.javaKeywords', 'javaKeywords', errLbl + ' could not contains reserved Java keyword!', name) + +error-feedback('form[ngModelName].$error.javaPackageSpecified', 'javaPackageSpecified', errLbl + ' does not have package specified!', name) + +error-feedback('form[ngModelName].$error.javaIdentifier', 'javaIdentifier', errLbl + ' is invalid Java identifier!', name) + +//- Mixin for text field with enabled condition with options. +mixin java-class-typeahead(lbl, model, name, options, enabled, required, placeholder, tip) + -var errLbl = lbl.substring(0, lbl.length - 1) + + ignite-form-field + ignite-form-field-label + | #{lbl} + ignite-form-field-tooltip + | !{tip} + ignite-form-field-input-datalist( + data-id=name + data-name=name + data-ng-model=model + data-options=options + data-placeholder=placeholder + data-ng-disabled='!(#{enabled})' + data-ng-required=required + + data-java-identifier='true' + data-java-package-specified='allow-built-in' + data-java-keywords='true' + ) + +error-feedback('form[ngModelName].$error.javaKeywords', 'javaKeywords', errLbl + ' could not contains reserved Java keyword!', name) + +error-feedback('form[ngModelName].$error.javaPackageSpecified', 'javaPackageSpecified', errLbl + ' does not have package specified!', name) + +error-feedback('form[ngModelName].$error.javaIdentifier', 'javaIdentifier', errLbl + ' is invalid Java identifier!', name) + +//- Mixin for text field with IP address check. +mixin text-ip-address(lbl, model, name, enabled, placeholder, tip) + ignite-form-field + ignite-form-field-label + | #{lbl} + ignite-form-field-tooltip + | !{tip} + ignite-form-field-input-text( + data-id=name + data-name=name + data-ng-model=model + data-ipaddress='true' + data-ng-disabled='!(#{enabled})' + data-placeholder=placeholder + ) + +ipaddress-feedback('form[ngModelName].$error.ipaddress', name) + + +//- Mixin for text field with IP address and port check. +mixin text-ip-address-with-port(lbl, model, name, enabled, placeholder, tip) + ignite-form-field + ignite-form-field-label + | #{lbl} + ignite-form-field-tooltip + | !{tip} + ignite-form-field-input-text( + data-id=name + data-name=name + data-ng-model=model + data-ipaddress='true' + data-ipaddress-with-port='true' + data-ng-disabled='!(#{enabled})' + data-placeholder=placeholder + ) + +ipaddress-feedback('form[ngModelName].$error.ipaddress', name) + +ipaddress-port-feedback('form[ngModelName].$error.ipaddressPort', name) + +//- Mixin for text field. +mixin text-enabled(lbl, model, name, enabled, required, placeholder, tip) + ignite-form-field + ignite-form-field-label + | #{lbl} + ignite-form-field-tooltip + | !{tip} + ignite-form-field-input-text( + data-id=name + data-name=name + data-ng-model=model + data-placeholder=placeholder + data-ng-disabled='!(#{enabled})' + data-ng-required=required + ) + +//- Mixin for text field. +mixin text(lbl, model, name, required, placeholder, tip) + +text-enabled(lbl, model, name, 'true', required, placeholder, tip) + +//- Mixin for text field with enabled condition with options. +mixin text-options(lbl, model, name, options, enabled, required, placeholder, tip) + ignite-form-field + ignite-form-field-label + | #{lbl} + ignite-form-field-tooltip + | !{tip} + ignite-form-field-input-datalist( + data-id=name + data-name=name + data-ng-model=model + data-options=options + data-placeholder=placeholder + data-ng-disabled='!(#{enabled})' + data-ng-required=required + ) + +//- Mixin for required numeric field. +mixin number-required(lbl, model, name, enabled, required, placeholder, min, tip) + ignite-form-field + ignite-form-field-label + | #{lbl} + ignite-form-field-tooltip + | !{tip} + ignite-form-field-input-number( + data-id=name + data-name=name + data-ng-model=model + data-ng-required=required + data-ng-disabled='!(#{enabled})' + data-placeholder=placeholder + data-min=min + ) + +//- Mixin for required numeric field with maximum and minimum limit. +mixin number-min-max(lbl, model, name, enabled, placeholder, min, max, tip) + +number-min-max-step(lbl, model, name, enabled, 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 + ignite-form-field-label + | #{lbl} + ignite-form-field-tooltip + | !{tip} + ignite-form-field-input-number( + data-id=name + data-name=name + data-ng-model=model + data-ng-disabled='!(#{enabled})' + data-placeholder=placeholder + data-min=min + data-max=max + data-step=step + ) + +//- Mixin for numeric field. +mixin number(lbl, model, name, enabled, placeholder, min, tip) + +number-required(lbl, model, name, enabled, 'false', placeholder, min, tip) + +//- Mixin for required dropdown field. +mixin dropdown-required-empty(lbl, model, name, enabled, required, placeholder, placeholderEmpty, options, tip) + ignite-form-field + ignite-form-field-label + | #{lbl} + ignite-form-field-tooltip + | !{tip} + ignite-form-field-dropdown( + data-id=name + data-name=name + data-options=options + data-ng-model=model + data-ng-disabled='!(#{enabled})' + data-ng-required=required + data-placeholder='{{#{options}.length > 0 ? "#{placeholder}" : "#{placeholderEmpty}"}}' + ) + +//- Mixin for required dropdown field. +mixin dropdown-required(lbl, model, name, enabled, required, placeholder, options, tip) + ignite-form-field + ignite-form-field-label + | #{lbl} + ignite-form-field-tooltip + | !{tip} + ignite-form-field-dropdown( + data-id=name + data-name=name + data-options=options + data-ng-model=model + data-ng-disabled='!(#{enabled})' + data-ng-required=required + data-placeholder=placeholder + ) + +//- Mixin for dropdown field. +mixin dropdown(lbl, model, name, enabled, placeholder, options, tip) + +dropdown-required(lbl, model, name, enabled, 'false', placeholder, options, tip) + +//- Mixin for dropdown-multiple field. +mixin dropdown-multiple(lbl, model, name, enabled, placeholder, placeholderEmpty, options, tip) + ignite-form-field + ignite-form-field-label + | !{lbl} + ignite-form-field-tooltip + | !{tip} + ignite-form-field-dropdown( + data-id=name + data-name=name + data-multiple='true' + data-options=options + data-ng-model=model + data-ng-disabled='!(#{enabled})' + data-placeholder='{{ #{options}.length > 0 ? "#{placeholder}" : "#{placeholderEmpty}" }}' + data-disabled='!#{options}.length' + ) + +//- Mixin for table text field. +mixin table-text-field(field, 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 + ';' + + ignite-form-field-input-text( + data-name=field + data-ng-model=field + data-ng-required='true' + data-placeholder=placeholder + data-ignite-unique=items + data-ignite-form-field-input-autofocus='true' + on-enter=onEnter + on-escape=onEscape + ng-blur=onBlur + ) + block + +//- Mixin for table java class field. +mixin table-java-class-field(lbl, field, 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 + ';' + + ignite-form-field-input-text( + data-name=field + data-ng-model=field + data-ng-required='true' + data-ignite-unique=items + data-ignite-form-field-input-autofocus='true' + + data-java-identifier='true' + data-java-package-specified='true' + data-java-keywords='true' + data-java-built-in-class='true' + + data-placeholder='Enter fully qualified class name' + + on-enter=onEnter + on-escape=onEscape + ng-blur=onBlur + ) + +error-feedback('form[ngModelName].$error.javaBuiltInClass', 'javaBuiltInClass', lbl + ' should not be the Java built-in class!') + +error-feedback('form[ngModelName].$error.javaKeywords', 'javaKeywords', lbl + ' could not contains reserved Java keyword!') + +error-feedback('form[ngModelName].$error.javaPackageSpecified', 'javaPackageSpecified', lbl + ' does not have package specified!') + +error-feedback('form[ngModelName].$error.javaIdentifier', 'javaIdentifier', lbl + ' is invalid Java identifier!') + + block + +//- Mixin for table java package field. +mixin table-java-package-field(field, 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 + ';' + + ignite-form-field-input-text( + data-name=field + data-ng-model=field + data-ng-required='true' + data-placeholder='Enter package name' + data-java-keywords='true' + data-java-package-name='true' + data-ignite-unique=items + data-ignite-form-field-input-autofocus='true' + on-enter=onEnter + on-escape=onEscape + ng-blur=onBlur + ) + block + +//- Mixin for table address field. +mixin table-address-field(field, 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 + ';' + + ignite-form-field-input-text( + data-name=field + data-ng-model=field + data-ng-required='true' + data-placeholder='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' + on-enter=onEnter + on-escape=onEscape + ng-blur=onBlur + ) + block + +//- 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( + 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) + i.tipField.fa.fa-remove( + ng-show='#{show} && !field.edit' + bs-tooltip='"#{tip}"' + ng-click='#{items}.splice(#{items}.indexOf(model), 1)' + ) + +//- Mixin for table remove button. +mixin table-remove-button(items, tip) + +table-remove-conditional-button(items, 'true', tip) + +//- 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-if=kind) + a.customize(ng-show='__.expanded' ng-click='__.expanded = false') Hide settings + a.customize(ng-hide='__.expanded' ng-click='__.expanded = true') Show settings + .panel-details(ng-if='__.expanded') + .details-row + +number('Batch size', policy + '.batchSize', name + 'batchSize', enabled, '1', '0', + '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({id: ' + model + '._id})"> (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({id: ' + model + '._id})"> (add)</a>', + model + '.caches', 'caches', 'true', 'Choose caches', 'No caches configured', 'caches', tip) + +//- Mixin for XML and Java preview. +mixin preview-xml-java(master, generator, detail) + ignite-ui-ace-tabs + .preview-panel(ng-init='mode = false') + .preview-legend + a(ng-class='{active: !mode, inactive: mode}' ng-click='mode = false') XML + | + a(ng-class='{active: mode, inactive: !mode}' ng-click='mode = true') Java + .preview-content(ng-if='mode') + ignite-ui-ace-java(data-master=master data-generator=generator ng-model='$parent.data' data-detail=detail) + .preview-content(ng-if='!mode') + ignite-ui-ace-xml(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 enter-focus-next=valFocusId type='text' ng-model=keyModel placeholder=keyPlaceholder bs-typeahead container='body' retain-selection data-min-length='1' bs-options='javaClass for javaClass in javaBuiltInClasses' on-escape='tableReset()') + else + input.form-control(id=keyFocusId enter-focus-next=valFocusId type='text' ng-model=keyModel placeholder=keyPlaceholder on-escape='tableReset()') + .col-xs-6.col-sm-6.col-md-6 + -var arg = keyModel + ', ' + valModel + -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' retain-selection data-min-length='1' bs-options='javaClass for javaClass in javaBuiltInClasses' on-enter=btnVisibleAndSave on-escape='tableReset()') + else + input.form-control(id=valFocusId type='text' ng-model=valModel placeholder=valPlaceholder on-enter=btnVisibleAndSave on-escape='tableReset()') http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/index.js b/modules/web-console/src/main/js/app/index.js new file mode 100644 index 0000000..a8bd741 --- /dev/null +++ b/modules/web-console/src/main/js/app/index.js @@ -0,0 +1,241 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import _ from 'lodash'; +import ace from 'ace'; +import angular from 'angular'; +import pdfMake from 'pdfmake'; + +ace.config.set('basePath', '/jspm_packages/github/ajaxorg/[email protected]'); + +window._ = _; +window.require = ace.require; // TODO Should be removed after full refactoring to directives. +window.pdfMake = pdfMake; + +import 'angular-animate'; +import 'angular-sanitize'; +import 'angular-strap'; +import 'angular-socket-io'; +import 'angular-retina'; +import 'angular-ui-router'; +import 'angular-ui-router-metatags'; +import 'angular-smart-table'; +import 'angular-ui-grid'; +import 'angular-drag-and-drop-lists'; +import 'angular-nvd3'; +import 'angular-tree-control'; +import 'angular-gridster'; + +import 'bootstrap-carousel'; +import 'file-saver'; +import 'jszip'; +import 'query-command-supported'; + +import 'public/stylesheets/style.css!'; + +import 'angular-gridster/dist/angular-gridster.min.css!'; +import 'angular-tree-control/css/tree-control-attribute.css!'; +import 'angular-tree-control/css/tree-control.css!'; +import 'angular-ui-grid/ui-grid.css!'; +import 'angular-motion/dist/angular-motion.css!'; + +import './decorator/select'; +import './decorator/tooltip'; + +import './modules/Demo/Demo.module'; +import './modules/form/form.module'; +import './services/JavaTypes.service.js'; +import './modules/QueryNotebooks/QueryNotebooks.provider'; + +import './modules/states/signin.state'; +import './modules/states/logout.state'; +import './modules/states/password.state'; +import './modules/states/configuration.state'; +import './modules/states/sql.state'; +import './modules/states/profile.state'; +import './modules/states/admin.state'; + +// ignite:modules +import './modules/user/user.module'; +import './modules/branding/branding.module'; +import './modules/navbar/navbar.module'; +import './modules/configuration/configuration.module'; +import './modules/getting-started/GettingStarted.provider'; +import './modules/dialog/dialog.module'; +import './modules/Version/Version.provider'; +import './modules/ace.module'; +import './modules/socket.module'; +import './modules/loading/loading.module'; +// endignite + +// Directives. +import igniteHideOnStateChange from './directives/hide-on-state-change/hide-on-state-change.directive'; +import igniteInformation from './directives/information/information.directive'; +import igniteUiAceTabs from './directives/ui-ace-tabs.directive'; +import igniteUiAceXml from './directives/ui-ace-xml/ui-ace-xml.directive'; +import igniteUiAceJava from './directives/ui-ace-java/ui-ace-java.directive'; +import igniteUiAcePom from './directives/ui-ace-pom/ui-ace-pom.directive'; +import igniteUiAceDocker from './directives/ui-ace-docker/ui-ace-docker.directive'; +import igniteUiAcePojos from './directives/ui-ace-pojos/ui-ace-pojos.directive'; +import igniteBsAffixUpdate from './directives/bs-affix-update.directive'; +import igniteСentered from './directives/centered/centered.directive.js'; + +// Services. +import cleanup from './services/cleanup.service'; +import confirm from './services/confirm.service'; +import IgniteInetAddress from './services/InetAddress.service'; +import IgniteCountries from './services/Countries.service'; +import IgniteChartColors from './services/ChartColors.service'; +import IgniteAgentMonitor from './services/AgentMonitor.service'; +import JavaTypes from './services/JavaTypes.service'; + +// Providers. + +// Filters. +import hasPojo from './filters/hasPojo.filter'; +import byName from './filters/byName.filter'; + +// Generators +import $generatorCommon from 'generator/generator-common'; +import $generatorJava from 'generator/generator-java'; +import $generatorOptional from 'generator/generator-optional'; +import $generatorProperties from 'generator/generator-properties'; +import $generatorReadme from 'generator/generator-readme'; +import $generatorXml from 'generator/generator-xml'; + +window.$generatorCommon = $generatorCommon; +window.$generatorJava = $generatorJava; +window.$generatorOptional = $generatorOptional; +window.$generatorProperties = $generatorProperties; +window.$generatorReadme = $generatorReadme; +window.$generatorXml = $generatorXml; + +// Add legacy logic; +import consoleModule from 'controllers/common-module'; +window.consoleModule = consoleModule; + +import 'controllers/admin-controller'; +import 'controllers/caches-controller'; +import 'controllers/clusters-controller'; +import 'controllers/domains-controller'; +import 'controllers/igfs-controller'; +import 'controllers/profile-controller'; +import 'controllers/sql-controller'; + +// Inject external modules. +import 'ignite_modules_temp/index'; + +angular +.module('ignite-console', [ + 'ngRetina', + 'btford.socket-io', + 'ngAnimate', + 'ngSanitize', + 'mgcrea.ngStrap', + 'ui.router', + 'gridster', + // Base modules. + 'ignite-console.user', + 'ignite-console.branding', + 'ignite-console.Form', + 'ignite-console.QueryNotebooks', + 'ignite-console.ace', + 'ignite-console.demo', + 'ignite-console.socket', + // States. + 'ignite-console.states.login', + 'ignite-console.states.logout', + 'ignite-console.states.password', + 'ignite-console.states.configuration', + 'ignite-console.states.sql', + 'ignite-console.states.profile', + 'ignite-console.states.admin', + // Common modules. + 'ignite-console.dialog', + 'ignite-console.navbar', + 'ignite-console.configuration', + 'ignite-console.getting-started', + 'ignite-console.version', + 'ignite-console.loading', + // Ignite legacy module. + 'ignite-console.legacy', + // Ignite modules. + 'ignite-console.modules' +]) +// Directives. +.directive(...igniteHideOnStateChange) +.directive(...igniteInformation) +.directive(...igniteUiAceTabs) +.directive(...igniteUiAceXml) +.directive(...igniteUiAceJava) +.directive(...igniteUiAcePom) +.directive(...igniteUiAceDocker) +.directive(...igniteUiAcePojos) +.directive(...igniteBsAffixUpdate) +.directive(...igniteСentered) +// Services. +.service(...cleanup) +.service(...confirm) +.service(...IgniteInetAddress) +.service(...IgniteCountries) +.service(...IgniteChartColors) +.service(...IgniteAgentMonitor) +.service(...JavaTypes) +// Providers. +// Filters. +.filter(...hasPojo) +.filter(...byName) +.config(['$stateProvider', '$locationProvider', '$urlRouterProvider', ($stateProvider, $locationProvider, $urlRouterProvider) => { + // Set up the states. + $stateProvider + .state('base', { + url: '', + abstract: true, + templateUrl: '/base.html' + }) + .state('settings', { + url: '/settings', + abstract: true, + templateUrl: '/base.html' + }); + + $urlRouterProvider.otherwise('/'); + + $locationProvider.html5Mode(true); +}]) +.config(['$animateProvider', ($animateProvider) => { + $animateProvider.classNameFilter(/^((?!(fa-spin)).)*$/); +}]) +.run(['$rootScope', ($root) => { + $root._ = _; +}]) +.run(['$rootScope', '$state', 'MetaTags', 'Auth', 'User', 'IgniteAgentMonitor', ($root, $state, $meta, Auth, User, agentMonitor) => { + $root.$state = $state; + + $root.$meta = $meta; + + if (Auth.authorized) { + User.read() + .then((user) => $root.$broadcast('user', user)) + .then(() => Auth.authorized && agentMonitor.init()); + } +}]) +.run(['$rootScope', ($root) => { + $root.$on('$stateChangeStart', () => { + _.forEach(angular.element('.modal'), (m) => angular.element(m).scope().$hide()); + }); +}]); http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/Demo/Demo.module.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/Demo/Demo.module.js b/modules/web-console/src/main/js/app/modules/Demo/Demo.module.js new file mode 100644 index 0000000..adf5a82 --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/Demo/Demo.module.js @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import angular from 'angular'; + +import DEMO_INFO from 'app/data/demo-info.json!'; + +angular +.module('ignite-console.demo', [ + 'ignite-console.socket' +]) +.config(['$stateProvider', ($stateProvider) => { + $stateProvider + .state('demo', { + abstract: true, + template: '<ui-view></ui-view>' + }) + .state('demo.resume', { + url: '/demo', + controller: ['$state', ($state) => { + $state.go('base.configuration.clusters'); + }], + metaTags: { + } + }) + .state('demo.reset', { + url: '/demo/reset', + controller: ['$state', '$http', '$common', ($state, $http, $common) => { + $http.post('/api/v1/demo/reset') + .then(() => $state.go('base.configuration.clusters')) + .catch((errMsg) => { + $state.go('base.configuration.clusters'); + + $common.showError(errMsg); + }); + }], + metaTags: { + } + }); +}]) +.provider('Demo', ['$stateProvider', '$httpProvider', 'igniteSocketFactoryProvider', function($state, $http, socketFactory) { + if (/(\/demo.*)/ig.test(location.pathname)) + sessionStorage.setItem('IgniteDemoMode', 'true'); + + const enabled = sessionStorage.getItem('IgniteDemoMode') === 'true'; + + if (enabled) { + socketFactory.set({query: 'IgniteDemoMode=true'}); + + $http.interceptors.push('demoInterceptor'); + } + + this.$get = ['$rootScope', ($root) => { + $root.IgniteDemoMode = enabled; + + return {enabled}; + }]; +}]) +.factory('demoInterceptor', ['Demo', (Demo) => { + const isApiRequest = (url) => /\/api\/v1/ig.test(url); + + return { + request(cfg) { + if (Demo.enabled && isApiRequest(cfg.url)) + cfg.headers.IgniteDemoMode = true; + + return cfg; + } + }; +}]) +.controller('demoController', ['$scope', '$state', '$window', '$confirm', ($scope, $state, $window, $confirm) => { + const _openTab = (stateName) => $window.open($state.href(stateName), '_blank'); + + $scope.startDemo = () => { + if (!$scope.user.demoCreated) + return _openTab('demo.reset'); + + $confirm.confirm('Would you like to continue with previous demo session?', true, false) + .then((resume) => { + if (resume) + return _openTab('demo.resume'); + + _openTab('demo.reset'); + }); + }; + + $scope.closeDemo = () => { + $window.close(); + }; +}]) +.provider('igniteDemoInfo', [function() { + const items = DEMO_INFO; + + this.update = (data) => items[0] = data; + + this.$get = [() => { + return items; + }]; +}]) +.service('DemoInfo', ['$rootScope', '$modal', '$state', 'igniteDemoInfo', 'IgniteAgentMonitor', ($rootScope, $modal, $state, igniteDemoInfo, agentMonitor) => { + const scope = $rootScope.$new(); + + function _fillPage() { + const model = igniteDemoInfo; + + scope.title = model[0].title; + scope.message = model[0].message.join(' '); + } + + const dialog = $modal({ + templateUrl: '/templates/demo-info.html', + scope, + placement: 'center', + show: false, + backdrop: 'static' + }); + + scope.close = () => { + dialog.hide(); + }; + + scope.gotoConfiguration = () => { + scope.$$postDigest(() => $state.go('base.configuration.clusters')); + }; + + scope.downloadAgent = () => { + const lnk = document.createElement('a'); + + lnk.setAttribute('href', '/api/v1/agent/download/zip'); + lnk.setAttribute('target', '_self'); + lnk.setAttribute('download', null); + lnk.style.display = 'none'; + + document.body.appendChild(lnk); + + lnk.click(); + + document.body.removeChild(lnk); + }; + + return { + show: () => { + _fillPage(); + + dialog.$promise + .then(dialog.show) + .then(() => agentMonitor.awaitAgent()) + .then(() => scope.hasAgents = true); + } + }; +}]); http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/QueryNotebooks/QueryNotebooks.provider.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/QueryNotebooks/QueryNotebooks.provider.js b/modules/web-console/src/main/js/app/modules/QueryNotebooks/QueryNotebooks.provider.js new file mode 100644 index 0000000..7e4e523 --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/QueryNotebooks/QueryNotebooks.provider.js @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import angular from 'angular'; + +angular + .module('ignite-console.QueryNotebooks', [ + + ]) + .provider('QueryNotebooks', function() { + const _demoNotebook = { + name: 'SQL demo', + paragraphs: [ + { + name: 'Query with refresh rate', + cacheName: 'CarCache', + pageSize: 50, + query: 'SELECT count(*)\nFROM "CarCache".Car', + result: 'bar', + timeLineSpan: '1', + rate: { + value: 3, + unit: 1000, + installed: true + } + }, + { + name: 'Simple query', + cacheName: 'CarCache', + pageSize: 50, + query: 'SELECT * FROM "CarCache".Car', + result: 'table', + timeLineSpan: '1', + rate: { + value: 30, + unit: 1000, + installed: false + } + }, + { + name: 'Query with aggregates', + cacheName: 'CarCache', + pageSize: 50, + query: 'SELECT p.name, count(*) AS cnt\nFROM "ParkingCache".Parking p\nINNER JOIN "CarCache".Car c\n ON (p.id) = (c.parkingId)\nGROUP BY P.NAME', + result: 'table', + timeLineSpan: '1', + rate: { + value: 30, + unit: 1000, + installed: false + } + } + ], + expandedParagraphs: [0, 1, 2] + }; + + this.$get = ['$q', '$http', '$rootScope', ($q, $http, $root) => { + return { + read(noteId) { + if ($root.IgniteDemoMode) + return $q.when(angular.copy(_demoNotebook)); + + return $http.post('/api/v1/notebooks/get', {noteId}) + .then(({data}) => data) + .catch(({data}) => $q.reject(data)); + }, + save(notebook) { + if ($root.IgniteDemoMode) + return $q.when(); + + return $http.post('/api/v1/notebooks/save', notebook) + .then(({data}) => data) + .catch(({data}) => $q.reject(data)); + }, + remove(notebook) { + if ($root.IgniteDemoMode) + return $q.reject(`Removing "${notebook.name}" notebook is not supported.`); + + return $http.post('/api/v1/notebooks/remove', {_id: notebook._id}) + .then(() => { + const idx = _.findIndex($root.notebooks, (item) => { + return item._id === notebook._id; + }); + + if (idx >= 0) { + $root.notebooks.splice(idx, 1); + + $root.rebuildDropdown(); + + if (idx < $root.notebooks.length) + return $root.notebooks[idx]; + } + + if ($root.notebooks.length > 0) + return $root.notebooks[$root.notebooks.length - 1]; + }) + .catch(({data}) => $q.reject(data)); + } + }; + }]; + }); http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/Version/Version.provider.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/Version/Version.provider.js b/modules/web-console/src/main/js/app/modules/Version/Version.provider.js new file mode 100644 index 0000000..84582fb --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/Version/Version.provider.js @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import angular from 'angular'; + +angular + .module('ignite-console.version', []) + .provider('IgniteVersion', function() { + const version = { + version: '1.6' + }; + + this.update = (newVersion) => { + version.version = newVersion; + }; + + this.$get = [() => version]; + }); http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/ace.module.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/ace.module.js b/modules/web-console/src/main/js/app/modules/ace.module.js new file mode 100644 index 0000000..2477965 --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/ace.module.js @@ -0,0 +1,269 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import angular from 'angular'; + +angular + .module('ignite-console.ace', []) + .constant('igniteAceConfig', {}) + .directive('igniteAce', ['igniteAceConfig', (aceConfig) => { + if (angular.isUndefined(window.ace)) + throw new Error('ignite-ace need ace to work... (o rly?)'); + + /** + * Sets editor options such as the wrapping mode or the syntax checker. + * + * The supported options are: + * + * <ul> + * <li>showGutter</li> + * <li>useWrapMode</li> + * <li>onLoad</li> + * <li>theme</li> + * <li>mode</li> + * </ul> + * + * @param acee + * @param session ACE editor session. + * @param {object} opts Options to be set. + */ + const setOptions = (acee, session, opts) => { + // Sets the ace worker path, if running from concatenated or minified source. + if (angular.isDefined(opts.workerPath)) { + const config = window.ace.require('ace/config'); + + config.set('workerPath', opts.workerPath); + } + + // Ace requires loading. + _.forEach(opts.require, (n) => window.ace.require(n)); + + // Boolean options. + if (angular.isDefined(opts.showGutter)) + acee.renderer.setShowGutter(opts.showGutter); + + if (angular.isDefined(opts.useWrapMode)) + session.setUseWrapMode(opts.useWrapMode); + + if (angular.isDefined(opts.showInvisibles)) + acee.renderer.setShowInvisibles(opts.showInvisibles); + + if (angular.isDefined(opts.showIndentGuides)) + acee.renderer.setDisplayIndentGuides(opts.showIndentGuides); + + if (angular.isDefined(opts.useSoftTabs)) + session.setUseSoftTabs(opts.useSoftTabs); + + if (angular.isDefined(opts.showPrintMargin)) + acee.setShowPrintMargin(opts.showPrintMargin); + + // Commands. + if (angular.isDefined(opts.disableSearch) && opts.disableSearch) { + acee.commands.addCommands([{ + name: 'unfind', + bindKey: { + win: 'Ctrl-F', + mac: 'Command-F' + }, + exec: _.constant(false), + readOnly: true + }]); + } + + // Base options. + if (angular.isString(opts.theme)) + acee.setTheme('ace/theme/' + opts.theme); + + if (angular.isString(opts.mode)) + session.setMode('ace/mode/' + opts.mode); + + if (angular.isDefined(opts.firstLineNumber)) { + if (angular.isNumber(opts.firstLineNumber)) + session.setOption('firstLineNumber', opts.firstLineNumber); + else if (angular.isFunction(opts.firstLineNumber)) + session.setOption('firstLineNumber', opts.firstLineNumber()); + } + + // Advanced options. + if (angular.isDefined(opts.advanced)) { + for (const key in opts.advanced) { + if (opts.advanced.hasOwnProperty(key)) { + // Create a javascript object with the key and value. + const obj = {name: key, value: opts.advanced[key]}; + + // Try to assign the option to the ace editor. + acee.setOption(obj.name, obj.value); + } + } + } + + // Advanced options for the renderer. + if (angular.isDefined(opts.rendererOptions)) { + for (const key in opts.rendererOptions) { + if (opts.rendererOptions.hasOwnProperty(key)) { + // Create a javascript object with the key and value. + const obj = {name: key, value: opts.rendererOptions[key]}; + + // Try to assign the option to the ace editor. + acee.renderer.setOption(obj.name, obj.value); + } + } + } + + // onLoad callbacks. + _.forEach(opts.callbacks, (cb) => { + if (angular.isFunction(cb)) + cb(acee); + }); + }; + + return { + restrict: 'EA', + require: ['?ngModel', '?^form'], + link: (scope, elm, attrs, [ngModel, form]) => { + /** + * Corresponds the igniteAceConfig ACE configuration. + * + * @type object + */ + const options = aceConfig.ace || {}; + + /** + * IgniteAceConfig merged with user options via json in attribute or data binding. + * + * @type object + */ + let opts = angular.extend({}, options, scope.$eval(attrs.igniteAce)); + + /** + * ACE editor. + * + * @type object + */ + const acee = window.ace.edit(elm[0]); + + /** + * ACE editor session. + * + * @type object + * @see [EditSession]{@link http://ace.c9.io/#nav=api&api=edit_session} + */ + const session = acee.getSession(); + + /** + * Reference to a change listener created by the listener factory. + * + * @function + * @see listenerFactory.onChange + */ + let onChangeListener; + + /** + * Creates a change listener which propagates the change event and the editor session + * to the callback from the user option onChange. + * It might be exchanged during runtime, if this happens the old listener will be unbound. + * + * @param callback Callback function defined in the user options. + * @see onChangeListener + */ + const onChangeFactory = (callback) => { + return (e) => { + const newValue = session.getValue(); + + if (ngModel && newValue !== ngModel.$viewValue && + // HACK make sure to only trigger the apply outside of the + // digest loop 'cause ACE is actually using this callback + // for any text transformation ! + !scope.$$phase && !scope.$root.$$phase) + scope.$eval(() => ngModel.$setViewValue(newValue)); + + if (angular.isDefined(callback)) { + scope.$evalAsync(() => { + if (angular.isFunction(callback)) + callback([e, acee]); + else + throw new Error('ignite-ace use a function as callback'); + }); + } + }; + }; + + attrs.$observe('readonly', (value) => acee.setReadOnly(!!value || value === '')); + + // Value Blind. + if (ngModel) { + // Remove "ngModel" controller from parent form for correct dirty checks. + form && form.$removeControl(ngModel); + + ngModel.$formatters.push((value) => { + if (angular.isUndefined(value) || value === null) + return ''; + + if (angular.isObject(value) || angular.isArray(value)) + throw new Error('ignite-ace cannot use an object or an array as a model'); + + return value; + }); + + ngModel.$render = () => session.setValue(ngModel.$viewValue); + + acee.on('change', () => ngModel.$setViewValue(acee.getValue())); + } + + // Listen for option updates. + const updateOptions = (current, previous) => { + if (current === previous) + return; + + opts = angular.extend({}, options, scope.$eval(attrs.igniteAce)); + + opts.callbacks = [opts.onLoad]; + + // Also call the global onLoad handler. + if (opts.onLoad !== options.onLoad) + opts.callbacks.unshift(options.onLoad); + + // Unbind old change listener. + session.removeListener('change', onChangeListener); + + // Bind new change listener. + onChangeListener = onChangeFactory(opts.onChange); + + session.on('change', onChangeListener); + + setOptions(acee, session, opts); + }; + + scope.$watch(attrs.igniteAce, updateOptions, /* deep watch */ true); + + // Set the options here, even if we try to watch later, + // if this line is missing things go wrong (and the tests will also fail). + updateOptions(options); + + elm.on('$destroy', () => { + acee.session.$stopWorker(); + acee.destroy(); + }); + + scope.$watch(() => [elm[0].offsetWidth, elm[0].offsetHeight], + () => { + acee.resize(); + acee.renderer.updateFull(); + }, true); + } + }; + }]); http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/branding/branding.module.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/branding/branding.module.js b/modules/web-console/src/main/js/app/modules/branding/branding.module.js new file mode 100644 index 0000000..bd28c68 --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/branding/branding.module.js @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import angular from 'angular'; + +import IgniteBranding from './branding.provider'; + +import igniteHeaderLogo from './header-logo.directive'; +import igniteHeaderTitle from './header-title.directive'; +import igniteTerms from './terms.directive'; +import igniteFeatures from './features.directive'; +import igniteFooter from './footer.directive'; +import ignitePoweredByApache from './powered-by-apache.directive'; + +angular +.module('ignite-console.branding', [ + 'ui.router.metatags' +]) +.provider(...IgniteBranding) +.config(['UIRouterMetatagsProvider', (UIRouterMetatagsProvider) => { + UIRouterMetatagsProvider + .setDefaultTitle('Apache Ignite - Management Tool and Configuration Wizard') + .setTitleSuffix(' â Apache Ignite Web Console') + .setDefaultDescription('The Apache Ignite Web Console is an interactive management tool and configuration wizard which walks you through the creation of config files. Try it now.'); +}]) +.directive(...ignitePoweredByApache) +.directive(...igniteHeaderLogo) +.directive(...igniteHeaderTitle) +.directive(...igniteTerms) +.directive(...igniteFeatures) +.directive(...igniteFooter); + http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/branding/branding.provider.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/branding/branding.provider.js b/modules/web-console/src/main/js/app/modules/branding/branding.provider.js new file mode 100644 index 0000000..ce14b34 --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/branding/branding.provider.js @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default ['IgniteBranding', [function() { + let titleSuffix = ' â Apache Ignite Web Console'; + + let headerLogo = '/images/ignite-logo.png'; + + let headerText = 'Management console for Apache Ignite'; + + let showIgniteLogo = false; + + let footerHtml = [ + '<p>Apache Ignite Web Console</p>', + '<p>© 2016 The Apache Software Foundation.</p>', + '<p>Apache, Apache Ignite, the Apache feather and the Apache Ignite logo are trademarks of The Apache Software Foundation.</p>' + ]; + + let termsState; + + let featuresHtml = [ + '<p>Web Console is an interactive management tool which allows to:</p>', + '<ul>', + ' <li>Create and download cluster configurations</li>', + ' <li>Automatically import domain model from any RDBMS</li>', + ' <li>Connect to cluster and run SQL analytics on it</li>', + '</ul>' + ]; + + /** + * Change title suffix. + * + * @param {String} suffix. + */ + this.titleSuffix = (suffix) => { + titleSuffix = suffix; + }; + + /** + * Change logo in header. + * + * @param {String} url Logo path. + */ + this.headerLogo = (url) => { + headerLogo = url; + + showIgniteLogo = true; + }; + + /** + * Change text in header. + * + * @param {String} text Header text. + */ + this.headerText = (text) => { + headerText = text; + }; + + /** + * Change text in features. + * + * @param {Array.<String>} rows Features text. + */ + this.featuresHtml = (rows) => { + featuresHtml = rows; + }; + + /** + * Change text in footer. + * + * @param {Array.<String>} rows Footer text. + */ + this.footerHtml = (rows) => { + footerHtml = rows; + }; + + /** + * Set terms and conditions stage. + * + * @param {String} state + */ + this.termsState = (state) => { + termsState = state; + }; + + this.$get = [() => { + return { + titleSuffix, + headerLogo, + headerText, + featuresHtml: featuresHtml.join('\n'), + footerHtml: footerHtml.join('\n'), + showIgniteLogo, + termsState + }; + }]; +}]]; http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/branding/features.directive.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/branding/features.directive.js b/modules/web-console/src/main/js/app/modules/branding/features.directive.js new file mode 100644 index 0000000..9226a3f --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/branding/features.directive.js @@ -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. + */ + +const template = '<div class="features" ng-bind-html="features.html"></div>'; + +export default ['igniteFeatures', ['IgniteBranding', (branding) => { + function controller() { + const ctrl = this; + + ctrl.html = branding.featuresHtml; + } + + return { + restrict: 'E', + template, + controller, + controllerAs: 'features', + replace: true + }; +}]]; + http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/branding/footer.directive.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/branding/footer.directive.js b/modules/web-console/src/main/js/app/modules/branding/footer.directive.js new file mode 100644 index 0000000..f0b1994 --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/branding/footer.directive.js @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const template = '<div class="footer" ng-bind-html="footer.html"></div>'; + +export default ['igniteFooter', ['IgniteBranding', (branding) => { + function controller() { + const ctrl = this; + + ctrl.html = branding.footerHtml; + } + + return { + restrict: 'E', + template, + controller, + controllerAs: 'footer', + replace: true + }; +}]]; http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/branding/header-logo.directive.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/branding/header-logo.directive.js b/modules/web-console/src/main/js/app/modules/branding/header-logo.directive.js new file mode 100644 index 0000000..1bfbc45 --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/branding/header-logo.directive.js @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import template from './header-logo.jade!'; + +export default ['igniteHeaderLogo', ['IgniteBranding', (branding) => { + function controller() { + const ctrl = this; + + ctrl.url = branding.headerLogo; + } + + return { + restrict: 'E', + template, + controller, + controllerAs: 'logo', + replace: true + }; +}]]; http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/branding/header-logo.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/branding/header-logo.jade b/modules/web-console/src/main/js/app/modules/branding/header-logo.jade new file mode 100644 index 0000000..b807921 --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/branding/header-logo.jade @@ -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(href='/') + img.navbar-brand(ng-src='{{logo.url}}' height='40') http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/branding/header-title.directive.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/branding/header-title.directive.js b/modules/web-console/src/main/js/app/modules/branding/header-title.directive.js new file mode 100644 index 0000000..d560e0a --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/branding/header-title.directive.js @@ -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. + */ + +const template = '<h1 class="title">{{::title.text}}</h1>'; + +export default ['igniteHeaderTitle', ['IgniteBranding', (branding) => { + function controller() { + const ctrl = this; + + ctrl.text = branding.headerText; + } + + return { + restrict: 'E', + template, + controller, + controllerAs: 'title', + replace: true + }; +}]]; + http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.directive.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.directive.js b/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.directive.js new file mode 100644 index 0000000..37f1dec --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.directive.js @@ -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. + */ + +import templatePoweredByApache from './powered-by-apache.jade!'; + +export default ['ignitePoweredByApache', ['IgniteBranding', (branding) => { + function controller() { + const ctrl = this; + + ctrl.show = branding.showIgniteLogo; + } + + return { + restrict: 'E', + template: templatePoweredByApache, + controller, + controllerAs: 'poweredBy', + replace: true + }; +}]]; + http://git-wip-us.apache.org/repos/asf/ignite/blob/eb5ac0ae/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.jade b/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.jade new file mode 100644 index 0000000..af9aadf --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.jade @@ -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/eb5ac0ae/modules/web-console/src/main/js/app/modules/branding/terms.directive.js ---------------------------------------------------------------------- diff --git a/modules/web-console/src/main/js/app/modules/branding/terms.directive.js b/modules/web-console/src/main/js/app/modules/branding/terms.directive.js new file mode 100644 index 0000000..0207745 --- /dev/null +++ b/modules/web-console/src/main/js/app/modules/branding/terms.directive.js @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default ['igniteTerms', ['IgniteBranding', (branding) => { + function controller() { + const ctrl = this; + + ctrl.termsState = branding.termsState; + } + + return { + restrict: 'A', + controller, + controllerAs: 'terms' + }; +}]];
