PinsPanel.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. 'use strict';
  2. /**
  3. * Licensed Materials - Property of IBM
  4. * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2014, 2020
  5. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  6. */
  7. define(['../lib/@waca/dashboard-common/dist/ui/SearchableListView', '../lib/@waca/core-client/js/core-client/utils/Deferred', 'text!./templates/PinView.html', 'text!./templates/PinListItem.html', 'text!./templates/EmptyPinsList.html', '../app/nls/StringResources', 'jquery', 'underscore', 'doT', '../lib/@waca/core-client/js/core-client/utils/Utils', '../lib/@waca/core-client/js/core-client/utils/BidiUtil', '../lib/@waca/core-client/js/core-client/utils/ContentFormatter', '../lib/@waca/dashboard-common/dist/ui/toolbar_components/ToggleMenuBar', '../lib/@waca/dashboard-common/dist/lib/@ba-ui-toolkit/ba-graphics/dist/illustrations-js/no-pins_128'], function (SearchableListView, Deferred, ViewTemplate, PinListItem, EmptyPinsList, StringResources, $, _, dot, Utils, BidiUtil, ContentFormatter, ToggleMenuBar, noPinIcon) {
  8. var DEFAULT_DELAY = 500;
  9. /**
  10. * The Panel which shows the pinned content
  11. */
  12. var View = SearchableListView.extend({
  13. events: {
  14. 'mousedown .pinItem>div:not(.prop-deleteButton-item)': 'onDragStart',
  15. 'mouseup .pinItem>div:not(.prop-deleteButton-item)': 'onMouseUp',
  16. 'dragstart .pinItem': 'onDragStart',
  17. 'primaryaction .prop-deleteButton-item': 'onSingleRemove',
  18. 'deleteaction .pinItem': 'onSingleRemove'
  19. },
  20. itemTemplate: PinListItem,
  21. templateString: ViewTemplate,
  22. init: function init(attributes) {
  23. View.inherited('init', this, arguments);
  24. this.ajaxSvc = attributes.ajaxSvc;
  25. this.glassContext = attributes.glassContext;
  26. this.canvasController = attributes.canvasController;
  27. this.dashboardApi = this.canvasController.dashboardApi;
  28. this._icons = this.dashboardApi.getFeature('Icons');
  29. this.logger = this.glassContext.getCoreSvc('.Logger');
  30. this.dndManager = attributes.dndManager;
  31. this.dashboardPinningService = attributes.dashboardPinningService;
  32. this.smartNamingSvc = attributes.smartNamingSvc;
  33. this.promiseMap = {};
  34. this.pinCount = 0;
  35. this.viewMode = attributes.viewMode;
  36. this.elementClass = 'pinsPanel';
  37. this.dateFilterString = 'all';
  38. if (this.dashboardPinningService) {
  39. //register creating-pin handler
  40. this.addHandler = this.dashboardPinningService.on('pin:created', this.addPin.bind(this));
  41. //register deleting-pin handler
  42. this.postDeletionHandler = this.dashboardPinningService.on('pin:deleted', this.postDeletion.bind(this));
  43. //register fake-deleting-pin handler
  44. this.fakeDeletionHandler = this.dashboardPinningService.on('pin:fakeDeleted', this.fakeDeletion.bind(this));
  45. //register undo-deleting-pin handler
  46. this.undoDeletionHandler = this.dashboardPinningService.on('pin:undoDeletion', this.undoDeletion.bind(this));
  47. } else {
  48. throw new Error('Pinning service not provided to PinsPanel constructor');
  49. }
  50. },
  51. /**
  52. * Click event handler
  53. *
  54. * @param event:
  55. * The event to process
  56. * @public
  57. */
  58. onItemClick: function onItemClick(event) {
  59. // stop more events
  60. event.stopPropagation();
  61. //clear the existing selection as we only supports single selection for now
  62. this._clearSelections();
  63. // get target
  64. var $target = $(this.getTarget(event.currentTarget, 'pinItem'));
  65. this._toggleSelection($target);
  66. // update action buttons
  67. this._updateActionButtons();
  68. },
  69. onKeyDown: function onKeyDown(event) {
  70. var $target = $(this.getTarget(event.currentTarget, 'pinItem'));
  71. if (['Enter', ' '].indexOf(event.key) !== -1) {
  72. // Tab into the item does not select it so do the selection here and create on key
  73. if (!$target.hasClass('selected')) {
  74. this._toggleSelection($target);
  75. }
  76. this.onKeyDownToCreatePin(event);
  77. } else {
  78. View.inherited('onKeyDown', this, arguments);
  79. }
  80. },
  81. /**
  82. * Alias for the click event handler
  83. *
  84. * @param event:
  85. * The event to process
  86. * @public
  87. */
  88. onSelectItem: function onSelectItem(event) {
  89. this.onItemClick(event);
  90. },
  91. /**
  92. * Click handler for the remove button. It handles deleting the pins and updating the UI.
  93. *
  94. * @public
  95. * @return promise
  96. */
  97. onRemoveClick: function onRemoveClick() {
  98. // get selected pin
  99. var pinId = this._getSelectedPin();
  100. return this.deletePin(pinId);
  101. },
  102. /**
  103. * primary action handler for clicking/tapping the remove icon on a single pin in the list.
  104. * delete action handler for deleting a single list item in the list
  105. * it creates a pin object with the selected pin id and jQuery element, and calls deletePin() to delete the selected single pin
  106. *
  107. * @public
  108. *
  109. * @param {Event} EventObject - the event object to process
  110. * @return promise
  111. */
  112. onSingleRemove: function onSingleRemove(event) {
  113. var pinEl = $(event.currentTarget).parents('.listitem')[0] || event.target;
  114. var pinToRemove = pinEl.getAttribute('data-id');
  115. return this.deletePin(pinToRemove);
  116. },
  117. /**
  118. * Called by the DnD manager to check if this drop zone accept the dragged object
  119. *
  120. * @returns {Boolean}
  121. */
  122. accepts: function accepts(dragObject) {
  123. return dragObject.type === 'pin';
  124. },
  125. /**
  126. * Handles dragging action.
  127. * The function sends the id of a pin to pinning service and calls the dnd manager with the pin spec result
  128. *
  129. * @public
  130. *
  131. * @param {object} event - The event to process
  132. */
  133. onDragStart: function onDragStart(event) {
  134. var _this = this;
  135. this._mouseUp = false;
  136. if (this.dashboardApi.getMode() !== this.dashboardApi.MODES.EDIT) {
  137. return Promise.resolve(true);
  138. }
  139. var pinEl = $(event.currentTarget).parents('.listitem')[0] || event.target;
  140. var id = pinEl.getAttribute('data-id');
  141. if (id) {
  142. return this.getPin(id).then(function (pinSpec) {
  143. // If the mouse is up before we start dragging then just return
  144. if (_this._mouseUp) {
  145. return;
  146. }
  147. pinSpec = JSON.parse(JSON.stringify(pinSpec));
  148. if (!_.isEmpty(pinSpec) && !_this._stoppedDrag) {
  149. _this.dndManager.startDrag({
  150. event: event,
  151. type: 'pin',
  152. data: _this._buildDropInfo(pinSpec),
  153. avatar: _this._buildAvatar(pinSpec),
  154. moveXThreshold: 20,
  155. moveYThreshold: 20,
  156. callerCallbacks: {
  157. onDragDone: _this.onDragStop.bind(_this)
  158. }
  159. });
  160. }
  161. });
  162. } else {
  163. return Promise.resolve();
  164. }
  165. },
  166. // User might of single clicked, so stop the drag from starting
  167. onMouseUp: function onMouseUp() {
  168. this._mouseUp = true;
  169. this.onDragStop();
  170. },
  171. onDragStop: function onDragStop() {
  172. this._clearSelections();
  173. },
  174. /**
  175. * Gets a pin spec from calling glassContext using a pin id
  176. *
  177. * @public
  178. *
  179. * @param {stirng} id - The id of a pin
  180. * @return {string} pinSpec - The spec of a pin
  181. */
  182. getPin: function getPin(id) {
  183. return this.dashboardPinningService.getPin(id);
  184. },
  185. /**
  186. * A helper function to build avatar for a pin
  187. * @param {string} pinSpec - the spec of a pin
  188. * @return {object} - a jquery object with an img of the pin if present.
  189. */
  190. _buildAvatar: function _buildAvatar(pinSpec) {
  191. var avatar = $('<img/>', {
  192. class: 'avatar pin'
  193. });
  194. avatar.attr('src', pinSpec.thumbUri);
  195. return avatar;
  196. },
  197. /**
  198. * a helper method to build drop info based on the pin spec that was received from the server
  199. *
  200. * @private
  201. *
  202. * @param {object} pinSpec - description of a pin
  203. * @return {object} dropInfo
  204. */
  205. _buildDropInfo: function _buildDropInfo(pinSpec) {
  206. return {
  207. operation: 'new',
  208. pinSpec: pinSpec
  209. };
  210. },
  211. /**
  212. * Deletes pins by sending an ajax request and updates the UI
  213. *
  214. * @param id:
  215. * string - a pin id to delete
  216. * @public
  217. */
  218. deletePin: function deletePin(id) {
  219. this.dashboardPinningService.deletePin(id);
  220. },
  221. /**
  222. * Undo deletion handler. It gets called if the undo deletion event is triggered.
  223. * The selected pin slides down and the pin count increments by 1
  224. * @param id:
  225. * string - a pin id to delete
  226. * @public
  227. * @return promise
  228. */
  229. undoDeletion: function undoDeletion(pinId) {
  230. var that = this;
  231. var deferred = new Deferred();
  232. this.promiseMap[pinId].promise.done(function () {
  233. var $pinItem = that.$el.find('.pinItem[data-id=' + pinId + ']');
  234. $pinItem.slideDown(DEFAULT_DELAY, function () {
  235. // increment the pin count
  236. that.pinCount++;
  237. that._updatePinCount();
  238. // remove from the promise map
  239. delete that.promiseMap[pinId];
  240. deferred.resolve();
  241. });
  242. });
  243. return deferred.promise;
  244. },
  245. /**
  246. * Fake deletion handler. It gets called if the fake deletion event is triggered.
  247. * The selected pin slides up and the pin count decrements by 1
  248. *
  249. * @param id:
  250. * string - a pin id to delete
  251. * @public
  252. */
  253. fakeDeletion: function fakeDeletion(pinId) {
  254. var _this2 = this;
  255. var deferred = new Deferred();
  256. //save the promise into the promise map
  257. this.promiseMap[pinId] = deferred;
  258. var $pinItem = this.$el.find('.pinItem[data-id=' + pinId + ']');
  259. $pinItem.slideUp(DEFAULT_DELAY, function () {
  260. //decrement the pin count by one in the panel
  261. _this2.pinCount--;
  262. _this2._updatePinCount();
  263. //clear the selection state and update the action button
  264. _this2._clearSelections();
  265. _this2._updateActionButtons();
  266. deferred.resolve();
  267. });
  268. },
  269. /**
  270. * post deletion handler. It gets called if a pin:deleted event is triggered.
  271. * The pin item gets removed from the DOM after fake deletion finishes
  272. *
  273. * @param id:
  274. * string - a pin id to delete
  275. * @public
  276. * @returns promise
  277. */
  278. postDeletion: function postDeletion(pinId) {
  279. var view = this;
  280. var deferred = new Deferred();
  281. if (this.promiseMap[pinId]) {
  282. this.promiseMap[pinId].promise.done(function () {
  283. var $el = view.$el.find('.pinItem[data-id=' + pinId + ']');
  284. $el.remove();
  285. //make the first item in the list tabbable after deletion
  286. var firstEl = view.$el.find('.pinItem:first');
  287. if (firstEl.length) {
  288. firstEl.attr('tabindex', '0');
  289. }
  290. //remove from the promise map
  291. delete view.promiseMap[pinId];
  292. deferred.resolve();
  293. });
  294. } else {
  295. deferred.resolve();
  296. }
  297. return deferred.promise;
  298. },
  299. /**
  300. * primary action handler for adding pin to canvas
  301. *
  302. * @public
  303. * @param {event} event - The event object to process
  304. */
  305. onKeyDownToCreatePin: function onKeyDownToCreatePin(event) {
  306. // get selected pin
  307. var pinId = this._getSelectedPin();
  308. if (pinId) {
  309. return this.getPin(pinId).then(function (pinSpec) {
  310. pinSpec = JSON.parse(JSON.stringify(pinSpec)); //Clone the pin spec, as the add operation is side-effecting, and we don't want any updates to change the cached pin.
  311. if (!_.isEmpty(pinSpec)) {
  312. var fragmentModel = {
  313. layout: pinSpec.content.layout,
  314. widgets: pinSpec.content.widgets,
  315. dataSources: pinSpec.content.dataSources,
  316. version: pinSpec.version ? pinSpec.content.specVersion : 6,
  317. sourceName: pinSpec.sourceName
  318. };
  319. if (pinSpec.content.episodes) {
  320. fragmentModel.episodes = pinSpec.content.episodes;
  321. }
  322. var options = {
  323. model: fragmentModel
  324. };
  325. if (pinSpec.content.layout && pinSpec.content.layout.style) {
  326. options.layoutProperties = {
  327. style: _.omit(pinSpec.content.layout.style, 'top', 'left')
  328. };
  329. }
  330. var isTouch = event.type === 'tap';
  331. this._addPinToLayout(options, isTouch);
  332. this._clearSelections();
  333. }
  334. }.bind(this));
  335. } else {
  336. return Promise.resolve();
  337. }
  338. },
  339. _addPinToLayout: function _addPinToLayout(options, isTouch) {
  340. this.canvasController.addPin(options, isTouch);
  341. },
  342. /**
  343. * Callback function for when the render is completed. This one updates the pin count in the UI and puts the focus on the first pin.
  344. *
  345. * @public
  346. */
  347. renderComplete: function renderComplete() {
  348. // update the pin count
  349. this._updatePinCount();
  350. this._middleShortenPins();
  351. this._setIcons();
  352. this._setFocus();
  353. },
  354. renderList: function renderList(items) {
  355. this.pinCount = items ? items.length : 0;
  356. View.inherited('renderList', this, arguments);
  357. },
  358. render: function render() {
  359. var deferred = new Deferred();
  360. this.dndManager.removeDropTarget(this.el);
  361. View.inherited('render', this).done(function () {
  362. this.dndManager.addDropTarget(this.el, {
  363. accepts: this.accepts
  364. });
  365. this._renderDateFilterDropdown().then(function () {
  366. deferred.resolve();
  367. });
  368. }.bind(this));
  369. return deferred.promise;
  370. },
  371. _filterByDate: function _filterByDate(filterString) {
  372. var _this3 = this;
  373. if (!filterString) {
  374. return;
  375. }
  376. this.dateFilterString = filterString;
  377. if (this.dateFilterString !== 'all') {
  378. this.$el.find('.filterWrapper').addClass('filtered');
  379. } else {
  380. this.$el.find('.filterWrapper').removeClass('filtered');
  381. }
  382. return this._getPins().then(function (pins) {
  383. _this3.pinCount = pins.length;
  384. _this3.renderList(pins);
  385. // re-apply any search that may already be in place.
  386. _this3.$el.find('.treeSearchInput').trigger('input');
  387. _this3.renderComplete();
  388. });
  389. },
  390. _renderDateFilterDropdown: function _renderDateFilterDropdown() {
  391. var _this4 = this;
  392. var $filterWrapper = this.$el.find('.filterWrapper');
  393. var menuItems = [{
  394. 'name': 'all',
  395. 'label': StringResources.get('pinDateFilterAll'),
  396. 'cssStyleClass': 'blueSelectedBar',
  397. 'action': function action() {
  398. _this4._filterByDate('all');
  399. }
  400. }, {
  401. 'name': 'today',
  402. 'label': StringResources.get('pinDateFilterToday'),
  403. 'cssStyleClass': 'blueSelectedBar',
  404. 'action': function action() {
  405. _this4._filterByDate('today');
  406. }
  407. }, {
  408. 'name': 'yesterday',
  409. 'label': StringResources.get('pinDateFilterYesterday'),
  410. 'cssStyleClass': 'blueSelectedBar',
  411. 'action': function action() {
  412. _this4._filterByDate('yesterday');
  413. }
  414. }, {
  415. 'name': 'pastWeek',
  416. 'label': StringResources.get('pinDateFilterPastWeek'),
  417. 'cssStyleClass': 'blueSelectedBar',
  418. 'action': function action() {
  419. _this4._filterByDate('pastWeek');
  420. }
  421. }, {
  422. 'name': 'pastMonth',
  423. 'label': StringResources.get('pinDateFilterPastMonth'),
  424. 'cssStyleClass': 'blueSelectedBar',
  425. 'action': function action() {
  426. _this4._filterByDate('pastMonth');
  427. }
  428. }, {
  429. 'name': 'earlier',
  430. 'label': StringResources.get('pinDateFilterEarlier'),
  431. 'cssStyleClass': 'blueSelectedBar',
  432. 'action': function action() {
  433. _this4._filterByDate('earlier');
  434. }
  435. }];
  436. this.ddMenu = new ToggleMenuBar({
  437. 'label': StringResources.get('pinDateFilter'),
  438. 'items': menuItems,
  439. 'actionElement': $filterWrapper,
  440. 'ddMenuPlacement': 'bottom-left',
  441. 'showTitle': false,
  442. 'updateLabel': true,
  443. 'icon': 'common-filter'
  444. });
  445. return this.ddMenu.render().then(function ($el) {
  446. Utils.setIcon($el.find('.common-filter'), _this4._icons.getIcon('filter').id, StringResources.get('pinDateFilter'));
  447. _this4.$el.find('.filterWrapper').append($el);
  448. });
  449. },
  450. _setFocus: function _setFocus() {
  451. this.$el.find('.searchWrapper input').focus();
  452. this.$el.find('.pinItem:first').attr('tabindex', '0');
  453. },
  454. _setIcons: function _setIcons() {
  455. var $deleteIcon = this.$el.find('.deleteButtonHolder:not(:has(svg))');
  456. Utils.setIcon($deleteIcon, 'dashboard-remove', StringResources.get('pinRemove'));
  457. },
  458. /**
  459. * shows an empty pins list with IBM bee when there is no pins
  460. * otherwise remove the empty content list
  461. */
  462. _updateEmptyPinsList: function _updateEmptyPinsList() {
  463. if (!this.pinCount) {
  464. this.$el.find('.list').append(dot.template(EmptyPinsList)({
  465. text: StringResources.get('NoPinsCollected'),
  466. emptyBeeIcon: noPinIcon.default.id
  467. }));
  468. } else {
  469. this.$el.find('.list .emptyTableContent').remove();
  470. }
  471. },
  472. _middleShortenPins: function _middleShortenPins() {
  473. if (this.pinCount) {
  474. var $pinTexts = this.$el.find('.pinName, .pinSource, .pinAge');
  475. for (var i = 0; i < $pinTexts.length; i++) {
  476. ContentFormatter.middleShortenString($pinTexts[i]);
  477. }
  478. }
  479. },
  480. /**
  481. * overridden method providing pin specific properties for dot.
  482. */
  483. getCustomRenderProperties: function getCustomRenderProperties() {
  484. return {
  485. searchText: StringResources.get('pinSearchOld'),
  486. lbl_listView: StringResources.get('pinListView'),
  487. lbl_iconView: StringResources.get('pinIconView'),
  488. lbl_remove: StringResources.get('pinRemove'),
  489. lbl_add: StringResources.get('add'),
  490. roleType: 'listitem',
  491. searchIcon: this._icons.getIcon('search').id
  492. };
  493. },
  494. /**
  495. * This function is called by the renderer. It fetches the list of pins
  496. *
  497. * @public
  498. * @return promise
  499. */
  500. getListItems: function getListItems() {
  501. var _this5 = this;
  502. return this._getPins().then(function (pins) {
  503. _this5.pinCount = pins.length;
  504. return pins;
  505. });
  506. },
  507. _getPins: function _getPins() {
  508. return this.dashboardPinningService.getPins(this.dateFilterString);
  509. },
  510. /**
  511. * Add a pin to this view
  512. *
  513. * @public
  514. */
  515. addPin: function addPin(pin) {
  516. if (!pin) {
  517. return;
  518. }
  519. // render
  520. if (this.dateFilterString !== 'yesterday' && this.dateFilterString !== 'earlier') {
  521. this.pinCount++;
  522. this._renderPin(pin);
  523. }
  524. this.$el.find('.treeSearchInput').trigger('input');
  525. },
  526. /**
  527. * Add a new pin to the rendered list.
  528. * @private
  529. */
  530. _renderPin: function _renderPin(pin) {
  531. var sHtml = this._getListItemsHtml([pin]);
  532. var $list = this.$el.find(this.controlClassSelector);
  533. var view = this;
  534. // queue up pin to be added to the list
  535. $list.queue(function () {
  536. var $item = $(this);
  537. $(sHtml).hide().css('opacity', 0.0).prependTo($list).delay(200).slideDown('slow', function () {
  538. $(this).animate({
  539. opacity: 1.0
  540. }).show();
  541. view.renderComplete();
  542. // allow animations to complete before kicking off the next one.
  543. window.setTimeout(function () {
  544. $item.dequeue();
  545. }, 500);
  546. });
  547. });
  548. },
  549. /**
  550. * Callback function for each list item to process it before rendering
  551. *
  552. * @param item:
  553. * list item object to process
  554. * @public
  555. * @return Object: The processed list object
  556. */
  557. prepareListItem: function prepareListItem(item) {
  558. item.cssClass = 'pinItem';
  559. item.selected = false;
  560. item.canSingleDelete = true;
  561. item.label_delete = StringResources.get('pinRemove');
  562. item.isSingleGroup = true;
  563. return item;
  564. },
  565. /**
  566. * Helper function to toggle the users pin selection.
  567. *
  568. * @param item: JQuery list item object to select
  569. * @private
  570. */
  571. _toggleSelection: function _toggleSelection($item) {
  572. // see if the item is selected and toggle accordingly
  573. this._selectItem($item, !$item.hasClass('selected'));
  574. },
  575. /**
  576. * Helper function to select the given item
  577. *
  578. * @param item: JQuery list item object to select
  579. * @param select: Boolean flag to indicate select or deselect
  580. * @private
  581. */
  582. _selectItem: function _selectItem($item, select) {
  583. if (select) {
  584. // style the item as selected
  585. $item.addClass('selected');
  586. } else {
  587. // remove selected styling
  588. $item.removeClass('selected');
  589. }
  590. },
  591. /**
  592. * Helper function to set the disabled status of the action buttons
  593. *
  594. * @private
  595. */
  596. _updateActionButtons: function _updateActionButtons() {
  597. // get buttons
  598. var $buttons = this.$el.find('.actionButton');
  599. // check if there are selected pins
  600. if (this.$el.find('.pinItem.selected').length > 0 && this.dashboardApi.getMode() === this.dashboardApi.MODES.EDIT) {
  601. // enable action buttons
  602. $buttons.removeClass('disabled');
  603. $buttons.prop('disabled', false);
  604. $buttons.attr('tabindex', '0');
  605. } else {
  606. // disable action buttons
  607. $buttons.addClass('disabled');
  608. $buttons.prop('disabled', true);
  609. $buttons.attr('tabindex', '-1');
  610. }
  611. },
  612. /**
  613. * Helper function to get the selected pin
  614. *
  615. * @private
  616. * @return the id of a pin
  617. */
  618. _getSelectedPin: function _getSelectedPin() {
  619. // get selected pin list elements
  620. var $listItems = this.$el.find('.pinItem.selected');
  621. if ($listItems.length === 1) {
  622. return $listItems[0].getAttribute('data-id');
  623. }
  624. },
  625. /**
  626. * Helper function to update the UI to indicate the number of pins
  627. *
  628. * @private
  629. */
  630. _updatePinCount: function _updatePinCount() {
  631. // get the pin count element
  632. var formattedCount = BidiUtil.enforceNumericShaping(this.pinCount);
  633. this.$el.find('.pinCount').text(StringResources.get('pinCount', {
  634. smart_count: formattedCount,
  635. count: formattedCount
  636. }));
  637. this._updateEmptyPinsList();
  638. },
  639. /**
  640. * Overridden method to provide a list of items that are searchable for this view
  641. */
  642. _getSearchableItems: function _getSearchableItems() {
  643. return this.dashboardPinningService.getCachedPins(this.dateFilterString);
  644. },
  645. /**
  646. * Overridden method to provide the searchable string for a view object
  647. */
  648. _getSearchableFieldValue: function _getSearchableFieldValue(value) {
  649. var _this6 = this;
  650. // concatenate multiple values to search
  651. var separator = '___';
  652. var fields = value.displayName + separator + value.sourceName;
  653. if (value.contentType === 'boardFragment' && value.content.widgets) {
  654. // if looking at a boardFragment with widgets, use the mapping labels
  655. _.each(value.content.widgets, function (widget) {
  656. fields = fields + separator + _this6.smartNamingSvc.getLocalizedWidgetType(widget);
  657. _.each(widget.mapping, function (mapping) {
  658. fields = fields + separator + mapping.label;
  659. });
  660. // check live widgets
  661. var items = widget.data && widget.data.dataViews && widget.data.dataViews[0] && widget.data.dataViews[0].dataItems;
  662. _.each(items, function (item) {
  663. fields = fields + separator + item.itemLabel;
  664. });
  665. });
  666. }
  667. return fields;
  668. },
  669. _clearSelections: function _clearSelections() {
  670. this.$el.find('.listitem').removeClass('selected');
  671. },
  672. /**
  673. * Un-registers all of the handlers
  674. */
  675. remove: function remove() {
  676. this.addHandler.remove();
  677. this.postDeletionHandler.remove();
  678. this.fakeDeletionHandler.remove();
  679. this.undoDeletionHandler.remove();
  680. View.inherited('remove', this, arguments);
  681. }
  682. });
  683. return View;
  684. });
  685. //# sourceMappingURL=PinsPanel.js.map