/** * External dependencies */ import moment from 'moment'; import { EMPTY_ARRAY, EMPTY_OBJECT } from '@nelio-content/constants'; import { date } from '@nelio-content/date'; import { createIndexedSelector } from '@nelio-content/utils'; import type { Item, ItemSummary, ItemType, Maybe, PostId, PostSummary, SocialMessageSummary, Uuid, } from '@nelio-content/types'; /** * Internal dependencies */ import { toCSV } from './csv'; import type { State } from '../config'; export function getItem( state: State, type: ItemType, itemId?: Item[ 'id' ] ): Maybe< Item > { if ( ! itemId ) { return undefined; } switch ( type ) { case 'social': return state.entities.messages.byId[ itemId as Uuid ]; case 'task': return state.entities.tasks.byId[ itemId as Uuid ]; case 'external-event': return state.entities.externalEvents[ itemId as Uuid ]; case 'internal-event': return state.entities.internalEvents[ itemId as Uuid ]; case 'post': return state.entities.posts[ itemId as PostId ]; default: { const items: Record< number | string, Item > = state.entities.premiumByType[ type ]?.byId ?? EMPTY_OBJECT; return items[ itemId ]; } } } const getRawItemsInDay = ( state: State, localDay: string ) => state.calendar.days[ localDay ] || EMPTY_ARRAY; export const getItemsInDay = createIndexedSelector( ( state: State, localDay: string ) => { const items = getRawItemsInDay( state, localDay ); let needsFilter = false; for ( const sum of items ) { if ( sum.type === 'social' ) { needsFilter = true; break; } } if ( ! needsFilter ) { return items; } return filterOutInvalidAutoMessages( state, items ); }, ( state: State, localDay: string ) => ( { key: localDay, dependants: [ getRawItemsInDay( state, localDay ), state.entities.messages.byId, state.social.profiles.byId, ], } ) ); export function getUnscheduledPosts( state: State ): ReadonlyArray< PostSummary > { return ( getItemsInDay( state, '0000-00-00' ) || EMPTY_ARRAY ) as ReadonlyArray< PostSummary >; } export function getCSV( state: State, firstDay: string, lastDay: string ): string { let items: ReadonlyArray< ItemSummary > = []; const mday = moment( date( 'c', firstDay ) ); let sday = date( 'Y-m-d', mday ); while ( sday <= lastDay ) { items = [ ...items, ...getItemsInDay( state, sday ) ]; mday.add( 1, 'day' ); sday = date( 'Y-m-d', mday ); } return items.reduce( ( acc, i ) => acc + toCSV( state, i.type, getItem( state, i.type, i.id ) ), '"Date","Type","Author/Profile/Assignee","Title/Text/Task","Permalink","Status"\n' ); } // ======= // HELPERS // ======= function filterOutInvalidAutoMessages( state: State, items: ReadonlyArray< ItemSummary > ) { return items.filter( ( sum ): sum is SocialMessageSummary => { if ( 'social' !== sum.type ) { return true; } const item = state.entities.messages.byId[ sum.id ]; if ( ! item ) { return false; } const profile = state.social.profiles.byId[ item.profileId ]; if ( ! profile ) { return false; } if ( 'publication' === item.auto && 0 >= profile.publicationFrequency ) { return false; } if ( [ 'timeline', 'reshare' ].includes( item.auto ?? '' ) && 0 >= profile.reshareFrequency ) { return false; } return true; } ); }