/** * External dependencies */ import { find, keys, isEqual, pick, some } from 'lodash'; import { EMPTY_ARRAY } from '@nelio-content/constants'; import type { AuthorId, EditorialComment, EditorialTask, Maybe, PostId, PostStatusSlug, PostTypeName, PremiumItems, PremiumItemType, Series, TaxonomySlug, Term, Url, } from '@nelio-content/types'; /** * Internal dependencies */ import type { EditorialReference, State } from '../types'; export function getAllAttributes( state: State ): State[ 'attributes' ] { return state.attributes; } export function getId( state: State ): Maybe< PostId > { return state.attributes.id; } export function getTitle( state: State ): string { return state.attributes.title || ''; } export function isSticky( state: State ): boolean { return !! state.attributes.isSticky; } export function isRewrite( state: State ): boolean { return !! state.attributes.isRewrite; } export function canBeRewritten( state: State ): boolean { return !! state.attributes.canBeRewritten; } export function rewriteUrl( state: State ): Maybe< Url > { return state.attributes.rewriteUrl; } export function getPostType( state: State ): Maybe< PostTypeName > { return state.attributes.type; } export function getPostStatus( state: State ): Maybe< PostStatusSlug > { return state.attributes.status; } export function getPostTerms( state: State, taxonomy: TaxonomySlug ): ReadonlyArray< Term > { return state.attributes.taxonomies[ taxonomy ] ?? EMPTY_ARRAY; } export function getPostTermsByTaxonomy( state: State ): Record< TaxonomySlug, ReadonlyArray< Term > > { return state.attributes.taxonomies; } export function getAuthorId( state: State ): Maybe< AuthorId > { return state.attributes.authorId; } export function getDateValue( state: State ): string { return state.attributes.dateValue; } export function getSeries( state: State ): ReadonlyArray< Series > { return state.attributes.series; } export function getTimeValue( state: State ): string { return state.attributes.timeValue; } export function getTasks( state: State ): ReadonlyArray< EditorialTask > { return state.attributes.tasks; } type GetPremiumItems = typeof _getPremiumItems & { CurriedSignature: < Type extends PremiumItemType >( typeName: Type ) => ReadonlyArray< PremiumItems[ Type ] >; }; export const getPremiumItems: GetPremiumItems = _getPremiumItems as GetPremiumItems; function _getPremiumItems< Type extends PremiumItemType >( state: State, typeName: Type ): ReadonlyArray< PremiumItems[ Type ] > { return state.attributes.premiumItemsByType[ typeName ] ?? EMPTY_ARRAY; } type ArePremiumItemsDirty = typeof _arePremiumItemsDirty & { CurriedSignature: < Type extends PremiumItemType >( typeName: Type, oldPremiumItems: ReadonlyArray< PremiumItems[ Type ] > ) => boolean; }; export const arePremiumItemsDirty: ArePremiumItemsDirty = _arePremiumItemsDirty as ArePremiumItemsDirty; function _arePremiumItemsDirty< Type extends PremiumItemType >( state: State, typeName: Type, oldPremiumItems: ReadonlyArray< PremiumItems[ Type ] > ): boolean { const premiumItems = getPremiumItems( state, typeName ); return ( premiumItems.length !== oldPremiumItems.length || some( premiumItems, ( a ) => { const oa = find( oldPremiumItems, { id: a.id } ); return ! oa || ! isEqual( pick( a, keys( oa ) ), oa ); } ) ); } type OldTask = Pick< EditorialTask, 'id' | 'task' | 'dateType' | 'dateValue' | 'color' | 'assigneeId' >; export function areTasksDirty( state: State, oldTasks: ReadonlyArray< OldTask > ): boolean { const { tasks } = state.attributes; oldTasks = oldTasks.map( ( t ) => pick( t, [ 'id', 'task', 'dateType', 'dateValue', 'color', 'assigneeId', ] ) ); return ( tasks.length !== oldTasks.length || some( tasks, ( t ) => { const ot = find( oldTasks, { id: t.id } ); return ! ot || ! isEqual( pick( t, keys( ot ) ), ot ); } ) ); } export function getReferenceInput( state: State ): string { return state.attributes.referenceInput; } export function getReferences( state: State ): ReadonlyArray< EditorialReference > { return state.attributes.references; } export function getNewComments( state: State ): ReadonlyArray< EditorialComment > { return state.attributes.newComments; } type OldRef = { readonly url: Url }; export function areReferencesDirty( state: State, oldReferences: ReadonlyArray< OldRef > ): boolean { const oldRefs = oldReferences.map( ( r ) => r.url ); const refs = state.attributes.references; return ( oldRefs.length !== refs.length || some( refs, ( r ) => ! oldRefs.includes( r.url ) ) ); } export function areSeriesDirty( state: State, oldSeries: ReadonlyArray< Series > ): boolean { const series = state.attributes.series; return ( oldSeries.length !== series.length || some( series, ( s ) => ! oldSeries.find( ( o ) => o.id === s.id && o.part === s.part ) ) ); }