This repository has been archived by the owner on Feb 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 217
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
467 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import { QueryBlockQuery } from './types'; | ||
|
||
export const QUERY_DEFAULT_ATTRIBUTES: { query: QueryBlockQuery } = { | ||
query: { | ||
perPage: 6, | ||
pages: 0, | ||
offset: 0, | ||
postType: 'product', | ||
order: 'desc', | ||
orderBy: 'date', | ||
author: '', | ||
search: '', | ||
exclude: [], | ||
sticky: '', | ||
inherit: false, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { Block } from '@wordpress/blocks'; | ||
import { addFilter } from '@wordpress/hooks'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import './inspector-controls'; | ||
import './variations/product-query'; | ||
import './variations/products-on-sale'; | ||
|
||
function registerProductQueryVariationAttributes( | ||
props: Block, | ||
blockName: string | ||
) { | ||
if ( blockName === 'core/query' ) { | ||
// Gracefully handle if settings.attributes is undefined. | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore -- We need this because `attributes` is marked as `readonly` | ||
props.attributes = { | ||
...props.attributes, | ||
__woocommerceVariationProps: { | ||
type: 'object', | ||
}, | ||
}; | ||
} | ||
return props; | ||
} | ||
|
||
addFilter( | ||
'blocks.registerBlockType', | ||
'core/custom-class-name/attribute', | ||
registerProductQueryVariationAttributes | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { __ } from '@wordpress/i18n'; | ||
import { InspectorControls } from '@wordpress/block-editor'; | ||
import { ToggleControl } from '@wordpress/components'; | ||
import { addFilter } from '@wordpress/hooks'; | ||
import { EditorBlock } from '@woocommerce/types'; | ||
import { ElementType } from 'react'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { ProductQueryBlock } from './types'; | ||
import { isWooQueryBlockVariation, setCustomQueryAttribute } from './utils'; | ||
|
||
export const INSPECTOR_CONTROLS = { | ||
onSale: ( props: ProductQueryBlock ) => ( | ||
<ToggleControl | ||
label={ __( | ||
'Show only products on sale', | ||
'woo-gutenberg-products-block' | ||
) } | ||
checked={ | ||
props.attributes.__woocommerceVariationProps?.attributes?.query | ||
?.onSale || false | ||
} | ||
onChange={ ( onSale ) => { | ||
setCustomQueryAttribute( props, { onSale } ); | ||
} } | ||
/> | ||
), | ||
}; | ||
|
||
export const withProductQueryControls = | ||
< T extends EditorBlock< T > >( BlockEdit: ElementType ) => | ||
( props: ProductQueryBlock ) => { | ||
return isWooQueryBlockVariation( props ) ? ( | ||
<> | ||
<BlockEdit { ...props } /> | ||
<InspectorControls> | ||
{ Object.entries( INSPECTOR_CONTROLS ).map( | ||
( [ key, Control ] ) => | ||
props.attributes.__woocommerceVariationProps.attributes?.disabledInspectorControls?.includes( | ||
key | ||
) ? null : ( | ||
<Control { ...props } /> | ||
) | ||
) } | ||
</InspectorControls> | ||
</> | ||
) : ( | ||
<BlockEdit { ...props } /> | ||
); | ||
}; | ||
|
||
addFilter( 'editor.BlockEdit', 'core/query', withProductQueryControls ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { BlockInstance } from '@wordpress/blocks'; | ||
import type { EditorBlock } from '@woocommerce/types'; | ||
|
||
export interface ProductQueryArguments { | ||
/** | ||
* Display only products on sale. | ||
* | ||
* Will generate the following `meta_query`: | ||
* | ||
* ``` | ||
* array( | ||
* 'relation' => 'OR', | ||
* array( // Simple products type | ||
* 'key' => '_sale_price', | ||
* 'value' => 0, | ||
* 'compare' => '>', | ||
* 'type' => 'numeric', | ||
* ), | ||
* array( // Variable products type | ||
* 'key' => '_min_variation_sale_price', | ||
* 'value' => 0, | ||
* 'compare' => '>', | ||
* 'type' => 'numeric', | ||
* ), | ||
* ) | ||
* ``` | ||
*/ | ||
onSale?: boolean; | ||
} | ||
|
||
export type ProductQueryBlock = | ||
WooCommerceBlockVariation< ProductQueryAttributes >; | ||
|
||
export interface ProductQueryAttributes { | ||
/** | ||
* An array of controls to disable in the inspector. | ||
* | ||
* @example `[ 'stockStatus' ]` will not render the dropdown for stock status. | ||
*/ | ||
disabledInspectorControls?: string[]; | ||
/** | ||
* Query attributes that define which products will be fetched. | ||
*/ | ||
query?: ProductQueryArguments; | ||
} | ||
|
||
export interface QueryBlockQuery { | ||
author?: string; | ||
exclude?: string[]; | ||
inherit: boolean; | ||
offset?: number; | ||
order: 'asc' | 'desc'; | ||
orderBy: 'date' | 'relevance'; | ||
pages?: number; | ||
parents?: number[]; | ||
perPage?: number; | ||
postType: string; | ||
search?: string; | ||
sticky?: string; | ||
taxQuery?: string; | ||
} | ||
|
||
export enum QueryVariation { | ||
/** The main, fully customizable, Product Query block */ | ||
PRODUCT_QUERY = 'product-query', | ||
PRODUCTS_ON_SALE = 'query-on-sale', | ||
} | ||
|
||
export type WooCommerceBlockVariation< T > = EditorBlock< { | ||
// Disabling naming convention because we are namespacing our | ||
// custom attributes inside a core block. Prefixing with underscores | ||
// will help signify our intentions. | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
__woocommerceVariationProps: Partial< BlockInstance< T > >; | ||
} >; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import { | ||
ProductQueryArguments, | ||
ProductQueryBlock, | ||
QueryVariation, | ||
} from './types'; | ||
|
||
/** | ||
* Identifies if a block is a Query block variation from our conventions | ||
* | ||
* We are extending Gutenberg's core Query block with our variations, and | ||
* also adding extra namespaced attributes. If those namespaced attributes | ||
* are present, we can be fairly sure it is our own registered variation. | ||
*/ | ||
export function isWooQueryBlockVariation( block: ProductQueryBlock ) { | ||
return ( | ||
block.name === 'core/query' && | ||
block.attributes.__woocommerceVariationProps && | ||
Object.values( QueryVariation ).includes( | ||
block.attributes.__woocommerceVariationProps | ||
.name as unknown as QueryVariation | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Sets the new query arguments of a Product Query block | ||
* | ||
* Because we add a new set of deeply nested attributes to the query | ||
* block, this utility function makes it easier to change just the | ||
* options relating to our custom query, while keeping the code | ||
* clean. | ||
*/ | ||
export function setCustomQueryAttribute( | ||
block: ProductQueryBlock, | ||
attributes: Partial< ProductQueryArguments > | ||
) { | ||
const { __woocommerceVariationProps } = block.attributes; | ||
|
||
block.setAttributes( { | ||
__woocommerceVariationProps: { | ||
...__woocommerceVariationProps, | ||
attributes: { | ||
...__woocommerceVariationProps.attributes, | ||
query: { | ||
...__woocommerceVariationProps.attributes?.query, | ||
...attributes, | ||
}, | ||
}, | ||
}, | ||
} ); | ||
} |
50 changes: 50 additions & 0 deletions
50
assets/js/blocks/product-query/variations/product-query.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { isExperimentalBuild } from '@woocommerce/block-settings'; | ||
import { registerBlockVariation } from '@wordpress/blocks'; | ||
import { Icon } from '@wordpress/components'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { sparkles } from '@wordpress/icons'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { QUERY_DEFAULT_ATTRIBUTES } from '../constants'; | ||
|
||
if ( isExperimentalBuild() ) { | ||
registerBlockVariation( 'core/query', { | ||
name: 'woocommerce/product-query', | ||
title: __( 'Product Query', 'woo-gutenberg-products-block' ), | ||
isActive: ( attributes ) => { | ||
return ( | ||
attributes?.__woocommerceVariationProps?.name === | ||
'product-query' | ||
); | ||
}, | ||
icon: { | ||
src: ( | ||
<Icon | ||
icon={ sparkles } | ||
className="wc-block-editor-components-block-icon wc-block-editor-components-block-icon--sparkles" | ||
/> | ||
), | ||
}, | ||
attributes: { | ||
...QUERY_DEFAULT_ATTRIBUTES, | ||
__woocommerceVariationProps: { | ||
name: 'product-query', | ||
}, | ||
}, | ||
innerBlocks: [ | ||
[ | ||
'core/post-template', | ||
{}, | ||
[ [ 'core/post-title' ], [ 'core/post-featured-image' ] ], | ||
], | ||
[ 'core/query-pagination' ], | ||
[ 'core/query-no-results' ], | ||
], | ||
scope: [ 'block', 'inserter' ], | ||
} ); | ||
} |
53 changes: 53 additions & 0 deletions
53
assets/js/blocks/product-query/variations/products-on-sale.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { isExperimentalBuild } from '@woocommerce/block-settings'; | ||
import { registerBlockVariation } from '@wordpress/blocks'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { Icon, percent } from '@wordpress/icons'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { QUERY_DEFAULT_ATTRIBUTES } from '../constants'; | ||
|
||
if ( isExperimentalBuild() ) { | ||
registerBlockVariation( 'core/query', { | ||
name: 'woocommerce/query-products-on-sale', | ||
title: __( 'Products on Sale', 'woo-gutenberg-products-block' ), | ||
isActive: ( blockAttributes ) => | ||
blockAttributes?.__woocommerceVariationProps?.name === | ||
'query-products-on-sale' || | ||
blockAttributes?.__woocommerceVariationProps?.query?.onSale === | ||
true, | ||
icon: { | ||
src: ( | ||
<Icon | ||
icon={ percent } | ||
className="wc-block-editor-components-block-icon wc-block-editor-components-block-icon--percent" | ||
/> | ||
), | ||
}, | ||
attributes: { | ||
...QUERY_DEFAULT_ATTRIBUTES, | ||
__woocommerceVariationProps: { | ||
name: 'query-products-on-sale', | ||
attributes: { | ||
query: { | ||
onSale: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
innerBlocks: [ | ||
[ | ||
'core/post-template', | ||
{}, | ||
[ [ 'core/post-title' ], [ 'core/post-featured-image' ] ], | ||
], | ||
[ 'core/query-pagination' ], | ||
[ 'core/query-no-results' ], | ||
], | ||
scope: [ 'block', 'inserter' ], | ||
} ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.