metastore.mako 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  1. ## Licensed to Cloudera, Inc. under one
  2. ## or more contributor license agreements. See the NOTICE file
  3. ## distributed with this work for additional information
  4. ## regarding copyright ownership. Cloudera, Inc. licenses this file
  5. ## to you under the Apache License, Version 2.0 (the
  6. ## "License"); you may not use this file except in compliance
  7. ## with the License. You may obtain a copy of the License at
  8. ##
  9. ## http://www.apache.org/licenses/LICENSE-2.0
  10. ##
  11. ## Unless required by applicable law or agreed to in writing, software
  12. ## distributed under the License is distributed on an "AS IS" BASIS,
  13. ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. ## See the License for the specific language governing permissions and
  15. ## limitations under the License.
  16. <%!
  17. from django.utils.html import escape
  18. from django.utils.translation import ugettext as _
  19. from desktop import conf
  20. from desktop.conf import USE_NEW_EDITOR
  21. from beeswax.conf import LIST_PARTITIONS_LIMIT
  22. from desktop.lib.i18n import smart_unicode
  23. from desktop.views import commonheader, commonfooter, _ko
  24. %>
  25. <%namespace name="actionbar" file="actionbar.mako" />
  26. <%namespace name="assist" file="/assist.mako" />
  27. <%namespace name="components" file="components.mako" />
  28. ${ commonheader(_("Metastore"), app_name, user) | n,unicode }
  29. ${ components.menubar() }
  30. <script src="${ static('desktop/ext/js/jquery/plugins/jquery-ui-1.10.4.custom.min.js') }"></script>
  31. <script src="${ static('desktop/ext/js/jquery/plugins/jquery.mousewheel.min.js') }"></script>
  32. <script src="${ static('desktop/ext/js/knockout.min.js') }"></script>
  33. <script src="${ static('desktop/ext/js/selectize.min.js') }"></script>
  34. <script src="${ static('desktop/js/apiHelper.js') }"></script>
  35. <script src="${ static('metastore/js/metastore.ko.js') }"></script>
  36. <script src="${ static('desktop/js/ko.charts.js') }"></script>
  37. <script src="${ static('desktop/ext/js/knockout-mapping.min.js') }"></script>
  38. <script src="${ static('desktop/ext/js/knockout-sortable.min.js') }"></script>
  39. <script src="${ static('desktop/js/ko.editable.js') }"></script>
  40. <script src="${ static('desktop/js/ko.hue-bindings.js') }"></script>
  41. <script src="${ static('desktop/ext/js/bootstrap-editable.min.js') }" type="text/javascript" charset="utf-8"></script>
  42. <script src="${ static('desktop/ext/js/d3.v3.js') }" type="text/javascript" charset="utf-8"></script>
  43. <script src="${ static('beeswax/js/stats.utils.js') }"></script>
  44. <script src="${ static('desktop/js/nv.d3.js') }" type="text/javascript" charset="utf-8"></script>
  45. <script src="${ static('desktop/js/nv.d3.growingPie.js') }" type="text/javascript" charset="utf-8"></script>
  46. <script src="${ static('desktop/js/nv.d3.growingPieChart.js') }" type="text/javascript" charset="utf-8"></script>
  47. <script src="${ static('desktop/js/jquery.hiveautocomplete.js') }" type="text/javascript" charset="utf-8"></script>
  48. <script src="${ static('desktop/js/jquery.huedatatable.js') }"></script>
  49. <script src="${ static('desktop/js/assist/assistDbEntry.js') }"></script>
  50. <script src="${ static('desktop/js/assist/assistDbSource.js') }"></script>
  51. <script src="${ static('desktop/js/assist/assistHdfsEntry.js') }"></script>
  52. <script src="${ static('desktop/js/fileBrowser/hueDocument.js') }"></script>
  53. <script src="${ static('desktop/js/fileBrowser/hueFileEntry.js') }"></script>
  54. <link rel="stylesheet" href="${ static('desktop/ext/css/bootstrap-editable.css') }">
  55. <link rel="stylesheet" href="${ static('metastore/css/metastore.css') }" type="text/css">
  56. <link rel="stylesheet" href="${ static('notebook/css/notebook.css') }">
  57. <link rel="stylesheet" href="${ static('desktop/ext/css/nv.d3.min.css') }">
  58. <link rel="stylesheet" href="${ static('desktop/css/nv.d3.css') }">
  59. <style type="text/css">
  60. % if conf.CUSTOM.BANNER_TOP_HTML.get():
  61. .show-assist {
  62. top: 110px!important;
  63. }
  64. .main-content {
  65. top: 112px!important;
  66. }
  67. % endif
  68. </style>
  69. ${ assist.assistPanel() }
  70. <script type="text/html" id="metastore-breadcrumbs">
  71. <ul class="nav nav-pills hueBreadcrumbBar" id="breadcrumbs">
  72. <li>
  73. <a href="javascript:void(0);" data-bind="click: databasesBreadcrumb">${_('Databases')}</a>
  74. <!-- ko if: database -->
  75. <span class="divider">&gt;</span>
  76. <!-- /ko -->
  77. </li>
  78. <!-- ko with: database -->
  79. <li>
  80. <a href="javascript:void(0);" data-bind="text: name, click: $root.tablesBreadcrumb"></a>
  81. <!-- ko if: table -->
  82. <span class="divider">&gt;</span>
  83. <!-- /ko -->
  84. </li>
  85. <!-- ko with: table -->
  86. <li class="editable-breadcrumbs" title="${_('Edit path')}" data-bind="click: function(){ $parent.editingTable(true); }, visible: !$parent.editingTable()">
  87. <span data-bind="text: name"></span>
  88. </li>
  89. <!-- /ko -->
  90. <!-- ko if: editingTable -->
  91. <!-- ko with: table -->
  92. <li class="editable-breadcrumb-input">
  93. <input type="text" data-bind="hivechooser: {data: name, database: $parent.name, skipColumns: true, searchEverywhere: true, onChange: function(val){ $parent.setTableByName(val); $parent.editingTable(false); }}" autocomplete="off" />
  94. </li>
  95. <!-- /ko -->
  96. <!-- /ko -->
  97. <!-- /ko -->
  98. </ul>
  99. </script>
  100. <script type="text/html" id="metastore-columns-table">
  101. <div style="overflow-x: auto; overflow-y: hidden">
  102. <table class="table table-striped table-condensed table-nowrap">
  103. <br/>
  104. <thead>
  105. <tr>
  106. <th width="2%">&nbsp;</th>
  107. <th width="2%" class="no-sort">&nbsp;</th>
  108. <th width="17%">${_('Name')}</th>
  109. <th width="15%">${_('Type')}</th>
  110. <!-- ko if: $root.optimizerEnabled -->
  111. <th width="15%">${_('Popularity')}</th>
  112. <!-- /ko -->
  113. <th width="50%">${_('Comment')}</th>
  114. </tr>
  115. </thead>
  116. <tbody data-bind="hueach: {data: $data, itemHeight: 29, scrollable: '.right-panel', scrollableOffset: 200, disableHueEachRowCount: 5, scrollUp: true}">
  117. <tr>
  118. <td data-bind="text: $index() + $indexOffset() + 1"></td>
  119. <td><a class="blue" href="javascript:void(0)" data-bind="click: showContextPopover"><i class="fa fa-bar-chart" title="${_('Show details')}"></i></a></td>
  120. <td title="${ _("Scroll to the column") }">
  121. <!-- ko if: $root.database().table().samples.loading() -->
  122. <span data-bind="text: name"></span>
  123. <!-- /ko -->
  124. <!-- ko ifnot: $root.database().table().samples.loading() -->
  125. <a href="javascript:void(0)" class="column-selector" data-bind="text: name, click: scrollToColumn"></a>
  126. <!-- /ko -->
  127. </td>
  128. <td data-bind="text: type"></td>
  129. <!-- ko if: $root.optimizerEnabled -->
  130. <td>
  131. <div class="progress" style="height: 10px; width: 70px; margin-top:5px;" data-bind="attr: { 'title': popularity() }">
  132. <div class="bar" style="background-color: #338bb8" data-bind="style: { 'width' : popularity() + '%' }"></div>
  133. </div>
  134. </td>
  135. <!-- /ko -->
  136. <td>
  137. % if has_write_access:
  138. <span data-bind="editable: comment, editableOptions: {enabled: true, placement: 'left', emptytext: '${ _ko('Add a comment...') }', inputclass: 'input-xlarge'}" class="editable editable-click editable-empty">
  139. ${ _('Add a comment...') }</span>
  140. % else:
  141. <span data-bind="text: comment"></span>
  142. % endif
  143. </td>
  144. </tr>
  145. </tbody>
  146. </table>
  147. </div>
  148. </script>
  149. <script type="text/html" id="metastore-partition-columns-table">
  150. <div style="overflow-x: auto; overflow-y: hidden">
  151. <table class="table table-striped table-condensed table-nowrap">
  152. <thead>
  153. <tr>
  154. <th style="width: 1%">&nbsp;</th>
  155. <th>${_('Name')}</th>
  156. <th>${_('Type')}</th>
  157. </tr>
  158. </thead>
  159. <tbody>
  160. <!-- ko foreach: detailedKeys -->
  161. <tr>
  162. <td data-bind="text: $index() + 1"></td>
  163. <td data-bind="text: $data.name"></td>
  164. <td data-bind="text: $data.type"></td>
  165. </tr>
  166. <!-- /ko -->
  167. </tbody>
  168. </table>
  169. </div>
  170. </script>
  171. <script type="text/html" id="metastore-partition-values-table">
  172. <div style="overflow-x: auto; overflow-y: hidden">
  173. <table class="table table-striped table-condensed table-nowrap">
  174. <thead>
  175. <tr>
  176. <th style="width: 1%">&nbsp;</th>
  177. <th>${_('Values')}</th>
  178. <th>${_('Spec')}</th>
  179. <th>${_('Browse')}</th>
  180. </tr>
  181. </thead>
  182. <tbody>
  183. <!-- ko foreach: values -->
  184. <tr>
  185. <td data-bind="text: $index()+1"></td>
  186. <td><a data-bind="attr: {'href': readUrl }, text: '[\'' + columns.join('\',\'') + '\']'"></a></td>
  187. <td data-bind="text: partitionSpec"></td>
  188. <td>
  189. <a data-bind="attr: {'href': readUrl }"><i class="fa fa-th"></i> ${_('Data')}</a>
  190. <a data-bind="attr: {'href': browseUrl }"><i class="fa fa-file-o"></i> ${_('Files')}</a>
  191. </td>
  192. </tr>
  193. <!-- /ko -->
  194. </tbody>
  195. </table>
  196. </div>
  197. </script>
  198. <script type="text/html" id="metastore-samples-table">
  199. <table class="table table-striped table-condensed table-nowrap sample-table">
  200. <thead>
  201. <tr>
  202. <th style="width: 1%">&nbsp;</th>
  203. <!-- ko foreach: headers -->
  204. <th data-bind="text: $data"></th>
  205. <!-- /ko -->
  206. </tr>
  207. </thead>
  208. <tbody>
  209. <!-- ko foreach: rows -->
  210. <tr>
  211. <td data-bind="text: $index()+1"></td>
  212. <!-- ko foreach: $data -->
  213. <td data-bind="text: $data"></td>
  214. <!-- /ko -->
  215. </tr>
  216. <!-- /ko -->
  217. </tbody>
  218. </table>
  219. <div id="jumpToColumnAlert" class="alert hide" style="margin-top: 12px;">
  220. <button type="button" class="close" data-dismiss="alert">&times;</button>
  221. <strong>${_('Did you know?')}</strong>
  222. <ul>
  223. <li>${ _('If the sample contains a large number of columns, click a row to select a column to jump to') }</li>
  224. </ul>
  225. </div>
  226. </script>
  227. <script type="text/html" id="metastore-table-properties">
  228. <i data-bind="visible: loadingDetails" class="fa fa-spinner fa-spin fa-2x muted" style="display: none;"></i>
  229. <!-- ko with: tableDetails -->
  230. <h4>${ _('Properties') }</h4>
  231. <div class="row-fluid">
  232. <div title="${ _('Type') }">
  233. <!-- ko if: is_view -->
  234. <i class="fa fa-fw fa-eye muted"></i> ${ _('View') }
  235. <!-- /ko -->
  236. <!-- ko ifnot: is_view -->
  237. <i class="fa fa-fw fa-table muted"></i> ${ _('Table') }
  238. <!-- /ko -->
  239. </div>
  240. <div title="${ _('Owner') }">
  241. <i class="fa fa-fw fa-user muted"></i> <span data-bind="text: details.properties.owner"></span>
  242. </div>
  243. <div title="${ _('Created') }"><i class="fa fa-fw fa-clock-o muted"></i> <span data-bind="text: localeFormat(details.properties.create_time)"></span></div>
  244. <div title="${ _('Format') }">
  245. <i class="fa fa-fw fa-file-o muted"></i> <span data-bind="text: details.properties.format"></span>
  246. <i class="fa fa-fw fa-archive muted"></i> <span data-bind="visible: details.properties.compressed" style="display:none;">${_('Compressed')}</span>
  247. <span data-bind="visible: !details.stats.compressed" style="display:none;">${_('Not compressed')}</span>
  248. </div>
  249. </div>
  250. <!-- /ko -->
  251. </script>
  252. <script type="text/html" id="metastore-table-stats">
  253. <!-- ko if: tableDetails() && ! tableDetails().is_view -->
  254. <!-- ko with: tableDetails -->
  255. <h4>${ _('Stats') }
  256. <!-- ko ifnot: partition_keys.length -->
  257. % if has_write_access:
  258. <!-- ko if: $parent.refreshingTableStats -->
  259. <i class="fa fa-refresh fa-spin"></i>
  260. <!-- /ko -->
  261. <!-- ko ifnot: $parent.refreshingTableStats() || is_view -->
  262. <a class="pointer" href="javascript: void(0);" data-bind="click: $parent.refreshTableStats"><i class="fa fa-refresh"></i></a>
  263. <!-- /ko -->
  264. % endif
  265. <span data-bind="visible: details.stats.COLUMN_STATS_ACCURATE == 'false' && ! is_view" rel="tooltip" data-placement="top" title="${ _('The column stats for this table are not accurate') }"><i class="fa fa-exclamation-triangle"></i></span>
  266. <!-- /ko -->
  267. </h4>
  268. <div class="row-fluid">
  269. <div>
  270. <i class="fa fa-fw fa-hdd-o muted"></i> <a data-bind="attr: {'href': hdfs_link, 'rel': path_location}">${_('Location')}</a>
  271. </div>
  272. <!-- ko with: $parent.tableStats -->
  273. <!-- ko if: typeof last_modified_by !== 'undefined' -->
  274. <div title="${ _('Last modified by') }"><i class="fa fa-fw fa-user muted"></i> <span data-bind="text: last_modified_by"></span> </div>
  275. <!-- /ko -->
  276. <!-- ko if: typeof last_modified_time !== 'undefined' -->
  277. <div title="${ _('Last modified time') }"><i class="fa fa-fw fa-clock-o muted"></i> <span data-bind="text: localeFormat(last_modified_time*1000)"></span></div>
  278. <!-- /ko -->
  279. <!-- ko if: typeof numFiles !== 'undefined' && typeof last_modified_by === 'undefined' -->
  280. <div title="${ _('Number of files') }"><i class="fa fa-fw fa-files-o muted"></i> <span data-bind="text: numFiles"></span> ${ _('files') }</div>
  281. <!-- /ko -->
  282. <!-- ko if: typeof numRows !== 'undefined' -->
  283. <div title="${ _('Number of rows') }"><i class="fa fa-fw fa-list muted"></i> <span data-bind="text: numRows"></span> ${ _('rows') }</div>
  284. <!-- /ko -->
  285. <!-- ko if: typeof totalSize !== 'undefined' && typeof last_modified_by === 'undefined' -->
  286. <div title="${ _('Total size') }"><i class="fa fa-fw fa-tasks muted"></i> <span data-bind="text: filesize(totalSize)"></span></div>
  287. <!-- /ko -->
  288. <!-- /ko -->
  289. </div>
  290. <!-- /ko -->
  291. <!-- /ko -->
  292. </script>
  293. <a title="${_('Toggle Assist')}" class="pointer show-assist" data-bind="visible: !$root.isLeftPanelVisible() && $root.assistAvailable(), click: function() { $root.isLeftPanelVisible(true); }">
  294. <i class="fa fa-chevron-right"></i>
  295. </a>
  296. <script type="text/html" id="metastore-databases">
  297. <div class="actionbar-actions" data-bind="dockable: { scrollable: '.right-panel', nicescroll: true, jumpCorrection: 5 }">
  298. <input class="input-xlarge search-query margin-left-10" type="text" placeholder="${ _('Search for a database...') }" data-bind="clearable: databaseQuery, value: databaseQuery, valueUpdate: 'afterkeydown'"/>
  299. % if has_write_access:
  300. <button class="btn toolbarBtn margin-left-20" title="${_('Drop the selected databases')}" data-bind="click: function () { $('#dropDatabase').modal('show'); }, disable: selectedDatabases().length === 0"><i class="fa fa-times"></i> ${_('Drop')}</button>
  301. <div id="dropDatabase" class="modal hide fade">
  302. <form id="dropDatabaseForm" action="/metastore/databases/drop" method="POST">
  303. ${ csrf_token(request) | n,unicode }
  304. <div class="modal-header">
  305. <a href="#" class="close" data-dismiss="modal">&times</a>
  306. <div class="alert-message block-message warning">${ _('Warning: This will drop all tables and objects within the database.') }</div>
  307. </br>
  308. <h3 id="dropDatabaseMessage">${ _('Do you really want to delete the following database(s)?') }</h3>
  309. <ul data-bind="foreach: selectedDatabases">
  310. <li>
  311. <span data-bind="text: name"></span>
  312. <!-- ko if: $data.tables().length > 0 -->
  313. (<span data-bind="text: $data.tables().length"></span> tables)
  314. <!-- /ko -->
  315. </li>
  316. </ul>
  317. </div>
  318. <div class="modal-footer">
  319. <input type="button" class="btn" data-dismiss="modal" value="${_('No')}">
  320. <input type="submit" class="btn btn-danger" value="${_('Yes')}"/>
  321. </div>
  322. <!-- ko foreach: selectedDatabases -->
  323. <input type="hidden" name="database_selection" data-bind="value: name" />
  324. <!-- /ko -->
  325. </form>
  326. </div>
  327. % endif
  328. </div>
  329. <table id="databasesTable" class="table table-condensed datatables" style="margin-bottom: 10px" data-bind="visible: filteredDatabases().length > 0">
  330. <thead>
  331. <tr>
  332. <th width="1%" style="text-align: center"><div class="hueCheckbox fa" data-bind="hueCheckAll: { allValues: filteredDatabases, selectedValues: selectedDatabases }"></div></th>
  333. <th>${ _('Database Name') }</th>
  334. </tr>
  335. </thead>
  336. <tbody data-bind="hueach: {data: filteredDatabases, itemHeight: 29, scrollable: '.right-panel', scrollableOffset: 145, scrollUp: true}">
  337. <tr>
  338. <td width="1%" style="text-align: center">
  339. <div class="hueCheckbox fa" data-bind="multiCheck: '#databasesTable', value: $data, hueChecked: $parent.selectedDatabases"></div>
  340. </td>
  341. <td>
  342. <a href="javascript: void(0);" data-bind="text: name, click: function () { $parent.setDatabase($data, function(){ huePubSub.publish('metastore.url.change'); }) }"></a>
  343. </td>
  344. </tr>
  345. </tbody>
  346. </table>
  347. <span class="margin-left-10" data-bind="visible: filteredDatabases().length === 0" style="font-style: italic; display: none;">${_('No databases found')}</span>
  348. </script>
  349. <script type="text/html" id="metastore-tables">
  350. <div class="row-fluid">
  351. <!-- ko with: stats -->
  352. <div class="
  353. %if is_optimizer_enabled:
  354. span8
  355. %else:
  356. span12
  357. %endif
  358. tile">
  359. <div class="span6 tile">
  360. <h4>${ _('Properties') }</h4>
  361. <div title="${ _('Comment') }"><i class="fa fa-fw fa-comment muted"></i>
  362. <!-- ko if: comment -->
  363. <span data-bind="text: comment"></span>
  364. <!-- /ko -->
  365. <!-- ko ifnot: comment -->
  366. <i>${_('No comment.')}</i>
  367. <!-- /ko -->
  368. <div title="${ _('Owner') }">
  369. <i class="fa fa-fw fa-user muted"></i>
  370. <span data-bind="text: owner_name"></span> (<span data-bind="text: owner_type"></span>)
  371. </br>
  372. <i class="fa fa-fw fa-hdd-o muted"></i> <a data-bind="attr: {'href': hdfs_link, 'rel': location }"> ${_('Location')}</a>
  373. </div>
  374. </div>
  375. </div>
  376. <div class="span3 tile">
  377. <!-- ko if: $root.navigatorEnabled() -->
  378. <h4>${ _('Tagging') }</h4>
  379. <div style="margin-top: 5px" data-bind="component: { name: 'nav-tags', params: {
  380. sourceType: 'hive',
  381. database: db_name
  382. } }"></div>
  383. <!-- /ko -->
  384. </div>
  385. <!-- ko with: parameters -->
  386. <div class="row-fluid">
  387. <div class="span12">
  388. <div title="${ _('Parameters') }">
  389. <!-- ko template: { name: 'metastore-databases-parameters', data: hueUtils.parseHivePseudoJson($data) }--><!-- /ko -->
  390. </div>
  391. </div>
  392. </div>
  393. <!-- /ko -->
  394. </div>
  395. <!-- /ko -->
  396. <!-- ko if: $root.optimizerEnabled() && $root.database().optimizerStats() && $root.database().optimizerStats().length > 0 -->
  397. <div class="span4 tile chart-container">
  398. <h4>${ _('Popular tables') }</h4>
  399. <div data-bind="attr:{'id': 'optimizerPieChart'}, pieChart: {data: {counts: $root.database().optimizerStats().sort(function(a, b) { return -(a.popularity - b.popularity); }).slice(0, 5)}, fqs: ko.observableArray([]),
  400. transformer: pieChartDataTransformer, maxWidth: 200, parentSelector: '.chart-container' }" class="chart"></div>
  401. </div>
  402. <!-- /ko -->
  403. </div>
  404. <div class="row-fluid">
  405. <div class="span12 tile">
  406. <h4>${ _('Tables') }</h4>
  407. <div class="actionbar-actions" data-bind="visible: tables().length > 0, dockable: { scrollable: '.right-panel', nicescroll: true, jumpCorrection: 5 }">
  408. <input class="input-xlarge search-query margin-left-10" type="text" placeholder="${ _('Search for a table...') }" data-bind="clearable: tableQuery, value: tableQuery, valueUpdate: 'afterkeydown'"/>
  409. <button class="btn toolbarBtn margin-left-20" title="${_('Browse the selected table')}" data-bind="click: function () { setTable(selectedTables()[0]); selectedTables([]); }, disable: selectedTables().length !== 1"><i class="fa fa-eye"></i> ${_('View')}</button>
  410. <button class="btn toolbarBtn" title="${_('Query the selected table')}" data-bind="click: function () { location.href = '/notebook/browse/' + name + '/' + selectedTables()[0].name; }, disable: selectedTables().length !== 1">
  411. <i class="fa fa-pencil-square-o"></i> ${_('Query')}
  412. </button>
  413. % if has_write_access:
  414. <button id="dropBtn" class="btn toolbarBtn" title="${_('Delete the selected tables')}" data-bind="click: function () { $('#dropTable').modal('show'); }, disable: selectedTables().length === 0"><i class="fa fa-times"></i> ${_('Drop')}</button>
  415. % endif
  416. <!-- ko if: $root.optimizerEnabled -->
  417. &nbsp;
  418. &nbsp;
  419. <button class="btn toolbarBtn" title="${_('View the selected table')}" data-bind="click: function () { window.open($root.optimizerUrl() + '#/table/' + selectedTables()[0].optimizerStats().eid, '_blank'); }, disable: selectedTables().length !== 1">
  420. <i class="fa fa-skyatlas"></i> ${_('View in Optimizer')}
  421. </button>
  422. <!-- /ko -->
  423. </div>
  424. <table id="tablesTable" class="table table-striped table-condensed table-nowrap" style="margin-bottom: 10px; width: 100%" data-bind="visible: filteredTables().length > 0">
  425. <thead>
  426. <tr>
  427. <th width="1%" style="text-align: center"><div class="hueCheckbox fa" data-bind="hueCheckAll: { allValues: filteredTables, selectedValues: selectedTables }"></div></th>
  428. <th>&nbsp;</th>
  429. <th width="30%">${ _('Table Name') }</th>
  430. <th width="48%">${ _('Comment') }</th>
  431. <!-- ko if: $root.optimizerEnabled -->
  432. <th width="10%">${ _('Popularity') }</th>
  433. <th width="10%">${ _('Columns') }</th>
  434. <!-- /ko -->
  435. <th width="1%">${ _('Type') }</th>
  436. </tr>
  437. </thead>
  438. <tbody data-bind="hueach: {data: filteredTables, itemHeight: 29, scrollable: '.right-panel', scrollableOffset: 277, scrollUp: true}">
  439. <tr>
  440. <td width="1%" style="text-align: center">
  441. <div class="hueCheckbox fa" data-bind="multiCheck: '#tablesTable', value: $data, hueChecked: $parent.selectedTables"></div>
  442. </td>
  443. <td width="1%"><a class="blue" href="javascript:void(0)" data-bind="click: showContextPopover"><i class="fa fa-bar-chart" title="${_('Show details')}"></i></a></td>
  444. <td>
  445. <a class="tableLink" href="javascript:void(0);" data-bind="text: name, click: function() { $parent.setTable($data, function(){ huePubSub.publish('metastore.url.change'); }) }"></a>
  446. </td>
  447. <td style="text-overflow: ellipsis; overflow: hidden; max-width: 0" data-bind="text: comment, attr: {title: comment}"></td>
  448. <!-- ko if: $root.optimizerEnabled -->
  449. <!-- ko if: optimizerStats() -->
  450. <td>
  451. <div class="progress" style="height: 10px; width: 70px; margin-top:5px;" data-bind="attr: {'title': optimizerStats().popularity}">
  452. <div class="bar" style="background-color: #338bb8" data-bind="style: { 'width' : optimizerStats().popularity + '%' }"></div>
  453. </div>
  454. </td>
  455. <td data-bind="text: optimizerStats().column_count"></td>
  456. <!-- /ko -->
  457. <!-- ko ifnot: optimizerStats() -->
  458. <td></td>
  459. <td></td>
  460. <!-- /ko -->
  461. <!-- /ko -->
  462. <td class="center">
  463. <!-- ko if: type == 'Table' -->
  464. <i class="fa fa-fw fa-table muted" title="${ _('Table') }"></i>
  465. <!-- /ko -->
  466. <!-- ko if: type == 'View' -->
  467. <i class="fa fa-fw fa-eye muted" title="${ _('View') }"></i>
  468. <!-- /ko -->
  469. <!-- ko if: $root.optimizerEnabled -->
  470. <!-- ko if: optimizerStats() -->
  471. <!-- ko if: optimizerStats().is_fact -->
  472. <i class="fa fa-fw muted fa-database" title="${ _('Fact table') }"></i>
  473. <!-- /ko -->
  474. <!-- ko ifnot: optimizerStats().is_fact -->
  475. <i class="fa fa-fw muted fa-calendar" title="${ _('Dimension table') }"></i>
  476. <!-- /ko -->
  477. <!-- /ko -->
  478. <!-- /ko -->
  479. </td>
  480. </tr>
  481. </tbody>
  482. </table>
  483. <span data-bind="visible: filteredTables().length === 0, css: {'margin-left-10': tables().length > 0}" style="font-style: italic; display: none;">${_('No tables found.')}</span>
  484. </div>
  485. </div>
  486. % if has_write_access:
  487. <div id="dropTable" class="modal hide fade">
  488. <form data-bind="attr: { 'action': '/metastore/tables/drop/' + name }" method="POST">
  489. ${ csrf_token(request) | n,unicode }
  490. <div class="modal-header">
  491. <a href="#" class="close" data-dismiss="modal">&times;</a>
  492. <h3 id="dropTableMessage">${_('Do you really want to drop the selected table(s)?')}</h3>
  493. </div>
  494. <div class="modal-footer">
  495. <input type="button" class="btn" data-dismiss="modal" value="${_('No')}" />
  496. <input type="submit" class="btn btn-danger" value="${_('Yes')}"/>
  497. </div>
  498. <!-- ko foreach: selectedTables -->
  499. <input type="hidden" name="table_selection" data-bind="value: name" />
  500. <!-- /ko -->
  501. </form>
  502. </div>
  503. % endif
  504. </script>
  505. <script type="text/html" id="metastore-databases-parameters">
  506. <div data-bind="toggleOverflow: {height: 24}">
  507. <div class="inline margin-right-20"><i class="fa fa-fw fa-cog muted"></i></div>
  508. <!-- ko foreach: Object.keys($data) -->
  509. <div class="inline margin-right-20"><strong data-bind="text: $data"></strong>: <span data-bind="text: $parent[$data]"></span></div>
  510. <!-- /ko -->
  511. </div>
  512. </script>
  513. <script type="text/html" id="metastore-databases-actions">
  514. <div class="inline-block pull-right">
  515. <a class="inactive-action" href="javascript:void(0)" data-bind="click: function () { huePubSub.publish('assist.db.refresh', 'hive'); }"><i class="pointer fa fa-refresh" data-bind="css: { 'fa-spin blue' : $root.reloading }" title="${_('Refresh')}"></i></a>
  516. % if has_write_access:
  517. <a class="inactive-action margin-left-10" href="${ url('beeswax:create_database') }" title="${_('Create a new database')}"><i class="fa fa-plus"></i></a>
  518. % endif
  519. </div>
  520. </script>
  521. <script type="text/html" id="metastore-tables-actions">
  522. <div class="inline-block pull-right">
  523. <a class="inactive-action" href="javascript:void(0)" data-bind="click: function () { huePubSub.publish('assist.db.refresh', 'hive'); }"><i class="pointer fa fa-refresh" data-bind="css: { 'fa-spin blue' : $root.reloading }" title="${_('Refresh')}"></i></a>
  524. % if has_write_access:
  525. <a class="inactive-action margin-left-10" data-bind="attr: { 'href': '/beeswax/create/import_wizard/' + database().name }" title="${_('Create a new table from a file')}"><span class="fa-stack fa-fw" style="width: 1.28571429em"><i class="fa fa-file-o fa-stack-1x"></i><i class="fa fa-plus-circle fa-stack-1x" style="font-size: 14px; margin-left: 5px; margin-top: 6px;"></i></span></a>
  526. <a class="inactive-action margin-left-10" data-bind="attr: { 'href': '/beeswax/create/create_table/' + database().name }" title="${_('Create a new table manually')}"><i class="fa fa-plus"></i></a>
  527. % endif
  528. </div>
  529. </script>
  530. <script type="text/html" id="metastore-describe-table-actions">
  531. <div class="inline-block pull-right">
  532. <!-- ko with: database -->
  533. <!-- ko with: table -->
  534. % if USE_NEW_EDITOR.get():
  535. <a class="inactive-action" data-bind="attr: { 'href': '/notebook/browse/' + database.name + '/' + name }" title="${_('Query the table')}"><i class="fa fa-pencil-square-o"></i></a>
  536. % else:
  537. <a class="inactive-action" data-bind="attr: { 'href': '/metastore/table/'+ database.name + '/' + name + '/read' }" title="${_('Browse Data')}"><i class="fa fa-list"></i></a>
  538. % endif
  539. <a class="inactive-action margin-left-10" href="javascript:void(0)" data-bind="click: function () { huePubSub.publish('assist.db.refresh', 'hive'); }"><i class="pointer fa fa-refresh" data-bind="css: { 'fa-spin blue' : $root.reloading }" title="${_('Refresh')}"></i></a>
  540. <!-- ko if: $root.optimizerEnabled() && $root.database().table().optimizerStats() -->
  541. <a class="inactive-action margin-left-10" title="${_('View in Optimizer')}" data-bind="attr: { 'href': $root.optimizerUrl() + '#/table/' + $root.database().table().optimizerStats().eid }" target="_blank"><i class="fa fa-skyatlas"></i></a>
  542. <!-- /ko -->
  543. ## <a class="inactive-action margin-left-10" href="javascript: void(0);"><i class="fa fa-star"></i></a>
  544. % if has_write_access:
  545. <a class="inactive-action margin-left-10" href="#" data-bind="click: showImportData, visible: tableDetails() && ! tableDetails().is_view" title="${_('Import Data')}"><i class="fa fa-upload"></i></a>
  546. % endif
  547. % if has_write_access:
  548. <a class="inactive-action margin-left-10" href="#dropSingleTable" data-toggle="modal" data-bind="attr: { 'title' : tableDetails() && tableDetails().is_view ? '${_('Drop View')}' : '${_('Drop Table')}' }"><i class="fa fa-times"></i></a>
  549. % endif
  550. <!-- ko if: tableDetails() -->
  551. <a class="inactive-action margin-left-10" data-bind="visible: tableDetails().hdfs_link, attr: {'href': tableDetails().hdfs_link, 'rel': tableDetails().path_location}" title="${_('View File Location')}"><i class="fa fa-fw fa-hdd-o"></i></a>
  552. <!-- ko if: tableDetails().partition_keys.length -->
  553. <a class="inactive-action margin-left-10" data-bind="attr: { 'href': '/metastore/table/' + database.name + '/' + name + '/partitions' }" title="${_('Show Partitions')}"><i class="fa fa-sitemap"></i></a>
  554. <!-- /ko -->
  555. <!-- /ko -->
  556. <!-- /ko -->
  557. <!-- /ko -->
  558. </div>
  559. </script>
  560. <script type="text/html" id="metastore-overview-tab">
  561. <div class="row-fluid margin-top-10">
  562. <div class="span3 tile">
  563. <!-- ko template: 'metastore-table-properties' --><!-- /ko -->
  564. </div>
  565. <div class="span3 tile">
  566. <!-- ko template: 'metastore-table-stats' --><!-- /ko -->
  567. </div>
  568. <!-- ko if: $root.navigatorEnabled() && navigatorStats() -->
  569. <div class="span6 tile">
  570. <h4>${ _('Tagging') }</h4>
  571. <div style="margin-top: 5px" data-bind="component: { name: 'nav-tags', params: {
  572. sourceType: 'hive',
  573. database: database.name,
  574. table: name
  575. } }"></div>
  576. </div>
  577. <!-- /ko -->
  578. </div>
  579. <div class="tile">
  580. <h4>${ _('Columns') } (<span data-bind="text: columns().length"></span>) <i data-bind="visible: loadingColumns" class="fa fa-spinner fa-spin" style="display: none;"></i></h4>
  581. <!-- ko with: favouriteColumns -->
  582. <!-- ko template: "metastore-columns-table" --><!-- /ko -->
  583. <!-- /ko -->
  584. <a class="pointer" data-bind="visible: columns().length >= 3, click: function() { $('li a[href=\'#columns\']').click(); }">
  585. ${_('View more...')}
  586. </a>
  587. </div>
  588. <div class="tile">
  589. <h4>${ _('Sample') } <i data-bind="visible: samples.loading" class='fa fa-spinner fa-spin' style="display: none;"></i></h4>
  590. <!-- ko with: samples -->
  591. <!-- ko if: loaded -->
  592. <!-- ko with: preview -->
  593. <!-- ko template: { if: rows().length, name: 'metastore-samples-table' } --><!-- /ko -->
  594. <a class="pointer" data-bind="visible: rows().length >= 3, click: function() { $('li a[href=\'#sample\']').click(); }" style="display: none;">
  595. ${_('View more...')}
  596. </a>
  597. <!-- /ko -->
  598. <div data-bind="visible: !rows().length && metastoreTable.tableDetails().is_view" style="display: none;">${ _('The view does not contain any data.') }</div>
  599. <div data-bind="visible: !rows().length && !metastoreTable.tableDetails().is_view" style="display: none;">${ _('The table does not contain any data.') }</div>
  600. <!-- /ko -->
  601. <!-- /ko -->
  602. </div>
  603. <div class="tile" data-bind="visible: tableDetails() && tableDetails().partition_keys.length" style="display: none;">
  604. <!-- ko with: partitions -->
  605. <h4>${ _('Partitions') } <i data-bind="visible: loading" class='fa fa-spinner fa-spin' style="display: none;"></i></h4>
  606. <!-- ko if: loaded -->
  607. <!-- ko with: preview -->
  608. <!-- ko template: { if: values().length, name: 'metastore-partition-values-table' } --><!-- /ko -->
  609. <a class="pointer" data-bind="visible: values().length >= 3, click: function() { $('li a[href=\'#partitions\']').click(); }" style="display: none;">
  610. ${_('View more...')}
  611. </a>
  612. <!-- /ko -->
  613. <span data-bind="visible: !values().length" style="display: none;">${ _('The partition does not contain any values') }</span>
  614. <!-- /ko -->
  615. <!-- /ko -->
  616. </div>
  617. </script>
  618. <script type="text/html" id="metastore-columns-tab">
  619. <!-- ko with: filteredColumns -->
  620. <!-- ko template: "metastore-columns-table" --><!-- /ko -->
  621. <!-- /ko -->
  622. </script>
  623. <script type="text/html" id="metastore-partitions-tab">
  624. <!-- ko with: partitions -->
  625. <div class="tile" data-bind="visible: true" style="display: none;">
  626. <h4>${ _('Columns') }</h4>
  627. <!-- ko template: 'metastore-partition-columns-table' --><!-- /ko -->
  628. </div>
  629. <div class="tile" data-bind="visible: true" style="display: none;">
  630. <h4>${ _('Partitions') } <i data-bind="visible: loading" class='fa fa-spinner fa-spin' style="display: none;"></i></h4>
  631. <!-- ko if: loaded -->
  632. <!-- ko template: { if: values().length, name: 'metastore-partition-values-table' } --><!-- /ko -->
  633. <span data-bind="visible: !values().length" style="display: none;">${ _('The partition does not contain any values') }</span>
  634. <!-- /ko -->
  635. </div>
  636. <!-- /ko -->
  637. <a data-bind="attr: { 'href': '/metastore/table/' + database.name + '/' + name + '/partitions' }">${ _('View all') }</a>
  638. </script>
  639. <script type="text/html" id="metastore-sample-tab">
  640. <!-- ko with: samples -->
  641. <!-- ko if: loading -->
  642. <div class="empty-message">
  643. <i data-bind="visible: loading" class='fa fa-spinner fa-spin' style="display: none;"></i>
  644. </div>
  645. <!-- /ko -->
  646. <!-- ko if: loaded -->
  647. <!-- ko template: { if: rows().length, name: 'metastore-samples-table' } --><!-- /ko -->
  648. <div data-bind="visible: !rows().length && metastoreTable.tableDetails().is_view" style="display: none;" class="empty-message">${ _('The view does not contain any data.') }</div>
  649. <div data-bind="visible: !rows().length && !metastoreTable.tableDetails().is_view" style="display: none;" class="empty-message">${ _('The table does not contain any data.') }</div>
  650. <!-- /ko -->
  651. <!-- /ko -->
  652. </script>
  653. <script type="text/html" id="metastore-queries-tab">
  654. <br/>
  655. <i class="fa fa-spinner fa-spin" data-bind="visible: $root.loadingQueries"></i>
  656. <table data-bind="visible: ! loadingQueries() && $data.optimizerDetails().FullQueryList().length > 0" class="table table-condensed">
  657. <thead>
  658. <tr>
  659. <th width="10%">${ _('Id') }</th>
  660. <th width="10%">${ _('Count') }</th>
  661. <th>${ _('Character') }</th>
  662. <th width="20%">${ _('Complexity') }</th>
  663. <th width="10%">${ _('Hive Compatible') }</th>
  664. <th width="10%">${ _('Impala Compatible') }</th>
  665. </tr>
  666. </thead>
  667. <tbody data-bind="hueach: {data: $data.optimizerDetails().FullQueryList(), itemHeight: 29, scrollable: '.right-panel', scrollableOffset: 200}">
  668. <tr class="pointer" data-bind="click: function(){ window.open($root.optimizerUrl() + '#/query/' + eid(), '_blank'); }">
  669. <td data-bind="text: eid"></td>
  670. <td data-bind="text: instanceCount"></td>
  671. <td><code data-bind="text: character"></code></td>
  672. <td data-bind="text: complexity, css: {'alert-success': complexity() == 'Low', 'alert-warning': complexity() == 'Medium', 'alert-danger': complexity() == 'High'}" class="alert"></td>
  673. <td data-bind="text: compatibility.hive"></td>
  674. <td data-bind="text: compatibility.impala"></td>
  675. </tr>
  676. </tbody>
  677. </table>
  678. <div data-bind="visible: ! loadingQueries() && $data.optimizerDetails().FullQueryList().length == 0" class="empty-message">
  679. ${ _('No queries found for the current table.') }
  680. </div>
  681. </script>
  682. <script type="text/html" id="metastore-details-tab">
  683. <!-- ko with: tableDetails -->
  684. <table class="properties-table">
  685. <tbody data-bind="foreach: properties">
  686. <!-- ko if: col_name.indexOf('#') === 0 -->
  687. <tr>
  688. <td colspan="3"><h4 data-bind="text: col_name.substring(1)"></h4></td>
  689. </tr>
  690. <!-- /ko -->
  691. <!-- ko ifnot: col_name.indexOf('#') === 0 -->
  692. <tr>
  693. <td class="property-name" data-bind="text: col_name || '&nbsp;'"></td>
  694. <td data-bind="text: data_type || '&nbsp;'"></td>
  695. <td data-bind="text: comment || '&nbsp;'"></td>
  696. </tr>
  697. <!-- /ko -->
  698. </tbody>
  699. </table>
  700. <!-- /ko -->
  701. </script>
  702. <script type="text/html" id="metastore-describe-table">
  703. <div class="clearfix"></div>
  704. % if has_write_access:
  705. <span data-bind="editable: comment, editableOptions: {enabled: true, placement: 'bottom', emptytext: '${ _ko('Add a description...') }', inputclass:'input-xlarge', rows: 10 }" class="editable editable-click editable-empty" data-type="textarea">
  706. ${ _('Add a description...') }
  707. </span>
  708. % else:
  709. <span data-bind="text: comment"></span>
  710. %endif
  711. <ul class="nav nav-pills margin-top-30">
  712. <li><a href="#overview" data-toggle="tab" data-bind="click: function(){ $root.currentTab('table-overview'); }">${_('Overview')}</a></li>
  713. <li><a href="#columns" data-toggle="tab" data-bind="click: function(){ $root.currentTab('table-columns'); }">${_('Columns')} (<span data-bind="text: columns().length"></span>)</a></li>
  714. <!-- ko if: tableDetails() && tableDetails().partition_keys.length -->
  715. <li><a href="#partitions" data-toggle="tab" data-bind="click: function(){ $root.currentTab('table-partitions'); }">${_('Partitions')} (<span data-bind="text: partitionsCountLabel"></span>)</a></li>
  716. <!-- /ko -->
  717. <li><a href="#sample" data-toggle="tab" data-bind="click: function(){ $root.currentTab('table-sample'); }">${_('Sample')}</a></li>
  718. <!-- ko if: $root.optimizerEnabled() -->
  719. <!-- ko if: $root.database().table().optimizerDetails() -->
  720. <li><a href="#permissions" data-toggle="tab" data-bind="click: function(){ $root.currentTab('table-permissions'); }">${_('Permissions')}</a></li>
  721. <li><a href="#queries" data-toggle="tab" data-bind="click: function(){ $root.currentTab('table-queries'); }">${_('Queries')} (<span data-bind="text: $root.database().table().optimizerDetails().total"></span>)</a></li>
  722. <li><a href="#joins" data-toggle="tab" data-bind="click: function(){ $root.currentTab('table-joins'); }">${_('Joins')} (<span data-bind="text: $root.database().table().optimizerDetails().joinCount"></span>)</a></li>
  723. <!-- /ko -->
  724. <!-- ko if: $root.database().table().relationshipsDetails() -->
  725. <li><a href="#relationships" data-toggle="tab" data-bind="click: function(){ $root.currentTab('table-relationships'); }">${_('Relationships')} (<span data-bind="text: $root.database().table().relationshipsDetails().inputs().length + $root.database().table().relationshipsDetails().targets().length"></span>)</a></li>
  726. <!-- /ko -->
  727. <!-- /ko -->
  728. <li><a href="#details" data-toggle="tab" data-bind="click: function(){ $root.currentTab('table-details'); }">${ _('Details') }</a></li>
  729. </ul>
  730. <div class="tab-content margin-top-10" style="border: none; overflow: hidden">
  731. <div class="tab-pane" id="overview">
  732. <!-- ko if: $root.currentTab() == 'table-overview' -->
  733. <!-- ko template: 'metastore-overview-tab' --><!-- /ko -->
  734. <!-- /ko -->
  735. </div>
  736. <div class="tab-pane" id="columns">
  737. <!-- ko if: $root.currentTab() == 'table-columns' -->
  738. <input class="input-xlarge search-query margin-left-10" type="text" placeholder="${ _('Search for a column...') }" data-bind="clearable: columnQuery, value: columnQuery, valueUpdate: 'afterkeydown'"/>
  739. <!-- ko template: 'metastore-columns-tab' --><!-- /ko -->
  740. <!-- /ko -->
  741. </div>
  742. <div class="tab-pane" id="partitions">
  743. <!-- ko if: $root.currentTab() == 'table-partitions' -->
  744. <!-- ko template: 'metastore-partitions-tab' --><!-- /ko -->
  745. <!-- /ko -->
  746. </div>
  747. <div class="tab-pane" id="sample">
  748. <!-- ko if: $root.currentTab() == 'table-sample' -->
  749. <!-- ko template: 'metastore-sample-tab' --><!-- /ko -->
  750. <!-- /ko -->
  751. </div>
  752. <div class="tab-pane" id="permissions">
  753. <div class="acl-panel-content" style="height: 988px;">
  754. <div class="pull-right">
  755. <input class="input-medium no-margin" type="text" placeholder="Search privileges..."> &nbsp;
  756. <a class="btn pointer">
  757. <i class="fa fa-plus-circle"></i> Add role
  758. </a>
  759. </div>
  760. <h4 style="margin-top: 4px;">Privileges &nbsp;</h4>
  761. <div class="acl-block-title">
  762. <i class="fa fa-cube muted"></i> <a class="pointer"><span>customerFraud</span></a>
  763. </div>
  764. <div>
  765. <div class="acl-block acl-block-airy">
  766. <span class="muted" title="3 months ago">TABLE</span>
  767. <span>
  768. <a class="muted" target="_blank" style="margin-left: 4px" title="Open in Sentry" href="/security/hive"><i class="fa fa-external-link"></i></a>
  769. </span>
  770. <br>
  771. server=<span>server1</span>
  772. <span>
  773. <i class="fa fa-long-arrow-right"></i> db=<a class="pointer" title="Browse db privileges"><span data-bind="text: $root.database().name"></span></a>
  774. </span>
  775. <span>
  776. <i class="fa fa-long-arrow-right"></i> table=<a class="pointer" title="Browse table privileges"><span data-bind="text: name"></span></a>
  777. </span>
  778. <span style="display: none;">
  779. <i class="fa fa-long-arrow-right"></i> column=<a class="pointer" title="Browse column privileges"><span></span></a>
  780. </span>
  781. <i class="fa fa-long-arrow-right"></i> action=INSERT
  782. </div>
  783. <div class="acl-block acl-block-airy">
  784. <span class="muted" title="3 months ago">TABLE</span>
  785. <span>
  786. <a class="muted" target="_blank" style="margin-left: 4px" title="Open in Sentry" href="/security/hive"><i class="fa fa-external-link"></i></a>
  787. </span>
  788. <br>
  789. server=server1
  790. <span>
  791. <i class="fa fa-long-arrow-right"></i> db=<a class="pointer" title="Browse db privileges"><span data-bind="text: $root.database().name"></span></a>
  792. </span>
  793. <span>
  794. <i class="fa fa-long-arrow-right"></i> table=<a class="pointer" title="Browse table privileges"><span data-bind="text: name"></span></a>
  795. </span>
  796. <span style="display: none;">
  797. <i class="fa fa-long-arrow-right"></i> column=<a class="pointer" title="Browse column privileges"><span></span></a>
  798. </span>
  799. <i class="fa fa-long-arrow-right"></i> action=<span>SELECT</span>
  800. </div>
  801. </div>
  802. <div class="acl-block acl-actions">
  803. <span class="pointer" title="Show 50 more..." style="display: none;"><i class="fa fa-ellipsis-h"></i></span>
  804. <span class="pointer" title="Add privilege"><i class="fa fa-plus"></i></span>
  805. <span class="pointer" title="Undo" style="display: none;"> &nbsp; <i class="fa fa-undo"></i></span>
  806. <span class="pointer" title="Save" style="display: none;"> &nbsp; <i class="fa fa-save"></i></span>
  807. </div>
  808. <div class="acl-block-title">
  809. <i class="fa fa-cube muted"></i> <a class="pointer"><span>customerAccess</span></a>
  810. </div>
  811. <div>
  812. <div class="acl-block acl-block-airy">
  813. <span class="muted" title="3 months ago">TABLE</span>
  814. <span>
  815. <a class="muted" target="_blank" style="margin-left: 4px" title="Open in Sentry" href="/security/hive"><i class="fa fa-external-link"></i></a>
  816. </span>
  817. <br>
  818. server=server1
  819. <span>
  820. <i class="fa fa-long-arrow-right"></i> db=<a class="pointer" title="Browse db privileges"><span data-bind="text: $root.database().name"></span></a>
  821. </span>
  822. <span>
  823. <i class="fa fa-long-arrow-right"></i> table=<a class="pointer" title="Browse table privileges"><span data-bind="text: name"></span></a>
  824. </span>
  825. <span style="display: none;">
  826. <i class="fa fa-long-arrow-right"></i> column=<a class="pointer" title="Browse column privileges"><span></span></a>
  827. </span>
  828. <i class="fa fa-long-arrow-right"></i> action=<span>ALL</span>
  829. </div>
  830. <div class="acl-block acl-actions">
  831. <span class="pointer" title="Show 50 more..." style="display: none;"><i class="fa fa-ellipsis-h"></i></span>
  832. <span class="pointer" title="Add privilege"><i class="fa fa-plus"></i></span>
  833. <span class="pointer" title="Undo" style="display: none;"> &nbsp; <i class="fa fa-undo"></i></span>
  834. <span class="pointer" title="Save" style="display: none;"> &nbsp; <i class="fa fa-save"></i></span>
  835. </div>
  836. </div>
  837. </div>
  838. <style>
  839. .acl-panel {
  840. border-left: 1px solid #e5e5e5;
  841. padding-top: 6px;
  842. padding-left: 12px;
  843. }
  844. .acl-panel .nav-tabs {
  845. margin-bottom: 0;
  846. }
  847. .acl-panel h4:not(:first-child) {
  848. margin-top: 20px;
  849. }
  850. .acl-panel-content {
  851. padding: 6px;
  852. overflow-y: scroll;
  853. }
  854. .acl-block-title {
  855. background-color: #eeeeee;
  856. font-weight: bold;
  857. padding: 3px;
  858. margin-top: 14px;
  859. margin-bottom: 4px;
  860. }
  861. .acl-block {
  862. background-color: #f6f6f6;
  863. padding: 3px;
  864. margin-bottom: 4px;
  865. }
  866. .acl-block .checkbox, .acl-block .radio {
  867. margin-left: 6px;
  868. }
  869. .acl-block-airy {
  870. padding: 6px;
  871. }
  872. .acl-block-airy input {
  873. margin-bottom: 0;
  874. }
  875. .acl-block-section {
  876. margin-top: 10px;
  877. }
  878. .acl-block-section input {
  879. margin-left: 14px;
  880. }
  881. .span6 .acl-block input[type='text'] {
  882. width: 25%;
  883. }
  884. .span6 .acl-block input[type='text'] {
  885. width: 21%;
  886. }
  887. .acl-actions {
  888. padding: 5px;
  889. text-align: center;
  890. color: #CCC;
  891. font-size: 20px;
  892. }
  893. .acl-actions span:hover {
  894. color: #999;
  895. }
  896. </style>
  897. </div>
  898. <div class="tab-pane" id="queries">
  899. <!-- ko if: $root.optimizerEnabled() && $root.currentTab() == 'table-queries' -->
  900. <!-- ko template: {name: 'metastore-queries-tab', data: $root.database().table()} --><!-- /ko -->
  901. <!-- /ko -->
  902. </div>
  903. <div class="tab-pane" id="joins">
  904. <!-- ko if: $root.optimizerEnabled() && $root.database().table().optimizerDetails() -->
  905. <!-- ko with: $root.database().table().optimizerDetails().table_donut -->
  906. <table data-bind="visible: joinedtables().length > 0" class="table table-condensed">
  907. <thead>
  908. <tr>
  909. <th width="10%">${ _('Id') }</th>
  910. <th width="10%">${ _('Join Percentage') }</th>
  911. <th width="30%">${ _('Table Name') }</th>
  912. <th>${ _('Join Column') }</th>
  913. <th width="10%">${ _('Join counts') }</th>
  914. </tr>
  915. </thead>
  916. <tbody data-bind="hueach: {data: joinedtables(), itemHeight: 29, scrollable: '.right-panel', scrollableOffset: 200}">
  917. <tr>
  918. <td class="pointer" data-bind="text: tableEid, click: function(){ window.open($root.optimizerUrl() + '#/table/' + tableEid(), '_blank'); }"></td>
  919. <td style="height: 10px; width: 70px; margin-top:5px;" data-bind="attr: {'title': joinpercent()}">
  920. <div class="progress bar" style="background-color: #338bb8" data-bind="style: { 'width' : joinpercent() + '%' }"></div>
  921. </td>
  922. <td><a data-bind="text: tableName, attr: { href: '/metastore/table/' + $root.database().name + '/' + tableName() }"</a></td>
  923. <td class="pointer"><code data-bind="text: joinColumns, click: scrollToColumn"></code></td>
  924. <td data-bind="text: joincount"></td>
  925. </tr>
  926. </tbody>
  927. </table>
  928. <!-- /ko -->
  929. <!-- /ko -->
  930. </div>
  931. <div class="tab-pane" id="relationships">
  932. <!-- ko if: $root.currentTab() == 'table-relationships' && $root.database().table().relationshipsDetails() -->
  933. <!-- ko with: $root.database().table().relationshipsDetails() -->
  934. <h4>${ _('Inputs') }</h4>
  935. <div class="row-fluid">
  936. <!-- ko foreach: inputs -->
  937. <div data-bind="text: $data"></div>
  938. <!-- /ko -->
  939. <!-- ko if: inputs().length == 0 -->
  940. ${ _('Not inputs') }
  941. <!-- /ko -->
  942. </div>
  943. </br>
  944. <h4>${ _('Targets') }</h4>
  945. <div class="row-fluid">
  946. <!-- ko foreach: targets -->
  947. <div data-bind="text: $data"></div>
  948. <!-- /ko -->
  949. <!-- ko if: targets().length == 0 -->
  950. ${ _('Not targets') }
  951. <!-- /ko -->
  952. </div>
  953. </br>
  954. <h4>${ _('Source query') }</h4>
  955. <div class="row-fluid">
  956. <!-- ko if: source_query().length > 0 -->
  957. <code data-bind="text: source_query"></code>
  958. <!-- /ko -->
  959. <!-- ko if: source_query().length == 0 -->
  960. ${ _('No source query') }
  961. <!-- /ko -->
  962. </div>
  963. </br>
  964. <h4>${ _('Target queries') }</h4>
  965. <div class="row-fluid">
  966. <!-- ko foreach: target_queries -->
  967. <div>
  968. <code data-bind="text: $data"></code>
  969. </div>
  970. <!-- /ko -->
  971. <!-- ko if: target_queries().length == 0 -->
  972. ${ _('Not target queries') }
  973. <!-- /ko -->
  974. </div>
  975. </br>
  976. <h4>${ _('Lineage') }</h4>
  977. <div class="row-fluid">
  978. <button class="btn toolbarBtn" title="${_('Open in Navigator ')}" data-bind="click: function () { window.open($root.navigatorUrl() + '?view=detailsView&id=' + id() + '&b=rFlCX&tab=lineage', '_blank'); }">
  979. <i class="fa fa-skyatlas"></i> ${_('View in Navigator')}
  980. </button>
  981. </div>
  982. <!-- /ko -->
  983. <!-- /ko -->
  984. </div>
  985. <div class="tab-pane" id="details">
  986. <!-- ko if: $root.currentTab() == 'table-details' -->
  987. <!-- ko template: 'metastore-details-tab' --><!-- /ko -->
  988. <!-- /ko -->
  989. </div>
  990. </div>
  991. </script>
  992. <div class="main-content">
  993. <div class="vertical-full container-fluid" data-bind="style: { 'padding-left' : $root.isLeftPanelVisible() ? '0' : '20px' }">
  994. <div class="vertical-full row-fluid panel-container">
  995. <div class="assist-container left-panel" data-bind="visible: $root.isLeftPanelVisible() && $root.assistAvailable()">
  996. <a title="${_('Toggle Assist')}" class="pointer hide-assist" data-bind="click: function() { $root.isLeftPanelVisible(false) }">
  997. <i class="fa fa-chevron-left"></i>
  998. </a>
  999. <div class="assist" data-bind="component: {
  1000. name: 'assist-panel',
  1001. params: {
  1002. user: '${user.username}',
  1003. sql: {
  1004. sourceTypes: [{
  1005. name: 'hive',
  1006. type: 'hive'
  1007. }],
  1008. navigationSettings: {
  1009. openItem: true,
  1010. showStats: true
  1011. }
  1012. },
  1013. visibleAssistPanels: ['sql']
  1014. }
  1015. }"></div>
  1016. </div>
  1017. <div class="resizer" data-bind="visible: $root.isLeftPanelVisible() && $root.assistAvailable(), splitDraggable : { appName: 'notebook', leftPanelVisible: $root.isLeftPanelVisible }"><div class="resize-bar">&nbsp;</div></div>
  1018. <div class="right-panel" data-bind="niceScroll">
  1019. <div class="metastore-main">
  1020. <h3>
  1021. <!-- ko template: { if: database() !== null && database().table() !== null, name: 'metastore-describe-table-actions' }--><!-- /ko -->
  1022. <!-- ko template: { if: database() !== null && database().table() === null, name: 'metastore-tables-actions' }--><!-- /ko -->
  1023. <!-- ko template: { if: database() === null, name: 'metastore-databases-actions' }--><!-- /ko -->
  1024. <!-- ko template: 'metastore-breadcrumbs' --><!-- /ko -->
  1025. </h3>
  1026. <i data-bind="visible: loading" class="fa fa-spinner fa-spin fa-2x margin-left-10" style="color: #999; display: none;"></i>
  1027. <!-- ko template: { if: !loading() && database() === null, name: 'metastore-databases' } --><!-- /ko -->
  1028. <!-- ko with: database -->
  1029. <i data-bind="visible: loading" class="fa fa-spinner fa-spin fa-2x margin-left-10" style="color: #999; display: none;"></i>
  1030. <!-- ko template: { if: !loading() && table() === null, name: 'metastore-tables' } --><!-- /ko -->
  1031. <!-- ko with: table -->
  1032. <!-- ko template: 'metastore-describe-table' --><!-- /ko -->
  1033. <!-- /ko -->
  1034. <!-- /ko -->
  1035. </div>
  1036. </div>
  1037. </div>
  1038. </div>
  1039. <div id="dropSingleTable" class="modal hide fade">
  1040. <form method="POST">
  1041. ${ csrf_token(request) | n,unicode }
  1042. <div class="modal-header">
  1043. <a href="#" class="close" data-dismiss="modal">&times;</a>
  1044. <h3>${_('Drop Table')}</h3>
  1045. </div>
  1046. <div class="modal-body">
  1047. <div>${_('Do you really want to drop the table')} <span style="font-weight: bold;" data-bind="text: database() && database().table() ? database().table().name : ''"></span>?</div>
  1048. </div>
  1049. <div class="modal-footer">
  1050. <input type="hidden" name="table_selection" data-bind="value: database() && database().table() ? database().table().name : ''" />
  1051. <input type="button" class="btn" data-dismiss="modal" value="${_('No')}"/>
  1052. <input type="submit" data-bind="click: function (vm, e) { var $form = $(e.target).parents('form'); $form.attr('action', '/metastore/tables/drop/' + vm.database().name); return true; }" class="btn btn-danger" value="${_('Yes, drop this table')}"/>
  1053. </div>
  1054. </form>
  1055. </div>
  1056. <div id="import-data-modal" class="modal hide fade"></div>
  1057. </div>
  1058. <script type="text/javascript" charset="utf-8">
  1059. function pieChartDataTransformer(rawDatum) {
  1060. var _data = [];
  1061. $(rawDatum.counts).each(function (cnt, item) {
  1062. _data.push({
  1063. label: item.name,
  1064. value: item.popularity,
  1065. obj: item
  1066. });
  1067. });
  1068. _data.sort(function (a, b) {
  1069. return a.value - b.value
  1070. });
  1071. return _data;
  1072. }
  1073. (function () {
  1074. ko.options.deferUpdates = true;
  1075. $(document).ready(function () {
  1076. var options = {
  1077. user: '${ user.username }',
  1078. i18n: {
  1079. errorFetchingTableDetails: '${_('An error occurred fetching the table details. Please try again.')}',
  1080. errorFetchingTableFields: '${_('An error occurred fetching the table fields. Please try again.')}',
  1081. errorFetchingTableSample: '${_('An error occurred fetching the table sample. Please try again.')}',
  1082. errorRefreshingTableStats: '${_('An error occurred refreshing the table stats. Please try again.')}',
  1083. errorLoadingDatabases: '${ _('There was a problem loading the databases. Please try again.') }',
  1084. errorLoadingTablePreview: '${ _('There was a problem loading the table preview. Please try again.') }'
  1085. },
  1086. optimizerEnabled: '${ is_optimizer_enabled }' === 'True',
  1087. navigatorEnabled: '${ is_navigator_enabled }' === 'True',
  1088. optimizerUrl: '${ optimizer_url }',
  1089. navigatorUrl: '${ navigator_url }',
  1090. partitionsLimit: ${ LIST_PARTITIONS_LIMIT.get() }
  1091. };
  1092. var viewModel = new MetastoreViewModel(options);
  1093. huePubSub.subscribe('metastore.scroll.to.top', function () {
  1094. $(".right-panel").scrollTop(0);
  1095. $('.right-panel').getNiceScroll().resize();
  1096. });
  1097. viewModel.currentTab.subscribe(function(tab){
  1098. if (tab == 'table-relationships') {
  1099. // viewModel.database().table().getRelationships();
  1100. } else if (tab == 'table-sample') {
  1101. var selector = '#sample .sample-table';
  1102. if ($(selector).parents('.dataTables_wrapper').length == 0){
  1103. hueUtils.waitForRendered(selector, function(el){ return el.find('td').length > 0 }, function(){
  1104. $(selector).dataTable({
  1105. "bPaginate": false,
  1106. "bLengthChange": false,
  1107. "bInfo": false,
  1108. "bDestroy": true,
  1109. "bFilter": false,
  1110. "bAutoWidth": false,
  1111. "oLanguage": {
  1112. "sEmptyTable": "${_('No data available')}",
  1113. "sZeroRecords": "${_('No matching records')}"
  1114. },
  1115. "fnDrawCallback": function (oSettings) {
  1116. $(selector).parents('.dataTables_wrapper').css('overflow-x', 'hidden');
  1117. $(selector).jHueTableExtender({
  1118. fixedHeader: true,
  1119. fixedFirstColumn: true,
  1120. includeNavigator: false,
  1121. parentId: 'sample',
  1122. classToRemove: 'sample-table',
  1123. mainScrollable: '.right-panel',
  1124. stickToTopPosition: 73,
  1125. clonedContainerPosition: "fixed"
  1126. });
  1127. $(selector).jHueHorizontalScrollbar();
  1128. },
  1129. "aoColumnDefs": [
  1130. {
  1131. "sType": "numeric",
  1132. "aTargets": [ "sort-numeric" ]
  1133. },
  1134. {
  1135. "sType": "string",
  1136. "aTargets": [ "sort-string" ]
  1137. },
  1138. {
  1139. "sType": "date",
  1140. "aTargets": [ "sort-date" ]
  1141. }
  1142. ]
  1143. });
  1144. });
  1145. }
  1146. }
  1147. $('.right-panel').getNiceScroll().resize();
  1148. });
  1149. ko.applyBindings(viewModel);
  1150. if (location.getParameter('refresh') === 'true') {
  1151. huePubSub.publish('assist.db.refresh', 'hive');
  1152. hueUtils.replaceURL('?');
  1153. }
  1154. window.scrollToColumn = function (col) {
  1155. if (!col.table.samples.loading()) {
  1156. $('a[href="#sample"]').click();
  1157. window.setTimeout(function () {
  1158. var sampleTable = $('#sample').find('table');
  1159. var sampleCol = sampleTable.find('th').filter(function () {
  1160. return $.trim($(this).text()).indexOf(col.name()) > -1;
  1161. });
  1162. sampleTable.find('.columnSelected').removeClass('columnSelected');
  1163. sampleTable.find('tr td:nth-child(' + (sampleCol.index() + 1) + ')').addClass('columnSelected');
  1164. var scrollLeft = 0;
  1165. sampleTable.find('th:lt(' + sampleCol.index() + ')').each(function () {
  1166. scrollLeft += $(this).outerWidth();
  1167. });
  1168. sampleTable.parent().scrollLeft(scrollLeft);
  1169. }, 200);
  1170. }
  1171. }
  1172. });
  1173. })();
  1174. </script>
  1175. ${ commonfooter(request, messages) | n,unicode }