Merge branch 'create-changelog-during-build' into new-cfe-workflow

This commit is contained in:
Naman Malhotra 2024-09-09 18:35:54 +03:00 committed by GitHub
commit 67a0209331
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
286 changed files with 5260 additions and 4593 deletions

View File

@ -1,4 +1,11 @@
name: Pre build step - Compile changelog file
on:
workflow_dispatch:
inputs:
version:
description: 'Version override. Default version is fetched from monthly release calendar, you can override the version but make sure the that the branch release/{version} exists on remote.'
required: false
default: ''
env:
GIT_COMMITTER_NAME: 'WooCommerce Bot'
@ -38,10 +45,11 @@ jobs:
- name: 'Get the versions for the accelerated and monthly releases'
id: get-versions
if: ${{ github.event.inputs.version == '' }}
run: pnpm utils code-freeze get-version
- name: Generate changelog changes and create PR
id: changelog
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: pnpm utils code-freeze changelog -o ${{ github.repository_owner }} -v ${{ steps.get-versions.outputs.monthlyVersionXY }}
run: pnpm utils code-freeze changelog -o ${{ github.repository_owner }} -v ${{ github.event.inputs.version || steps.get-versions.outputs.monthlyVersionXY }}

View File

@ -691,7 +691,7 @@
"post_title": "Integrating with coming soon mode",
"tags": "how-to, coming-soon",
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/docs/extension-development/integrating-coming-soon-mode.md",
"hash": "910dbbab77c6fb4735e7704796242c38d86f3bf3b897de1075338eb47194f8f5",
"hash": "8c2087952ae79bb4c3e3977c57d9e933fcfaa418a5bc643b3827059daa5879a7",
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/docs/extension-development/integrating-coming-soon-mode.md",
"id": "787743efb6ef0ad509b17735eaf58b2a9a08afbc"
},
@ -1804,5 +1804,5 @@
"categories": []
}
],
"hash": "12e9abfbcdbeae7dd5cc12dc3af3818332f272cb4b3ad12993cc010299009013"
"hash": "8199f0d3c854474839300ed606f03f9f286ace35f65d7c47ffc6477762eaf51e"
}

View File

