import * as React from 'react'; import {ISuperdesk, IArticle, IArticleQueryResult, IDesk, IUser} from 'superdesk-api'; function noop() { // } interface IState { articles: IArticleQueryResult | null; desks: Array | null; user: IUser | null; } // copied from the PUBLISHED_STATES constant // since this is a temporary workaround, I'm not moving the constant to extensions API const publishedStates = [ 'published', 'scheduled', 'corrected', 'killed', 'recalled', 'being_corrected', 'unpublished', ]; export function getMarkedForMeComponent(superdesk: ISuperdesk) { const {Badge, GroupLabel, TopMenuDropdownButton} = superdesk.components; return class MarkedForMe extends React.PureComponent<{}, IState> { private removeMarkedListener: () => void; private removeUnmarkedListener: () => void; constructor(props: {}) { super(props); this.state = { articles: null, desks: null, user: null, }; this.queryAndSetArticles = this.queryAndSetArticles.bind(this); this.removeMarkedListener = noop; this.removeUnmarkedListener = noop; } private queryAndSetArticles() { const {user} = this.state; if (user != null) { superdesk.dataApiByEntity.article.query({ page: {from: 0, size: 300}, sort: [{'_updated': 'desc'}], filterValues: {marked_for_user: [user._id]}, filterValuesNegative: {state: publishedStates}, aggregations: true, }).then((articles) => { this.setState({articles}); }); } } componentDidMount() { Promise.all([ superdesk.dataApi.query('desks', 1, {field: '_id', direction: 'ascending'}, {}), superdesk.session.getCurrentUser(), ]).then((res) => { const [desksResponse, user] = res; this.setState({desks: desksResponse._items, user}); this.queryAndSetArticles(); }); this.removeMarkedListener = superdesk.addWebsocketMessageListener('item:marked', this.queryAndSetArticles); this.removeUnmarkedListener = superdesk.addWebsocketMessageListener( 'item:unmarked', this.queryAndSetArticles, ); } componentWillUnmount() { this.removeMarkedListener(); this.removeUnmarkedListener(); } render() { const {articles, desks} = this.state; if (articles === null || desks == null) { return null; } const {gettext} = superdesk.localization; const {getClass} = superdesk.utilities.CSS; const DropdownTree = superdesk.components.getDropdownTree(); const {ArticleItemConcise} = superdesk.components; const itemsByDesk: {[id: string]: Array} = {}; articles._items.forEach((item) => { if (item.task != null && item.task.desk != null) { if (typeof itemsByDesk[item.task.desk] === 'undefined') { itemsByDesk[item.task.desk] = []; } itemsByDesk[item.task.desk].push(item); } }); const desksInOrder: Array = []; if (articles._aggregations.desk != null) { articles._aggregations.desk.buckets.forEach((bucket) => { // Skip non-ID aggregations SDESK-4497 if (itemsByDesk[bucket.key] != null) { desksInOrder.push(bucket.key); } }); } const hasItemsMarked = articles._items.length > 0; return ( ({ render: () => ( {itemsByDesk[deskId].length} {desks.find(({_id}) => _id === deskId)!.name} ), items: itemsByDesk[deskId], }))} getToggleElement={(isOpen, onClick) => ( { if (desksInOrder.length > 0) { onClick(); } }} active={isOpen} disabled={hasItemsMarked === false} pulsate={hasItemsMarked} data-test-id="toggle-button" > {articles._items.length} {gettext('Marked for me')} )} renderItem={(key, item, closeDropdown) => { return ( ); }} wrapperStyles={{width: 430, padding: 15, paddingTop: 0}} data-test-id="marked-for-me-dropdown" /> ); } }; }