Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin' into tweak/blocks-e2e-workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
WunderBart committed Mar 7, 2024
2 parents cbc7912 + 9a14411 commit a99bc62
Show file tree
Hide file tree
Showing 13 changed files with 367 additions and 31 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/blocks-playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ on:
- 'plugins/woocommerce/src/Blocks/**'
- 'plugins/woocommerce/templates/**'
- 'plugins/woocommerce/patterns/**'
# Allow manually triggering the workflow.
workflow_dispatch:


env:
FORCE_COLOR: 1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: add

Add message after publishing a product to pre-publish panel #44864
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { MouseEvent } from 'react';
*/
import { useValidations } from '../../../../contexts/validation-context';
import { WPError } from '../../../../utils/get-product-error-message';
import { useProductURL } from '../../../../hooks/use-product-url';
import { PreviewButtonProps } from '../../preview-button';

export function usePreview( {
Expand All @@ -36,11 +37,7 @@ export function usePreview( {
'id'
);

const [ permalink ] = useEntityProp< string >(
'postType',
productType,
'permalink'
);
const { getProductURL } = useProductURL( productType );

const { hasEdits, isDisabled } = useSelect(
( select ) => {
Expand Down Expand Up @@ -72,12 +69,6 @@ export function usePreview( {
// @ts-expect-error There are no types for this.
const { editEntityRecord, saveEditedEntityRecord } = useDispatch( 'core' );

let previewLink: URL | undefined;
if ( typeof permalink === 'string' ) {
previewLink = new URL( permalink );
previewLink.searchParams.append( 'preview', 'true' );
}

/**
* Overrides the default anchor behaviour when the product has unsaved changes.
* Before redirecting to the preview page all changes are saved and then the
Expand Down Expand Up @@ -157,7 +148,7 @@ export function usePreview( {
'aria-disabled': ariaDisabled,
// Note that the href is always passed for a11y support. So
// the final rendered element is always an anchor.
href: previewLink?.toString(),
href: getProductURL( true ),
variant: 'tertiary',
onClick: handleClick,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './post-publish-section';
export * from './post-publish-title';
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* External dependencies
*/
import { createElement, useState, Fragment } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { Button, PanelBody, TextControl } from '@wordpress/components';
import { recordEvent } from '@woocommerce/tracks';
import { useCopyToClipboard } from '@wordpress/compose';
import { Ref } from 'react';
import { getNewPath } from '@woocommerce/navigation';

/**
* Internal dependencies
*/
import { useProductScheduled } from '../../../hooks/use-product-scheduled';
import { CopyButtonProps, PostPublishSectionProps } from './types';
import { TRACKS_SOURCE } from '../../../constants';
import { useProductURL } from '../../../hooks/use-product-url';

export function PostPublishSection( { postType }: PostPublishSectionProps ) {
const { getProductURL } = useProductURL( postType );
const { isScheduled } = useProductScheduled( postType );

const [ showCopyConfirmation, setShowCopyConfirmation ] =
useState< boolean >( false );

const productURL = getProductURL( isScheduled );

const CopyButton = ( { text, onCopy, children }: CopyButtonProps ) => {
const ref = useCopyToClipboard(
text,
onCopy
) as Ref< HTMLButtonElement >;
return (
<Button variant="secondary" ref={ ref }>
{ children }
</Button>
);
};

const onCopyURL = () => {
recordEvent( 'product_prepublish_panel', {
source: TRACKS_SOURCE,
action: 'copy_product_url',
} );
setShowCopyConfirmation( true );
setTimeout( () => {
setShowCopyConfirmation( false );
}, 4000 );
};

const onSelectInput = ( event: React.FocusEvent< HTMLInputElement > ) => {
event.target.select();
};

return (
<PanelBody>
<p className="post-publish-section__postpublish-subheader">
<strong>{ __( 'What’s next?', 'woocommerce' ) }</strong>
</p>
<div className="post-publish-section__postpublish-post-address-container">
{ /* eslint-disable-next-line @typescript-eslint/ban-ts-comment */ }
{ /* @ts-ignore TextControl requires an 'onChange' but it's not necessary here. */ }
<TextControl
className="post-publish-section__postpublish-post-address"
readOnly
label={ __( 'product address', 'woocommerce' ) }
value={ productURL }
onFocus={ onSelectInput }
/>

<div className="post-publish-section__copy-button-wrap">
<CopyButton text={ productURL } onCopy={ onCopyURL }>
<>
{ showCopyConfirmation
? __( 'Copied!', 'woocommerce' )
: __( 'Copy', 'woocommerce' ) }
</>
</CopyButton>
</div>
</div>

<div className="post-publish-section__postpublish-buttons">
{ ! isScheduled && (
<Button variant="primary" href={ productURL }>
{ __( 'View Product', 'woocommerce' ) }
</Button>
) }
<Button
variant={ isScheduled ? 'primary' : 'secondary' }
href={ getNewPath( {}, '/add-product', {} ) }
>
{ __( 'Add New Product', 'woocommerce' ) }
</Button>
</div>
</PanelBody>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* External dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import { createElement, createInterpolateElement } from '@wordpress/element';
import { useEntityProp } from '@wordpress/core-data';

/**
* Internal dependencies
*/
import { PostPublishTitleProps } from './types';
import { useProductURL } from '../../../hooks/use-product-url';
import { useProductScheduled } from '../../../hooks/use-product-scheduled';

export function PostPublishTitle( {
productType = 'product',
}: PostPublishTitleProps ) {
const { getProductURL } = useProductURL( productType );
const { isScheduled, formattedDate } = useProductScheduled( productType );
const [ editedProductName ] = useEntityProp< string >(
'postType',
productType,
'name'
);

const productURLString = getProductURL( false );
const getPostPublishedTitle = () => {
if ( isScheduled ) {
return createInterpolateElement(
sprintf(
/* translators: %s is the date when the product will be published */
__(
'<productURL /> is now scheduled. It will go live on %s',
'woocommerce'
),
formattedDate
),
{
productURL: (
<a
className="woocommerce-product-list__product-name"
href={ productURLString }
target="_blank"
rel="noreferrer"
>
{ editedProductName }
</a>
),
}
);
}
return createInterpolateElement(
__( '<productURL /> is now live.', 'woocommerce' ),
{
productURL: (
<a
className="woocommerce-product-list__product-name"
href={ productURLString }
target="_blank"
rel="noreferrer"
>
{ editedProductName }
</a>
),
}
);
};

return (
<div className="woocommerce-product-publish-panel__published">
{ getPostPublishedTitle() }
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type PostPublishSectionProps = {
postType: string;
};

export type PostPublishTitleProps = {
productType: string;
};

export type CopyButtonProps = {
text: string;
onCopy: () => void;
children: JSX.Element;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { createElement } from '@wordpress/element';
import { createElement, Fragment } from '@wordpress/element';
import { Button } from '@wordpress/components';
import { useDispatch } from '@wordpress/data';
import { recordEvent } from '@woocommerce/tracks';
import { useEntityProp } from '@wordpress/core-data';
import { closeSmall } from '@wordpress/icons';
import classnames from 'classnames';
import type { Product } from '@woocommerce/data';

/**
* Internal dependencies
Expand All @@ -18,6 +21,7 @@ import { TRACKS_SOURCE } from '../../constants';
import { VisibilitySection } from './visibility-section';
import { ScheduleSection } from './schedule-section';
import { ShowPrepublishChecksSection } from './show-prepublish-checks-section';
import { PostPublishSection, PostPublishTitle } from './post-publish';

export function PrepublishPanel( {
productType = 'product',
Expand All @@ -33,8 +37,17 @@ export function PrepublishPanel( {
'date_created'
);

const [ productStatus, , prevStatus ] = useEntityProp<
Product[ 'status' ]
>( 'postType', productType, 'status' );

const { closePrepublishPanel } = useDispatch( productEditorUiStore );

const isPublishedOrScheduled =
productType === 'product' && prevStatus !== 'future'
? productStatus === 'publish'
: true;

if ( editedDate !== date ) {
title = __( 'Are you ready to schedule this product?', 'woocommerce' );
description = __(
Expand All @@ -43,9 +56,25 @@ export function PrepublishPanel( {
);
}

return (
<div className="woocommerce-product-publish-panel">
<div className="woocommerce-product-publish-panel__header">
function getHeaderActions() {
if ( isPublishedOrScheduled ) {
return (
<Button
className="woocommerce-publish-panel-close"
icon={ closeSmall }
label={ __( 'Close panel', 'woocommerce' ) }
onClick={ () => {
recordEvent( 'product_prepublish_panel', {
source: TRACKS_SOURCE,
action: 'close',
} );
closePrepublishPanel();
} }
/>
);
}
return (
<>
<PublishButton productType={ productType } />
<Button
variant={ 'secondary' }
Expand All @@ -59,14 +88,48 @@ export function PrepublishPanel( {
>
{ __( 'Cancel', 'woocommerce' ) }
</Button>
</div>
<div className="woocommerce-product-publish-panel__title">
</>
);
}

function getPanelTitle() {
if ( isPublishedOrScheduled ) {
return <PostPublishTitle productType={ productType } />;
}
return (
<>
<h4>{ title }</h4>
<span>{ description }</span>
</div>
<div className="woocommerce-product-publish-panel__content">
</>
);
}

function getPanelSections() {
if ( isPublishedOrScheduled ) {
return <PostPublishSection postType={ productType } />;
}
return (
<>
<VisibilitySection productType={ productType } />
<ScheduleSection postType={ productType } />
</>
);
}

return (
<div
className={ classnames( 'woocommerce-product-publish-panel', {
'is-published': isPublishedOrScheduled,
} ) }
>
<div className="woocommerce-product-publish-panel__header">
{ getHeaderActions() }
</div>
<div className="woocommerce-product-publish-panel__title">
{ getPanelTitle() }
</div>
<div className="woocommerce-product-publish-panel__content">
{ getPanelSections() }
</div>
<div className="woocommerce-product-publish-panel__footer">
<ShowPrepublishChecksSection />
Expand Down

0 comments on commit a99bc62

Please sign in to comment.