@ -3,7 +3,7 @@ post_title: Integrating with coming soon mode
tags: how-to, coming-soon
---
This guide provides examples for third-party developers and hosting providers on how to integrate their systems with WooCommerce's coming soon mode. For more details, please read the [developer blog post](https://developer.woocommerce.com/2024/06/18/introducing-coming-soon-mode/).
This guide provides examples for third-party developers and hosting providers on how to integrate their systems with WooCommerce's coming soon mode. For more details, please read the [developer blog post](https://developer.woocommerce.com/2024/06/18/introducing-coming-soon-mode/). For site visibility settings, please refer to the [admin documentation](https://woocommerce.com/document/configuring-woocommerce-settings/coming-soon-mode/).
## Introduction
@ -49,8 +49,8 @@ function sync_coming_soon_to_other_plugins( $old_value, $new_value, $option ) {
$is_enabled = $new_value === 'yes';
// Implement your logic to sync coming soon status.
if ( function_exists( 'set_your_plugin_status' ) ) {
set_your_plugin_status( $is_enabled );
if ( function_exists( 'your_plugin_set_coming_soon' ) ) {
your_plugin_set_coming_soon( $is_enabled );
}
}
```
@ -84,8 +84,8 @@ function sync_coming_soon_to_other_plugins( $old_value, $new_value, $option ) {
$is_enabled = $new_value === 'yes';
// Implement your logic to sync coming soon status.
if ( function_exists( 'set_your_plugin_status' ) ) {
set_your_plugin_status( $is_enabled );
if ( function_exists( 'your_plugin_set_coming_soon' ) ) {
your_plugin_set_coming_soon( $is_enabled );
}
}
@ -108,6 +108,38 @@ function sync_coming_soon_from_other_plugins( $is_enabled ) {
}
```
#### One-way binding with option override
We could also programmatically bind the coming soon option from another plugin by overriding the `woocommerce_coming_soon` option. This is advantageous since it simplifies state management and prevents possible out-of-sync issues.
In the following example, we're binding the coming soon option from another plugin by overriding the `woocommerce_coming_soon` option.
```php
add_filter( 'pre_option_woocommerce_coming_soon', 'override_option_woocommerce_coming_soon' );
function override_option_woocommerce_coming_soon( $current_value ) {
// Implement your logic to sync coming soon status.
if ( function_exists( 'your_plugin_is_coming_soon' ) ) {
return your_plugin_is_coming_soon() ? 'yes' : 'no';
}
return $current_value;
}
add_filter( 'pre_update_option_woocommerce_coming_soon', 'override_update_woocommerce_coming_soon', 10, 2 );
function override_update_woocommerce_coming_soon( $new_value, $old_value ) {
// Check user capability.
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'You do not have sufficient permissions to access this page.' );
}
// Implement your logic to sync coming soon status.
if ( function_exists( 'your_plugin_set_coming_soon' ) ) {
your_plugin_set_coming_soon( $new_value === 'yes' );
}
}
```
### Custom exclusions filter
It is possible for developers to add custom exclusions that bypass the coming soon protection. This is useful for exclusions like always bypassing the screen on a specific IP address, or making a specific landing page available.
@ -134,3 +166,35 @@ add_filter( 'woocommerce_coming_soon_exclude', function( $is_excluded ) {
return $is_excluded;
}, 10 );
```
#### Custom share links
The following example shows how to integrate with a custom share code. We recommend using cookies or other storage to persist the access when users navigate across the site:
```php
add_filter( 'woocommerce_coming_soon_exclude', function( $exclude ) {
// Implement your logic to get and validate share code.
if ( function_exists( 'your_plugin_get_share_code' ) && function_exists( 'your_plugin_is_valid_share_code' ) ) {
$share_code = your_plugin_get_share_code();
if ( your_plugin_is_valid_share_code( $share_code ) ) {
return true;
}
}
return $exclude;
} );
```
### Extend "Apply to store pages only" setting
When using the `Apply to store pages only` setting, you may want to add a custom page to the list of store pages which will be restricted by coming soon mode. You can use the following example to add a custom page:
```php
add_filter( 'woocommerce_store_pages', function( $pages ) {
$page = get_page_by_path( 'your-page-slug' );
if ( $page ) {
$pages[] = $page->ID;
}
return $pages;
} );
```

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
Update storybook file format in support with Storybook 7 story indexer.

View File

@ -132,18 +132,10 @@
"devDependencies": {
"@babel/core": "^7.23.5",
"@babel/runtime": "^7.23.5",
"@storybook/addon-actions": "6.5.17-alpha.0",
"@storybook/addon-console": "^1.2.3",
"@storybook/addon-controls": "6.5.17-alpha.0",
"@storybook/addon-docs": "6.5.17-alpha.0",
"@storybook/addon-knobs": "^6.4.0",
"@storybook/addon-links": "6.5.17-alpha.0",
"@storybook/addons": "6.5.17-alpha.0",
"@storybook/api": "6.5.17-alpha.0",
"@storybook/components": "6.5.17-alpha.0",
"@storybook/core-events": "6.5.17-alpha.0",
"@storybook/addon-docs": "7.6.19",
"@storybook/addon-links": "7.6.19",
"@storybook/react": "6.5.17-alpha.0",
"@storybook/theming": "6.5.17-alpha.0",
"@testing-library/dom": "8.11.3",
"@testing-library/jest-dom": "5.16.2",
"@testing-library/react": "12.1.3",

View File

@ -7,7 +7,7 @@ import { createElement } from '@wordpress/element';
/**
* Internal dependencies
*/
import { Basic } from '../stories/index';
import { Basic } from '../stories/compare-filter.story';
import { CompareFilter } from '../index';
import Search from '../../search';
import productAutocompleter from '../../search/autocompleters/product';

View File

@ -8,7 +8,7 @@ import { createElement } from '@wordpress/element';
/**
* Internal dependencies
*/
import { Basic } from '../stories/index';
import { Basic } from '../stories/filter-picker.story';
import FilterPicker from '../index';
import Search from '../../search';
import productAutocompleter from '../../search/autocompleters/product';

View File

@ -8,7 +8,7 @@ import React from 'react';
* Internal dependencies
*/
import { ImageGallery, ImageGalleryItem } from '../';
import { MockMediaUpload } from '../../media-uploader/stories/index.tsx';
import { MockMediaUpload } from '../../media-uploader/stories/mock-media-uploader';
export const Basic: React.FC = () => {
return (

View File

@ -2,7 +2,7 @@
* External dependencies
*/
import React, { createElement } from 'react';
import { Modal, Notice } from '@wordpress/components';
import { Notice } from '@wordpress/components';
import { MediaItem } from '@wordpress/media-utils';
import { useState } from '@wordpress/element';
import { cloudUpload } from '@wordpress/icons';
@ -12,59 +12,7 @@ import { cloudUpload } from '@wordpress/icons';
*/
import { MediaUploader } from '../';
import { File } from '../types';
const MockMediaUpload = ( { onSelect, render } ) => {
const [ isOpen, setOpen ] = useState( false );
return (
<>
{ render( {
open: () => setOpen( true ),
} ) }
{ isOpen && (
<Modal
title="Media Modal"
onRequestClose={ ( event ) => {
setOpen( false );
event.stopPropagation();
} }
>
<p>
Use the default built-in{ ' ' }
<code>MediaUploadComponent</code> prop to render the WP
Media Modal.
</p>
{ Array( ...Array( 3 ) ).map( ( n, i ) => {
return (
<button
key={ i }
onClick={ ( event ) => {
onSelect( {
alt: 'Random',
url: `https://picsum.photos/200?i=${ i }`,
} );
setOpen( false );
event.stopPropagation();
} }
style={ {
marginRight: '16px',
} }
>
<img
src={ `https://picsum.photos/200?i=${ i }` }
alt="Random"
style={ {
maxWidth: '100px',
} }
/>
</button>
);
} ) }
</Modal>
) }
</>
);
};
import { MockMediaUpload } from './mock-media-uploader';
const ImageGallery = ( { images }: { images: File[] } ) => {
return (

View File

@ -0,0 +1,59 @@
/**
* External dependencies
*/
import React, { createElement } from 'react';
import { Modal } from '@wordpress/components';
import { useState } from '@wordpress/element';
export const MockMediaUpload = ( { onSelect, render } ) => {
const [ isOpen, setOpen ] = useState( false );
return (
<>
{ render( {
open: () => setOpen( true ),
} ) }
{ isOpen && (
<Modal
title="Media Modal"
onRequestClose={ ( event ) => {
setOpen( false );
event.stopPropagation();
} }
>
<p>
Use the default built-in{ ' ' }
<code>MediaUploadComponent</code> prop to render the WP
Media Modal.
</p>
{ Array( ...Array( 3 ) ).map( ( n, i ) => {
return (
<button
key={ i }
onClick={ ( event ) => {
onSelect( {
alt: 'Random',
url: `https://picsum.photos/200?i=${ i }`,
} );
setOpen( false );
event.stopPropagation();
} }
style={ {
marginRight: '16px',
} }
>
<img
src={ `https://picsum.photos/200?i=${ i }` }
alt="Random"
style={ {
maxWidth: '100px',
} }
/>
</button>
);
} ) }
</Modal>
) }
</>
);
};

View File

@ -11,7 +11,12 @@ import {
} from '@wordpress/element';
import { SyntheticEvent, useCallback } from 'react';
import { useDispatch, useSelect } from '@wordpress/data';
import { PLUGINS_STORE_NAME, InstallPluginsResponse } from '@woocommerce/data';
import { PLUGINS_STORE_NAME } from '@woocommerce/data';
import type {
InstallPluginsResponse,
PluginSelectors,
PluginActions,
} from '@woocommerce/data';
type PluginsProps = {
onComplete: (
@ -52,10 +57,14 @@ export const Plugins = ( {
const [ hasErrors, setHasErrors ] = useState( false );
// Tracks action so that multiple instances of this button don't all light up when one is clicked
const [ hasBeenClicked, setHasBeenClicked ] = useState( false );
const { installAndActivatePlugins } = useDispatch( PLUGINS_STORE_NAME );
const { installAndActivatePlugins }: PluginActions =
useDispatch( PLUGINS_STORE_NAME );
const { isRequesting } = useSelect( ( select ) => {
const { getActivePlugins, getInstalledPlugins, isPluginsRequesting } =
select( PLUGINS_STORE_NAME );
const {
getActivePlugins,
getInstalledPlugins,
isPluginsRequesting,
}: PluginSelectors = select( PLUGINS_STORE_NAME );
return {
isRequesting:
@ -64,7 +73,7 @@ export const Plugins = ( {
activePlugins: getActivePlugins(),
installedPlugins: getInstalledPlugins(),
};
} );
}, [] );
const handleErrors = useCallback(
( errors: unknown, response: InstallPluginsResponse ) => {

View File

@ -13,7 +13,7 @@ import { useDispatch } from '@wordpress/data';
import { Plugins } from '../index';
jest.mock( '@wordpress/data', () => ( {
...jest.requireActual( '@wordpress/data' ),
__esModule: true,
useDispatch: jest
.fn()
.mockReturnValue( { installAndActivatePlugins: jest.fn() } ),

View File

@ -12,7 +12,6 @@ import * as actions from './actions';
import { STORE_NAME } from './constants';
export const store = createReduxStore( STORE_NAME, {
// @ts-expect-error reducer has correct format.
reducer,
selectors,
actions,

View File

@ -8,6 +8,7 @@ export type ProductFieldDefinition = {
type?: HTMLInputTypeAttribute;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
render?: ComponentType;
attributes?: Record< string, string >;
};
export type ProductFieldState = {

View File

@ -43,7 +43,7 @@ export const EditorWritingFlow = ( {
editorMode: __unstableGetEditorMode(),
selectedBlockClientIds: getSelectedBlockClientIds(),
};
} );
}, [] );
// This is a workaround to prevent focusing the block on initialization.
// Changing to a mode other than "edit" ensures that no initial position

View File

@ -1,107 +0,0 @@
/**
* External dependencies
*/
import { date, text } from '@storybook/addon-knobs';
import GridIcon from 'gridicons';
/**
* Internal dependencies
*/
import Timeline, { orderByOptions } from '../';
export default {
title: 'WooCommerce Admin/components/Timeline',
component: Timeline,
};
export const Empty = () => <Timeline />;
const itemDate = ( label, value ) => {
const d = date( label, value );
return new Date( d );
};
export const Filled = () => (
<Timeline
orderBy={ orderByOptions.DESC }
items={ [
{
date: itemDate(
'event 1 date',
new Date( 2020, 0, 20, 1, 30 )
),
body: [
<p key={ '1' }>
{ text( 'event 1, first event', 'p element in body' ) }
</p>,
text( 'event 1, second event', 'string in body' ),
],
headline: (
<p>{ text( 'event 1, headline', 'p tag in headline' ) }</p>
),
icon: (
<GridIcon
className={ 'is-success' }
icon={ text( 'event 1 gridicon', 'checkmark' ) }
size={ 16 }
/>
),
hideTimestamp: true,
},
{
date: itemDate(
'event 2 date',
new Date( 2020, 0, 20, 23, 45 )
),
body: [],
headline: (
<span>
{ text( 'event 2, headline', 'span in headline' ) }
</span>
),
icon: (
<GridIcon
className={ 'is-warning' }
icon={ text( 'event 2 gridicon', 'refresh' ) }
size={ 16 }
/>
),
},
{
date: itemDate(
'event 3 date',
new Date( 2020, 0, 22, 15, 13 )
),
body: [
<span key={ '1' }>
{ text( 'event 3, second event', 'span in body' ) }
</span>,
],
headline: text( 'event 3, headline', 'string in headline' ),
icon: (
<GridIcon
className={ 'is-error' }
icon={ text( 'event 3 gridicon', 'cross' ) }
size={ 16 }
/>
),
},
{
date: itemDate(
'event 4 date',
new Date( 2020, 0, 17, 1, 45 )
),
headline: text(
'event 4, headline',
'undefined body and string headline'
),
icon: (
<GridIcon
icon={ text( 'event 4 gridicon', 'cross' ) }
size={ 16 }
/>
),
},
] }
/>
);

View File

@ -0,0 +1,71 @@
/**
* External dependencies
*/
import GridIcon from 'gridicons';
/**
* Internal dependencies
*/
import Timeline, { orderByOptions } from '../';
export const Filled = () => {
return (
<Timeline
orderBy={ orderByOptions.DESC }
items={ [
{
date: new Date( 2020, 0, 20, 1, 30 ),
body: [
<p key="1">p element in body</p>,
'string in body',
],
headline: <p>p tag in headline</p>,
icon: (
<GridIcon
className="is-success"
icon="checkmark"
size={ 16 }
/>
),
hideTimestamp: true,
},
{
date: new Date( 2020, 0, 20, 23, 45 ),
body: [],
headline: <span>span in headline</span>,
icon: (
<GridIcon
className={ 'is-warning' }
icon="refresh"
size={ 16 }
/>
),
},
{
date: new Date( 2020, 0, 22, 15, 13 ),
body: [ <span key="1">span in body</span> ],
headline: 'string in headline',
icon: (
<GridIcon
className={ 'is-error' }
icon="cross"
size={ 16 }
/>
),
},
{
date: new Date( 2020, 0, 17, 1, 45 ),
headline: 'undefined body and string headline',
icon: <GridIcon icon="cross" size={ 16 } />,
},
] }
/>
);
};
export default {
title: 'WooCommerce Admin/components/Timeline',
component: Filled,
};
export const Empty = () => <Timeline />;

View File

@ -0,0 +1,4 @@
Significance: patch
Type: update
Add wooPaymentsIncentiveId to the TaskType additionalData.

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
Export plugin related data store types for selectors and actions.

View File

@ -85,6 +85,8 @@ export {
} from './product-form/types';
export * from './onboarding/types';
export * from './plugins/types';
export { PluginSelectors } from './plugins/selectors';
export { ActionDispatchers as PluginActions } from './plugins/actions';
export * from './products/types';
export type {
PartialProductVariation,

View File

@ -35,6 +35,7 @@ export type TaskType = {
stripeTaxActivated?: boolean;
woocommerceTaxActivated?: boolean;
woocommerceShippingActivated?: boolean;
wooPaymentsIncentiveId?: string;
};
// Possibly added in DeprecatedTasks.mergeDeprecatedCallbackFunctions
isDeprecated?: boolean;

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
Update storybook file format in support with Storybook 7 story indexer.

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
Update storybook file format in support with Storybook 7 story indexer.

View File

@ -71,7 +71,6 @@
},
"devDependencies": {
"@babel/core": "^7.23.5",
"@storybook/addon-knobs": "^7.0.2",
"@testing-library/react": "12.1.3",
"@types/jest": "^27.5.2",
"@types/react": "^17.0.71",

View File

@ -0,0 +1,4 @@
Significance: patch
Type: update
Increase specificity of product data views styles to avoid conflicts.

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
Update storybook file format in support with Storybook 7 story indexer.

Some files were not shown because too many files have changed in this diff Show More