Skip to content
This repository was archived by the owner on Oct 4, 2022. It is now read-only.

Commit 5f32614

Browse files
authored
Merge pull request #1116 from Yoast/P2-706-orange-analysis
Show an orange bullet in the sidebar analysis when a recommended block is removed
2 parents f0edfb4 + 5e2faf6 commit 5f32614

File tree

16 files changed

+228
-111
lines changed

16 files changed

+228
-111
lines changed

packages/schema-blocks/src/core/Definition.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { isArray, mergeWith } from "lodash";
44
import Instruction from "./Instruction";
55
import Leaf from "./Leaf";
66
import logger from "../functions/logger";
7+
import { BlockPresence } from "./validation/BlockValidationResult";
78

89
export type DefinitionClass<T extends Definition> = {
910
new( separator: string, template?: string, instructions?: Record<string, Instruction>, tree?: Leaf ): T;
@@ -80,7 +81,7 @@ export default abstract class Definition {
8081
return null;
8182
}
8283

83-
const validation = new BlockValidationResult( blockInstance.clientId, blockInstance.name, BlockValidation.Unknown );
84+
const validation = new BlockValidationResult( blockInstance.clientId, blockInstance.name, BlockValidation.Unknown, BlockPresence.Unknown );
8485

8586
logger.startGroup( `Validation results: ${ blockInstance.name }` );
8687

packages/schema-blocks/src/core/Instruction.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { BlockInstance } from "@wordpress/blocks";
22
import logger from "../functions/logger";
33
import { BlockValidationResult, BlockValidation } from "./validation";
4+
import { BlockPresence } from "./validation/BlockValidationResult";
45
export type InstructionPrimitive = string | number | boolean;
56
export type InstructionValue = InstructionPrimitive | InstructionObject | InstructionArray;
67
export type InstructionArray = readonly InstructionValue[];
@@ -60,7 +61,7 @@ export default abstract class Instruction {
6061
* @returns {BlockValidationResult} The validation result.
6162
*/
6263
validate( blockInstance: BlockInstance ): BlockValidationResult {
63-
return new BlockValidationResult( blockInstance.clientId, blockInstance.name, BlockValidation.Unknown );
64+
return new BlockValidationResult( blockInstance.clientId, blockInstance.name, BlockValidation.Unknown, BlockPresence.Unknown );
6465
}
6566

6667
/**

packages/schema-blocks/src/core/blocks/BlockInstruction.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import BlockLeaf from "./BlockLeaf";
2-
import { RenderSaveProps, RenderEditProps } from "./BlockDefinition";
2+
import { RenderEditProps, RenderSaveProps } from "./BlockDefinition";
33
import { ReactElement } from "@wordpress/element";
44
import { BlockConfiguration, BlockInstance } from "@wordpress/blocks";
5-
import { BlockValidationResult, BlockValidation } from "../validation";
5+
import { BlockValidation, BlockValidationResult } from "../validation";
66
import Instruction, { InstructionOptions } from "../Instruction";
77
import { attributeExists, attributeNotEmpty } from "../../functions/validators";
88
import validateMany from "../../functions/validators/validateMany";
99
import logger from "../../functions/logger";
10+
import { BlockPresence } from "../validation/BlockValidationResult";
1011

1112
export type BlockInstructionClass = {
1213
new( id: number, options: InstructionOptions ): BlockInstruction;
@@ -78,16 +79,18 @@ export default abstract class BlockInstruction extends Instruction {
7879
* @returns {BlockValidationResult} The validation result.
7980
*/
8081
validate( blockInstance: BlockInstance ): BlockValidationResult {
81-
const validation = new BlockValidationResult( blockInstance.clientId, blockInstance.name, BlockValidation.Skipped );
82+
const validation = new BlockValidationResult( blockInstance.clientId, blockInstance.name, BlockValidation.Skipped, BlockPresence.Unknown );
8283

8384
if ( this.options && this.options.required === true ) {
8485
const attributeValid = attributeExists( blockInstance, this.options.name as string ) &&
8586
attributeNotEmpty( blockInstance, this.options.name as string );
8687
if ( attributeValid ) {
87-
validation.issues.push( new BlockValidationResult( blockInstance.clientId, this.options.name, BlockValidation.Valid ) );
88+
validation.issues.push( new BlockValidationResult( blockInstance.clientId, this.options.name,
89+
BlockValidation.Valid, BlockPresence.Unknown ) );
8890
} else {
8991
logger.warning( "block " + blockInstance.name + " has a required attributes " + this.options.name + " but it is missing or empty" );
90-
validation.issues.push( new BlockValidationResult( blockInstance.clientId, this.options.name, BlockValidation.MissingAttribute ) );
92+
validation.issues.push( new BlockValidationResult( blockInstance.clientId, this.options.name,
93+
BlockValidation.MissingAttribute, BlockPresence.Unknown ) );
9194
validation.result = BlockValidation.Invalid;
9295
}
9396
} else {

packages/schema-blocks/src/core/schema/SchemaInstruction.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { SchemaValue, SchemaDefinitionConfiguration } from "./SchemaDefinition";
1+
import { SchemaDefinitionConfiguration, SchemaValue } from "./SchemaDefinition";
22
import Instruction, { InstructionOptions } from "../Instruction";
33
import { BlockInstance } from "@wordpress/blocks";
44
import { BlockValidation, BlockValidationResult } from "../validation";
5+
import { BlockPresence } from "../validation/BlockValidationResult";
56

67
export type SchemaInstructionClass = { new( id: number, options: InstructionOptions ): SchemaInstruction };
78

@@ -39,6 +40,6 @@ export default abstract class SchemaInstruction extends Instruction {
3940
* @returns {BlockValidationResult} The validation results.
4041
*/
4142
validate( blockInstance: BlockInstance ): BlockValidationResult {
42-
return new BlockValidationResult( blockInstance.clientId, blockInstance.name, BlockValidation.Valid );
43+
return new BlockValidationResult( blockInstance.clientId, blockInstance.name, BlockValidation.Valid, BlockPresence.Unknown );
4344
}
4445
}

packages/schema-blocks/src/core/validation/BlockValidation.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
export enum BlockValidation {
32
/** This block was skipped during validation, on purpose. If you ever see this value, that's a bug. */
43
Skipped = -2,

packages/schema-blocks/src/core/validation/BlockValidationResult.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { BlockValidation } from ".";
22
import { BlockInstance } from "@wordpress/blocks";
33

4+
export enum BlockPresence {
5+
Required = "required",
6+
Recommended = "recommended",
7+
Optional = "optional",
8+
Unknown = "unknown"
9+
}
10+
411
/**
512
* Contains the result of a block validation.
613
*/
@@ -16,24 +23,31 @@ export class BlockValidationResult {
1623
public clientId: string;
1724

1825
/**
19-
* The validation result;
26+
* The validation result.
2027
*/
2128
public result: BlockValidation;
2229

30+
/**
31+
* The block presence.
32+
*/
33+
public blockPresence: BlockPresence;
34+
2335
/**
2436
* The validation issues for this block's innerblocks or attributes, if any.
2537
*/
2638
public issues: BlockValidationResult[]
2739

2840
/**
29-
* @param clientId The clientId of the validated block.
30-
* @param name The name of the validated block.
31-
* @param result The validation result.
41+
* @param clientId The clientId of the validated block.
42+
* @param name The name of the validated block.
43+
* @param result The validation result.
44+
* @param blockPresence The block type.
3245
*/
33-
constructor( clientId: string, name: string, result: BlockValidation ) {
34-
this.name = name;
46+
constructor( clientId: string, name: string, result: BlockValidation, blockPresence: BlockPresence ) {
3547
this.clientId = clientId;
48+
this.name = name;
3649
this.result = result;
50+
this.blockPresence = blockPresence;
3751
this.issues = [];
3852
}
3953

@@ -50,6 +64,7 @@ export class BlockValidationResult {
5064
blockInstance.clientId,
5165
name || blockInstance.name,
5266
BlockValidation.MissingAttribute,
67+
BlockPresence.Unknown,
5368
);
5469
}
5570

@@ -66,6 +81,7 @@ export class BlockValidationResult {
6681
blockInstance.clientId,
6782
name || blockInstance.name,
6883
BlockValidation.Valid,
84+
BlockPresence.Unknown,
6985
);
7086
}
7187
}

packages/schema-blocks/src/core/validation/RequiredBlock.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { RequiredBlockOption } from ".";
21
import { InstructionOptions } from "../Instruction";
2+
import { RequiredBlockOption } from ".";
33
import { SuggestedBlockProperties } from "./SuggestedBlockProperties";
44

55
/**

packages/schema-blocks/src/functions/gutenberg/watch.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { getBlockDefinition } from "../../core/blocks/BlockDefinitionRepository"
77
import { BlockValidation, BlockValidationResult } from "../../core/validation";
88
import storeBlockValidation from "./storeBlockValidation";
99
import logger from "../logger";
10+
import { BlockPresence } from "../../core/validation/BlockValidationResult";
1011

1112
let updatingSchema = false;
1213
let previousRootBlocks: BlockInstance[];
@@ -104,7 +105,7 @@ export function validateBlocks( blocks: BlockInstance[] ): BlockValidationResult
104105
validations.push( definition.validate( block ) );
105106
} else {
106107
logger.warning( "Unable to validate block of type [" + block.name + "] " + block.clientId );
107-
validations.push( new BlockValidationResult( block.clientId, block.name, BlockValidation.Unknown ) );
108+
validations.push( new BlockValidationResult( block.clientId, block.name, BlockValidation.Unknown, BlockPresence.Unknown ) );
108109

109110
// Recursively validate all blocks' innerblocks.
110111
if ( block.innerBlocks && block.innerBlocks.length > 0 ) {

packages/schema-blocks/src/functions/presenters/InnerBlocksSidebarPresenter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { SvgIcon } from "@yoast/components";
1111
* Renders warnings and appenders for any block's InnerBlocks.
1212
*
1313
* @param currentBlock The innerblocks instance.
14-
* @param options The InnerBlocksInstructionOptions of the innerblock.
14+
* @param options The InnerBlocksInstructionOptions of the innerblock.
1515
*
1616
* @returns {ReactElement[]} React Elements representing the sidebar elements for these innerblocks.
1717
*/

packages/schema-blocks/src/functions/presenters/SidebarWarningPresenter.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import { __ } from "@wordpress/i18n";
44
import { get } from "lodash";
55
import { BlockValidationResult } from "../../core/validation";
66
import { BlockValidation } from "../../core/validation";
7+
import { BlockPresence } from "../../core/validation/BlockValidationResult";
78

89
const analysisMessageTemplates: Record<number, string> = {
9-
[ BlockValidation.MissingBlock ]: "The '{child}' block is {status} but missing.",
10+
[ BlockValidation.MissingBlock ]: "The '{child}' block is {presence} but missing.",
1011
[ BlockValidation.MissingAttribute ]: "The '{child}' block is empty.",
1112
};
1213

@@ -16,7 +17,7 @@ type analysisIssue = {
1617
name: string;
1718
parent: string;
1819
result: BlockValidation;
19-
status: string;
20+
presence: string;
2021
};
2122

2223
export type sidebarWarning = {
@@ -51,7 +52,7 @@ export function replaceVariables( issue: analysisIssue ): string {
5152
const warning = get( analysisMessageTemplates, issue.result, "" );
5253
return warning.replace( "{parent}", __( issue.parent, "wpseo-schema-blocks" ) )
5354
.replace( "{child}", __( issue.name, "wpseo-schema-blocks" ) )
54-
.replace( "{status}", __( issue.status, "wpseo-schema-blocks" ) );
55+
.replace( "{presence}", __( issue.presence, "wpseo-schema-blocks" ) );
5556
}
5657

5758
/**
@@ -63,20 +64,26 @@ export function replaceVariables( issue: analysisIssue ): string {
6364
* @returns {sidebarWarning} Any analysis conclusions that should be in the footer.
6465
*/
6566
function getAnalysisConclusion( validation: BlockValidation, issues: analysisIssue[] ): sidebarWarning {
66-
if ( issues.some( issue => issue.result === BlockValidation.MissingBlock ||
67+
// Show a red bullet when not all required blocks have been completed.
68+
if ( issues.some( issue => issue.result === BlockValidation.MissingBlock && issue.presence === BlockPresence.Required ||
6769
issue.result === BlockValidation.MissingAttribute ) ) {
6870
return {
69-
text: __( "Not all required blocks are completed! No " + issues[ 0 ].parent +
71+
text: __( "Not all required blocks have been completed! No " + issues[ 0 ].parent +
7072
" schema will be generated for your page.", "wpseo-schema-blocks" ),
7173
color: "red",
7274
} as sidebarWarning;
7375
}
7476

77+
// Show a green bullet when all required blocks have been completed.
78+
const requiredBlockIssues = issues.filter( issue => {
79+
return issue.presence === BlockPresence.Required;
80+
} );
81+
7582
if ( validation === BlockValidation.Valid ||
76-
issues.every( issue => issue.result !== BlockValidation.MissingAttribute &&
83+
requiredBlockIssues.every( issue => issue.result !== BlockValidation.MissingAttribute &&
7784
issue.result !== BlockValidation.MissingBlock ) ) {
7885
return {
79-
text: __( "Good job! All required blocks are completed.", "wpseo-schema-blocks" ),
86+
text: __( "Good job! All required blocks have been completed.", "wpseo-schema-blocks" ),
8087
color: "green",
8188
} as sidebarWarning;
8289
}
@@ -87,7 +94,7 @@ function getAnalysisConclusion( validation: BlockValidation, issues: analysisIss
8794
*
8895
* @param validation The root validation result.
8996
*
90-
* @return all validation results.
97+
* @return All validation results.
9198
*/
9299
function getAllDescendantIssues( validation: BlockValidationResult ): BlockValidationResult[] {
93100
let results = [ validation ];
@@ -114,10 +121,11 @@ export function createAnalysisMessages( validation: BlockValidationResult ): sid
114121
name: sanitizeBlockName( issue.name ),
115122
parent: sanitizeParentName( parent ),
116123
result: issue.result,
117-
status: "required",
124+
presence: issue.blockPresence,
118125
} ) );
126+
119127
const messages = messageData.map( msg => {
120-
return { text: replaceVariables( msg ), color: "red" } as sidebarWarning;
128+
return { text: replaceVariables( msg ), color: ( msg.presence === BlockPresence.Recommended ? "orange" : "red" ) } as sidebarWarning;
121129
} );
122130

123131
const conclusion = getAnalysisConclusion( validation.result, messageData );

0 commit comments

Comments
 (0)