| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024 |
- ## Licensed to Cloudera, Inc. under one
- ## or more contributor license agreements. See the NOTICE file
- ## distributed with this work for additional information
- ## regarding copyright ownership. Cloudera, Inc. 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.
- <%!
- from desktop import conf
- from desktop.conf import USE_NEW_SIDE_PANELS
- from desktop.lib.i18n import smart_unicode
- from desktop.views import _ko
- from django.utils.translation import ugettext as _
- from metadata.conf import has_navigator
- %>
- <%def name="assistJSModels()">
- <script src="${ static('desktop/js/assist/assistDbEntry.js') }"></script>
- <script src="${ static('desktop/js/assist/assistDbSource.js') }"></script>
- <script src="${ static('desktop/js/assist/assistHdfsEntry.js') }"></script>
- <script src="${ static('desktop/js/assist/assistS3Entry.js') }"></script>
- <script src="${ static('desktop/js/assist/assistCollectionEntry.js') }"></script>
- <script src="${ static('desktop/js/assist/assistHBaseEntry.js') }"></script>
- <script src="${ static('desktop/js/document/hueDocument.js') }"></script>
- <script src="${ static('desktop/js/document/hueFileEntry.js') }"></script>
- </%def>
- <%def name="assistPanel(is_s3_enabled=False)">
- <%namespace name="sqlContextPopover" file="/sql_context_popover.mako" />
- <%namespace name="nav_components" file="/nav_components.mako" />
- ${ sqlContextPopover.sqlContextPopover() }
- ${ nav_components.nav_tags(readOnly=not user.has_hue_permission(action="write", app="metadata")) }
- <style>
- .assist-icon {
- width: 16px;
- height: 16px;
- -webkit-filter: grayscale(1);
- filter: grayscale(1);
- opacity: .8;
- }
- .assist {
- position: relative;
- height: 100%;
- }
- .assist-resizer {
- cursor: row-resize;
- }
- .assist-spinner {
- font-size: 20px;
- color: #BBB;
- }
- .assist-header {
- -ms-flex: 1;
- flex: 1;
- color: #338bb8;
- background-color: #f9f9f9;
- border-top: 1px solid #f1f1f1;
- border-bottom: 1px solid #f1f1f1;
- font-weight: bold;
- letter-spacing: 0.035em;
- font-size: 0.975em;
- line-height: 25px;
- padding-left: 10px;
- height: 24px;
- margin-bottom: 8px;
- }
- .assist-inner-panel {
- position: absolute;
- overflow: hidden;
- padding-right: 3px;
- top: 10px;
- right: 0;
- bottom: 2px;
- left: 10px;
- }
- .assist-inner-header {
- width: 100%;
- color: #737373;
- margin-left:3px;
- margin-bottom:2px;
- font-weight: bold;
- margin-top: 0
- }
- .assist-stretchable-list {
- position:relative;
- overflow-y: auto;
- overflow-x: hidden;
- width: 100%;
- border: none;
- padding: 0;
- margin-bottom: 1px;
- margin-top:3px;
- }
- .assist-header-actions {
- float: right;
- margin-right: 3px;
- opacity: 0;
- }
- .assist-header-actions > div {
- cursor: pointer;
- }
- .assist-panel-switches {
- padding-left: 12px;
- height: 40px;
- border-bottom: 1px solid #f1f1f1;
- }
- .assist-type-switch {
- display: inline-block;
- font-size: 18px;
- margin-right: 2px;
- cursor: pointer;
- }
- .assist-column {
- position: relative;
- }
- .assist-entry,a {
- white-space: nowrap;
- }
- .assist-file-entry {
- margin-right: 15px;
- border: 1px solid transparent;
- }
- .assist-file-entry-drop {
- border: 1px solid #338BB8 !important;
- }
- .assist-tables {
- margin-left: 0;
- }
- .assist-tables a {
- text-decoration: none;
- }
- .assist-tables li {
- list-style: none;
- }
- .assist-breadcrumb > a:hover {
- color: #338bb8;
- }
- .assist-errors {
- padding: 4px 5px;
- font-style: italic;
- }
- .assist-tables > li {
- position: relative;
- padding-top: 2px;
- padding-bottom: 2px;
- padding-left: 4px;
- margin-right: 15px;
- overflow-x: hidden;
- }
- .assist-tables > li.selected {
- background-color: #EEE;
- }
- .assist-breadcrumb {
- padding-top: 0;
- padding-left: 0;
- }
- .assist-breadcrumb span {
- color: #737373;
- }
- .assist-breadcrumb a:not(.inactive-action) {
- cursor: pointer;
- text-decoration: none;
- color: #737373;
- -webkit-transition: color 0.2s ease;
- -moz-transition: color 0.2s ease;
- -ms-transition: color 0.2s ease;
- transition: color 0.2s ease;
- }
- .assist-breadcrumb-text {
- font-size: 14px;
- line-height: 16px;
- vertical-align: top;
- }
- .assist-breadcrumb-back {
- font-size: 15px;
- margin-right:8px;
- }
- .assist-tables-counter {
- color: #d1d1d1;
- font-weight: normal;
- }
- .assist-table-link {
- font-size: 13px;
- }
- .assist-field-link {
- font-size: 12px;
- }
- .assist-table-link,
- .assist-table-link:focus {
- color: #444;
- }
- .assist-field-link,
- .assist-field-link:focus {
- white-space: nowrap;
- color: #737373;
- }
- .assist-db-header-actions {
- position:absolute;
- top: 0;
- right: 0;
- padding-left:4px;
- padding-right: 13px;
- background-color: #FFF;
- }
- .assist-db-header-actions > * {
- margin-left: 2px;
- }
- .assist-actions {
- position:absolute;
- top: 0;
- right: 0;
- padding-left:4px;
- background-color: #FFF;
- }
- .assist-file-actions {
- position:absolute;
- top: 0;
- right: 0;
- padding-right: 2px;
- padding-left:4px;
- background-color: #FFF;
- }
- .table-actions {
- padding-top:2px;
- }
- .assist-tables > li.selected .assist-actions {
- background-color: #EEE;
- }
- .assist-details-wrap {
- display: table;
- width: 100%;
- table-layout: fixed;
- }
- .assist-details-wrap > div {
- display: table-row;
- }
- .highlightable {
- -webkit-transition: all .5s linear;
- -moz-transition: all .5s linear;
- -o-transition: all .5s linear;
- transition: all .5s linear;
- }
- .highlight {
- color: #338BB8 !important;
- padding-left: 8px;
- }
- .assist-details-header {
- display: table-cell;
- width: 95px;
- font-weight: bold;
- }
- .assist-details-value {
- display: table-cell;
- }
- .no-entries {
- font-style: italic;
- }
- .assist-flex-panel {
- position: relative;
- display: -ms-flexbox;
- display: flex;
- -ms-flex-flow: column nowrap;
- flex-flow: column nowrap;
- align-items: stretch;
- height:100%;
- }
- .assist-flex-header {
- overflow: hidden;
- position: relative;
- -ms-flex: 0 0 25px;
- flex: 0 0 25px;
- white-space: nowrap;
- }
- .assist-flex-table-search {
- overflow: hidden;
- position: relative;
- -ms-flex: 0 0 65px;
- flex: 0 0 65px;
- white-space: nowrap;
- }
- .assist-flex-search {
- overflow: hidden;
- position: relative;
- -ms-flex: 0 0 43px;
- flex: 0 0 43px;
- white-space: nowrap;
- }
- .assist-flex-fill {
- position: relative;
- -ms-flex: 1 1 100%;
- flex: 1 1 100%;
- white-space: nowrap;
- overflow-x: hidden;
- overflow-y: auto;
- outline: none !important;
- }
- .database-tree ul {
- margin: 0 !important;
- }
- .database-tree ul li {
- padding-left: 15px;
- }
- .result-entry {
- position: relative;
- clear: both;
- overflow: hidden;
- margin: 0 10px 15px 10px;
- }
- .result-entry .doc-desc {
- font-style: italic;
- font-size: 12px;
- line-height: 15px;
- white-space: normal;
- margin-left: 35px;
- }
- .nav-search-tags {
- display: inline-block;
- margin-left: 3px;
- }
- .nav-search-tags div {
- display: inline-block;
- margin: 0 1px;
- line-height: 10px;
- font-size: 11px;
- padding: 3px 6px;
- color: #FFF;
- background-color: #338BB8;
- border-radius: 6px;
- }
- .result-entry .icon-col {
- width: 35px;
- float:left;
- vertical-align: top;
- padding-top: 7px;
- font-size: 20px;
- color: #338bb8;
- }
- .result-entry .doc-col {
- white-space: nowrap;
- }
- .doc-col-no-desc {
- padding-top: 7px;
- }
- .result-entry .hue-icon {
- font-size: 30px;
- }
- </style>
- <script type="text/html" id="assist-no-database-entries">
- <ul class="assist-tables">
- <li>
- <span style="font-style: italic">${_('The database has no tables')}</span>
- </li>
- </ul>
- </script>
- <script type="text/html" id="assist-no-table-entries">
- <ul>
- <li>
- <span style="font-style: italic" class="assist-entry assist-field-link">${_('The table has no columns')}</span>
- </li>
- </ul>
- </script>
- <script type="text/html" id="assist-entry-actions">
- <div class="assist-actions" data-bind="css: { 'table-actions' : definition.isTable || definition.isView, 'column-actions': definition.isColumn, 'database-actions' : definition.isDatabase } " style="opacity: 0">
- <a class="inactive-action" href="javascript:void(0)" data-bind="visible: navigationSettings.showStats, click: function (data, event) { showContextPopover(data, event); }, css: { 'blue': statsVisible }"><i class="fa fa-fw fa-info" title="${_('Show details')}"></i></a>
- <a class="inactive-action" href="javascript:void(0)" data-bind="visible: navigationSettings.openItem || (navigationSettings.openDatabase && definition.isDatabase), click: openItem"><i class="fa fa-long-arrow-right" title="${_('Open')}"></i></a>
- </div>
- </script>
- <script type="text/html" id="sql-context-items">
- <li><a href="javascript:void(0);" data-bind="click: function (data) { showContextPopover(data, { target: $parentContext.$contextSourceElement }, { left: 4, top: 2 }); }"><i class="fa fa-fw fa-info"></i> ${ _('Show details') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: dblClick"><i class="fa fa-fw fa-pencil"></i> ${ _('Insert') }</a></li>
- <!-- ko if: definition.isColumn -->
- <li class="divider"></li>
- <!-- ko template: { name: 'query-builder-context-items' } --><!-- /ko -->
- <!-- /ko -->
- </script>
- <script type="text/html" id="query-builder-context-items">
- <li data-bind="contextSubMenu: '.hue-context-sub-menu'">
- <a href="javascript:void(0);"><i class="fa fa-fw fa-magic"></i> ${ _('Project') }<i class="sub-icon fa fa-fw fa-chevron-right"></i></a>
- <ul class="hue-context-menu hue-context-sub-menu">
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Select', 'Project', '{0}', false, false); }">${ _('Select') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Select distinct', 'Project', '{0}', false, false); }">${ _('Select distinct') }</a></li>
- </ul>
- </li>
- <li data-bind="contextSubMenu: '.hue-context-sub-menu'">
- <a href="javascript:void(0);"><i class="fa fa-fw fa-magic"></i> ${ _('Aggregate') }<i class="sub-icon fa fa-fw fa-chevron-right"></i></a>
- <ul class="hue-context-menu hue-context-sub-menu">
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Count', 'Aggregate', 'COUNT({0}.{1}) as count_{1}', false, false); }">${ _('Count') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Count distinct', 'Aggregate', 'COUNT(DISTINCT {0}.{1}) as distinct_count_{1}', false, false); }">${ _('Count distinct') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Sum', 'Aggregate', 'SUM({0}.{1}) as sum_{1}', false, false); }">${ _('Sum') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Minimum', 'Aggregate', 'MIN({0}.{1}) as min_{1}', false, false); }">${ _('Minimum') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Maximum', 'Aggregate', 'MAX({0}.{1}) as max_{1}', false, false); }">${ _('Maximum') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Average', 'Aggregate', 'AVG({0}.{1}) as avg_{1}', false, false); }">${ _('Average') }</a></li>
- </ul>
- </li>
- <li data-bind="contextSubMenu: '.hue-context-sub-menu'">
- <a href="javascript:void(0);"><i class="fa fa-fw fa-magic"></i> ${ _('Filter') }<i class="sub-icon fa fa-fw fa-chevron-right"></i></a>
- <ul class="hue-context-menu hue-context-sub-menu">
- <li><a href="javascript:void(0);" data-bind="click: function () { var isNotNullRule = QueryBuilder.getRule(databaseName, tableName, columnName, 'Is not null'); if (isNotNullRule.length) { isNotNullRule.attr('rule', 'Is null'); isNotNullRule.find('.rule').text('Is null'); } else { QueryBuilder.addRule(databaseName, tableName, columnName, 'Is null', 'Filter', '{0}.{1} = null', false, false); } }">${ _('Is null') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { var isNullRule = QueryBuilder.getRule(databaseName, tableName, columnName, 'Is null'); if (isNullRule.length) { isNullRule.attr('rule', 'Is not null'); isNullRule.find('.rule').text('Is not null'); } else { QueryBuilder.addRule(databaseName, tableName, columnName, 'Is not null', 'Filter', '{0}.{1} != null', false, false); } }">${ _('Is not null') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Equal to', 'Filter', '{0}.{1} = {2}', true, true); }">${ _('Equal to') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Not equal to', 'Filter', '{0}.{1} != {2}', true, true); }">${ _('Not equal to') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Greater than', 'Filter', '{0}.{1} > {2}', true, false) }">${ _('Greater than') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { QueryBuilder.addRule(databaseName, tableName, columnName, 'Less than', 'Filter', '{0}.{1} < {2}', true, false); }">${ _('Less than') }</a></li>
- </ul>
- </li>
- <li data-bind="contextSubMenu: '.hue-context-sub-menu'">
- <a href="javascript:void(0);"><i class="fa fa-fw fa-magic"></i> ${ _('Order') }<i class="sub-icon fa fa-fw fa-chevron-right"></i></a>
- <ul class="hue-context-menu hue-context-sub-menu">
- <li><a href="javascript:void(0);" data-bind="click: function () { var descendingRule = QueryBuilder.getRule(databaseName, tableName, columnName, 'Descending'); if (descendingRule.length) { descendingRule.attr('rule', 'Ascending'); descendingRule.find('.rule').text('Ascending'); } else { QueryBuilder.addRule(databaseName, tableName, columnName, 'Ascending', 'Order', '{0}.{1} ASC', false, false); } }">${ _('Ascending') }</a></li>
- <li><a href="javascript:void(0);" data-bind="click: function () { var ascendingRule = QueryBuilder.getRule(databaseName, tableName, columnName, 'Ascending'); if (ascendingRule.length) { ascendingRule.attr('rule', 'Descending'); ascendingRule.find('.rule').text('Descending'); } else { QueryBuilder.addRule(databaseName, tableName, columnName, 'Descending', 'Order', '{0}.{1} DESC', false, false); } }">${ _('Descending') }</a></li>
- </ul>
- </li>
- </script>
- <script type="text/html" id="assist-table-entry">
- <li class="assist-table" data-bind="templateContextMenu: { template: 'sql-context-items', scrollContainer: '.assist-db-scrollable' }, visibleOnHover: { override: statsVisible, selector: '.table-actions' }">
- <div class="assist-actions table-actions" style="opacity: 0">
- <a class="inactive-action" href="javascript:void(0)" data-bind="visible: navigationSettings.showStats, click: showContextPopover, css: { 'blue': statsVisible }"><i class="fa fa-fw fa-info" title="${_('Show details')}"></i></a>
- <a class="inactive-action" href="javascript:void(0)" data-bind="visible: navigationSettings.openItem, click: openItem"><i class="fa fa-long-arrow-right" title="${_('Open')}"></i></a>
- </div>
- <a class="assist-entry assist-table-link" href="javascript:void(0)" data-bind="click: toggleOpen, attr: {'title': definition.title }, draggableText: { text: editorText, meta: {'type': 'sql', 'table': tableName, 'database': databaseName} }">
- <i class="fa fa-fw fa-table muted valign-middle" data-bind="css: { 'fa-eye': definition.isView, 'fa-table': definition.isTable }"></i>
- <span data-bind="text: definition.displayName, css: { 'highlight': highlight }"></span>
- </a>
- <div class="center" data-bind="visible: loading"><i class="fa fa-spinner fa-spin assist-spinner"></i></div>
- <!-- ko template: { if: open, name: 'assist-db-entries' } --><!-- /ko -->
- </li>
- </script>
- <script type="text/html" id="assist-column-entry">
- <li data-bind="templateContextMenu: { template: 'sql-context-items', scrollContainer: '.assist-db-scrollable' }, visible: ! hasErrors(), visibleOnHover: { childrenOnly: true, override: statsVisible, selector: definition.isView ? '.table-actions' : '.column-actions' }, css: { 'assist-table': definition.isView, 'assist-column': definition.isColumn || definition.isComplex }">
- <div class="assist-actions column-actions" style="opacity: 0">
- <a class="inactive-action" href="javascript:void(0)" data-bind="visible: navigationSettings.showStats, click: showContextPopover, css: { 'blue': statsVisible }"><i class="fa fa-fw fa-info" title="${_('Show details')}"></i></a>
- </div>
- <!-- ko if: expandable -->
- <a class="assist-entry assist-field-link" href="javascript:void(0)" data-bind="click: toggleOpen, attr: {'title': definition.title }">
- <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName }, text: definition.displayName, draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName } }"></span>
- </a>
- <!-- /ko -->
- <!-- ko ifnot: expandable -->
- <div style="cursor: default;" class="assist-entry assist-field-link" href="javascript:void(0)" data-bind="event: { dblClick: dblClick }, attr: {'title': definition.title }">
- <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName}, text: definition.displayName, draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName} }"></span>
- </div>
- <!-- /ko -->
- <div class="center" data-bind="visible: loading"><i class="fa fa-spinner fa-spin assist-spinner"></i></div>
- <!-- ko template: { if: open, name: 'assist-db-entries' } --><!-- /ko -->
- </li>
- </script>
- <script type="text/html" id="assist-db-entries">
- <!-- ko if: ! hasErrors() && hasEntries() && ! loading() && filteredEntries().length == 0 -->
- <ul class="assist-tables">
- <li class="assist-entry no-entries">${_('No results found')}</li>
- </ul>
- <!-- /ko -->
- <!-- ko if: ! hasErrors() && hasEntries() && ! loading() && filteredEntries().length > 0 -->
- <ul class="database-tree" data-bind="foreachVisible: { data: filteredEntries, minHeight: (definition.isTable || definition.isView ? 20 : 25), container: '.assist-db-scrollable' }, css: { 'assist-tables': definition.isDatabase }">
- <!-- ko template: { if: definition.isTable || definition.isView, name: 'assist-table-entry' } --><!-- /ko -->
- <!-- ko template: { ifnot: definition.isTable || definition.isView, name: 'assist-column-entry' } --><!-- /ko -->
- </ul>
- <!-- /ko -->
- <!-- ko template: { if: ! hasEntries() && ! loading() && (definition.isTable || definition.isView), name: 'assist-no-table-entries' } --><!-- /ko -->
- <!-- ko template: { if: ! hasEntries() && ! loading() && definition.isDatabase, name: 'assist-no-database-entries' } --><!-- /ko -->
- <!-- ko if: hasErrors -->
- <ul class="assist-tables">
- <!-- ko if: definition.isTable -->
- <li class="assist-errors">${ _('Error loading columns.') }</li>
- <!-- /ko -->
- <!-- ko ifnot: definition.isTable -->
- <li class="assist-errors">${ _('Error loading fields.') }</li>
- <!-- /ko -->
- </ul>
- <!-- /ko -->
- </script>
- <script type="text/html" id="assist-db-breadcrumb">
- <div class="assist-flex-header assist-breadcrumb">
- <!-- ko if: selectedSource() && ! selectedSource().selectedDatabase() && sources().length === 1 -->
- <i class="fa fa-server assist-breadcrumb-text"></i>
- <span class="assist-breadcrumb-text" data-bind="text: breadcrumb"></span>
- <!-- /ko -->
- <!-- ko if: selectedSource() && ! selectedSource().selectedDatabase() && sources().length > 1 -->
- <a data-bind="click: back">
- <i class="fa fa-chevron-left assist-breadcrumb-back"></i>
- <i class="fa fa-server assist-breadcrumb-text"></i>
- <span class="assist-breadcrumb-text" data-bind="text: breadcrumb"></span>
- </a>
- <!-- /ko -->
- <!-- ko if: selectedSource() && selectedSource().selectedDatabase() -->
- <a data-bind="click: back">
- <i class="fa fa-chevron-left assist-breadcrumb-back" ></i>
- <i class="fa fa-database assist-breadcrumb-text"></i>
- <span class="assist-breadcrumb-text" data-bind="text: breadcrumb"></span>
- </a>
- <!-- /ko -->
- </div>
- </script>
- <script type="text/html" id="assist-sql-inner-panel">
- <div class="assist-inner-panel">
- <div class="assist-flex-panel">
- <!-- ko template: { if: breadcrumb() !== null, name: 'assist-db-breadcrumb' } --><!-- /ko -->
- <!-- ko template: { ifnot: selectedSource, name: 'assist-sources-template' } --><!-- /ko -->
- <!-- ko with: selectedSource -->
- <!-- ko template: { ifnot: selectedDatabase, name: 'assist-databases-template' }--><!-- /ko -->
- <!-- ko with: selectedDatabase -->
- <!-- ko template: { name: 'assist-tables-template' } --><!-- /ko -->
- <!-- /ko -->
- <!-- /ko -->
- </div>
- <!-- ko with: $parents[1] -->
- <!-- ko template: { if: searchActive() && searchInput() !== '' && navigatorEnabled(), name: 'nav-search-result' } --><!-- /ko -->
- <!-- /ko -->
- </div>
- </script>
- <script type="text/html" id="s3-details-content">
- <!-- ko with: definition -->
- <div class="assist-details-wrap">
- <div><div class="assist-details-header">${ _('Size') }</div><div class="assist-details-value" data-bind="text: humansize"></div></div>
- <div><div class="assist-details-header">${ _('Permissions') }</div><div class="assist-details-value" data-bind="text: rwx"></div></div>
- </div>
- <!-- /ko -->
- </script>
- <script type="text/html" id="s3-details-title">
- <span data-bind="text: definition.name"></span>
- </script>
- <script type="text/html" id="assist-s3-header-actions">
- <div class="assist-db-header-actions" style="margin-top: -1px;">
- <a class="inactive-action" href="javascript:void(0)" data-bind="click: function () { huePubSub.publish('assist.s3.refresh'); }"><i class="pointer fa fa-refresh" data-bind="css: { 'fa-spin blue' : loading }" title="${_('Manual refresh')}"></i></a>
- </div>
- </script>
- <script type="text/html" id="assist-s3-inner-panel">
- <div class="assist-inner-panel">
- <div class="assist-flex-panel">
- <!-- ko with: selectedS3Entry -->
- <div class="assist-flex-header assist-breadcrumb" >
- <!-- ko if: parent !== null -->
- <a href="javascript: void(0);" data-bind="click: function () { huePubSub.publish('assist.selectS3Entry', parent); }">
- <i class="fa fa-chevron-left" style="font-size: 15px;margin-right:8px;"></i>
- <i class="fa fa-folder-o" style="font-size: 14px; line-height: 16px; vertical-align: top; margin-right:4px;"></i>
- <span style="font-size: 14px;line-height: 16px;vertical-align: top;" data-bind="text: path"></span>
- </a>
- <!-- /ko -->
- <!-- ko if: parent === null -->
- <div>
- <i class="fa fa-folder-o" style="font-size: 14px; line-height: 16px;vertical-align: top; margin-right:4px;"></i>
- <span style="font-size: 14px;line-height: 16px;vertical-align: top;" data-bind="text: path"></span>
- </div>
- <!-- /ko -->
- <!-- ko template: 'assist-s3-header-actions' --><!-- /ko -->
- </div>
- <div class="assist-flex-fill assist-s3-scrollable">
- <div data-bind="visible: ! loading() && ! hasErrors()" style="position: relative;">
- <!-- ko hueSpinner: { spin: loadingMore, overlay: true } --><!-- /ko -->
- <ul class="assist-tables" data-bind="foreachVisible: { data: entries, minHeight: 20, container: '.assist-s3-scrollable', fetchMore: $data.fetchMore.bind($data) }">
- <li class="assist-entry assist-table-link" style="position: relative;" data-bind="visibleOnHover: { 'selector': '.assist-actions' }">
- <div class="assist-actions table-actions" style="opacity: 0;" >
- <a style="padding: 0 3px;" class="inactive-action" href="javascript:void(0);" data-bind="templatePopover : { contentTemplate: 's3-details-content', titleTemplate: 's3-details-title', minWidth: '320px' }">
- <i class='fa fa-info' title="${ _('Details') }"></i>
- </a>
- </div>
- <a href="javascript:void(0)" class="assist-entry assist-table-link" data-bind="multiClick: { click: toggleOpen, dblClick: dblClick }, attr: {'title': definition.name }">
- <!-- ko if: definition.type === 'dir' -->
- <i class="fa fa-fw fa-folder-o muted valign-middle"></i>
- <!-- /ko -->
- <!-- ko if: definition.type === 'file' -->
- <i class="fa fa-fw fa-file-o muted valign-middle"></i>
- <!-- /ko -->
- <span draggable="true" data-bind="text: definition.name, draggableText: { text: '\'' + path + '\'', meta: {'type': 's3', 'definition': definition} }"></span>
- </a>
- </li>
- </ul>
- <!-- ko if: !loading() && entries().length === 0 -->
- <ul class="assist-tables">
- <li class="assist-entry" style="font-style: italic;">${_('Empty directory')}</li>
- </ul>
- <!-- /ko -->
- </div>
- <!-- ko hueSpinner: { spin: loading, center: true, size: 'large' } --><!-- /ko -->
- <div class="assist-errors" data-bind="visible: ! loading() && hasErrors()">
- <span>${ _('Error loading contents.') }</span>
- </div>
- </div>
- <!-- /ko -->
- </div>
- <!-- ko with: $parents[1] -->
- <!-- ko template: { if: searchActive() && searchInput() !== '' && navigatorEnabled(), name: 'nav-search-result' } --><!-- /ko -->
- <!-- /ko -->
- </div>
- </script>
- <script type="text/html" id="hdfs-details-content">
- <!-- ko with: definition -->
- <div class="assist-details-wrap">
- <div><div class="assist-details-header">${ _('Size') }</div><div class="assist-details-value" data-bind="text: humansize"></div></div>
- <!-- ko with: stats -->
- <div><div class="assist-details-header">${ _('User') }</div><div class="assist-details-value" data-bind="text: user"></div></div>
- <div><div class="assist-details-header">${ _('Group') }</div><div class="assist-details-value" data-bind="text: group"></div></div>
- <!-- /ko -->
- <div><div class="assist-details-header">${ _('Permissions') }</div><div class="assist-details-value" data-bind="text: rwx"></div></div>
- <div><div class="assist-details-header">${ _('Date') }</div><div class="assist-details-value" data-bind="text: mtime"></div></div>
- </div>
- <!-- /ko -->
- </script>
- <script type="text/html" id="hdfs-details-title">
- <span data-bind="text: definition.name"></span>
- </script>
- <script type="text/html" id="assist-hdfs-header-actions">
- <div class="assist-db-header-actions" style="margin-top: -1px;">
- <a class="inactive-action" href="javascript:void(0)" data-bind="click: function () { huePubSub.publish('assist.hdfs.refresh'); }"><i class="pointer fa fa-refresh" data-bind="css: { 'fa-spin blue' : loading }" title="${_('Manual refresh')}"></i></a>
- </div>
- </script>
- <script type="text/html" id="assist-hdfs-inner-panel">
- <div class="assist-inner-panel">
- <div class="assist-flex-panel">
- <!-- ko with: selectedHdfsEntry -->
- <div class="assist-flex-header assist-breadcrumb" >
- <!-- ko if: parent !== null -->
- <a href="javascript: void(0);" data-bind="click: function () { huePubSub.publish('assist.selectHdfsEntry', parent); }">
- <i class="fa fa-chevron-left" style="font-size: 15px;margin-right:8px;"></i>
- <i class="fa fa-folder-o" style="font-size: 14px; line-height: 16px; vertical-align: top; margin-right:4px;"></i>
- <span style="font-size: 14px;line-height: 16px;vertical-align: top;" data-bind="text: path"></span>
- </a>
- <!-- /ko -->
- <!-- ko if: parent === null -->
- <div>
- <i class="fa fa-folder-o" style="font-size: 14px; line-height: 16px;vertical-align: top; margin-right:4px;"></i>
- <span style="font-size: 14px;line-height: 16px;vertical-align: top;" data-bind="text: path"></span>
- </div>
- <!-- /ko -->
- <!-- ko template: 'assist-hdfs-header-actions' --><!-- /ko -->
- </div>
- <div class="assist-flex-fill assist-hdfs-scrollable">
- <div data-bind="visible: ! loading() && ! hasErrors()" style="position: relative;">
- <!-- ko hueSpinner: { spin: loadingMore, overlay: true } --><!-- /ko -->
- <ul class="assist-tables" data-bind="foreachVisible: { data: entries, minHeight: 20, container: '.assist-hdfs-scrollable', fetchMore: $data.fetchMore.bind($data) }">
- <li class="assist-entry assist-table-link" style="position: relative;" data-bind="visibleOnHover: { 'selector': '.assist-actions' }">
- <div class="assist-actions table-actions" style="opacity: 0;" >
- <a style="padding: 0 3px;" class="inactive-action" href="javascript:void(0);" data-bind="templatePopover : { contentTemplate: 'hdfs-details-content', titleTemplate: 'hdfs-details-title', minWidth: '320px' }">
- <i class='fa fa-info' title="${ _('Details') }"></i>
- </a>
- </div>
- <a href="javascript:void(0)" class="assist-entry assist-table-link" data-bind="multiClick: { click: toggleOpen, dblClick: dblClick }, attr: {'title': definition.name }">
- <!-- ko if: definition.type === 'dir' -->
- <i class="fa fa-fw fa-folder-o muted valign-middle"></i>
- <!-- /ko -->
- <!-- ko if: definition.type === 'file' -->
- <i class="fa fa-fw fa-file-o muted valign-middle"></i>
- <!-- /ko -->
- <span draggable="true" data-bind="text: definition.name, draggableText: { text: '\'' + path + '\'', meta: {'type': 'hdfs', 'definition': definition} }"></span>
- </a>
- </li>
- </ul>
- <!-- ko if: !loading() && entries().length === 0 -->
- <ul class="assist-tables">
- <li class="assist-entry" style="font-style: italic;">${_('Empty directory')}</li>
- </ul>
- <!-- /ko -->
- </div>
- <!-- ko hueSpinner: { spin: loading, center: true, size: 'large' } --><!-- /ko -->
- <div class="assist-errors" data-bind="visible: ! loading() && hasErrors()">
- <span>${ _('Error loading contents.') }</span>
- </div>
- </div>
- <!-- /ko -->
- </div>
- <!-- ko with: $parents[1] -->
- <!-- ko template: { if: searchActive() && searchInput() !== '' && navigatorEnabled(), name: 'nav-search-result' } --><!-- /ko -->
- <!-- /ko -->
- </div>
- </script>
- <script type="text/html" id="file-details-content">
- <!-- ko with: definition -->
- <div class="assist-details-wrap">
- <div><div class="assist-details-header">${ _('Description') }</div><div class="assist-details-value" data-bind="text: description"></div></div>
- <div><div class="assist-details-header">${ _('Modified') }</div><div class="assist-details-value" data-bind="text: localeFormat(last_modified)"></div></div>
- <div><div class="assist-details-header">${ _('Owner') }</div><div class="assist-details-value" data-bind="text: owner"></div></div>
- </div>
- <!-- /ko -->
- </script>
- <script type="text/html" id="file-details-title">
- <span data-bind="text: definition().name"></span>
- </script>
- <script type="text/html" id="assist-document-header-actions">
- <div class="assist-header-actions" style="margin-top: -1px;">
- <a class="inactive-action" href="javascript:void(0)"><i class="pointer fa fa-filter" title="${_('Filter')}"></i></a>
- <a class="inactive-action" href="javascript:void(0)" data-bind="click: function () { huePubSub.publish('assist.file.refresh'); }"><i class="pointer fa fa-refresh" data-bind="css: { 'fa-spin blue' : loading }" title="${_('Manual refresh')}"></i></a>
- </div>
- </script>
- <script type="text/html" id="assist-document-panel">
- <div class="assist-inner-panel">
- <div class="assist-flex-header">
- <!-- ko with: activeEntry -->
- <div class="assist-inner-header assist-breadcrumb">
- <!-- ko ifnot: isRoot -->
- <a href="javascript: void(0);" data-bind="click: function () { parent.makeActive(); }">
- <i class="fa fa-chevron-left" style="font-size: 15px;margin-right:8px;"></i>
- <i class="fa fa-folder-o" style="font-size: 14px; line-height: 16px; vertical-align: top; margin-right:4px;"></i>
- <span style="font-size: 14px;line-height: 16px;vertical-align: top;" data-bind="text: definition().name"></span>
- </a>
- <!-- /ko -->
- <!-- ko if: isRoot -->
- <div>
- <i class="fa fa-folder-o" style="font-size: 14px; line-height: 16px;vertical-align: top;margin-right:4px;"></i>
- <span style="font-size: 14px;line-height: 16px;vertical-align: top;">/</span>
- </div>
- <!-- /ko -->
- <!-- ko template: 'assist-document-header-actions' --><!-- /ko -->
- </div>
- <!-- /ko -->
- </div>
- <div class="assist-flex-fill assist-file-scrollable">
- <!-- ko with: activeEntry -->
- <div data-bind="visible: ! loading() && ! hasErrors() && entries().length > 0">
- <ul class="assist-tables" data-bind="foreachVisible: {data: entries, minHeight: 20, container: '.assist-file-scrollable' }">
- <li class="assist-entry assist-file-entry" style="position: relative;" data-bind="assistFileDroppable, visibleOnHover: { 'selector': '.assist-file-actions' }">
- <div class="assist-file-actions table-actions" style="opacity: 0;" >
- <a style="padding: 0 3px;" class="inactive-action" href="javascript:void(0);" data-bind="templatePopover : { contentTemplate: 'file-details-content', titleTemplate: 'file-details-title', minWidth: '350px' }">
- <i class='fa fa-info' title="${ _('Details') }"></i>
- </a>
- </div>
- <a href="javascript:void(0)" class="assist-entry assist-table-link" data-bind="click: open, attr: {'title': name }">
- <!-- ko if: isDirectory -->
- <i class="fa fa-fw fa-folder-o muted valign-middle"></i>
- <!-- /ko -->
- <!-- ko ifnot: isDirectory -->
- <i class="fa fa-fw fa-file-o muted valign-middle"></i>
- <!-- /ko -->
- <span data-bind="draggableText: { text: definition().name, meta: {'type': 'document', 'definition': definition()} }, text: definition().name"></span>
- </a>
- </li>
- </ul>
- </div>
- <div data-bind="visible: !loading() && ! hasErrors() && entries().length === 0">
- <span style="font-style: italic;">${_('Empty directory')}</span>
- </div>
- <div class="center" data-bind="visible: loading() && ! hasErrors()">
- <!--[if !IE]><!--><i class="fa fa-spinner fa-spin" style="font-size: 20px; color: #BBB"></i><!--<![endif]-->
- <!--[if IE]><img src="${ static('desktop/art/spinner.gif') }"/><![endif]-->
- </div>
- <div class="assist-errors" data-bind="visible: ! loading() && hasErrors()">
- <span>${ _('Error loading contents.') }</span>
- </div>
- <!-- /ko -->
- <!-- ko with: $parents[1] -->
- <!-- ko template: { if: searchActive() && searchInput() !== '' && navigatorEnabled(), name: 'nav-search-result' } --><!-- /ko -->
- <!-- /ko -->
- </div>
- </div>
- </script>
- <script type="text/html" id="assist-documents-inner-panel">
- <div class="assist-inner-panel">
- <div class="assist-flex-panel">
- <!-- ko template: 'assist-document-panel' --><!-- /ko -->
- </div>
- </div>
- </script>
- <script type="text/html" id="assist-collections-header-actions">
- <div class="assist-db-header-actions" style="margin-top: -1px;">
- <a class="inactive-action" href="javascript:void(0)" data-bind="click: $parent.toggleSearch, css: { 'blue' : $parent.isSearchVisible }"><i class="pointer fa fa-filter" title="${_('Filter')}"></i></a>
- <a class="inactive-action" href="javascript:void(0)" data-bind="click: function () { huePubSub.publish('assist.collections.refresh'); }"><i class="pointer fa fa-refresh" data-bind="css: { 'fa-spin blue' : loading }" title="${_('Manual refresh')}"></i></a>
- </div>
- </script>
- <script type="text/html" id="assist-collections-inner-panel">
- <div class="assist-inner-panel">
- <div class="assist-flex-panel">
- <!-- ko with: selectedCollectionEntry -->
- <div class="assist-inner-header assist-breadcrumb">
- ${_('Collections')}
- <!-- ko template: 'assist-collections-header-actions' --><!-- /ko -->
- </div>
- <div class="assist-flex-table-search" data-bind="visible: $parent.isSearchVisible() && !loading() && !hasErrors() && entries().length > 0">
- <div>
- <label class="checkbox inline-block margin-left-5"><input type="checkbox" data-bind="checked: $parent.showCores" />${_('Show cores')}</label>
- </div>
- <div><input id="searchInput" class="clearable" type="text" placeholder="${ _('Collection name...') }" style="width:90%;" data-bind="hasFocus: $parent.editingSearch, clearable: $parent.filter, value: $parent.filter, valueUpdate: 'afterkeydown'"/></div>
- </div>
- <div class="assist-flex-fill assist-collections-scrollable">
- <div data-bind="visible: ! loading() && ! hasErrors()" style="position: relative;">
- <ul class="assist-tables" data-bind="foreachVisible: { data: filteredEntries, minHeight: 20, container: '.assist-collections-scrollable' }">
- <li class="assist-entry assist-table-link" style="position: relative;" data-bind="visibleOnHover: { 'selector': '.assist-actions' }">
- <a href="javascript:void(0)" class="assist-entry assist-table-link" data-bind="multiClick: { click: click, dblClick: dblClick }, attr: {'title': definition.name }">
- <i class="fa fa-fw fa-search muted valign-middle"></i>
- <span draggable="true" data-bind="text: definition.name, draggableText: { text: '\'' + path + '\'', meta: {'type': 'collection', 'definition': definition} }"></span>
- </a>
- </li>
- </ul>
- <!-- ko if: !loading() && entries().length === 0 -->
- <ul class="assist-tables">
- <li class="assist-entry" style="font-style: italic;">${_('No collections available.')}</li>
- </ul>
- <!-- /ko -->
- </div>
- <!-- ko hueSpinner: { spin: loading, center: true, size: 'large' } --><!-- /ko -->
- <div class="assist-errors" data-bind="visible: ! loading() && hasErrors()">
- <span>${ _('Error loading contents.') }</span>
- </div>
- </div>
- <!-- /ko -->
- </div>
- <!-- ko with: $parents[1] -->
- <!-- ko template: { if: searchActive() && searchInput() !== '' && navigatorEnabled(), name: 'nav-search-result' } --><!-- /ko -->
- <!-- /ko -->
- </div>
- </script>
- <script type="text/html" id="assist-hbase-header-actions">
- <div class="assist-db-header-actions" style="margin-top: -1px;">
- <a class="inactive-action" href="javascript:void(0)" data-bind="click: function () { huePubSub.publish('assist.hbase.refresh'); }"><i class="pointer fa fa-refresh" data-bind="css: { 'fa-spin blue' : loading }" title="${_('Manual refresh')}"></i></a>
- </div>
- </script>
- <script type="text/html" id="assist-hbase-inner-panel">
- <div class="assist-inner-panel">
- <div class="assist-flex-panel">
- <!-- ko with: selectedHBaseEntry -->
- <div class="assist-inner-header assist-breadcrumb" >
- <!-- ko if: definition.host !== '' -->
- <a href="javascript: void(0);" data-bind="click: function () { huePubSub.publish('assist.clickHBaseRootItem'); }">
- <i class="fa fa-chevron-left" style="font-size: 15px;margin-right:8px;"></i>
- <i class="fa fa-th-large" style="font-size: 14px; line-height: 16px; vertical-align: top; margin-right:4px;"></i>
- <span style="font-size: 14px;line-height: 16px;vertical-align: top;" data-bind="text: definition.name"></span>
- </a>
- <!-- /ko -->
- <!-- ko if: definition.host === '' -->
- ${_('Clusters')}
- <!-- /ko -->
- <!-- ko template: 'assist-hbase-header-actions' --><!-- /ko -->
- </div>
- <div class="assist-flex-fill assist-hbase-scrollable">
- <div data-bind="visible: ! loading() && ! hasErrors()" style="position: relative;">
- <ul class="assist-tables" data-bind="foreachVisible: { data: entries, minHeight: 20, container: '.assist-hbase-scrollable' }">
- <li class="assist-entry assist-table-link" style="position: relative;" data-bind="visibleOnHover: { 'selector': '.assist-actions' }">
- <a href="javascript:void(0)" class="assist-entry assist-table-link" data-bind="multiClick: { click: click, dblClick: dblClick }, attr: {'title': definition.name }">
- <!-- ko if: definition.host -->
- <i class="fa fa-fw fa-th-large muted valign-middle"></i>
- <!-- /ko -->
- <!-- ko ifnot: definition.host -->
- <i class="fa fa-fw fa-th muted valign-middle"></i>
- <!-- /ko -->
- <span draggable="true" data-bind="text: definition.name, draggableText: { text: '\'' + definition.name + '\'', meta: {'type': 'collection', 'definition': definition} }"></span>
- </a>
- </li>
- </ul>
- <!-- ko if: !loading() && entries().length === 0 -->
- <ul class="assist-tables">
- <li class="assist-entry" style="font-style: italic;">
- <!-- ko if: definition.host === '' -->
- ${_('No clusters available.')}
- <!-- /ko -->
- <!-- ko if: definition.host !== '' -->
- ${_('No tables available.')}
- <!-- /ko -->
- </li>
- </ul>
- <!-- /ko -->
- </div>
- <!-- ko hueSpinner: { spin: loading, center: true, size: 'large' } --><!-- /ko -->
- <div class="assist-errors" data-bind="visible: ! loading() && hasErrors()">
- <span>${ _('Error loading contents.') }</span>
- </div>
- </div>
- <!-- /ko -->
- </div>
- <!-- ko with: $parents[1] -->
- <!-- ko template: { if: searchActive() && searchInput() !== '' && navigatorEnabled(), name: 'nav-search-result' } --><!-- /ko -->
- <!-- /ko -->
- </div>
- </script>
- <script type="text/html" id="assist-sources-template">
- <div class="assist-flex-header">
- <div class="assist-inner-header">
- ${_('Sources')}
- </div>
- </div>
- <div class="assist-flex-fill">
- <ul class="assist-tables" data-bind="foreach: sources">
- <li class="assist-table">
- <a class="assist-table-link" href="javascript: void(0);" data-bind="click: function () { $parent.selectedSource($data); }"><i class="fa fa-fw fa-server muted valign-middle"></i> <span data-bind="text: name"></span></a>
- </li>
- </ul>
- </div>
- </script>
- <script type="text/html" id="ask-for-invalidate-title">
- <a class="pull-right pointer close-popover inactive-action"><i class="fa fa-times"></i></a>
- </script>
- <script type="text/html" id="ask-for-invalidate-content">
- <label class="radio" style="margin-bottom: 2px;">
- <input type="radio" name="refreshImpala" value="cache" data-bind="checked: invalidateOnRefresh" />
- ${ _('Clear cache') }
- </label>
- <label class="radio" style="margin-bottom: 2px;">
- <input type="radio" name="refreshImpala" value="invalidate" data-bind="checked: invalidateOnRefresh" />
- ${ _('Perform incremental metadata update') }
- </label>
- <div style="display: inline-block; margin-left: 20px; font-style: italic; color: #999;">${ _('This will sync missing tables in Hive.') }</div>
- <label class="radio" style="margin-bottom: 2px;">
- <input type="radio" name="refreshImpala" value="invalidateAndFlush" data-bind="checked: invalidateOnRefresh" />
- ${ _('Invalidate all metadata and rebuild index') }
- </label>
- <div style="display: inline-block; margin-left: 20px; font-style: italic; color: #999;">${ _('WARNING: This can be both resource and time-intensive.') }</div>
- <div style="width: 100%; display: inline-block; margin-top: 5px;"><button class="pull-right btn btn-primary" data-bind="css: { 'btn-primary': invalidateOnRefresh() !== 'invalidateAndFlush', 'btn-danger': invalidateOnRefresh() === 'invalidateAndFlush' }, click: function () { huePubSub.publish('close.popover'); triggerRefresh(); }, clickBubble: false">${ _('Refresh') }</button></div>
- </script>
- <script type="text/html" id="assist-db-header-actions">
- <div class="assist-db-header-actions">
- <span class="assist-tables-counter">(<span data-bind="text: filteredEntries().length"></span>)</span>
- <!-- ko ifnot: loading -->
- <a class="inactive-action" href="javascript:void(0)" data-bind="click: toggleSearch, css: { 'blue' : isSearchVisible }"><i class="pointer fa fa-filter" title="${_('Filter')}"></i></a>
- <!-- ko if: sourceType === 'impala' -->
- <a class="inactive-action" href="javascript:void(0)" data-bind="templatePopover : { contentTemplate: 'ask-for-invalidate-content', titleTemplate: 'ask-for-invalidate-title', trigger: 'click', minWidth: '320px' }"><i class="pointer fa fa-refresh" data-bind="css: { 'fa-spin blue' : loading }" title="${_('Manually refresh the table list')}"></i></a>
- <!-- /ko -->
- <!-- ko if: sourceType !== 'impala' -->
- <a class="inactive-action" href="javascript:void(0)" data-bind="click: triggerRefresh"><i class="pointer fa fa-refresh" data-bind="css: { 'fa-spin blue' : loading }" title="${_('Manually refresh the table list')}"></i></a>
- <!-- /ko -->
- <!-- /ko -->
- <!-- ko if: loading -->
- <span style="color: #aaa;"><i class="fa fa-filter" title="${_('Filter tables')}"></i></span>
- <i class="fa fa-refresh fa-spin blue" title="${_('Manually refresh the table list')}"></i>
- <!-- /ko -->
- </div>
- </script>
- <script type="text/html" id="assist-databases-template">
- <div class="assist-flex-header" data-bind="visibleOnHover: { selector: '.hover-actions', override: loading() || isSearchVisible() }">
- <div class="assist-inner-header">
- ${_('Databases')}
- <!-- ko template: 'assist-db-header-actions' --><!-- /ko -->
- </div>
- </div>
- <div class="assist-flex-search" data-bind="visible: hasEntries() && isSearchVisible() && ! hasErrors()">
- <div><input id="searchInput" class="clearable" type="text" placeholder="${ _('Database name...') }" style="margin-top:3px;width:90%;" data-bind="hasFocus: editingSearch, clearable: filter.query, value: filter.query, valueUpdate: 'afterkeydown'"/></div>
- </div>
- <div class="assist-flex-fill assist-db-scrollable" data-bind="visible: ! hasErrors() && ! loading() && hasEntries()">
- <!-- ko if: ! loading() && filteredEntries().length == 0 -->
- <ul class="assist-tables">
- <li class="assist-entry no-entries">${_('No results found')}</li>
- </ul>
- <!-- /ko -->
- <ul class="assist-tables" data-bind="foreachVisible: {data: filteredEntries, minHeight: 20, container: '.assist-db-scrollable' }">
- <li class="assist-table" data-bind="visibleOnHover: { selector: '.database-actions' }">
- <!-- ko template: { name: 'assist-entry-actions' } --><!-- /ko -->
- <a class="assist-table-link" href="javascript: void(0);" data-bind="click: function () { $parent.selectedDatabase($data); $parent.selectedDatabaseChanged(); }"><i class="fa fa-fw fa-database muted valign-middle"></i> <span class="highlightable" data-bind="text: definition.name, css: { 'highlight': highlight() }"></span></a>
- </li>
- </ul>
- </div>
- <div class="assist-flex-fill" data-bind="visible: loading">
- <!-- ko hueSpinner: { spin: loading, center: true, size: 'large' } --><!-- /ko -->
- </div>
- <div class="assist-flex-fill" data-bind="visible: hasErrors() && ! loading()">
- <span class="assist-errors">${ _('Error loading databases.') }</span>
- </div>
- <div class="assist-flex-fill" data-bind="visible: ! hasErrors() && ! loading() && ! hasEntries()">
- <span class="assist-errors">${ _('No databases found.') }</span>
- </div>
- </script>
- <script type="text/html" id="assist-tables-template">
- <div class="assist-flex-header">
- <div class="assist-inner-header" data-bind="visible: !$parent.loading() && !$parent.hasErrors()">
- ${_('Tables')}
- <!-- ko template: 'assist-db-header-actions' --><!-- /ko -->
- </div>
- </div>
- <div class="assist-flex-table-search" data-bind="visible: hasEntries() && isSearchVisible() && !$parent.loading() && !$parent.hasErrors()">
- <div>
- <label class="checkbox inline-block margin-left-5"><input type="checkbox" data-bind="checked: filter.showTables" />${_('Tables')}</label>
- <label class="checkbox inline-block margin-left-10"><input type="checkbox" data-bind="checked: filter.showViews" />${_('Views')}</label>
- <!-- ko if: filter.enableActiveFilter --><label class="checkbox inline-block margin-left-10"><input type="checkbox" data-bind="checked: filter.showActive" />${_('Active')}</label><!-- /ko -->
- </div>
- <div><input id="searchInput" class="clearable" type="text" placeholder="${ _('Table name...') }" style="width:90%;" data-bind="hasFocus: editingSearch, clearable: filter.query, value: filter.query, valueUpdate: 'afterkeydown'"/></div>
- </div>
- <div class="assist-flex-fill assist-db-scrollable" data-bind="visible: ! hasErrors() && ! loading()">
- <!-- ko template: 'assist-db-entries' --><!-- /ko -->
- </div>
- <div class="assist-flex-fill" data-bind="visible: loading() || $parent.loading()">
- <!-- ko hueSpinner: { spin: loading, center: true, size: 'large' } --><!-- /ko -->
- </div>
- <div class="assist-flex-fill" data-bind="visible: hasErrors() && ! loading()">
- <span class="assist-errors">${ _('Error loading tables.') }</span>
- </div>
- </script>
- <style>
- .nav-autocomplete-item .ui-state-focus {
- border: 1px solid #DBE8F1;
- background-color: #DBE8F1 !important;
- }
- .nav-autocomplete-item-link {
- height: 44px;
- overflow:hidden;
- }
- .nav-autocomplete-item-link i {
- font-size: 18px;
- color: #338bb8;
- }
- .nav-autocomplete-item-link em, .result-entry em {
- font-style: normal;
- font-weight: bold;
- }
- .nav-autocomplete-item-link > div {
- vertical-align: top;
- display:inline-block;
- }
- .nav-autocomplete-divider {
- height: 2px;
- border-top: 1px solid #dddddd;
- }
- </style>
- <script type="text/html" id="nav-search-autocomp-item">
- <a>
- <div class="nav-autocomplete-item-link">
- <div style="padding: 12px 8px 0 8px;"><i class="fa fa-fw" data-bind="css: icon"></i></div>
- <div>
- <div style="font-size: 14px; color: #338bb8" data-bind="html: label, style: { 'padding-top': description ? 0 : '10px' }"></div>
- <!-- ko if: description -->
- <div style="display:inline-block; width: 250px; overflow: hidden; white-space: nowrap; text-overflow:ellipsis; font-size: 12px;" data-bind="html: description"></div>
- <!-- /ko -->
- </div>
- </div>
- </a>
- </script>
- <script type="text/html" id="nav-search-autocomp-no-match">
- <div class="nav-autocomplete-item-link" style="height: 30px;">
- <div style="font-size: 12px; margin: 6px 8px; color: #737373; font-style: italic;">${ _('No recent match found') }</div>
- </div>
- </script>
- <script type="text/html" id="assist-panel-navigator-search">
- <!-- ko if: navigatorEnabled -->
- <div class="search-container" data-bind="style: { 'padding-right': tabsEnabled ? null : '20px' }">
- <input placeholder="${ _('Search...') }" type="text" data-bind="autocomplete: {
- source: navAutocompleteSource,
- itemTemplate: 'nav-search-autocomp-item',
- noMatchTemplate: 'nav-search-autocomp-no-match',
- classPrefix: 'nav-',
- showOnFocus: true,
- onEnter: performSearch,
- reopenPattern: /.*:$/
- },
- hasFocus: searchHasFocus,
- clearable: { value: searchInput, onClear: function () { searchActive(false); huePubSub.publish('autocomplete.close'); } },
- textInput: searchInput,
- valueUpdate: 'afterkeydown',
- attr: { placeholder: '${ _('Search ') }' + $parent.name.replace(/s$/g, '') + ($parent.type == 'sql' ? '${ _(' tables') }' : '${ _(' files') }' ) + '...' }">
- <a class="inactive-action" data-bind="click: performSearch"><i class="fa fa-search" data-bind="css: { 'blue': searchHasFocus() || searchActive() }"></i></a>
- </div>
- <!-- /ko -->
- </script>
- <script type="text/html" id="assist-panel-inner-header">
- <div class="assist-header assist-fixed-height" data-bind="visibleOnHover: { selector: '.assist-header-actions' }, css: { 'assist-resizer': $index() > 0 }" style="display:none;">
- <span data-bind="text: $parent.name"></span>
- <div class="assist-header-actions">
- <div class="inactive-action" data-bind="click: function () { $parent.visible(false) }"><i class="fa fa-times"></i></div>
- </div>
- </div>
- </script>
- <script type="text/html" id="assist-panel-template">
- <div style="display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; position:relative; height: 100%; overflow: hidden;">
- <!-- ko if: availablePanels.length > 1 -->
- <div style="position: relative; flex: 0 0 40px; line-height: 40px;" class="assist-panel-switches">
- <!-- ko foreach: availablePanels -->
- <div class="inactive-action assist-type-switch" data-bind="click: function () { $parent.visiblePanel($data); }, css: { 'blue': $parent.visiblePanel() === $data }, attr: { 'title': name }">
- <i class="fa fa-fw valign-middle" data-bind="css: icon"></i>
- </div>
- <!-- /ko -->
- </div>
- <!-- /ko -->
- <!-- ko with: visiblePanel -->
- <!-- ko template: { if: showNavSearch && $parent.navigatorEnabled, name: 'assist-panel-navigator-search', data: $parent }--><!-- /ko -->
- <div style="position: relative; -ms-flex: 1 1 100%; flex: 1 1 100%; overflow: hidden; padding-top: 10px;" data-bind="style: { 'padding-top': $parent.availablePanels.length > 1 ? '10px' : '5px' }">
- <!-- ko template: { name: templateName, data: panelData } --><!-- /ko -->
- </div>
- <!-- /ko -->
- </div>
- </script>
- <script type="text/html" id="nav-search-result">
- <div style="position:absolute; left:0; right: 0; top: 0; bottom: 0; overflow: hidden; background-color: #FFF;" data-bind="niceScroll">
- <div class="assist-inner-header" style="width: inherit;">${ _('Search result') }
- <div class="assist-db-header-actions">
- <span class="assist-tables-counter" data-bind="visible: searchResult().length > 0">(<span data-bind="text: searchResultCount">0</span>)</span>
- <a class="inactive-action" href="javascript:void(0)" data-bind="click: function() { searchActive(false); }"><i class="pointer fa fa-times" title="${ _('Close') }"></i></a>
- </div>
- </div>
- <!-- ko hueSpinner: { spin: searching, center: true, size: 'large' } --><!-- /ko -->
- <!-- ko if: !searching() -->
- <!-- ko if: searchResult().length == 0 -->
- <div class="result-entry">${ _('No result found.') }</div>
- <!-- /ko -->
- <div data-bind="foreach: searchResult" style="overflow-x:hidden">
- <div class="result-entry" data-bind="visibleOnHover: { override: statsVisible, selector: '.table-actions' }, event: { mouseover: showNavContextPopoverDelayed, mouseout: clearNavContextPopoverDelay }">
- <div class="icon-col">
- <i class="fa fa-fw valign-middle" data-bind="css: icon"></i>
- </div>
- <div class="doc-col" data-bind="css: { 'doc-col-no-desc' : !hasDescription }">
- <!-- ko if: typeof click !== 'undefined' -->
- <a class="pointer" data-bind="click: click, html: hue_name" target="_blank" ></a>
- <!-- /ko -->
- <!-- ko if: typeof click === 'undefined' -->
- <a class="pointer" data-bind="attr: { 'href': link }, text: originalName" target="_blank" ></a>
- <!-- /ko -->
- <div class="doc-desc" data-bind="html: hue_description"></div>
- </div>
- </div>
- </div>
- <!-- /ko -->
- </div>
- </script>
- <script type="text/javascript" charset="utf-8">
- (function () {
- ko.bindingHandlers.assistFileDroppable = {
- init: function(element, valueAccessor, allBindings, boundEntry) {
- var dragData;
- huePubSub.subscribe('doc.browser.dragging', function (data) {
- dragData = data;
- });
- var $element = $(element);
- if (boundEntry.isDirectory) {
- $element.droppable({
- drop: function () {
- if (dragData && !dragData.dragToSelect) {
- boundEntry.moveHere(dragData.selectedEntries);
- dragData.originEntry.load();
- }
- },
- over: function () {
- if (dragData && !dragData.dragToSelect) {
- $element.addClass('assist-file-entry-drop');
- }
- },
- out: function () {
- $element.removeClass('assist-file-entry-drop');
- }
- })
- }
- }
- };
- /**
- * @param {Object} options
- * @param {ApiHelper} options.apiHelper
- * @param {string} options.type
- * @param {number} options.minHeight
- * @param {string} options.icon
- * @param {boolean} options.visible
- * @param {boolean} [options.showNavSearch] - Default true
- * @param {(AssistDbPanel|AssistHdfsPanel|AssistDocumentsPanel|AssistS3Panel|AssistCollectionsPanel)} panelData
- * @constructor
- */
- function AssistInnerPanel (options) {
- var self = this;
- self.minHeight = options.minHeight;
- self.icon = options.icon;
- self.type = options.type;
- self.name = options.name;
- self.panelData = options.panelData;
- self.showNavSearch = typeof options.showNavSearch !== 'undefined' ? options.showNavSearch : true;
- self.visible = ko.observable(options.visible || true);
- options.apiHelper.withTotalStorage('assist', 'showingPanel_' + self.type, self.visible, false, options.visible);
- self.templateName = 'assist-' + self.type + '-inner-panel';
- var loadWhenVisible = function () {
- if (! self.visible()) {
- return;
- }
- if (self.type === 'documents' && !self.panelData.activeEntry().loaded()) {
- self.panelData.activeEntry().load();
- }
- };
- self.visible.subscribe(loadWhenVisible);
- loadWhenVisible();
- }
- /**
- * @param {Object} options
- * @param {ApiHelper} options.apiHelper
- * @param {Object} options.i18n
- * @param {Object[]} options.sourceTypes - All the available SQL source types
- * @param {string} options.sourceTypes[].name - Example: Hive SQL
- * @param {string} options.sourceTypes[].type - Example: hive
- * @param {string} [options.activeSourceType] - Example: hive
- * @param {Object} options.navigationSettings - enable/disable the links
- * @param {boolean} options.navigationSettings.openItem
- * @param {boolean} options.navigationSettings.showStats
- * @param {boolean} options.navigationSettings.pinEnabled
- * @constructor
- **/
- function AssistDbPanel(options) {
- var self = this;
- self.options = options;
- self.apiHelper = options.apiHelper;
- self.i18n = options.i18n;
- self.sources = ko.observableArray();
- self.sourceIndex = {};
- $.each(options.sourceTypes, function (idx, sourceType) {
- self.sourceIndex[sourceType.type] = new AssistDbSource({
- apiHelper: self.apiHelper,
- i18n: self.i18n,
- type: sourceType.type,
- name: sourceType.name,
- navigationSettings: options.navigationSettings
- });
- self.sources.push(self.sourceIndex[sourceType.type]);
- });
- huePubSub.subscribe('assist.db.highlight', function (location) {
- var foundSource;
- $.each(self.sources(), function (idx, source) {
- if (source.sourceType === location.sourceType) {
- foundSource = source;
- return false;
- }
- });
- if (foundSource) {
- if (foundSource.hasEntries()) {
- self.selectedSource(foundSource);
- foundSource.highlightInside(location.path);
- } else {
- foundSource.initDatabases(function () {
- self.selectedSource(foundSource);
- foundSource.highlightInside(location.path);
- });
- }
- }
- });
- self.selectedSource = ko.observable(null);
- self.setDatabaseWhenLoaded = function (databaseName) {
- if (self.selectedSource().loaded()) {
- self.selectedSource().setDatabase(databaseName);
- } else {
- var subscription = self.selectedSource().loaded.subscribe(function (newValue) {
- if (newValue) {
- self.selectedSource().setDatabase(databaseName);
- subscription.dispose();
- }
- });
- if (!self.selectedSource().loaded() && !self.selectedSource().loading()) {
- self.selectedSource().initDatabases();
- }
- }
- };
- huePubSub.subscribe("assist.set.database", function (databaseDef) {
- if (!databaseDef.source || !self.sourceIndex[databaseDef.source]) {
- return;
- }
- self.selectedSource(self.sourceIndex[databaseDef.source]);
- self.setDatabaseWhenLoaded(databaseDef.name);
- });
- huePubSub.subscribe("assist.get.database", function (source) {
- if (self.sourceIndex[source] && self.sourceIndex[source].selectedDatabase()) {
- huePubSub.publish("assist.database.set", {
- source: source,
- name: self.sourceIndex[source].selectedDatabase().databaseName
- });
- } else {
- huePubSub.publish("assist.database.set", {
- source: source,
- name: null
- });
- }
- });
- huePubSub.publish("assist.db.panel.ready");
- self.selectedSource.subscribe(function (newSource) {
- if (newSource) {
- if (newSource.databases().length === 0) {
- newSource.initDatabases();
- }
- self.apiHelper.setInTotalStorage('assist', 'lastSelectedSource', newSource.sourceType);
- } else {
- self.apiHelper.setInTotalStorage('assist', 'lastSelectedSource');
- }
- });
- self.breadcrumb = ko.computed(function () {
- if (self.selectedSource()) {
- if (self.selectedSource().selectedDatabase()) {
- return self.selectedSource().selectedDatabase().definition.name;
- }
- return self.selectedSource().name;
- }
- return null;
- });
- }
- AssistDbPanel.prototype.back = function () {
- var self = this;
- if (self.selectedSource() && self.selectedSource().selectedDatabase()) {
- self.selectedSource().selectedDatabase(null)
- } else if (self.selectedSource()) {
- self.selectedSource(null);
- }
- };
- AssistDbPanel.prototype.init = function () {
- var self = this;
- var storageSourceType = self.apiHelper.getFromTotalStorage('assist', 'lastSelectedSource');
- if (!self.selectedSource()) {
- if (self.options.activeSourceType) {
- self.selectedSource(self.sourceIndex[self.options.activeSourceType]);
- self.setDatabaseWhenLoaded();
- } else if (storageSourceType && self.sourceIndex[storageSourceType]) {
- self.selectedSource(self.sourceIndex[storageSourceType]);
- self.setDatabaseWhenLoaded();
- }
- }
- };
- /**
- * @param {Object} options
- * @param {ApiHelper} options.apiHelper
- * @param {string} options.user
- * @param {Object} options.i18n
- * @constructor
- **/
- function AssistDocumentsPanel (options) {
- var self = this;
- self.activeEntry = ko.observable();
- self.activeEntry(new HueFileEntry({
- activeEntry: self.activeEntry,
- trashEntry: ko.observable,
- apiHelper: options.apiHelper,
- app: 'documents',
- user: options.user,
- activeSort: ko.observable('name'),
- definition: {
- name: '/',
- type: 'directory'
- }
- }));
- huePubSub.subscribe('assist.document.refresh', function () {
- huePubSub.publish('assist.clear.document.cache');
- self.reload();
- });
- }
- AssistDocumentsPanel.prototype.init = function () {
- var self = this;
- if (! self.activeEntry().loaded()) {
- self.activeEntry().load();
- }
- };
- /**
- * @param {Object} options
- * @param {ApiHelper} options.apiHelper
- * @constructor
- **/
- function AssistHdfsPanel (options) {
- var self = this;
- self.apiHelper = options.apiHelper;
- self.selectedHdfsEntry = ko.observable();
- self.reload = function () {
- var lastKnownPath = self.apiHelper.getFromTotalStorage('assist', 'currentHdfsPath', '/');
- var parts = lastKnownPath.split('/');
- parts.shift();
- var currentEntry = new AssistHdfsEntry({
- definition: {
- name: '/',
- type: 'dir'
- },
- parent: null,
- apiHelper: self.apiHelper
- });
- currentEntry.loadDeep(parts, function (entry) {
- self.selectedHdfsEntry(entry);
- entry.open(true);
- });
- };
- huePubSub.subscribe('assist.selectHdfsEntry', function (entry) {
- self.selectedHdfsEntry(entry);
- self.apiHelper.setInTotalStorage('assist', 'currentHdfsPath', entry.path);
- });
- huePubSub.subscribe('assist.hdfs.refresh', function () {
- huePubSub.publish('assist.clear.hdfs.cache');
- self.reload();
- });
- }
- AssistHdfsPanel.prototype.init = function () {
- this.reload();
- };
- /**
- * @param {Object} options
- * @param {ApiHelper} options.apiHelper
- * @constructor
- **/
- function AssistS3Panel (options) {
- var self = this;
- self.apiHelper = options.apiHelper;
- self.selectedS3Entry = ko.observable();
- self.reload = function () {
- var lastKnownPath = self.apiHelper.getFromTotalStorage('assist', 'currentS3Path', '/');
- var parts = lastKnownPath.split('/');
- parts.shift();
- var currentEntry = new AssistS3Entry({
- definition: {
- name: '/',
- type: 'dir'
- },
- parent: null,
- apiHelper: self.apiHelper
- });
- currentEntry.loadDeep(parts, function (entry) {
- self.selectedS3Entry(entry);
- entry.open(true);
- });
- };
- huePubSub.subscribe('assist.selectS3Entry', function (entry) {
- self.selectedS3Entry(entry);
- self.apiHelper.setInTotalStorage('assist', 'currentS3Path', entry.path);
- });
- huePubSub.subscribe('assist.s3.refresh', function () {
- huePubSub.publish('assist.clear.s3.cache');
- self.reload();
- });
- }
- AssistS3Panel.prototype.init = function () {
- this.reload();
- };
- /**
- * @param {Object} options
- * @param {ApiHelper} options.apiHelper
- * @constructor
- **/
- function AssistCollectionsPanel (options) {
- var self = this;
- self.apiHelper = options.apiHelper;
- self.isSearchVisible = ko.observable(false);
- self.editingSearch = ko.observable(false);
- self.toggleSearch = function () {
- self.isSearchVisible(!self.isSearchVisible());
- self.editingSearch(self.isSearchVisible());
- };
- self.showCores = ko.observable(false);
- self.selectedCollectionEntry = ko.observable();
- self.filter = ko.observable('');
- self.reload = function () {
- var currentEntry = new AssistCollectionEntry({
- definition: {
- name: '/',
- type: 'collection'
- },
- apiHelper: self.apiHelper
- }, self.filter, self.showCores);
- self.selectedCollectionEntry(currentEntry);
- currentEntry.loadEntries();
- currentEntry.hasOnlyCores.subscribe(function (onlyCores) {
- self.showCores(onlyCores);
- });
- self.showCores(currentEntry.hasOnlyCores());
- };
- huePubSub.subscribe('assist.clickCollectionItem', function (entry) {
- });
- huePubSub.subscribe('assist.dblClickCollectionItem', function (entry) {
- window.open('/indexer/#edit/' + entry.definition.name);
- });
- huePubSub.subscribe('assist.collections.refresh', function () {
- huePubSub.publish('assist.clear.collections.cache');
- self.reload();
- });
- }
- AssistCollectionsPanel.prototype.init = function () {
- this.reload();
- };
- /**
- * @param {Object} options
- * @param {ApiHelper} options.apiHelper
- * @constructor
- **/
- function AssistHBasePanel(options) {
- var self = this;
- self.apiHelper = options.apiHelper;
- var root = new AssistHBaseEntry({
- definition: {
- host: '',
- name: '',
- port: 0
- },
- apiHelper: self.apiHelper
- });
- self.selectedHBaseEntry = ko.observable();
- self.reload = function () {
- self.selectedHBaseEntry(root);
- root.loadEntries();
- };
- huePubSub.subscribe('assist.clickHBaseItem', function (entry) {
- if (entry.definition.host) {
- entry.loadEntries();
- self.selectedHBaseEntry(entry);
- }
- });
- huePubSub.subscribe('assist.clickHBaseRootItem', function (entry) {
- self.reload();
- });
- huePubSub.subscribe('assist.dblClickHBaseItem', function (entry) {
- window.open('/hbase/#' + self.selectedHBaseEntry().definition.name + '/' + entry.definition.name);
- });
- huePubSub.subscribe('assist.hbase.refresh', function () {
- huePubSub.publish('assist.clear.hbase.cache');
- self.reload();
- });
- }
- AssistHBasePanel.prototype.init = function () {
- this.reload();
- };
- var NAV_FACET_ICON = 'fa-tags';
- var NAV_TYPE_ICONS = {
- 'DATABASE': 'fa-database',
- 'TABLE': 'fa-table',
- 'VIEW': 'fa-eye',
- 'FIELD': 'fa-columns',
- 'PARTITION': 'fa-th',
- 'SOURCE': 'fa-server',
- 'OPERATION': 'fa-cogs',
- 'OPERATION_EXECUTION': 'fa-cog',
- 'DIRECTORY': 'fa-folder-o',
- 'FILE': 'fa-file-o',
- 'SUB_OPERATION': 'fa-code-fork',
- 'COLLECTION': 'fa-search',
- 'HBASE': 'fa-th-large',
- 'HUE': 'fa-file-o'
- };
- /**
- * @param {Object} params
- * @param {string} params.user
- * @param {boolean} params.onlySql - For the old query editors
- * @param {string[]} params.visibleAssistPanels - Panels that will initially be shown regardless of total storage
- * @param {Object} params.sql
- * @param {Object[]} params.sql.sourceTypes - All the available SQL source types
- * @param {string} params.sql.sourceTypes[].name - Example: Hive SQL
- * @param {string} params.sql.sourceTypes[].type - Example: hive
- * @param {string} [params.sql.activeSourceType] - Example: hive
- * @param {Object} params.sql.navigationSettings - enable/disable the links
- * @param {boolean} params.sql.navigationSettings.openItem - Example: true
- * @param {boolean} params.sql.navigationSettings.showStats - Example: true
- * @constructor
- */
- function AssistPanel (params) {
- var self = this;
- var i18n = {
- errorLoadingDatabases: "${ _('There was a problem loading the databases') }",
- errorLoadingTablePreview: "${ _('There was a problem loading the table preview.') }",
- documentTypes: {
- 'query-hive': "${ _('Hive Query') }",
- 'query': "${ _('Query') }",
- 'notebook': "${ _('Notebook') }"
- }
- };
- self.apiHelper = ApiHelper.getInstance({
- i18n: i18n,
- user: params.user
- });
- self.navigatorEnabled = ko.observable('${ has_navigator(user) }' === 'True');
- self.tabsEnabled = '${ USE_NEW_SIDE_PANELS.get() }' === 'True';
- self.searchInput = ko.observable('').extend({rateLimit: 500});
- self.searchResult = ko.observableArray();
- self.searchResultCount = ko.observable();
- self.searchHasFocus = ko.observable(false);
- self.searching = ko.observable(false);
- self.searchActive = ko.observable(false);
- var lastQuery = -1;
- self.availablePanels = [
- new AssistInnerPanel({
- panelData: new AssistDbPanel($.extend({
- apiHelper: self.apiHelper,
- i18n: i18n
- }, params.sql)),
- apiHelper: self.apiHelper,
- name: '${ _("SQL") }',
- type: 'sql',
- icon: 'fa-database',
- minHeight: 75
- })
- ];
- if (self.tabsEnabled) {
- self.availablePanels.push(new AssistInnerPanel({
- panelData: new AssistHdfsPanel({
- apiHelper: self.apiHelper
- }),
- apiHelper: self.apiHelper,
- name: '${ _("HDFS") }',
- type: 'hdfs',
- icon: 'fa-folder-o',
- minHeight: 50
- }));
- if (window.IS_S3_ENABLED) { // coming from common_header.mako
- self.availablePanels.push(new AssistInnerPanel({
- panelData: new AssistS3Panel({
- apiHelper: self.apiHelper
- }),
- apiHelper: self.apiHelper,
- name: '${ _("S3") }',
- type: 's3',
- icon: 'fa-cubes',
- minHeight: 50,
- showNavSearch: false
- }));
- }
- self.availablePanels.push(new AssistInnerPanel({
- panelData: new AssistCollectionsPanel({
- apiHelper: self.apiHelper
- }),
- apiHelper: self.apiHelper,
- name: '${ _("Collections") }',
- type: 'collections',
- icon: 'fa-search-plus',
- minHeight: 50,
- showNavSearch: false
- }));
- self.availablePanels.push(new AssistInnerPanel({
- panelData: new AssistHBasePanel({
- apiHelper: self.apiHelper
- }),
- apiHelper: self.apiHelper,
- name: '${ _("HBase") }',
- type: 'hbase',
- icon: 'fa-th-large',
- minHeight: 50,
- showNavSearch: false
- }));
- self.availablePanels.push(new AssistInnerPanel({
- panelData: new AssistDocumentsPanel({
- user: params.user,
- apiHelper: self.apiHelper,
- i18n: i18n
- }),
- apiHelper: self.apiHelper,
- name: '${ _("Documents") }',
- type: 'documents',
- icon: 'fa-files-o',
- minHeight: 50,
- visible: params.visibleAssistPanels && params.visibleAssistPanels.indexOf('documents') !== -1
- }));
- }
- self.performSearch = function () {
- huePubSub.publish('autocomplete.close');
- if (self.searchInput() === '') {
- self.searchActive(false);
- return;
- }
- if (!self.searchActive()) {
- self.searchActive(true);
- } else if (self.searchInput() === lastQuery) {
- return;
- }
- if (self.searching()) {
- window.setTimeout(function() {
- self.performSearch();
- }, 100);
- return;
- }
- lastQuery = self.searchInput();
- self.searching(true);
- var showInAssist = function (entry) {
- self.searchInput('');
- self.searchHasFocus(false);
- var path = entry.parentPath.split('/').concat([entry.originalName]).splice(1);
- window.setTimeout(function () {
- huePubSub.publish('assist.db.highlight', { sourceType: entry.sourceType.toLowerCase(), path: path });
- }, 200); // For animation effect
- };
- var showNavContextPopover = function (entry, event) {
- if (entry.type && entry.type !== 'TABLE' && entry.type !== 'VIEW' && entry.type !== 'DATABASE' && entry.type !== 'FIELD') {
- return;
- }
- var $source = $(event.target).closest('.result-entry');
- var offset = $source.offset();
- entry.statsVisible(true);
- huePubSub.publish('sql.context.popover.show', {
- data: {
- type: entry.type === 'FIELD' ? 'column' : (entry.type === 'DATABASE' ? 'database' : 'table'),
- identifierChain: $.map(entry.parentPath.substring(1).split('/'), function (part) { return { name: part } }).concat({ name: entry.originalName })
- },
- delayedHide: '.result-entry',
- orientation: 'right',
- sourceType: entry.sourceType.toLowerCase(),
- defaultDatabase: entry.parentPath.substring(1),
- pinEnabled: params.sql.navigationSettings.pinEnabled,
- source: {
- element: event.target,
- left: offset.left,
- top: offset.top - 3,
- right: offset.left + $source.width() + 3,
- bottom: offset.top + $source.height() - 3
- }
- });
- huePubSub.subscribeOnce('sql.context.popover.hidden', function () {
- entry.statsVisible(false);
- });
- };
- var navContextPopoverTimeout = -1;
- var showNavContextPopoverDelayed = function (entry, event) {
- window.clearTimeout(navContextPopoverTimeout);
- navContextPopoverTimeout = window.setTimeout(function () {
- showNavContextPopover(entry, event);
- }, 500);
- };
- var clearNavContextPopoverDelay = function () {
- window.clearTimeout(navContextPopoverTimeout);
- };
- $.post('/desktop/api/search/entities', {
- query_s: ko.mapping.toJSON(self.searchInput()),
- limit: 25,
- sources: ko.mapping.toJSON([self.visiblePanel().type])
- }, function (data) {
- data.entities.forEach(function (entity) {
- entity.statsVisible = ko.observable(false);
- entity.showNavContextPopoverDelayed = showNavContextPopoverDelayed;
- entity.clearNavContextPopoverDelay = clearNavContextPopoverDelay;
- entity.icon = NAV_TYPE_ICONS[entity.type];
- switch (entity.type) {
- case 'DATABASE': { }
- case 'TABLE': { }
- case 'VIEW': { }
- case 'FIELD': {
- entity.click = function () {
- showInAssist(entity);
- };
- break;
- }
- case 'SOURCE': {
- entity.originalDescription = '${ _("Cluster") }: ' + entity.clusterName;
- entity.link = entity.sourceUrl;
- break;
- }
- case 'OPERATION_EXECUTION': {
- entity.link = '/jobbrowser/jobs/' + entity.jobID;
- break;
- }
- case 'DIRECTORY': {
- entity.originalDescription = entity.parentPath;
- entity.link = '/filebrowser/#' + entity.fileSystemPath;
- break;
- }
- case 'FILE': {
- entity.originalDescription = entity.parentPath;
- entity.link = '/filebrowser/#' + entity.fileSystemPath;
- break;
- }
- case 'SUB_OPERATION': {
- entity.originalDescription = entity.metaClassName;
- break;
- }
- case 'PARTITION': {}
- case 'OPERATION': {}
- }
- entity.hasDescription = typeof entity.originalDescription !== 'undefined' && entity.originalDescription !== null && entity.originalDescription.length > 0;
- });
- self.searchResult(data.entities);
- self.searchResultCount(data.count);
- self.searching(false);
- }).fail(function (xhr, textStatus, errorThrown) {
- $(document).trigger("error", xhr.responseText);
- self.searching(false);
- });
- };
- var lastOpenPanelType = self.apiHelper.getFromTotalStorage('assist', 'last.open.panel', self.availablePanels[0].type);
- var lastFoundPanel = self.availablePanels.filter(function (panel) { return panel.type === lastOpenPanelType });
- var dbPanel = self.availablePanels.filter(function (panel) { return panel.type === 'sql' });
- if (lastFoundPanel.length === 1) {
- dbPanel[0].panelData.init(); // always forces the db panel to load
- }
- self.visiblePanel = ko.observable(lastFoundPanel.length === 1 ? lastFoundPanel[0] : self.availablePanels[0]);
- self.visiblePanel().panelData.init();
- self.visiblePanel.subscribe(function(newValue) {
- self.apiHelper.setInTotalStorage('assist', 'last.open.panel', newValue.type);
- if (self.navigatorEnabled() && self.searchActive()) {
- lastQuery = 'refresh';
- self.performSearch();
- }
- newValue.panelData.init();
- });
- self.navAutocompleteSource = function (request, callback) {
- var facetMatch = request.term.match(/([a-z]+):\s*(\S+)?$/i);
- var isFacet = facetMatch !== null;
- var partialMatch = isFacet ? null : request.term.match(/\S+$/);
- var partial = isFacet && facetMatch[2] ? facetMatch[2] : (partialMatch ? partialMatch[0] : '');
- var beforePartial = request.term.substring(0, request.term.length - partial.length);
- self.apiHelper.navSearchAutocomplete({
- source: self.visiblePanel().type === 'sql' ?
- (self.visiblePanel().panelData.selectedSource() ? self.visiblePanel().panelData.selectedSource().sourceType : 'hive') : self.visiblePanel().type,
- query: request.term,
- successCallback: function (data) {
- var values = [];
- var facetPartialRe = new RegExp(partial.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i'); // Protect for 'tags:*axe'
- if (isFacet && typeof data.facets !== 'undefined') { // Is typed facet, e.g. type: type:bla
- var facetInQuery = facetMatch[1];
- if (typeof data.facets[facetInQuery] !== 'undefined') {
- $.map(data.facets[facetInQuery], function (count, value) {
- if (facetPartialRe.test(value)) {
- values.push({ data: { label: facetInQuery + ':' + value, icon: NAV_FACET_ICON, description: count }, value: beforePartial + value})
- }
- });
- }
- } else {
- if (typeof data.facets !== 'undefined') {
- Object.keys(data.facets).forEach(function (facet) {
- if (facetPartialRe.test(facet)) {
- if (Object.keys(data.facets[facet]).length > 0) {
- values.push({ data: { label: facet + ':', icon: NAV_FACET_ICON, description: $.map(data.facets[facet], function (key, value) { return value + ' (' + key + ')'; }).join(', ') }, value: beforePartial + facet + ':'});
- } else { // Potential facet from the list
- values.push({ data: { label: facet + ':', icon: NAV_FACET_ICON, description: '' }, value: beforePartial + facet + ':'});
- }
- } else if (partial.length > 0) {
- Object.keys(data.facets[facet]).forEach(function (facetValue) {
- if (facetValue.indexOf(partial) !== -1) {
- values.push({ data: { label: facet + ':' + facetValue, icon: NAV_FACET_ICON, description: facetValue }, value: beforePartial + facet + ':' + facetValue });
- }
- });
- }
- });
- }
- }
- if (values.length > 0) {
- values.push({ divider: true });
- }
- if (typeof data.results !== 'undefined') {
- data.results.forEach(function (result) {
- values.push({ data: { label: result.hue_name, icon: NAV_TYPE_ICONS[result.type], description: result.hue_description }, value: beforePartial + result.originalName });
- });
- }
- if (values.length > 0 && values[values.length - 1].divider) {
- values.pop();
- }
- if (values.length === 0) {
- values.push({ noMatch: true });
- }
- callback(values);
- },
- silenceErrors: true,
- errorCallback: function () {
- callback([]);
- }
- });
- };
- }
- ko.components.register('assist-panel', {
- viewModel: AssistPanel,
- template: { element: 'assist-panel-template' }
- });
- })();
- </script>
- </%def>
|