You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2017/12/06 03:37:41 UTC
[3/5] ignite git commit: IGNITE-6390 Web Console: Added component for
cluster selection.
http://git-wip-us.apache.org/repos/asf/ignite/blob/1367bc98/modules/web-console/frontend/app/components/page-queries/template.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/components/page-queries/template.tpl.pug b/modules/web-console/frontend/app/components/page-queries/template.tpl.pug
new file mode 100644
index 0000000..b2173f7
--- /dev/null
+++ b/modules/web-console/frontend/app/components/page-queries/template.tpl.pug
@@ -0,0 +1,385 @@
+//-
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+include /app/helpers/jade/mixins
+
+mixin btn-toolbar(btn, click, tip, focusId)
+ i.btn.btn-default.fa(class=btn ng-click=click bs-tooltip='' data-title=tip ignite-on-click-focus=focusId data-trigger='hover' data-placement='bottom')
+
+mixin btn-toolbar-data(btn, kind, tip)
+ i.btn.btn-default.fa(class=btn ng-click=`setResult(paragraph, '${kind}')` ng-class=`{active: resultEq(paragraph, '${kind}')}` bs-tooltip='' data-title=tip data-trigger='hover' data-placement='bottom')
+
+mixin result-toolbar
+ .btn-group(ng-model='paragraph.result' ng-click='$event.stopPropagation()' style='left: 50%; margin: 0 0 0 -70px;display: block;')
+ +btn-toolbar-data('fa-table', 'table', 'Show data in tabular form')
+ +btn-toolbar-data('fa-bar-chart', 'bar', 'Show bar chart<br/>By default first column - X values, second column - Y values<br/>In case of one column it will be treated as Y values')
+ +btn-toolbar-data('fa-pie-chart', 'pie', 'Show pie chart<br/>By default first column - pie labels, second column - pie values<br/>In case of one column it will be treated as pie values')
+ +btn-toolbar-data('fa-line-chart', 'line', 'Show line chart<br/>By default first column - X values, second column - Y values<br/>In case of one column it will be treated as Y values')
+ +btn-toolbar-data('fa-area-chart', 'area', 'Show area chart<br/>By default first column - X values, second column - Y values<br/>In case of one column it will be treated as Y values')
+
+mixin chart-settings
+ .total.row
+ .col-xs-7
+ .chart-settings-link(ng-show='paragraph.chart && paragraph.chartColumns.length > 0')
+ a(title='Click to show chart settings dialog' ng-click='$event.stopPropagation()' bs-popover data-template-url='{{ $ctrl.chartSettingsTemplateUrl }}' data-placement='bottom' data-auto-close='1' data-trigger='click')
+ i.fa.fa-bars
+ | Chart settings
+ div(ng-show='paragraphTimeSpanVisible(paragraph)')
+ label Show
+ button.select-manual-caret.btn.btn-default(ng-model='paragraph.timeLineSpan' ng-change='applyChartSettings(paragraph)' bs-options='item for item in timeLineSpans' bs-select data-caret-html='<span class="caret"></span>')
+ label min
+
+ div
+ label Duration: #[b {{paragraph.duration | duration}}]
+ label.margin-left-dflt(ng-show='paragraph.localQueryMode') NodeID8: #[b {{paragraph.resNodeId | id8}}]
+ .col-xs-2
+ +result-toolbar
+
+mixin notebook-rename
+ .docs-header.notebook-header
+ h1.col-sm-6(ng-hide='notebook.edit')
+ label(style='max-width: calc(100% - 60px)') {{notebook.name}}
+ .btn-group(ng-if='!demo')
+ +btn-toolbar('fa-pencil', 'notebook.edit = true;notebook.editName = notebook.name', 'Rename notebook')
+ +btn-toolbar('fa-trash', 'removeNotebook(notebook)', 'Remove notebook')
+ h1.col-sm-6(ng-show='notebook.edit')
+ i.btn.fa.fa-floppy-o(ng-show='notebook.editName' ng-click='renameNotebook(notebook.editName)' bs-tooltip data-title='Save notebook name' data-trigger='hover')
+ .input-tip
+ input.form-control(ng-model='notebook.editName' required ignite-on-enter='renameNotebook(notebook.editName)' ignite-on-escape='notebook.edit = false;')
+ h1.pull-right
+ a.dropdown-toggle(style='margin-right: 20px' data-toggle='dropdown' bs-dropdown='scrollParagraphs' data-placement='bottom-right') Scroll to query
+ span.caret
+ button.btn.btn-default(style='margin-top: 2px' ng-click='addQuery()' ignite-on-click-focus=focusId)
+ i.fa.fa-fw.fa-plus
+ | Add query
+
+ button.btn.btn-default(style='margin-top: 2px' ng-click='addScan()' ignite-on-click-focus=focusId)
+ i.fa.fa-fw.fa-plus
+ | Add scan
+
+mixin notebook-error
+ h2 Failed to load notebook
+ label.col-sm-12 Notebook not accessible any more. Go back to configuration or open to another notebook.
+ button.h3.btn.btn-primary(ui-sref='base.configuration.tabs.advanced.clusters') Back to configuration
+
+mixin paragraph-rename
+ .col-sm-6(ng-hide='paragraph.edit')
+ i.fa(ng-class='paragraphExpanded(paragraph) ? "fa-chevron-circle-down" : "fa-chevron-circle-right"')
+ label {{paragraph.name}}
+
+ .btn-group(ng-hide='notebook.paragraphs.length > 1')
+ +btn-toolbar('fa-pencil', 'paragraph.edit = true; paragraph.editName = paragraph.name; $event.stopPropagation();', 'Rename query', 'paragraph-name-{{paragraph.id}}')
+
+ .btn-group(ng-show='notebook.paragraphs.length > 1' ng-click='$event.stopPropagation();')
+ +btn-toolbar('fa-pencil', 'paragraph.edit = true; paragraph.editName = paragraph.name;', 'Rename query', 'paragraph-name-{{paragraph.id}}')
+ +btn-toolbar('fa-remove', 'removeParagraph(paragraph)', 'Remove query')
+
+ .col-sm-6(ng-show='paragraph.edit')
+ i.tipLabel.fa(style='float: left;' ng-class='paragraphExpanded(paragraph) ? "fa-chevron-circle-down" : "fa-chevron-circle-right"')
+ i.tipLabel.fa.fa-floppy-o(style='float: right;' ng-show='paragraph.editName' ng-click='renameParagraph(paragraph, paragraph.editName); $event.stopPropagation();' bs-tooltip data-title='Save query name' data-trigger='hover')
+ .input-tip
+ input.form-control(id='paragraph-name-{{paragraph.id}}' ng-model='paragraph.editName' required ng-click='$event.stopPropagation();' ignite-on-enter='renameParagraph(paragraph, paragraph.editName)' ignite-on-escape='paragraph.edit = false')
+
+mixin query-settings
+ .panel-top-align
+ label.tipLabel(bs-tooltip data-placement='bottom' data-title='Configure periodical execution of last successfully executed query') Refresh rate:
+ button.btn.btn-default.fa.fa-clock-o.tipLabel(ng-class='{"btn-info": paragraph.rate && paragraph.rate.installed}' bs-popover data-template-url='{{ $ctrl.paragraphRateTemplateUrl }}' data-placement='left' data-auto-close='1' data-trigger='click') {{rateAsString(paragraph)}}
+
+ label.tipLabel(bs-tooltip data-placement='bottom' data-title='Max number of rows to show in query result as one page') Page size:
+ button.btn.btn-default.select-toggle.tipLabel(ng-model='paragraph.pageSize' bs-select bs-options='item for item in pageSizes')
+
+ label.tipLabel(bs-tooltip data-placement='bottom' data-title='Limit query max results to specified number of pages') Max pages:
+ button.btn.btn-default.select-toggle.tipLabel(ng-model='paragraph.maxPages' bs-select bs-options='item.value as item.label for item in maxPages')
+
+ .panel-tip-container
+ .row(ng-if='nonCollocatedJoinsAvailable(paragraph)')
+ label.tipLabel(bs-tooltip data-placement='bottom' data-title='Non-collocated joins is a special mode that allow to join data across cluster without collocation.<br/>\
+ Nested joins are not supported for now.<br/>\
+ <b>NOTE</b>: In some cases it may consume more heap memory or may take a long time than collocated joins.' data-trigger='hover')
+ input(type='checkbox' ng-model='paragraph.nonCollocatedJoins')
+ span Allow non-collocated joins
+ .row(ng-if='enforceJoinOrderAvailable(paragraph)')
+ label.tipLabel(bs-tooltip data-placement='bottom' data-title='Enforce join order of tables in the query.<br/>\
+ If <b>set</b>, then query optimizer will not reorder tables within join.<br/>\
+ <b>NOTE:</b> It is not recommended to enable this property unless you have verified that\
+ indexes are not selected in optimal order.' data-trigger='hover')
+ input(type='checkbox' ng-model='paragraph.enforceJoinOrder')
+ span Enforce join order
+ .row(ng-if='lazyQueryAvailable(paragraph)')
+ label.tipLabel(bs-tooltip data-placement='bottom' data-title='By default Ignite attempts to fetch the whole query result set to memory and send it to the client.<br/>\
+ For small and medium result sets this provides optimal performance and minimize duration of internal database locks, thus increasing concurrency.<br/>\
+ If result set is too big to fit in available memory this could lead to excessive GC pauses and even OutOfMemoryError.<br/>\
+ Use this flag as a hint for Ignite to fetch result set lazily, thus minimizing memory consumption at the cost of moderate performance hit.' data-trigger='hover')
+ input(type='checkbox' ng-model='paragraph.lazy')
+ span Lazy result set
+
+mixin query-actions
+ button.btn.btn-primary(ng-disabled='!queryAvailable(paragraph)' ng-click='execute(paragraph)')
+ div
+ i.fa.fa-fw.fa-play(ng-hide='paragraph.executionInProgress(false)')
+ i.fa.fa-fw.fa-refresh.fa-spin(ng-show='paragraph.executionInProgress(false)')
+ span.tipLabelExecute Execute
+ button.btn.btn-primary(ng-disabled='!queryAvailable(paragraph)' ng-click='execute(paragraph, true)')
+ div
+ i.fa.fa-fw.fa-play(ng-hide='paragraph.executionInProgress(true)')
+ i.fa.fa-fw.fa-refresh.fa-spin(ng-show='paragraph.executionInProgress(true)')
+ span.tipLabelExecute Execute on selected node
+
+
+ a.btn.btn-default(ng-disabled='!queryAvailable(paragraph)' ng-click='explain(paragraph)' data-placement='bottom' bs-tooltip='' data-title='{{queryTooltip(paragraph, "explain query")}}') Explain
+
+mixin table-result-heading-query
+ .total.row
+ .col-xs-7
+ grid-column-selector(grid-api='paragraph.gridOptions.api')
+ .fa.fa-bars.icon
+ label Page: #[b {{paragraph.page}}]
+ label.margin-left-dflt Results so far: #[b {{paragraph.rows.length + paragraph.total}}]
+ label.margin-left-dflt Duration: #[b {{paragraph.duration | duration}}]
+ label.margin-left-dflt(ng-show='paragraph.localQueryMode') NodeID8: #[b {{paragraph.resNodeId | id8}}]
+ .col-xs-2
+ div(ng-if='paragraph.qryType === "query"')
+ +result-toolbar
+ .col-xs-3
+ .pull-right
+ .btn-group.panel-tip-container
+ button.btn.btn-primary.btn--with-icon(
+ ng-click='exportCsv(paragraph)'
+
+ ng-disabled='paragraph.loading'
+
+ bs-tooltip=''
+ ng-attr-title='{{ queryTooltip(paragraph, "export query results") }}'
+
+ data-trigger='hover'
+ data-placement='bottom'
+ )
+ svg(ignite-icon='csv' ng-if='!paragraph.csvIsPreparing')
+ i.fa.fa-fw.fa-refresh.fa-spin(ng-if='paragraph.csvIsPreparing')
+ span Export
+
+ -var options = [{ text: 'Export', click: 'exportCsv(paragraph)' }, { text: 'Export all', click: 'exportCsvAll(paragraph)' }, { divider: true }, { text: '<span title="Copy current result page to clipboard">Copy to clipboard</span>', click: 'exportCsvToClipBoard(paragraph)' }]
+ button.btn.dropdown-toggle.btn-primary(
+ ng-disabled='paragraph.loading'
+
+ bs-dropdown=`${JSON.stringify(options)}`
+
+ data-toggle='dropdown'
+ data-container='body'
+ data-placement='bottom-right'
+ data-html='true'
+ )
+ span.caret
+
+
+
+mixin table-result-heading-scan
+ .total.row
+ .col-xs-7
+ grid-column-selector(grid-api='paragraph.gridOptions.api')
+ .fa.fa-bars.icon
+ label Page: #[b {{paragraph.page}}]
+ label.margin-left-dflt Results so far: #[b {{paragraph.rows.length + paragraph.total}}]
+ label.margin-left-dflt Duration: #[b {{paragraph.duration | duration}}]
+ label.margin-left-dflt(ng-show='paragraph.localQueryMode') NodeID8: #[b {{paragraph.resNodeId | id8}}]
+ .col-xs-2
+ div(ng-if='paragraph.qryType === "query"')
+ +result-toolbar
+ .col-xs-3
+ .pull-right
+ .btn-group.panel-tip-container
+ // TODO: replace this logic for exporting under one component
+ button.btn.btn-primary.btn--with-icon(
+ ng-click='exportCsv(paragraph)'
+
+ ng-disabled='paragraph.loading || paragraph.csvIsPreparing'
+
+ bs-tooltip=''
+ ng-attr-title='{{ scanTooltip(paragraph) }}'
+
+ data-trigger='hover'
+ data-placement='bottom'
+ )
+ svg(ignite-icon='csv' ng-if='!paragraph.csvIsPreparing')
+ i.fa.fa-fw.fa-refresh.fa-spin(ng-if='paragraph.csvIsPreparing')
+ span Export
+
+ -var options = [{ text: "Export", click: 'exportCsv(paragraph)' }, { text: 'Export all', click: 'exportCsvAll(paragraph)' }, { divider: true }, { text: '<span title="Copy current result page to clipboard">Copy to clipboard</span>', click: 'exportCsvToClipBoard(paragraph)' }]
+ button.btn.dropdown-toggle.btn-primary(
+ ng-disabled='paragraph.loading || paragraph.csvIsPreparing'
+
+ bs-dropdown=`${JSON.stringify(options)}`
+
+ data-toggle='dropdown'
+ data-container='body'
+ data-placement='bottom-right'
+ data-html='true'
+ )
+ span.caret
+
+mixin table-result-body
+ .grid(ui-grid='paragraph.gridOptions' ui-grid-resize-columns ui-grid-exporter)
+
+mixin chart-result
+ div(ng-hide='paragraph.scanExplain()')
+ +chart-settings
+ .empty(ng-show='paragraph.chartColumns.length > 0 && !paragraph.chartColumnsConfigured()') Cannot display chart. Please configure axis using #[b Chart settings]
+ .empty(ng-show='paragraph.chartColumns.length == 0') Cannot display chart. Result set must contain Java build-in type columns. Please change query and execute it again.
+ div(ng-show='paragraph.chartColumnsConfigured()')
+ div(ng-show='paragraph.timeLineSupported() || !paragraph.chartTimeLineEnabled()')
+ div(ng-repeat='chart in paragraph.charts')
+ nvd3(options='chart.options' data='chart.data' api='chart.api')
+ .empty(ng-show='!paragraph.timeLineSupported() && paragraph.chartTimeLineEnabled()') Pie chart does not support 'TIME_LINE' column for X-axis. Please use another column for X-axis or switch to another chart.
+ .empty(ng-show='paragraph.scanExplain()')
+ .row
+ .col-xs-4.col-xs-offset-4
+ +result-toolbar
+ label.margin-top-dflt Charts do not support #[b Explain] and #[b Scan] query
+
+mixin paragraph-scan
+ .panel-heading(bs-collapse-toggle)
+ .row
+ +paragraph-rename
+ .panel-collapse(role='tabpanel' bs-collapse-target)
+ .col-sm-12.sql-controls
+ .col-sm-3
+ +dropdown-required('Cache:', 'paragraph.cacheName', '"cache"', 'true', 'false', 'Choose cache', 'caches')
+ .col-sm-3
+ +text-enabled('Filter:', 'paragraph.filter', '"filter"', true, false, 'Enter filter')
+ label.btn.btn-default.ignite-form-field__btn(ng-click='paragraph.caseSensitive = !paragraph.caseSensitive')
+ input(type='checkbox' ng-model='paragraph.caseSensitive')
+ span(bs-tooltip data-title='Select this checkbox for case sensitive search') Cs
+ label.tipLabel(bs-tooltip data-placement='bottom' data-title='Max number of rows to show in query result as one page') Page size:
+ button.btn.btn-default.select-toggle.tipLabel(ng-model='paragraph.pageSize' bs-select bs-options='item for item in pageSizes')
+
+ .col-sm-12.sql-controls
+ button.btn.btn-primary(ng-disabled='!scanAvailable(paragraph)' ng-click='scan(paragraph)')
+ div
+ i.fa.fa-fw.fa-play(ng-hide='paragraph.checkScanInProgress(false)')
+ i.fa.fa-fw.fa-refresh.fa-spin(ng-show='paragraph.checkScanInProgress(false)')
+ span.tipLabelExecute Scan
+
+ button.btn.btn-primary(ng-disabled='!scanAvailable(paragraph)' ng-click='scan(paragraph, true)')
+ i.fa.fa-fw.fa-play(ng-hide='paragraph.checkScanInProgress(true)')
+ i.fa.fa-fw.fa-refresh.fa-spin(ng-show='paragraph.checkScanInProgress(true)')
+ span.tipLabelExecute Scan on selected node
+
+ .col-sm-12.sql-result(ng-if='paragraph.queryExecuted()' ng-switch='paragraph.resultType()')
+ .error(ng-switch-when='error') Error: {{paragraph.error.message}}
+ .empty(ng-switch-when='empty') Result set is empty. Duration: #[b {{paragraph.duration | duration}}]
+ .table(ng-switch-when='table')
+ +table-result-heading-scan
+ +table-result-body
+ .footer.clearfix()
+ .pull-left
+ | Showing results for scan of #[b {{ paragraph.queryArgs.cacheName | defaultName }}]
+ span(ng-if='paragraph.queryArgs.filter') with filter: #[b {{ paragraph.queryArgs.filter }}]
+ span(ng-if='paragraph.queryArgs.localNid') on node: #[b {{ paragraph.queryArgs.localNid | limitTo:8 }}]
+
+ -var nextVisibleCondition = 'paragraph.resultType() != "error" && paragraph.queryId && paragraph.nonRefresh() && (paragraph.table() || paragraph.chart() && !paragraph.scanExplain())'
+
+ .pull-right(ng-show=`${nextVisibleCondition}` ng-class='{disabled: paragraph.loading}' ng-click='!paragraph.loading && nextPage(paragraph)')
+ i.fa.fa-chevron-circle-right
+ a Next
+
+mixin paragraph-query
+ .row.panel-heading(bs-collapse-toggle)
+ +paragraph-rename
+ .panel-collapse(role='tabpanel' bs-collapse-target)
+ .col-sm-12
+ .col-xs-8.col-sm-9(style='border-right: 1px solid #eee')
+ .sql-editor(ignite-ace='{onLoad: aceInit(paragraph), theme: "chrome", mode: "sql", require: ["ace/ext/language_tools"],' +
+ 'advanced: {enableSnippets: false, enableBasicAutocompletion: true, enableLiveAutocompletion: true}}'
+ ng-model='paragraph.query')
+ .col-xs-4.col-sm-3
+ div(ng-show='caches.length > 0' style='padding: 5px 10px' st-table='displayedCaches' st-safe-src='caches')
+ lable.labelField.labelFormField Caches:
+ i.fa.fa-database.tipField(title='Click to show cache types metadata dialog' bs-popover data-template-url='{{ $ctrl.cacheMetadataTemplateUrl }}' data-placement='bottom' data-trigger='click' data-container='#{{ paragraph.id }}')
+ .input-tip
+ input.form-control(type='text' st-search='label' placeholder='Filter caches...')
+ table.links
+ tbody.scrollable-y(style='max-height: 15em; display: block;')
+ tr(ng-repeat='cache in displayedCaches track by cache.name')
+ td(style='width: 100%')
+ input.labelField(id='cache_{{ [paragraph.id, $index].join("_") }}' type='radio' value='{{cache.name}}' ng-model='paragraph.cacheName')
+ label(for='cache_{{ [paragraph.id, $index].join("_") }} ' ng-bind-html='cache.label')
+ .settings-row
+ .row(ng-if='ddlAvailable(paragraph)')
+ label.tipLabel.use-cache(bs-tooltip data-placement='bottom'
+ data-title=
+ 'Use selected cache as default schema name.<br/>\
+ This will allow to execute query on specified cache without specify schema name.<br/>\
+ <b>NOTE:</b> In future version of Ignite this feature will be removed.'
+ data-trigger='hover')
+ input(type='checkbox' ng-model='paragraph.useAsDefaultSchema')
+ span Use selected cache as default schema name
+ .empty-caches(ng-show='displayedCaches.length == 0 && caches.length != 0')
+ label Wrong caches filter
+ .empty-caches(ng-show='caches.length == 0')
+ label No caches
+ .col-sm-12.sql-controls
+ +query-actions
+
+ .pull-right
+ +query-settings
+ .col-sm-12.sql-result(ng-if='paragraph.queryExecuted()' ng-switch='paragraph.resultType()')
+ .error(ng-switch-when='error')
+ label Error: {{paragraph.error.message}}
+ br
+ a(ng-show='paragraph.resultType() === "error"' ng-click='showStackTrace(paragraph)') Show more
+ .empty(ng-switch-when='empty') Result set is empty. Duration: #[b {{paragraph.duration | duration}}]
+ .table(ng-switch-when='table')
+ +table-result-heading-query
+ +table-result-body
+ .chart(ng-switch-when='chart')
+ +chart-result
+ .footer.clearfix(ng-show='paragraph.resultType() !== "error"')
+ a.pull-left(ng-click='showResultQuery(paragraph)') Show query
+
+ -var nextVisibleCondition = 'paragraph.resultType() !== "error" && paragraph.queryId && paragraph.nonRefresh() && (paragraph.table() || paragraph.chart() && !paragraph.scanExplain())'
+
+ .pull-right(ng-show=`${nextVisibleCondition}` ng-class='{disabled: paragraph.loading}' ng-click='!paragraph.loading && nextPage(paragraph)')
+ i.fa.fa-chevron-circle-right
+ a Next
+
+.row
+ .docs-content
+ header
+ h1 Queries
+ cluster-selector
+
+ .row(ng-if='notebook' bs-affix style='margin-bottom: 20px;')
+ +notebook-rename
+
+ ignite-information(data-title='With query notebook you can' style='margin-bottom: 30px')
+ ul
+ li Create any number of queries
+ li Execute and explain SQL queries
+ li Execute scan queries
+ li View data in tabular form and as charts
+
+ div(ng-if='notebookLoadFailed' style='text-align: center')
+ +notebook-error
+
+ div(ng-if='notebook' ignite-loading='sqlLoading' ignite-loading-text='{{ loadingText }}' ignite-loading-position='top')
+ .docs-body.paragraphs
+ .panel-group(bs-collapse ng-model='notebook.expandedParagraphs' data-allow-multiple='true' data-start-collapsed='false')
+
+ .panel-paragraph(ng-repeat='paragraph in notebook.paragraphs' id='{{paragraph.id}}' ng-form='form_{{paragraph.id}}')
+ .panel.panel-default(ng-if='paragraph.qryType === "scan"')
+ +paragraph-scan
+ .panel.panel-default(ng-if='paragraph.qryType === "query"')
+ +paragraph-query
http://git-wip-us.apache.org/repos/asf/ignite/blob/1367bc98/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/agent/AgentManager.service.js b/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
index 752b4f0..7668132 100644
--- a/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
+++ b/modules/web-console/frontend/app/modules/agent/AgentManager.service.js
@@ -38,7 +38,18 @@ class ConnectionState {
this.state = State.DISCONNECTED;
}
+ updateCluster(cluster) {
+ this.cluster = cluster;
+ this.cluster.connected = !!_.find(this.clusters, {id: this.cluster.id});
+
+ return cluster;
+ }
+
update(demo, count, clusters) {
+ _.forEach(clusters, (cluster) => {
+ cluster.name = cluster.id;
+ });
+
this.clusters = clusters;
if (_.isNil(this.cluster))
@@ -142,6 +153,7 @@ export default class IgniteAgentManager {
};
self.socket.on('connect_error', onDisconnect);
+
self.socket.on('disconnect', onDisconnect);
self.socket.on('agents:stat', ({clusters, count}) => {
@@ -152,6 +164,8 @@ export default class IgniteAgentManager {
self.connectionSbj.next(conn);
});
+ self.socket.on('cluster:changed', (cluster) => this.updateCluster(cluster));
+
self.socket.on('user:notifications', (notification) => this.UserNotifications.notification = notification);
}
@@ -163,6 +177,31 @@ export default class IgniteAgentManager {
}
}
+ updateCluster(newCluster) {
+ const state = this.connectionSbj.getValue();
+
+ const oldCluster = _.find(state.clusters, (cluster) => cluster.id === newCluster.id);
+
+ if (!_.isNil(oldCluster)) {
+ oldCluster.nids = newCluster.nids;
+ oldCluster.addresses = newCluster.addresses;
+ oldCluster.clusterVersion = newCluster.clusterVersion;
+ oldCluster.active = newCluster.active;
+
+ this.connectionSbj.next(state);
+ }
+ }
+
+ switchCluster(cluster) {
+ const state = this.connectionSbj.getValue();
+
+ state.updateCluster(cluster);
+
+ this.connectionSbj.next(state);
+
+ this.saveToStorage(cluster);
+ }
+
/**
* @param states
* @returns {Promise}
@@ -212,6 +251,8 @@ export default class IgniteAgentManager {
self.connectionSbj.next(conn);
+ this.modalSubscription && this.modalSubscription.unsubscribe();
+
self.modalSubscription = this.connectionSbj.subscribe({
next: ({state}) => {
switch (state) {
@@ -252,6 +293,8 @@ export default class IgniteAgentManager {
self.connectionSbj.next(conn);
+ this.modalSubscription && this.modalSubscription.unsubscribe();
+
self.modalSubscription = this.connectionSbj.subscribe({
next: ({state}) => {
switch (state) {
@@ -633,7 +676,6 @@ export default class IgniteAgentManager {
}
/**
- /**
* @param {String} nid Node id.
* @param {String} cacheName Cache name.
* @param {String} filter Filter text.
@@ -664,4 +706,17 @@ export default class IgniteAgentManager {
return this.queryScan(nid, cacheName, filter, regEx, caseSensitive, near, local, pageSz)
.then(fetchResult);
}
+
+ /**
+ * Change cluster active state.
+ *
+ * @returns {Promise}
+ */
+ toggleClusterState() {
+ const state = this.connectionSbj.getValue();
+ const active = !state.cluster.active;
+
+ return this.visorTask('toggleClusterState', null, active)
+ .then(() => state.updateCluster(Object.assign(state.cluster, { active })));
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/1367bc98/modules/web-console/frontend/app/modules/sql/Notebook.data.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/Notebook.data.js b/modules/web-console/frontend/app/modules/sql/Notebook.data.js
deleted file mode 100644
index 3f98bed..0000000
--- a/modules/web-console/frontend/app/modules/sql/Notebook.data.js
+++ /dev/null
@@ -1,168 +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.
- */
-
-const DEMO_NOTEBOOK = {
- name: 'SQL demo',
- paragraphs: [
- {
- name: 'Query with refresh rate',
- cacheName: 'CarCache',
- pageSize: 100,
- limit: 0,
- query: [
- 'SELECT count(*)',
- 'FROM "CarCache".Car'
- ].join('\n'),
- result: 'bar',
- timeLineSpan: '1',
- rate: {
- value: 3,
- unit: 1000,
- installed: true
- }
- },
- {
- name: 'Simple query',
- cacheName: 'CarCache',
- pageSize: 100,
- limit: 0,
- query: 'SELECT * FROM "CarCache".Car',
- result: 'table',
- timeLineSpan: '1',
- rate: {
- value: 30,
- unit: 1000,
- installed: false
- }
- },
- {
- name: 'Query with aggregates',
- cacheName: 'ParkingCache',
- pageSize: 100,
- limit: 0,
- query: [
- 'SELECT p.name, count(*) AS cnt',
- 'FROM "ParkingCache".Parking p',
- 'INNER JOIN "CarCache".Car c',
- ' ON (p.id) = (c.parkingId)',
- 'GROUP BY P.NAME'
- ].join('\n'),
- result: 'table',
- timeLineSpan: '1',
- rate: {
- value: 30,
- unit: 1000,
- installed: false
- }
- }
- ],
- expandedParagraphs: [0, 1, 2]
-};
-
-export default class NotebookData {
- static $inject = ['$rootScope', '$http', '$q'];
-
- constructor($root, $http, $q) {
- this.demo = $root.IgniteDemoMode;
-
- this.initLatch = null;
- this.notebooks = null;
-
- this.$http = $http;
- this.$q = $q;
- }
-
- load() {
- if (this.demo) {
- if (this.initLatch)
- return this.initLatch;
-
- return this.initLatch = this.$q.when(this.notebooks = [DEMO_NOTEBOOK]);
- }
-
- return this.initLatch = this.$http.get('/api/v1/notebooks')
- .then(({data}) => this.notebooks = data)
- .catch(({data}) => Promise.reject(data));
- }
-
- read() {
- if (this.initLatch)
- return this.initLatch;
-
- return this.load();
- }
-
- find(_id) {
- return this.read()
- .then(() => {
- const notebook = this.demo ? this.notebooks[0] : _.find(this.notebooks, {_id});
-
- if (_.isNil(notebook))
- return this.$q.reject('Failed to load notebook.');
-
- return notebook;
- });
- }
-
- findIndex(notebook) {
- return this.read()
- .then(() => _.findIndex(this.notebooks, {_id: notebook._id}));
- }
-
- save(notebook) {
- if (this.demo)
- return this.$q.when(DEMO_NOTEBOOK);
-
- return this.$http.post('/api/v1/notebooks/save', notebook)
- .then(({data}) => {
- const idx = _.findIndex(this.notebooks, {_id: data._id});
-
- if (idx >= 0)
- this.notebooks[idx] = data;
- else
- this.notebooks.push(data);
-
- return data;
- })
- .catch(({data}) => Promise.reject(data));
- }
-
- remove(notebook) {
- if (this.demo)
- return this.$q.reject(`Removing "${notebook.name}" notebook is not supported.`);
-
- const key = {_id: notebook._id};
-
- return this.$http.post('/api/v1/notebooks/remove', key)
- .then(() => {
- const idx = _.findIndex(this.notebooks, key);
-
- if (idx >= 0) {
- this.notebooks.splice(idx, 1);
-
- if (idx < this.notebooks.length)
- return this.notebooks[idx];
- }
-
- if (this.notebooks.length > 0)
- return this.notebooks[this.notebooks.length - 1];
-
- return null;
- })
- .catch(({data}) => Promise.reject(data));
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/1367bc98/modules/web-console/frontend/app/modules/sql/Notebook.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/Notebook.service.js b/modules/web-console/frontend/app/modules/sql/Notebook.service.js
deleted file mode 100644
index b0bb64f..0000000
--- a/modules/web-console/frontend/app/modules/sql/Notebook.service.js
+++ /dev/null
@@ -1,74 +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.
- */
-
-export default class Notebook {
- static $inject = ['$state', 'IgniteConfirm', 'IgniteMessages', 'IgniteNotebookData'];
-
- /**
- * @param $state
- * @param confirmModal
- * @param Messages
- * @param {NotebookData} NotebookData
- */
- constructor($state, confirmModal, Messages, NotebookData) {
- this.$state = $state;
- this.confirmModal = confirmModal;
- this.Messages = Messages;
- this.NotebookData = NotebookData;
- }
-
- read() {
- return this.NotebookData.read();
- }
-
- create(name) {
- return this.NotebookData.save({name});
- }
-
- save(notebook) {
- return this.NotebookData.save(notebook);
- }
-
- find(_id) {
- return this.NotebookData.find(_id);
- }
-
- _openNotebook(idx) {
- return this.NotebookData.read()
- .then((notebooks) => {
- const nextNotebook = notebooks.length > idx ? notebooks[idx] : _.last(notebooks);
-
- if (nextNotebook)
- this.$state.go('base.sql.notebook', {noteId: nextNotebook._id});
- else
- this.$state.go('base.configuration.tabs.advanced.clusters');
- });
- }
-
- remove(notebook) {
- return this.confirmModal.confirm(`Are you sure you want to remove notebook: "${notebook.name}"?`)
- .then(() => this.NotebookData.findIndex(notebook))
- .then((idx) => {
- this.NotebookData.remove(notebook)
- .then(() => {
- if (this.$state.includes('base.sql.notebook') && this.$state.params.noteId === notebook._id)
- return this._openNotebook(idx);
- })
- .catch(this.Messages.showError);
- });
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/1367bc98/modules/web-console/frontend/app/modules/sql/notebook.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/notebook.controller.js b/modules/web-console/frontend/app/modules/sql/notebook.controller.js
deleted file mode 100644
index 68d318a..0000000
--- a/modules/web-console/frontend/app/modules/sql/notebook.controller.js
+++ /dev/null
@@ -1,62 +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.
- */
-
-import templateUrl from 'views/sql/notebook-new.tpl.pug';
-
-// Controller that load notebooks in navigation bar .
-export default ['$scope', '$modal', '$state', 'IgniteMessages', 'IgniteNotebook',
- (scope, $modal, $state, Messages, Notebook) => {
- // Pre-fetch modal dialogs.
- const nameModal = $modal({scope, templateUrl, show: false});
-
- scope.create = (name) => {
- return Notebook.create(name)
- .then((notebook) => {
- nameModal.hide();
-
- $state.go('base.sql.notebook', {noteId: notebook._id});
- })
- .catch(Messages.showError);
- };
-
- scope.createNotebook = () => nameModal.$promise.then(nameModal.show);
-
- Notebook.read()
- .then((notebooks) => {
- scope.$watchCollection(() => notebooks, (changed) => {
- if (_.isEmpty(changed))
- return scope.notebooks = [];
-
- scope.notebooks = [
- {text: 'Create new notebook', click: scope.createNotebook},
- {divider: true}
- ];
-
- _.forEach(changed, (notebook) => scope.notebooks.push({
- data: notebook,
- action: {
- icon: 'fa-trash',
- click: (item) => Notebook.remove(item)
- },
- text: notebook.name,
- sref: `base.sql.notebook({noteId:"${notebook._id}"})`
- }));
- });
- })
- .catch(Messages.showError);
- }
-];