/**
* External dependencies
*/
import type { BlockEditProps } from '@wordpress/blocks';
import { InspectorControls } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import { type ElementType, useMemo } from '@wordpress/element';
import { EditorBlock } from '@woocommerce/types';
import { addFilter } from '@wordpress/hooks';
import { ProductCollectionFeedbackPrompt } from '@woocommerce/editor-components/feedback-prompt';
import {
enableAutoUpdate,
revertMigration,
getUpgradeStatus,
HOURS_TO_DISPLAY_UPGRADE_NOTICE,
UPGRADE_NOTICE_DISPLAY_COUNT_THRESHOLD,
} from '@woocommerce/blocks/migration-products-to-product-collection';
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 metadata from '../block.json';
import { ProductCollectionAttributes } from '../types';
import { setQueryAttribute } from '../utils';
import { DEFAULT_FILTERS, getDefaultSettings } from '../constants';
import UpgradeNotice from './upgrade-notice';
import ColumnsControl from './columns-control';
import InheritQueryControl from './inherit-query-control';
import OrderByControl from './order-by-control';
import OnSaleControl from './on-sale-control';
import StockStatusControl from './stock-status-control';
import KeywordControl from './keyword-control';
import AttributesControl from './attributes-control';
import TaxonomyControls from './taxonomy-controls';
import HandPickedProductsControl from './hand-picked-products-control';
import LayoutOptionsControl from './layout-options-control';
import FeaturedProductsControl from './featured-products-control';
import CreatedControl from './created-control';
const ProductCollectionInspectorControls = (
props: BlockEditProps< ProductCollectionAttributes >
) => {
const query = props.attributes.query;
const inherit = query?.inherit;
const displayQueryControls = inherit === false;
const setQueryAttributeBind = useMemo(
() => setQueryAttribute.bind( null, props ),
[ props ]
);
const displayControlProps = {
setAttributes: props.setAttributes,
displayLayout: props.attributes.displayLayout,
};
const queryControlProps = {
setQueryAttribute: setQueryAttributeBind,
query,
};
return (
{
const defaultSettings = getDefaultSettings(
props.attributes
);
props.setAttributes( defaultSettings );
} }
>
{ displayQueryControls ? (
) : null }
{ displayQueryControls ? (
void )[] ) => {
setQueryAttribute( props, DEFAULT_FILTERS );
resetAllFilters.forEach( ( resetFilter ) =>
resetFilter()
);
} }
className="wc-block-editor-product-collection-inspector-toolspanel__filters"
>
) : null }
);
};
export default ProductCollectionInspectorControls;
// Trigger Auto Upgrade of Products only once when module is loaded.
// This triggers subscription but only if:
// - auto update is enabled
// - user haven't reverted the migration
// - no other subscription is in place
enableAutoUpdate();
const isProductCollection = ( blockName: string ) =>
blockName === metadata.name;
const lessThanThresholdSinceUpdate = ( t: number ) => {
// Xh * 60m * 60s * 1000ms
const xHoursFromT = t + HOURS_TO_DISPLAY_UPGRADE_NOTICE * 60 * 60 * 1000;
return Date.now() < xHoursFromT;
};
const displayedLessThanThreshold = ( displayCount = 0 ) => {
return displayCount <= UPGRADE_NOTICE_DISPLAY_COUNT_THRESHOLD;
};
// Upgrade Notice should be displayed only if:
// - block is converted from Products
// - user haven't acknowledged seeing the notice
// - less than X hours since the notice was first displayed
// - notice was displayed less than X times
const shouldDisplayUpgradeNotice = ( props ) => {
const { attributes } = props;
const { convertedFromProducts } = attributes;
const { status, time, displayCount } = getUpgradeStatus();
return (
convertedFromProducts &&
status === 'notseen' &&
lessThanThresholdSinceUpdate( time ) &&
displayedLessThanThreshold( displayCount )
);
};
// Block should be unmarked as converted from Products if:
// block is converted from Products and either:
// - user acknowledged seeing the notice
// - it's more than X hours since the notice was first displayed
// - notice was displayed more than X times
// We do that to prevent showing the notice again after Products on
// other page were updated or local storage was cleared or user
// switched to another machine/browser etc.
const shouldBeUnmarkedAsConverted = ( props ) => {
const { attributes } = props;
const { convertedFromProducts } = attributes;
const { status, time, displayCount } = getUpgradeStatus();
return (
convertedFromProducts &&
( status === 'seen' ||
! lessThanThresholdSinceUpdate( time ) ||
! displayedLessThanThreshold( displayCount ) )
);
};
export const withUpgradeNoticeControls =
< T extends EditorBlock< T > >( BlockEdit: ElementType ) =>
( props: BlockEditProps< ProductCollectionAttributes > ) => {
if ( ! isProductCollection( props.name ) ) {
return ;
}
const displayUpgradeNotice = shouldDisplayUpgradeNotice( props );
const unmarkAsConverted = shouldBeUnmarkedAsConverted( props );
if ( unmarkAsConverted ) {
props.setAttributes( { convertedFromProducts: false } );
}
return (
<>
{ displayUpgradeNotice && (
{
}
) }
>
);
};
addFilter(
'editor.BlockEdit',
'woocommerce/product-collection',
withUpgradeNoticeControls
);