diff --git a/packages/schema-blocks/src/core/blocks/BlockDefinition.tsx b/packages/schema-blocks/src/core/blocks/BlockDefinition.tsx index a6fca8ca1..faf421786 100644 --- a/packages/schema-blocks/src/core/blocks/BlockDefinition.tsx +++ b/packages/schema-blocks/src/core/blocks/BlockDefinition.tsx @@ -85,7 +85,7 @@ export default class BlockDefinition extends Definition { configuration.edit = props => this.edit( props ); configuration.save = props => this.save( props ); - logger.info( "registering block " + name ); + logger.debug( "registering block " + name ); // Register the block to WordPress. registerBlockType( name, configuration ); diff --git a/packages/schema-blocks/src/functions/gutenberg/storeBlockValidation.ts b/packages/schema-blocks/src/functions/gutenberg/storeBlockValidation.ts index b84035206..5619f1150 100644 --- a/packages/schema-blocks/src/functions/gutenberg/storeBlockValidation.ts +++ b/packages/schema-blocks/src/functions/gutenberg/storeBlockValidation.ts @@ -1,6 +1,7 @@ import { dispatch } from "@wordpress/data"; import { BlockValidationResult } from "../../core/validation"; import logger from "../logger"; +import { YOAST_SCHEMA_BLOCKS_STORE_NAME } from "../redux"; /** * Updates the store with information about whether a block is valid or why it isn't. @@ -13,12 +14,14 @@ export default function storeBlockValidation( validations: BlockValidationResult logger.debug( "Updating the store with the validation results." ); - const store = dispatch( "yoast-seo/editor" ); + const store = dispatch( YOAST_SCHEMA_BLOCKS_STORE_NAME ); if ( store ) { store.resetBlockValidation(); validations.forEach( blockValidation => { logger.debug( "storing validation: ", blockValidation ); store.addBlockValidation( blockValidation ); } ); + } else { + logger.debug( "No Store!" ); } } diff --git a/packages/schema-blocks/src/functions/gutenberg/watch.ts b/packages/schema-blocks/src/functions/gutenberg/watch.ts index d11a7a133..fbad85cae 100644 --- a/packages/schema-blocks/src/functions/gutenberg/watch.ts +++ b/packages/schema-blocks/src/functions/gutenberg/watch.ts @@ -122,7 +122,7 @@ export function validateBlocks( blocks: BlockInstance[] ): BlockValidationResult export default function watch() { subscribe( debounce( () => { - if ( updatingSchema || select( "core/block-editor" ).isTyping() ) { + if ( updatingSchema ) { return; } diff --git a/packages/schema-blocks/src/functions/initialize.ts b/packages/schema-blocks/src/functions/initialize.ts index 4384b8256..591cbc84d 100644 --- a/packages/schema-blocks/src/functions/initialize.ts +++ b/packages/schema-blocks/src/functions/initialize.ts @@ -1,11 +1,11 @@ -import { registerBlockType } from "@wordpress/blocks"; - import "../instructions"; -import logger, { LogLevel } from "./logger"; +import { registerBlockType } from "@wordpress/blocks"; +import { initializeSchemaBlocksStore } from "../functions/redux"; import { WarningBlock } from "../blocks/warning-block/configuration"; import { processBlock, processSchema } from "./process"; import filter from "./gutenberg/filter"; import watch from "./gutenberg/watch"; +import logger, { LogLevel } from "./logger"; /** * Removes all whitespace including line breaks from a string. @@ -26,7 +26,9 @@ function removeWhitespace( text: string ): string { export function initialize( logLevel: LogLevel = LogLevel.ERROR ) { logger.setLogLevel( logLevel ); - registerBlockType( "yoast/warning-block", WarningBlock ); + initializeSchemaBlocksStore(); + + registerInternalBlocks(); jQuery( 'script[type="text/schema-template"]' ).each( function() { try { @@ -54,3 +56,10 @@ export function initialize( logLevel: LogLevel = LogLevel.ERROR ) { // Watch Gutenberg for block changes that require schema updates. watch(); } + +/** + * Registers additional blocks needed for schema blocks use cases. + */ +function registerInternalBlocks() { + registerBlockType( "yoast/warning-block", WarningBlock ); +} diff --git a/packages/schema-blocks/src/functions/presenters/SidebarWarningPresenter.ts b/packages/schema-blocks/src/functions/presenters/SidebarWarningPresenter.ts index 7664c0ffb..107539567 100644 --- a/packages/schema-blocks/src/functions/presenters/SidebarWarningPresenter.ts +++ b/packages/schema-blocks/src/functions/presenters/SidebarWarningPresenter.ts @@ -1,6 +1,6 @@ import { select } from "@wordpress/data"; import { __, sprintf } from "@wordpress/i18n"; - +import { YOAST_SCHEMA_BLOCKS_STORE_NAME } from "../redux"; import { BlockValidation, BlockValidationResult } from "../../core/validation"; import { getHumanReadableBlockName } from "../BlockHelper"; import { BlockPresence } from "../../core/validation/BlockValidationResult"; @@ -29,7 +29,7 @@ export type SidebarWarning = { * @returns {BlockValidationResult} The validation results, or null if none were found. */ function getValidationResult( clientId: string ): BlockValidationResult | null { - const validationResults: clientIdValidation = select( "yoast-seo/editor" ).getSchemaBlocksValidationResults(); + const validationResults: clientIdValidation = select( YOAST_SCHEMA_BLOCKS_STORE_NAME ).getSchemaBlocksValidationResults(); if ( ! validationResults ) { return null; } diff --git a/packages/schema-blocks/src/functions/redux/SchemaBlocksState.ts b/packages/schema-blocks/src/functions/redux/SchemaBlocksState.ts new file mode 100644 index 000000000..6627f99e0 --- /dev/null +++ b/packages/schema-blocks/src/functions/redux/SchemaBlocksState.ts @@ -0,0 +1,9 @@ +import { BlockValidationResult } from "../../core/validation"; + +export interface SchemaBlocksState { + validations: Record; +} + +export const SchemaBlocksDefaultState: SchemaBlocksState = { + validations: {}, +}; diff --git a/packages/schema-blocks/src/functions/redux/actions/index.ts b/packages/schema-blocks/src/functions/redux/actions/index.ts new file mode 100644 index 000000000..2de1ad255 --- /dev/null +++ b/packages/schema-blocks/src/functions/redux/actions/index.ts @@ -0,0 +1,41 @@ +import { BlockValidationResult } from "../../../core/validation"; + +import * as schemaBlocksActions from "./schemaBlocks"; + +const PREFIX = "WPSEO_"; + +export const SchemaBlocksStoreActions = { + ADD_BLOCK_VALIDATION: `${ PREFIX }ADD_BLOCK_VALIDATION`, + RESET_BLOCK_VALIDATIONS: `${ PREFIX }CLEAR_BLOCK_VALIDATIONS`, +}; + +export interface SchemaBlocksStoreCommand { + type: string; + validation?: BlockValidationResult; +} + +/** + * Configures a redux command to store a validation result. + * + * @param validation The validation to store. + * @returns The configured AddBlockValidation command. + */ +export function AddBlockValidationCommand( validation: BlockValidationResult ): SchemaBlocksStoreCommand { + return { + type: SchemaBlocksStoreActions.ADD_BLOCK_VALIDATION, + validation: validation, + }; +} + +/** + * Configures a redux command to reset the current validation results. + * + * @returns Thge configured ResetBlockValidation command + */ +export function ResetBlockValidationCommand(): SchemaBlocksStoreCommand { + return { + type: SchemaBlocksStoreActions.RESET_BLOCK_VALIDATIONS, + }; +} + +export { schemaBlocksActions }; diff --git a/packages/schema-blocks/src/functions/redux/actions/schemaBlocks.ts b/packages/schema-blocks/src/functions/redux/actions/schemaBlocks.ts new file mode 100644 index 000000000..bb99c57b9 --- /dev/null +++ b/packages/schema-blocks/src/functions/redux/actions/schemaBlocks.ts @@ -0,0 +1,21 @@ +import { BlockValidationResult } from "../../../core/validation"; +import { SchemaBlocksStoreCommand, AddBlockValidationCommand, ResetBlockValidationCommand } from "./"; + +/** + * Updates whether a block is valid. + * + * @param {blockValidationResult} blockValidationResult The block validation to store. + * + * @returns {SchemaBlocksStoreAction} An action for redux. + */ +export function addBlockValidation( blockValidationResult: BlockValidationResult ): SchemaBlocksStoreCommand { + return AddBlockValidationCommand( blockValidationResult ); +} + +/** + * Commands the store to reset the block validation store to initial state. + * @returns {SchemaBlocksStoreAction} The command to set the initial state for the block validation store. + */ +export function resetBlockValidation(): SchemaBlocksStoreCommand { + return ResetBlockValidationCommand(); +} diff --git a/packages/schema-blocks/src/functions/redux/index.ts b/packages/schema-blocks/src/functions/redux/index.ts new file mode 100644 index 000000000..58e3619d9 --- /dev/null +++ b/packages/schema-blocks/src/functions/redux/index.ts @@ -0,0 +1,6 @@ +export * from "./actions"; +export * from "./reducer"; +export * from "./selectors"; +export * from "./initializeSchemaStore"; + +export const YOAST_SCHEMA_BLOCKS_STORE_NAME = "yoast-seo/schema-blocks"; diff --git a/packages/schema-blocks/src/functions/redux/initializeSchemaStore.ts b/packages/schema-blocks/src/functions/redux/initializeSchemaStore.ts new file mode 100644 index 000000000..8cb47a66c --- /dev/null +++ b/packages/schema-blocks/src/functions/redux/initializeSchemaStore.ts @@ -0,0 +1,24 @@ +import { registerStore, StoreConfig } from "@wordpress/data"; +import { SchemaBlocksDefaultState, SchemaBlocksState } from "./SchemaBlocksState"; +import { schemaBlocksActions } from "./actions"; +import { schemaBlocksReducer } from "./reducer"; +import * as schemaBlocksSelectors from "./selectors"; +import { YOAST_SCHEMA_BLOCKS_STORE_NAME } from "."; + +/** + * Initializes the Schema Blocks store. + */ +export function initializeSchemaBlocksStore() { + const storeOptions: StoreConfig = { + reducer: schemaBlocksReducer, + selectors: { + ...schemaBlocksSelectors, + }, + actions: { + ...schemaBlocksActions, + }, + initialState: SchemaBlocksDefaultState, + }; + + registerStore( YOAST_SCHEMA_BLOCKS_STORE_NAME, storeOptions ); +} diff --git a/packages/schema-blocks/src/functions/redux/reducer/index.ts b/packages/schema-blocks/src/functions/redux/reducer/index.ts new file mode 100644 index 000000000..23e3adebf --- /dev/null +++ b/packages/schema-blocks/src/functions/redux/reducer/index.ts @@ -0,0 +1 @@ +export { schemaBlocksReducer } from "./schemaBlocks"; diff --git a/packages/schema-blocks/src/functions/redux/reducer/schemaBlocks.ts b/packages/schema-blocks/src/functions/redux/reducer/schemaBlocks.ts new file mode 100644 index 000000000..61a5d910a --- /dev/null +++ b/packages/schema-blocks/src/functions/redux/reducer/schemaBlocks.ts @@ -0,0 +1,30 @@ +import { SchemaBlocksStoreCommand, SchemaBlocksStoreActions } from "../actions"; +import { SchemaBlocksState, SchemaBlocksDefaultState } from "../SchemaBlocksState"; + +/** + * A reducer for the Schema blocks. + * + * @param {SchemaBlocksState} state The current state of the object. + * @param {SetBlockValidation} command The received command. + * + * @returns {SchemaBlocksState} The state. + */ +export function schemaBlocksReducer( state: SchemaBlocksState = SchemaBlocksDefaultState, command: SchemaBlocksStoreCommand ): SchemaBlocksState { + switch ( command.type ) { + case SchemaBlocksStoreActions.RESET_BLOCK_VALIDATIONS: { + return SchemaBlocksDefaultState; + } + case SchemaBlocksStoreActions.ADD_BLOCK_VALIDATION: { + const newState = Object.assign( {}, state ); + const validation = command.validation; + + newState.validations = newState.validations || {}; + newState.validations[ validation.clientId ] = validation; + + return newState; + } + default: { + return state; + } + } +} diff --git a/packages/schema-blocks/src/functions/redux/selectors/index.ts b/packages/schema-blocks/src/functions/redux/selectors/index.ts new file mode 100644 index 000000000..b842f4195 --- /dev/null +++ b/packages/schema-blocks/src/functions/redux/selectors/index.ts @@ -0,0 +1 @@ +export * from "./schemaBlocks"; diff --git a/packages/schema-blocks/src/functions/redux/selectors/schemaBlocks.ts b/packages/schema-blocks/src/functions/redux/selectors/schemaBlocks.ts new file mode 100644 index 000000000..8ae3ba99f --- /dev/null +++ b/packages/schema-blocks/src/functions/redux/selectors/schemaBlocks.ts @@ -0,0 +1,12 @@ +import { SchemaBlocksState, SchemaBlocksDefaultState } from "../SchemaBlocksState"; + +/** + * The schema validation results. + * + * @param {object} state The current state. + * + * @returns {Record} The schema blocks validation results. + */ +export function getSchemaBlocksValidationResults( state: SchemaBlocksState ): object { + return state.validations || SchemaBlocksDefaultState.validations; +} diff --git a/packages/schema-blocks/src/index.ts b/packages/schema-blocks/src/index.ts index bde6c386e..d055838ca 100644 --- a/packages/schema-blocks/src/index.ts +++ b/packages/schema-blocks/src/index.ts @@ -4,5 +4,4 @@ import { RenderEditProps, RenderSaveProps } from "./core/blocks/BlockDefinition" import { LogLevel } from "./functions/logger"; export { BlockInstruction, RenderSaveProps, RenderEditProps, LogLevel }; - export default initialize;