Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
Product Collection: Add 'on sale' filter and enhance settings managem…
Browse files Browse the repository at this point in the history
…ent in product collection block (#9549)

* Add columns control to product collection block editor settings

- `InspectorControls` from './inspector-controls' is now imported in `edit.tsx` and used in the returned JSX of `Edit` function.
- A new file `columns-control.tsx` is added under 'product-collection' block's 'inspector-controls' directory which exports a `ColumnsControl` component. This component uses `RangeControl` from '@wordpress/components' to control the number of columns in the product collection display layout when the layout type is 'flex'.
- The types file (`types.ts`) for 'product-collection' block is updated. The `Attributes` interface is renamed to `ProductCollectionAttributes` and the `ProductCollectionContext` interface is removed. The `ProductCollectionAttributes` now includes 'queryContext', 'templateSlug', and 'displayLayout' properties.

* Refactor: Simplify Fallback Return in ColumnsControl Component

This commit simplifies the fallback return value of the ColumnsControl component. Instead of returning an empty fragment (<> </>), it now returns null when the condition isn't met. This change improves readability and aligns with best practices for conditional rendering in React.

* Feature: Add 'Order By' Control to Product Collection Inspector

This commit adds a new 'Order By' control to the product collection inspector. The control allows users to specify the order of products in a collection by various attributes such as title and date. To support this, a new component 'OrderByControl' has been created and included in the product collection inspector. Additionally, the types for 'order' and 'orderBy' attributes have been updated and exported for reuse.

* Add more options to OrderBy type

* Add orderby handling on frontend & editor

The main changes include:
1. Added a new property 'isProductCollectionBlock' in the block.json to denote if a block is a product collection block.
2. In the ProductCollection PHP class, a new initialization function has been defined to hook into the WordPress lifecycle, register the block, and update the query based on this block.
3. Added methods to manage query parameters for both frontend rendering and the Editor.
4. Expanded allowed 'collection_params' for the REST API to include custom 'orderby' values.
5. Defined a function to build the query based on block attributes, filters, and global WP_Query.
6. Created utility functions to handle complex query operations such as merging queries, handling custom sort values, and merging arrays recursively.

These improvements allow for more flexible and robust handling of product collections in both the front-end display and the WordPress editor. It also extends support for custom 'orderby' values in the REST API, which allows for more advanced sorting options in product collections.

* Add 'on sale' filter and enhance settings management in product collection block

This commit introduces several changes to the product collection block.
- First, it adds a new 'on sale' filter that can be used to display only the products that are currently on sale.
- It also refactors the settings management in the product collection block to use the experimental ToolsPanel component from WordPress, which provides a more flexible and intuitive way to manage block settings.
- It moves the 'Columns' control into the ToolsPanel, along with the 'Order by' control.
- A new utility function `setQueryAttribute` is introduced to simplify setting nested query parameters.
- The structure of the `ProductCollectionAttributes` and `ProductCollectionQuery` types have been adjusted to accommodate the changes.
- Finally, it makes corresponding changes in the PHP part to handle the new 'on sale' query parameter.

This should enhance the flexibility and user-friendliness of the product collection block.
  • Loading branch information
imanish003 authored May 25, 2023
1 parent f317b6d commit abbaaff
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 34 deletions.
3 changes: 2 additions & 1 deletion assets/js/blocks/product-collection/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"inherit": false,
"taxQuery": null,
"parents": [],
"isProductCollectionBlock": true
"isProductCollectionBlock": true,
"woocommerceOnSale": false
}
},
"tagName": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,61 @@
/**
* External dependencies
*/
import { RangeControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { BlockEditProps } from '@wordpress/blocks';
import {
RangeControl,
// @ts-expect-error Using experimental features
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
__experimentalToolsPanelItem as ToolsPanelItem,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import { ProductCollectionAttributes } from '../types';
import {
ProductCollectionAttributes,
ProductCollectionDisplayLayout,
} from '../types';
import { getDefaultSettings } from './constants';

const ColumnsControl = (
props: BlockEditProps< ProductCollectionAttributes >
) => {
const { type, columns } = props.attributes.displayLayout;
const showColumnsControl = type === 'flex';

const defaultSettings = getDefaultSettings( props.attributes );

return showColumnsControl ? (
<RangeControl
<ToolsPanelItem
label={ __( 'Columns', 'woo-gutenberg-products-block' ) }
value={ columns }
onChange={ ( value: number ) =>
props.setAttributes( {
displayLayout: {
...props.attributes.displayLayout,
columns: value,
},
} )
hasValue={ () =>
defaultSettings.displayLayout?.columns !== columns ||
defaultSettings.displayLayout?.type !== type
}
min={ 2 }
max={ Math.max( 6, columns ) }
/>
isShownByDefault
onDeselect={ () => {
props.setAttributes( {
displayLayout:
defaultSettings.displayLayout as ProductCollectionDisplayLayout,
} );
} }
>
<RangeControl
value={ columns }
onChange={ ( value: number ) =>
props.setAttributes( {
displayLayout: {
...props.attributes.displayLayout,
columns: value,
},
} )
}
min={ 2 }
max={ Math.max( 6, columns ) }
/>
</ToolsPanelItem>
) : null;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Internal dependencies
*/
import blockJson from '../block.json';
import {
ProductCollectionAttributes,
TProductCollectionOrder,
TProductCollectionOrderBy,
} from '../types';

const defaultQuery = blockJson.attributes.query.default;

export const DEFAULT_FILTERS = {
woocommerceOnSale: defaultQuery.woocommerceOnSale,
};

export const getDefaultSettings = (
currentAttributes: ProductCollectionAttributes
): Partial< ProductCollectionAttributes > => ( {
displayLayout: blockJson.attributes.displayLayout.default,
query: {
...currentAttributes.query,
orderBy: blockJson.attributes.query.default
.orderBy as TProductCollectionOrderBy,
order: blockJson.attributes.query.default
.order as TProductCollectionOrder,
},
} );
30 changes: 26 additions & 4 deletions assets/js/blocks/product-collection/inspector-controls/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,49 @@
*/
import type { BlockEditProps } from '@wordpress/blocks';
import { InspectorControls } from '@wordpress/block-editor';
import { PanelBody } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import {
// @ts-expect-error Using experimental features
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
__experimentalToolsPanel as ToolsPanel,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import { ProductCollectionAttributes } from '../types';
import ColumnsControl from './columns-control';
import OrderByControl from './order-by-control';
import OnSaleControl from './on-sale-control';
import { setQueryAttribute } from './utils';
import { DEFAULT_FILTERS, getDefaultSettings } from './constants';

const ProductCollectionInspectorControls = (
props: BlockEditProps< ProductCollectionAttributes >
) => {
return (
<InspectorControls>
<PanelBody
title={ __( 'Settings', 'woo-gutenberg-products-block' ) }
<ToolsPanel
label={ __( 'Settings', 'woo-gutenberg-products-block' ) }
resetAll={ () => {
const defaultSettings = getDefaultSettings(
props.attributes
);
props.setAttributes( defaultSettings );
} }
>
<ColumnsControl { ...props } />
<OrderByControl { ...props } />
</PanelBody>
</ToolsPanel>

<ToolsPanel
label={ __( 'Filters', 'woo-gutenberg-products-block' ) }
resetAll={ () => {
setQueryAttribute( props, DEFAULT_FILTERS );
} }
>
<OnSaleControl { ...props } />
</ToolsPanel>
</InspectorControls>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { BlockEditProps } from '@wordpress/blocks';
import {
ToggleControl,
// @ts-expect-error Using experimental features
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
__experimentalToolsPanelItem as ToolsPanelItem,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import { ProductCollectionAttributes } from '../types';

const OnSaleControl = (
props: BlockEditProps< ProductCollectionAttributes >
) => {
const { query } = props.attributes;

return (
<ToolsPanelItem
label={ __( 'On Sale', 'woo-gutenberg-products-block' ) }
hasValue={ () => query.woocommerceOnSale }
isShownByDefault
onDeselect={ () => {
props.setAttributes( {
query: {
...query,
woocommerceOnSale: false,
},
} );
} }
>
<ToggleControl
label={ __(
'Show only products on sale',
'woo-gutenberg-products-block'
) }
checked={ query.woocommerceOnSale || false }
onChange={ ( woocommerceOnSale ) => {
props.setAttributes( {
query: {
...query,
woocommerceOnSale,
},
} );
} }
/>
</ToolsPanelItem>
);
};

export default OnSaleControl;
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
/**
* External dependencies
*/
import { SelectControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { BlockEditProps } from '@wordpress/blocks';
import {
SelectControl,
// @ts-expect-error Using experimental features
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
__experimentalToolsPanelItem as ToolsPanelItem,
} from '@wordpress/components';

/**
* Internal dependencies
Expand All @@ -13,6 +18,7 @@ import {
TProductCollectionOrder,
TProductCollectionOrderBy,
} from '../types';
import { getDefaultSettings } from './constants';

const orderOptions = [
{
Expand Down Expand Up @@ -45,22 +51,40 @@ const OrderByControl = (
props: BlockEditProps< ProductCollectionAttributes >
) => {
const { order, orderBy } = props.attributes.query;
const defaultSettings = getDefaultSettings( props.attributes );

return (
<SelectControl
<ToolsPanelItem
label={ __( 'Order by', 'woo-gutenberg-products-block' ) }
value={ `${ orderBy }/${ order }` }
options={ orderOptions }
onChange={ ( value ) => {
const [ newOrderBy, newOrder ] = value.split( '/' );
hasValue={ () =>
order !== defaultSettings.query?.order ||
orderBy !== defaultSettings.query?.orderBy
}
isShownByDefault
onDeselect={ () => {
props.setAttributes( {
query: {
...props.attributes.query,
order: newOrder as TProductCollectionOrder,
orderBy: newOrderBy as TProductCollectionOrderBy,
...defaultSettings.query,
},
} );
} }
/>
>
<SelectControl
value={ `${ orderBy }/${ order }` }
options={ orderOptions }
onChange={ ( value ) => {
const [ newOrderBy, newOrder ] = value.split( '/' );
props.setAttributes( {
query: {
...props.attributes.query,
order: newOrder as TProductCollectionOrder,
orderBy: newOrderBy as TProductCollectionOrderBy,
},
} );
} }
/>
</ToolsPanelItem>
);
};

Expand Down
28 changes: 28 additions & 0 deletions assets/js/blocks/product-collection/inspector-controls/utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* External dependencies
*/
import { BlockEditProps } from '@wordpress/blocks';

/**
* Internal dependencies
*/
import { ProductCollectionAttributes, ProductCollectionQuery } from '../types';

/**
* Sets the new query arguments of a Product Query block
*
* Shorthand for setting new nested query parameters.
*/
export function setQueryAttribute(
block: BlockEditProps< ProductCollectionAttributes >,
queryParams: Partial< ProductCollectionQuery >
) {
const { query } = block.attributes;

block.setAttributes( {
query: {
...query,
...queryParams,
},
} );
}
11 changes: 7 additions & 4 deletions assets/js/blocks/product-collection/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ export interface ProductCollectionAttributes {
}
];
templateSlug: string;
displayLayout: {
type: string;
columns: number;
};
displayLayout: ProductCollectionDisplayLayout;
}

export interface ProductCollectionDisplayLayout {
type: string;
columns: number;
}

export interface ProductCollectionQuery {
Expand All @@ -27,6 +29,7 @@ export interface ProductCollectionQuery {
search: string;
sticky: string;
taxQuery: string;
woocommerceOnSale: boolean;
}

export type TProductCollectionOrder = 'asc' | 'desc';
Expand Down
Loading

0 comments on commit abbaaff

Please sign in to comment.