blob: 7d91a3f48a82c91f1ff23f4705ac04b1fdba9ba3 [file] [log] [blame]
//-
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
.notebooks-top
breadcrumbs
a.link-success(ui-sref='^.') Notebooks
span(ui-sref='.' ui-sref-active) Notebook '{{notebook.name}}'
cluster-selector
.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)', '{{$ctrl.isDemo ? "Demo notebook cannot be deleted" : "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='default-state') 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() && !paragraph.scanningInProgress' 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') &nbsp; with filter: #[b {{ paragraph.queryArgs.filter }}]
span(ng-if='paragraph.queryArgs.localNid') &nbsp; 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
.row(ng-if='notebook' bs-affix style='margin-bottom: 20px;')
+notebook-rename
-var example = `CREATE TABLE Person(ID INTEGER PRIMARY KEY, NAME VARCHAR(100));\nINSERT INTO Person(ID, NAME) VALUES (1, 'Ed'), (2, 'Ann'), (3, 'Emma');\nSELECT * FROM Person;`;
ignite-information(
data-title='With query notebook you can'
style='margin-bottom: 30px'
ng-init=`example = "${example}"`
)
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
.example
.group
.group-legend
label Examples:
.group-content
.sql-editor(ignite-ace='{\
onLoad: aceInit({}),\
theme: "chrome",\
mode: "sql",\
require: ["ace/ext/language_tools"],\
showGutter: false,\
advanced: {\
enableSnippets: false,\
enableBasicAutocompletion: true,\
enableLiveAutocompletion: true\
}}'
ng-model='example'
readonly='true'
)
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