import _ from 'lodash'; class LinkFunction { scope: any; desks: any; authoring: any; highlightsService: any; filter: any; location: any; timeout: any; elem: any; constructor(desks, authoring, highlightsService, $filter, $location, $timeout, scope, elem) { this.desks = desks; this.authoring = authoring; this.highlightsService = highlightsService; this.filter = $filter; this.location = $location; this.timeout = $timeout; this.scope = scope; this.elem = elem; this.init(); } /** * @ngdoc method * @name sdMarkedItemTitle#init * @private * @description Initializes the directive with default values for the scope * and with necessary watchers. */ init() { // Initialize required data if (this.scope.markField === 'marked_desks') { this.scope.deskMarking = true; this.scope.service = this.desks; this.scope.fetchFunction = 'fetchDesks'; this.scope.idField = 'desk_id'; this.scope.hasMarkItemPrivilege = this.authoring.itemActions(this.scope.item).mark_item_for_desks; } else { this.scope.deskMarking = false; this.scope.service = this.highlightsService; this.scope.fetchFunction = 'get'; this.scope.idField = '_id'; this.scope.hasMarkItemPrivilege = this.authoring.itemActions(this.scope.item).mark_item_for_highlight; } // Watch marks updates - listen to the event from server this.scope.$on('item:' + this.scope.markField, ($event, data) => { if (this.scope.item._id !== data.item_id) { return; } let marks = this.scope.marks || []; this.scope.$apply(() => { if (data.marked) { this.scope.marks = marks.concat(data.mark_id); } else { this.scope.marks = _.without(marks, data.mark_id); } this.updateMarkedItems(); }); }); // Watch if the item being previewing/authored has changed this.scope.$watch('item', (item) => { if (item) { this.scope.marks = []; if (item[this.scope.markField] && item[this.scope.markField].length) { // (if) marked_desks is an array of objects (else) highlights is an array if string: highlight ids if (this.scope.deskMarking) { this.scope.marks = _.map(item[this.scope.markField], this.scope.idField); } else { this.scope.marks = item[this.scope.markField]; } } this.updateMarkedItems(); } }); // Putting these two methods on scope as they are accessed by the template url's ng-click this.scope.toggleClass = this.toggleClass.bind(this); this.scope.unmark = this.unmark.bind(this); } /** * @ngdoc method * @name sdMarkedItemTitle#unmark * @private * @param {string} mark - _id of the mark to be removed * @description Remove mark of an item and close the marks popup dropdown */ unmark(mark) { this.scope.service.markItem(mark, this.scope.item).then(() => { this.timeout(() => { let popup = $(this.elem).find('.highlights-list'); popup.filter('.open').children('.dropdown-toggle.dropdown__toggle') .click(); }); }); } /** * @ngdoc method * @name sdMarkedItemTitle#toggleClass * @param {Boolean} isOpen - toggle value to be applied * @description Toggles 'open' class on dropdown menu element * @returns {Boolean} */ toggleClass(isOpen, $event) { if ($event) { $event.preventDefault(); $event.stopPropagation(); } this.scope.open = isOpen; } /** * @ngdoc method * @name sdMarkedItemTitle#isActiveHighlights * @description Evaluates if any of item's highlights are active * @returns {Boolean} */ isActiveHighlights() { var highlightStatuses = {}; _.forEach(this.scope.markObjects, (highlight) => { var hours = this.filter('hoursFromNow')(this.scope.item.versioncreated); highlightStatuses[highlight._id] = this.highlightsService.isInDateRange(highlight, hours); }); if (this.location.path() === '/workspace/highlights') { return highlightStatuses[this.location.search().highlight]; } return this.scope.markObjects.some((h) => highlightStatuses[h._id]); } /** * @ngdoc method * @name sdMarkedItemTitle#updateMarkedItems * @description Updates the item's mark property */ updateMarkedItems() { this.scope.service[this.scope.fetchFunction]().then((result) => { this.scope.markObjects = result._items.filter((obj) => (this.scope.marks || []).includes(obj._id)); // (if) marked_desks is an array of objects (else) highlights is an array if string: highlight ids if (this.scope.deskMarking) { let updatedDdeskMarks = []; _.forEach(this.scope.marks, (m) => { updatedDdeskMarks.push({desk_id: m}); }); this.scope.item[this.scope.markField] = updatedDdeskMarks; } else { this.scope.item[this.scope.markField] = this.scope.marks; } // Do UI required changes if (this.scope.marks) { this.doIconUpdates(); } }); } /** * @ngdoc method * @name sdMarkedItemTitle#doIconUpdates * @description Adds required UI classes to the mark icons */ doIconUpdates() { // To do - Change this method when a multi bell icon is added for desk markings // If highlights, add appropriate multi icon and color if (this.scope.deskMarking) { this.scope.className = 'icon-bell'; } else { this.scope.className = this.scope.marks.length > 1 ? 'icon-multi-star' : 'icon-star'; if (this.isActiveHighlights()) { this.scope.className += ' red'; } } } } /** * @module superdesk.apps.archive * @ngdoc directive * @name sdMarkedItemTitle * @requires desks * @requires authoring * @requires highlightServce * @requires $filter * @requires $location * @requires $timeout * @description This directive is used in authoring-topbar and item preview to mark a story as a highlight or * to mark it for a desk. */ export function MarkedItemTitle(desks, authoring, highlightsService, $filter, $location, $timeout) { return { scope: { item: '=item', markField: '@field', }, template: require('scripts/apps/archive/views/marked_item_title.html'), link: (scope, elem) => new LinkFunction(desks, authoring, highlightsService, $filter, $location, $timeout, scope, elem), }; } MarkedItemTitle.$inject = ['desks', 'authoring', 'highlightsService', '$filter', '$location', '$timeout'];