home.mako 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  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 desktop.views import commonheader, commonfooter
  18. from django.utils.translation import ugettext as _
  19. %>
  20. ${ commonheader(_('Welcome Home'), "home", user) | n,unicode }
  21. <style type="text/css">
  22. .sidebar-nav {
  23. margin-bottom: 10px;
  24. }
  25. .sidebar-nav img {
  26. margin-right: 6px;
  27. }
  28. .sidebar-nav .dropdown-menu a {
  29. padding-left: 6px;
  30. }
  31. .tag {
  32. float: left;
  33. margin-right: 6px;
  34. margin-bottom: 4px;
  35. }
  36. .tag-counter {
  37. margin-top: 3px;
  38. margin-right: 4px;
  39. }
  40. .toggle-tag, .document-tags-modal-checkbox, .tags-modal-checkbox {
  41. cursor: pointer;
  42. }
  43. .badge-left {
  44. border-radius: 9px 0px 0px 9px;
  45. padding-right: 5px;
  46. }
  47. .badge-right {
  48. border-radius: 0px 9px 9px 0px;
  49. padding-left: 5px;
  50. }
  51. .airy li {
  52. margin-bottom: 6px;
  53. }
  54. .trash-share {
  55. cursor: pointer;
  56. }
  57. .white {
  58. padding: 9px 18px;
  59. margin-top: 1px;
  60. overflow: hidden;
  61. font-size: 14px;
  62. line-height: 1.4;
  63. color: #737373;
  64. text-overflow: ellipsis;
  65. }
  66. .baseShared {
  67. color: #999;
  68. }
  69. .isShared {
  70. color: #338bb8!important;
  71. }
  72. </style>
  73. <div class="navbar navbar-inverse navbar-fixed-top nokids">
  74. <div class="navbar-inner">
  75. <div class="container-fluid">
  76. <div class="nav-collapse">
  77. <ul class="nav">
  78. <li class="currentApp">
  79. <a href="${ url('desktop.views.home') }">
  80. <img src="/static/art/home.png" />
  81. ${ _('My documents') }
  82. </a>
  83. </li>
  84. </ul>
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. <div class="container-fluid">
  90. <div class="row-fluid">
  91. <div class="span2">
  92. <div class="sidebar-nav">
  93. <ul class="nav nav-list">
  94. <li class="nav-header">${_('Actions')}</li>
  95. <li class="dropdown">
  96. <a href="#" data-toggle="dropdown"><i class="fa fa-plus-circle"></i> ${_('New document')}</a>
  97. <ul class="dropdown-menu" role="menu">
  98. % if 'beeswax' in apps:
  99. <li><a href="${ url('beeswax:index') }"><img src="${ apps['beeswax'].icon_path }"/> ${_('Hive Query')}</a></li>
  100. % endif
  101. % if 'impala' in apps:
  102. <li><a href="${ url('impala:index') }"><img src="${ apps['impala'].icon_path }"/> ${_('Impala Query')}</a></li>
  103. % endif
  104. % if 'pig' in apps:
  105. <li><a href="${ url('beeswax:index') }"><img src="${ apps['pig'].icon_path }"/> ${_('Pig Script')}</a></li>
  106. % endif
  107. % if 'spark' in apps:
  108. <li><a href="${ url('spark:index') }"><img src="${ apps['spark'].icon_path }"/> ${_('Spark Job')}</a></li>
  109. % endif
  110. % if 'oozie' in apps:
  111. <li class="dropdown-submenu">
  112. <a href="#"><img src="${ apps['oozie'].icon_path }"/> ${_('Oozie Scheduler')}</a>
  113. <ul class="dropdown-menu">
  114. <li><a href="${ url('oozie:create_workflow') }"><img src="/oozie/static/art/icon_oozie_workflow_24.png"/> ${_('Workflow')}</a></li>
  115. <li><a href="${ url('oozie:create_coordinator') }"><img src="/oozie/static/art/icon_oozie_coordinator_24.png"/> ${_('Coordinator')}</a></li>
  116. <li><a href="${ url('oozie:create_bundle') }"><img src="/oozie/static/art/icon_oozie_bundle_24.png"/> ${_('Bundle')}</a></li>
  117. </ul>
  118. </li>
  119. % endif
  120. </ul>
  121. </li>
  122. <!-- ko template: { name: 'tag-template', data: history } -->
  123. <!-- /ko -->
  124. <!-- ko template: { name: 'tag-template', data: trash } -->
  125. <!-- /ko -->
  126. <li class="nav-header tag-mine-header">
  127. ${_('My Projects')}
  128. <div class="edit-tags" style="display: inline;cursor: pointer;margin-left: 6px">
  129. <i class="fa fa-plus-circle" data-bind="click: addTag" title="${ _('Create project') }" rel="tooltip" data-placement="right"></i>
  130. <i class="fa fa-minus-circle" data-bind="click: removeTag, visible: $root.selectedTag().hasOwnProperty('owner') && $root.selectedTag().owner() == '${user}' && $root.selectedTag().name() != 'history' && $root.selectedTag().name() != 'trash' && $root.selectedTag().name() != 'default'"
  131. title="${ _('Remove selected project') }" rel="tooltip" data-placement="right"></i>
  132. </div>
  133. </li>
  134. <!-- ko template: { name: 'tag-template', foreach: nyTags } -->
  135. <!-- /ko -->
  136. <li data-bind="visible: myTags().length == 0">
  137. <a href="javascript:void(0)" class="edit-tags" style="line-height:24px">
  138. <i class="fa fa-plus-circle"></i> ${_('You currently own no projects. Click here to add one now!')}
  139. </a>
  140. </li>
  141. <li class="nav-header tag-shared-header">
  142. ${_('Shared with me')}
  143. </li>
  144. <!-- ko template: { name: 'shared-tag-template', foreach: sharedTags } -->
  145. <!-- /ko -->
  146. <li data-bind="visible: sharedTags().length == 0">
  147. <a href="javascript:void(0)" style="line-height:24px"><i class="fa fa-plus-circle"></i> ${_('There are currently no projects shared with you.')}
  148. </a>
  149. </li>
  150. </ul>
  151. </div>
  152. </div>
  153. <div class="span10">
  154. <div class="card card-home" style="margin-top: 0">
  155. <input id="searchInput" type="text" placeholder="Search for name, description, etc..." class="input-xlarge search-query pull-right" style="margin-right: 10px;margin-top: 3px">
  156. <h2 class="card-heading simple">${_('My Documents')}</h2>
  157. <div class="card-body">
  158. <p>
  159. <table id="documents" class="table table-striped table-condensed" data-bind="visible: documents().length > 0">
  160. <thead>
  161. <tr>
  162. <th style="width: 26px">&nbsp;</th>
  163. <th style="width: 200px">${_('Name')}</th>
  164. <th>${_('Description')}</th>
  165. <th style="width: 150px">${_('Last Modified')}</th>
  166. <th style="width: 80px; text-align: center">${_('Project')}</th>
  167. <th style="width: 40px">${_('Sharing')}</th>
  168. </tr>
  169. </thead>
  170. <tbody data-bind="template: { name: 'document-template', foreach: renderableDocuments}">
  171. </tbody>
  172. <tfoot data-bind="visible: documents().length > 0">
  173. <tr>
  174. <td colspan="7">
  175. <div class="pull-right" style="margin-top: 10px" data-bind="visible: hasPrevious() || hasNext()">
  176. <span>${_('Page')} <input type="number" class="input-mini" style="text-align: center" data-bind="value: page"> ${_('of')} <span data-bind="text: totalPages"></span></span>
  177. </div>
  178. <div class="pagination">
  179. <ul>
  180. <li><a data-bind="click: previousPage, visible: hasPrevious">${_('Previous')}</a></li>
  181. <li><a data-bind="click: nextPage, visible: hasNext">${_('Next')}</a></li>
  182. </ul>
  183. </div>
  184. </td>
  185. </tr>
  186. </tfoot>
  187. </table>
  188. <div data-bind="visible: documents().length == 0">
  189. <h4 style="color: #777; margin-bottom: 30px">${_('There are currently no documents in this project or tag.')}</h4>
  190. </div>
  191. </p>
  192. </div>
  193. </div>
  194. </div>
  195. </div>
  196. </div>
  197. <script type="text/html" id="tag-template">
  198. <li data-bind="click: $root.filterDocs, css: {'active': $root.selectedTag().id == id}">
  199. <a href="javascript:void(0)" style="padding-right: 4px">
  200. <i data-bind="css: {'fa': true, 'fa-trash-o':name() == 'trash', 'fa-clock-o': name() == 'history', 'fa-tag': name() != 'trash' && name() != 'history'}"></i> <span data-bind="text: name"></span>
  201. <span class="badge pull-right tag-counter" data-bind="text: docs().length"></span>
  202. </a>
  203. </li>
  204. </script>
  205. <script type="text/html" id="shared-tag-template">
  206. <li class="white">
  207. <i class="fa fa-user"></i> <span data-bind="text: name"></span>
  208. </li>
  209. <!-- ko foreach: projects-->
  210. <li data-bind="click: $root.filterDocs, css: {'active': $root.selectedTag().id == id}">
  211. <a href="javascript:void(0)" style="padding-right: 4px">
  212. &nbsp;&nbsp;&nbsp;<i class="fa fa-tag"></i> <span data-bind="text: name"></span> <span class="badge pull-right tag-counter" data-bind="text: docs().length"></span>
  213. </a>
  214. </li>
  215. <!-- /ko -->
  216. </script>
  217. <script type="text/html" id="document-template">
  218. <tr>
  219. <td style="width: 26px"><img data-bind="attr: { src: icon }"></td>
  220. <td><a data-bind="attr: { href: url }, text: name"></a></td>
  221. <td data-bind="text: description"></td>
  222. <td data-bind="text: lastModified"></td>
  223. <td style="text-align: center; white-space: nowrap">
  224. <a href="javascript:void(0)" rel="tooltip" data-placement="left" data-bind="click: moveDoc, attr: {'data-original-title': '${ _("Change project for") } '+name}" style="padding-left:8px; padding-right: 8px">
  225. <span data-bind="foreach: tags">
  226. <!-- ko if: name != 'trash'-->
  227. <span class="badge" data-bind="text: name"></span>
  228. <!-- /ko -->
  229. </span>
  230. </a>
  231. </td>
  232. <td style="width: 40px; text-align: center">
  233. <a rel="tooltip" data-placement="left" style="padding-left:10px; padding-right: 10px" data-bind="click: shareDoc, attr: {'data-original-title': '${ _("Share") } '+name}, visible: isMine , css:{'baseShared': true, 'isShared': perms.read.users.length + perms.read.groups.length > 0}">
  234. <i class="fa fa-users"></i>
  235. </a>
  236. <i class="fa fa-ban" style="padding-left:8px; padding-right: 8px" data-bind="visible: !isMine"></i>
  237. </td>
  238. </tr>
  239. </script>
  240. <div id="addTagModal" class="modal hide fade">
  241. <form class="form-inline form-padding-fix" onsubmit="javascript:{return false;}">
  242. <div class="modal-header">
  243. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
  244. <h3>${_('Create project')}</h3>
  245. </div>
  246. <div class="modal-body">
  247. <p>
  248. <label>
  249. ${_('Project name')} <input id="tagsNew" type="text" class="input-xlarge">
  250. </label>
  251. </p>
  252. </div>
  253. <div class="modal-footer">
  254. <a href="#" data-dismiss="modal" class="btn">${_('Cancel')}</a>
  255. <a id="tagsNewBtn" href="#" class="btn btn-primary disable-feedback">${ _('Add') }</a>
  256. </div>
  257. </form>
  258. </div>
  259. <div id="removeTagModal" class="modal hide fade">
  260. <div class="modal-header">
  261. <a href="#" class="close" data-dismiss="modal">&times;</a>
  262. <h3>${_('Confirm Delete')}</h3>
  263. </div>
  264. <div class="modal-body">
  265. <p>${_('Are you sure you want to delete the project')} <strong><span data-bind="text: selectedTagForDelete().name"></span></strong>? ${_('All its documents will be moved to the default tag.')}</p>
  266. </div>
  267. <div class="modal-footer">
  268. <a class="btn" data-dismiss="modal">${_('No')}</a>
  269. <a data-bind="click: removeTagFinal" class="btn btn-danger">${_('Yes')}</a>
  270. </div>
  271. </div>
  272. <div id="documentMoveModal" class="modal hide fade">
  273. <div class="modal-header">
  274. <a href="#" class="close" data-dismiss="modal">&times;</a>
  275. <h3>${_('Move to a project')}</h3>
  276. </div>
  277. <div class="modal-body">
  278. <p>
  279. ${_('Select the project you want to move this document to')}
  280. <ul class="unstyled">
  281. <!-- ko foreach: myTags -->
  282. <li>
  283. <a href="javascript:void(0)" style="padding-left: 4px" data-bind="click: moveDocFinal">
  284. <i class="fa fa-tag"></i> <span data-bind="text: name"></span>
  285. </a>
  286. </li>
  287. <!-- /ko -->
  288. </ul>
  289. </p>
  290. </div>
  291. <div class="modal-footer">
  292. <a class="btn" data-dismiss="modal">${_('Cancel')}</a>
  293. </div>
  294. </div>
  295. <div id="documentShareModal" class="modal hide fade">
  296. <div class="modal-header">
  297. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
  298. <h3>${_('Sharing settings')}</h3>
  299. </div>
  300. <div class="modal-body">
  301. <p>
  302. <div class="row-fluid">
  303. <div class="span6">
  304. <h4 class="muted" style="margin-top:0px">${_('Users')}</h4>
  305. <div data-bind="visible: selectedDoc().perms.read.users.length == 0">${_('The document is not shared with any user.')}</div>
  306. <ul class="unstyled airy" data-bind="foreach: selectedDoc().perms.read.users">
  307. <li><span class="badge badge-left"><i class="fa fa-user"></i> <span data-bind="text: prettifyUsername(id)"></span></span><span class="badge badge-important badge-right trash-share" data-bind="click: removeUserShare"><i class="fa fa-times-circle"></i></span></li>
  308. </ul>
  309. </div>
  310. <div class="span6">
  311. <h4 class="muted" style="margin-top:0px">${_('Groups')}</h4>
  312. <div data-bind="visible: selectedDoc().perms.read.groups.length == 0">${_('The document is not shared with any group.')}</div>
  313. <ul class="unstyled airy" data-bind="foreach: selectedDoc().perms.read.groups">
  314. <li><span class="badge badge-left"><i class="fa fa-users"></i> <span data-bind="text: name"></span></span><span class="badge badge-important badge-right trash-share" data-bind="click: removeGroupShare"><i class="fa fa-times-circle"></i></span></li>
  315. </ul>
  316. </div>
  317. </div>
  318. <div class="clearfix"></div>
  319. <div style="margin-top: 20px">
  320. <div class="input-append">
  321. <input id="documentShareTypeahead" type="text" style="width: 460px" placeholder="${_('You can type a username or a group')}">
  322. <a id="documentShareAddBtn" class="btn" type="button"><i class="fa fa-plus-circle"></i> ${_('Add')}</a>
  323. </div>
  324. </div>
  325. </p>
  326. </div>
  327. <div class="modal-footer">
  328. <a href="#" data-dismiss="modal" class="btn btn-primary disable-feedback disable-enter">${_('Done')}</a>
  329. </div>
  330. </div>
  331. <script src="/static/ext/js/datatables-paging-0.1.js" type="text/javascript" charset="utf-8"></script>
  332. <script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
  333. <script src="/static/ext/js/knockout.mapping-2.3.2.js" type="text/javascript" charset="utf-8"></script>
  334. <script src="/static/js/home.vm.js"></script>
  335. <script type="text/javascript" charset="utf-8">
  336. var viewModel, JSON_USERS_GROUPS;
  337. function prettifyUsername(userId) {
  338. var _user = null;
  339. for (var i = 0; i < JSON_USERS_GROUPS.users.length; i++) {
  340. if (JSON_USERS_GROUPS.users[i].id == userId) {
  341. _user = JSON_USERS_GROUPS.users[i];
  342. }
  343. }
  344. if (_user != null) {
  345. return (_user.first_name != "" ? _user.first_name + " " : "") + (_user.last_name != "" ? _user.last_name + " " : "") + ((_user.first_name != "" || _user.last_name != "") ? "(" : "") + _user.username + ((_user.first_name != "" || _user.last_name != "") ? ")" : "");
  346. }
  347. return "";
  348. }
  349. $(document).ready(function () {
  350. viewModel = new HomeViewModel(${ json_tags | n,unicode }, ${ json_documents | n,unicode });
  351. ko.applyBindings(viewModel);
  352. var selectedUserOrGroup, map, dropdown = null;
  353. $.getJSON('/desktop/api/users/autocomplete', function (data) {
  354. JSON_USERS_GROUPS = data;
  355. dropdown = [];
  356. map = {};
  357. $.each(JSON_USERS_GROUPS.users, function (i, user) {
  358. var _display = prettifyUsername(user.id);
  359. map[_display] = user;
  360. dropdown.push(_display);
  361. });
  362. $.each(JSON_USERS_GROUPS.groups, function (i, group) {
  363. map[group.name] = group;
  364. dropdown.push(group.name);
  365. });
  366. $("#documentShareTypeahead").typeahead({
  367. source: function (query, process) {
  368. process(dropdown);
  369. },
  370. matcher: function (item) {
  371. if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) {
  372. return true;
  373. }
  374. },
  375. sorter: function (items) {
  376. return items.sort();
  377. },
  378. highlighter: function (item) {
  379. var _icon = "fa";
  380. var _display = "";
  381. if (map[item].hasOwnProperty("username")) {
  382. _icon += " fa-user";
  383. }
  384. else {
  385. _icon += " fa-users";
  386. }
  387. var regex = new RegExp('(' + this.query + ')', 'gi');
  388. return "<i class='" + _icon + "'></i> " + item.replace(regex, "<strong>$1</strong>");
  389. },
  390. updater: function (item) {
  391. selectedUserOrGroup = map[item];
  392. return item;
  393. }
  394. });
  395. $("#documentShareTypeahead").on("keyup", function (e) {
  396. var _code = (e.keyCode ? e.keyCode : e.which);
  397. if (_code == 13) {
  398. handleTypeaheadSelection();
  399. }
  400. });
  401. });
  402. viewModel.selectedTag.subscribe(function (value) {
  403. $("#searchInput").val("");
  404. $.totalStorage("hueHomeSelectedTag", value.id());
  405. });
  406. if ($.totalStorage("hueHomeSelectedTag") != null) {
  407. var _preselectedTag = viewModel.getTagById($.totalStorage("hueHomeSelectedTag"));
  408. if (_preselectedTag != null) {
  409. viewModel.filterDocs(_preselectedTag);
  410. }
  411. }
  412. else {
  413. viewModel.filterDocs(viewModel.history());
  414. }
  415. $("#searchInput").jHueDelayedInput(function () {
  416. viewModel.searchDocs($("#searchInput").val());
  417. });
  418. $("#tagsNewBtn").on("click", function () {
  419. var tag_name = $("#tagsNew").val(); // use ko var + bind enable/disable button accordingly (blank, duplicate, reserved...)?
  420. $.post("/desktop/api/tag/add_tag", {
  421. name: tag_name
  422. },function (data) {
  423. viewModel.createTag(data);
  424. $("#tagsNew").val("");
  425. $(document).trigger("info", "${_('Project created')}");
  426. $("#addTagModal").modal("hide");
  427. }).fail(function (xhr, textStatus, errorThrown) {
  428. $(document).trigger("error", xhr.responseText); // reserved name, duplicate etc
  429. });
  430. });
  431. $("#documentShareAddBtn").on("click", function () {
  432. handleTypeaheadSelection();
  433. });
  434. function handleTypeaheadSelection() {
  435. if (selectedUserOrGroup != null) {
  436. if (selectedUserOrGroup.hasOwnProperty("username")) {
  437. viewModel.selectedDoc().perms.read.users.push(selectedUserOrGroup);
  438. }
  439. else {
  440. viewModel.selectedDoc().perms.read.groups.push(selectedUserOrGroup);
  441. }
  442. viewModel.selectedDoc.valueHasMutated();
  443. shareDocFinal();
  444. }
  445. selectedUserOrGroup = null;
  446. $("#documentShareTypeahead").val("");
  447. }
  448. $("a[rel='tooltip']").tooltip();
  449. });
  450. function addTag() {
  451. $("#addTagModal").modal("show");
  452. }
  453. function removeTag() {
  454. viewModel.selectedTagForDelete(viewModel.selectedTag());
  455. $("#removeTagModal").modal("show");
  456. }
  457. function removeTagFinal() {
  458. var tag = viewModel.selectedTagForDelete();
  459. $.post("/desktop/api/tag/remove_tag", {
  460. tag_id: tag.id()
  461. }, function (response) {
  462. if (response != null) {
  463. if (response.status == 0) {
  464. $(document).trigger("info", response.message);
  465. $("#removeTagModal").modal("hide");
  466. viewModel.deleteTag(tag);
  467. viewModel.filterDocs(viewModel.history());
  468. }
  469. else {
  470. $(document).trigger("error", "${_("There was an error processing your action: ")}" + response.message);
  471. }
  472. }
  473. });
  474. }
  475. function moveDoc(doc) {
  476. viewModel.selectedDoc(doc);
  477. $("#documentMoveModal").modal("show");
  478. }
  479. function moveDocFinal(tag) {
  480. $.post("/desktop/api/doc/update_tags", {
  481. data: JSON.stringify({
  482. doc_id: viewModel.selectedDoc().id,
  483. tag_ids: [tag.id()]
  484. })
  485. }, function (response) {
  486. if (response != null){
  487. if (response.status != 0) {
  488. $(document).trigger("error", "${_("There was an error processing your action: ")}" + response.message);
  489. }
  490. else {
  491. $(document).trigger("info", "${ _("Project updated successfully.") }");
  492. viewModel.updateDoc(response.doc);
  493. }
  494. }
  495. $("#documentMoveModal").modal("hide");
  496. })
  497. }
  498. function shareDoc(doc) {
  499. viewModel.selectedDoc(doc);
  500. $("#documentShareModal").modal("show");
  501. }
  502. function removeUserShare(user) {
  503. $(viewModel.selectedDoc().perms.read.users).each(function (cnt, item) {
  504. if (item.id == user.id) {
  505. viewModel.selectedDoc().perms.read.users.splice(cnt, 1);
  506. }
  507. });
  508. viewModel.selectedDoc.valueHasMutated();
  509. shareDocFinal();
  510. }
  511. function removeGroupShare(group) {
  512. $(viewModel.selectedDoc().perms.read.groups).each(function (cnt, item) {
  513. if (item.id == group.id) {
  514. viewModel.selectedDoc().perms.read.groups.splice(cnt, 1);
  515. }
  516. });
  517. viewModel.selectedDoc.valueHasMutated();
  518. shareDocFinal();
  519. }
  520. function shareDocFinal() {
  521. var _postPerms = {
  522. read: {
  523. user_ids: [],
  524. group_ids: []
  525. }
  526. }
  527. $(viewModel.selectedDoc().perms.read.users).each(function (cnt, item) {
  528. _postPerms.read.user_ids.push(item.id);
  529. });
  530. $(viewModel.selectedDoc().perms.read.groups).each(function (cnt, item) {
  531. _postPerms.read.group_ids.push(item.id);
  532. });
  533. $.post("/desktop/api/doc/update_permissions", {
  534. doc_id: viewModel.selectedDoc().id,
  535. data: JSON.stringify(_postPerms)
  536. }, function (response) {
  537. if (response != null) {
  538. if (response.status != 0) {
  539. $(document).trigger("error", "${_("There was an error processing your action: ")}" + response.message);
  540. }
  541. else {
  542. viewModel.updateDoc(response.doc);
  543. }
  544. }
  545. });
  546. }
  547. </script>
  548. <style type="text/css">
  549. .tourSteps {
  550. min-height: 150px;
  551. }
  552. </style>
  553. <script src="/static/ext/js/routie-0.3.0.min.js" type="text/javascript" charset="utf-8"></script>
  554. <script type="text/javascript" charset="utf-8">
  555. $(document).ready(function(){
  556. var currentStep = "tourStep1";
  557. routie({
  558. "tourStep1":function () {
  559. showStep("tourStep1");
  560. },
  561. "tourStep2":function () {
  562. showStep("tourStep2");
  563. },
  564. "tourStep3":function () {
  565. showStep("tourStep3");
  566. }
  567. });
  568. function showStep(step) {
  569. currentStep = step;
  570. $("a.tourStep").parent().removeClass("active");
  571. $("a.tourStep[href=#" + step + "]").parent().addClass("active");
  572. if (step == "tourStep3") {
  573. $("#tourLastStep").parent().addClass("active");
  574. }
  575. $(".tourStepDetails").hide();
  576. $("#" + step).show();
  577. }
  578. if ($.totalStorage("jHueTourHideModal") == null || $.totalStorage("jHueTourHideModal") == false) {
  579. $("#jHueTourModal").modal();
  580. $.totalStorage("jHueTourHideModal", true);
  581. $("#jHueTourModalChk").attr("checked", "checked");
  582. $("#jHueTourModalChk").on("change", function () {
  583. $.totalStorage("jHueTourHideModal", $(this).is(":checked"));
  584. });
  585. $("#jHueTourModalClose").on("click", function () {
  586. $("#jHueTourFlag").click();
  587. $("#jHueTourModal").modal("hide");
  588. });
  589. }
  590. });
  591. </script>
  592. <div id="jHueTourModal" class="modal hide fade" tabindex="-1">
  593. <div class="modal-header">
  594. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
  595. <h3>${_('Did you know?')}</h3>
  596. </div>
  597. <div class="modal-body">
  598. <div class="row-fluid">
  599. <div id="properties" class="section">
  600. <ul class="nav nav-tabs" style="margin-bottom: 0">
  601. <li class="active"><a href="#tourStep1" class="tourStep">${ _('Step 1:') } ${ _('Add data') }</a></li>
  602. <li><a href="#tourStep2" class="tourStep">${ _('Step 2:') } ${ _('Query data') }</a></li>
  603. <li><a id="tourLastStep" href="#tourStep3" class="tourStep">${ _('Step 3:') } ${_('Do more!') }</a></li>
  604. </ul>
  605. </div>
  606. <div class="tourSteps">
  607. <div id="tourStep1" class="tourStepDetails">
  608. <div class="pull-left" style="color: #DDDDDD;font-size: 116px;margin: 10px; margin-right: 20px"><i class="fa fa-download"></i></div>
  609. <div style="margin: 40px">
  610. <p>
  611. ${ _('With') } <span class="badge badge-info"><i class="fa fa-file"></i> File Browser</span>
  612. ${ _('and the apps in the') } <span class="badge badge-info">Data Browsers <b class="caret"></b></span> ${ _('section, upload, view your data and create tables.') }
  613. </p>
  614. <p>
  615. ${ _('Pre-installed samples are also already there.') }
  616. </p>
  617. </div>
  618. </div>
  619. <div id="tourStep2" class="tourStepDetails hide">
  620. <div class="pull-left" style="color: #DDDDDD;font-size: 116px;margin: 10px; margin-right: 20px"><i class="fa fa-search"></i></div>
  621. <div style="margin: 40px">
  622. <p>
  623. ${ _('Then query and visualize the data with the') } <span class="badge badge-info">Query Editors <b class="caret"></b></span>
  624. ${ _('and') } <span class="badge badge-info">Search <b class="caret"></b></span>
  625. </p>
  626. </div>
  627. </div>
  628. <div id="tourStep3" class="tourStepDetails hide">
  629. <div class="pull-left" style="color: #DDDDDD;font-size: 116px;margin: 10px; margin-right: 20px"><i class="fa fa-flag-checkered"></i></div>
  630. <div style="margin: 40px">
  631. % if tours_and_tutorials:
  632. <p>
  633. ${ _('Tours were created to guide you around.') }
  634. ${ _('You can see the list of tours by clicking on the checkered flag icon') } <span class="badge badge-info"><i class="fa fa-flag-checkered"></i></span>
  635. ${ ('at the top right of this page.') }
  636. </p>
  637. % endif
  638. <p>
  639. ${ _('Additional documentation is available at') } <a href="http://learn.gethue.com">learn.gethue.com</a>.
  640. </p>
  641. </div>
  642. </div>
  643. </div>
  644. </div>
  645. <div class="modal-footer">
  646. <label class="checkbox" style="float:left"><input id="jHueTourModalChk" type="checkbox" />${_('Do not show this dialog again')}</label>
  647. <a id="jHueTourModalClose" href="#" class="btn btn-primary disable-feedback">${_('Got it, prof!')}</a>
  648. </div>
  649. </div>
  650. ${ commonfooter(messages) | n,unicode }