/** * WordPress dependencies */ import { createSelector } from '@safe-wordpress/data'; import { _x } from '@safe-wordpress/i18n'; /** * External dependencies */ import { find, map, omit, keys, values } from 'lodash'; import { EMPTY_OBJECT } from '@nelio-content/constants'; import type { AutomationGroup, AutomationGroupId, CustomField, CustomPlaceholder, Maybe, NetworkAutomationSettings, PostTypeName, ProfileAutomationSettings, SocialNetworkName, SocialProfile, SocialTemplate, TaxonomySlug, Uuid, } from '@nelio-content/types'; /** * Internal dependencies */ import type { AutoFrequencies, State, TemplateImporter, TemplateErrors, TemplateExporter, } from './types'; export function getAutomationGroups( state: State ): State[ 'automationGroups' ][ 'allIds' ] { return state.automationGroups.allIds; } export function getAutomationGroup( state: State, id: AutomationGroup[ 'id' ] ): Maybe< AutomationGroup > { return state.automationGroups.byId[ id ]; } export function getProfileAutomationSettings( state: State, groupId: AutomationGroupId, profileId: Uuid ): Maybe< ProfileAutomationSettings > { return find( getAutomationGroup( state, groupId )?.profileSettings, { profileId, } ); } export function getNetworkAutomationSettings( state: State, groupId: AutomationGroupId, name: SocialNetworkName ): Maybe< NetworkAutomationSettings > { return find( getAutomationGroup( state, groupId )?.networkSettings, { name, } ); } export function isDirty( state: State, groups: ReadonlyArray< AutomationGroup >, profiles: ReadonlyArray< SocialProfile > ): boolean { const editingGroups = values( state.automationGroups.byId ); const existingGroups = groups; const areProfilesDirty = profiles.some( ( p ) => { const fs = state.frequencies[ p.id ]; return ( fs?.publication !== Math.max( 1, p.publicationFrequency ) || fs?.reshare !== Math.max( 1, p.reshareFrequency ) ); } ); return ( areProfilesDirty || JSON.stringify( editingGroups ) !== JSON.stringify( existingGroups ) ); } export function isSaving( state: State ): boolean { return !! state.isSaving; } export function isEditingTemplate( state: State ): boolean { return !! state.templateEditor.attributes; } export function isEditingNewTemplate( state: State ): boolean { return isEditingTemplate( state ) && state.templateEditor.isNew; } export function isEditingNetworkTemplate( state: State ): boolean { return isEditingTemplate( state ) && state.templateEditor.isNetwork; } export const getEditingTemplate = createSelector( ( state: State ): Maybe< SocialTemplate > => { const attrs = state.templateEditor.attributes; return attrs ? ( omit( attrs, 'type' ) as SocialTemplate ) : undefined; }, ( state: State ) => [ state.templateEditor.attributes ] ); export function getEditingTemplateErrors( state: State ): TemplateErrors { return state.templateEditor.errors; } export function getEditingTemplateType( state: State ): 'publication' | 'reshare' { return state.templateEditor.attributes?.type || 'publication'; } export function getProfileFrequencies( state: State, profileId: Uuid ): Maybe< AutoFrequencies > { return state.frequencies[ profileId ]; } export function getCustomFields( state: State ): Record< PostTypeName, ReadonlyArray< Omit< CustomField, 'value' > > > { return state.templateEditor.customFields; } export function getCustomPlaceholders( state: State ): Record< PostTypeName, ReadonlyArray< Omit< CustomPlaceholder, 'value' > > > { return state.templateEditor.customPlaceholders; } export function isPostTypeValid( state: State, groupId: AutomationGroupId ): boolean { return state.validations[ groupId ]?.isPostTypeValid ?? true; } export function areAuthorsValid( state: State, groupId: AutomationGroupId ): boolean { return state.validations[ groupId ]?.areAuthorsValid ?? true; } export function getGroupTermsValidation( state: State, groupId: AutomationGroupId ): Record< TaxonomySlug, boolean > { return state.validations[ groupId ]?.areTermsValid || EMPTY_OBJECT; } export function isGroupValid( state: State, groupId: AutomationGroupId ): boolean { const areTermsValid = values( getGroupTermsValidation( state, groupId ) ).every( Boolean ); return ( isPostTypeValid( state, groupId ) && areAuthorsValid( state, groupId ) && areTermsValid && keys( getAutomationGroup( state, groupId )?.profileSettings ).every( ( profileId: Uuid ) => ! getProfileError( state, groupId, profileId ) ) ); } export function getProfileError( state: State, groupId: AutomationGroupId, profileId: Uuid ): string | false { const err = state.validations[ groupId ]?.socialProfileErrors[ profileId ]; if ( err ) { return err; } const profileSettings = getProfileAutomationSettings( state, groupId, profileId ); if ( ! profileSettings ) { return false; } const networkSettings = getNetworkAutomationSettings( state, groupId, profileSettings.network ); const isDisabled = ( settings: | ProfileAutomationSettings[ 'publication' | 'reshare' ] | NetworkAutomationSettings[ 'publication' | 'reshare' ] ) => 'enabled' in settings && ! settings.enabled; const isValid = ( settings?: | ProfileAutomationSettings[ 'publication' | 'reshare' ] | NetworkAutomationSettings[ 'publication' | 'reshare' ] ) => ! settings || isDisabled( settings ) || map( settings.templates, 'id' ).every( ( templateId ) => isTemplateValid( state, groupId, templateId ) ); if ( ! isValid( profileSettings.publication ) || ! isValid( networkSettings?.publication ) ) { return _x( 'Please review publication templates', 'user', 'nelio-content' ); } if ( ! isValid( profileSettings.reshare ) || ! isValid( networkSettings?.reshare ) ) { return _x( 'Please review reshare templates', 'text', 'nelio-content' ); } return false; } export function isTemplateValid( state: State, groupId: AutomationGroupId, templateId: Uuid ): boolean { const errs = state.validations[ groupId ]?.templateErrors[ templateId ]; return ( keys( omit( errs, 'taxonomies' ) ).every( ( k ) => ! errs?.[ k ] ) && keys( errs?.taxonomies ).every( ( k ) => ! errs?.taxonomies[ k ] ) ); } export function getTemplateErrors( state: State, groupId: AutomationGroupId, templateId: Uuid ): Maybe< TemplateErrors > { return state.validations[ groupId ]?.templateErrors[ templateId ]; } export function getImportExportData( state: State ): Maybe< TemplateImporter | TemplateExporter > { return state.templateImportExport; }