Merge pull request woocommerce/woocommerce-admin#2634 from woocommerce/revert-2596-update/2445-snackbar

Revert "Update to new Snackbar component and notice store"
This commit is contained in:
Paul Sealock 2019-07-12 08:08:56 +12:00 committed by GitHub
commit dcc412a26d
32 changed files with 438 additions and 339 deletions

View File

@ -51,13 +51,13 @@ class HistoricalData extends Component {
}
makeQuery( path, errorMessage ) {
const { createNotice } = this.props;
const { addNotice } = this.props;
apiFetch( { path, method: 'POST' } )
.then( response => {
if ( 'success' === response.status ) {
createNotice( 'success', response.message );
addNotice( { status: 'success', message: response.message } );
} else {
createNotice( 'error', errorMessage );
addNotice( { status: 'error', message: errorMessage } );
this.setState( {
activeImport: false,
lastImportStopTimestamp: Date.now(),
@ -66,7 +66,7 @@ class HistoricalData extends Component {
} )
.catch( error => {
if ( error && error.message ) {
createNotice( 'error', error.message );
addNotice( { status: 'error', message: error.message } );
this.setState( {
activeImport: false,
lastImportStopTimestamp: Date.now(),

View File

@ -84,22 +84,25 @@ class Settings extends Component {
};
componentDidUpdate() {
const { createNotice, isError, isRequesting } = this.props;
const { addNotice, isError, isRequesting } = this.props;
const { saving, isDirty } = this.state;
let newIsDirtyState = isDirty;
if ( saving && ! isRequesting ) {
if ( ! isError ) {
createNotice(
'success',
__( 'Your settings have been successfully saved.', 'woocommerce-admin' )
);
addNotice( {
status: 'success',
message: __( 'Your settings have been successfully saved.', 'woocommerce-admin' ),
} );
newIsDirtyState = false;
} else {
createNotice(
'error',
__( 'There was an error saving your settings. Please try again.', 'woocommerce-admin' )
);
addNotice( {
status: 'error',
message: __(
'There was an error saving your settings. Please try again.',
'woocommerce-admin'
),
} );
}
/* eslint-disable react/no-did-update-set-state */
this.setState( { saving: false, isDirty: newIsDirtyState } );
@ -148,7 +151,7 @@ class Settings extends Component {
}
render() {
const { createNotice } = this.props;
const { addNotice } = this.props;
const { hasError } = this.state;
if ( hasError ) {
return null;
@ -175,7 +178,7 @@ class Settings extends Component {
</Button>
</div>
</div>
<HistoricalData createNotice={ createNotice } />
<HistoricalData addNotice={ addNotice } />
</Fragment>
);
}
@ -192,11 +195,11 @@ export default compose(
return { getSettings, isError, isRequesting, settings };
} ),
withDispatch( dispatch => {
const { createNotice } = dispatch( 'core/notices' );
const { addNotice } = dispatch( 'wc-admin' );
const { updateSettings } = dispatch( 'wc-api' );
return {
createNotice,
addNotice,
updateSettings,
};
} )

View File

@ -74,7 +74,7 @@ class Setting extends Component {
};
handleInputCallback = () => {
const { createNotice, callback } = this.props;
const { addNotice, callback } = this.props;
if ( 'function' !== typeof callback ) {
return;
@ -82,7 +82,7 @@ class Setting extends Component {
return new Promise( ( resolve, reject ) => {
this.setState( { disabled: true } );
callback( resolve, reject, createNotice );
callback( resolve, reject, addNotice );
} )
.then( () => {
this.setState( { disabled: false } );
@ -197,7 +197,7 @@ Setting.propTypes = {
export default compose(
withDispatch( dispatch => {
const { createNotice } = dispatch( 'core/notices' );
return { createNotice };
const { addNotice } = dispatch( 'wc-admin' );
return { addNotice };
} )
)( Setting );

View File

@ -93,7 +93,7 @@ class ProfileWizard extends Component {
}
async goToNextStep() {
const { createNotice, isError, updateProfileItems } = this.props;
const { addNotice, isError, updateProfileItems } = this.props;
const currentStep = this.getCurrentStep();
const currentStepIndex = getSteps().findIndex( s => s.key === currentStep.key );
const nextStep = getSteps()[ currentStepIndex + 1 ];
@ -102,10 +102,10 @@ class ProfileWizard extends Component {
await updateProfileItems( { completed: true } );
if ( isError ) {
createNotice(
'error',
__( 'There was a problem completing the profiler.', 'woocommerce-admin' )
);
addNotice( {
status: 'error',
message: __( 'There was a problem completing the profiler.', 'woocommerce-admin' ),
} );
}
return;
}
@ -142,11 +142,10 @@ export default compose(
return { isError };
} ),
withDispatch( dispatch => {
const { updateProfileItems } = dispatch( 'wc-api' );
const { createNotice } = dispatch( 'core/notices' );
const { addNotice, updateProfileItems } = dispatch( 'wc-api' );
return {
createNotice,
addNotice,
updateProfileItems,
};
} )

View File

@ -40,7 +40,7 @@ class BusinessDetails extends Component {
}
async onContinue() {
const { createNotice, goToNextStep, isError, updateProfileItems } = this.props;
const { addNotice, goToNextStep, isError, updateProfileItems } = this.props;
const { other_platform, product_count, selling_venues } = this.state;
const extensions = keys( pickBy( this.state.extensions ) );
@ -62,10 +62,10 @@ class BusinessDetails extends Component {
if ( ! isError ) {
goToNextStep();
} else {
createNotice(
'error',
__( 'There was a problem updating your business details.', 'woocommerce-admin' )
);
addNotice( {
status: 'error',
message: __( 'There was a problem updating your business details.', 'woocommerce-admin' ),
} );
}
}
@ -316,11 +316,10 @@ export default compose(
return { isError };
} ),
withDispatch( dispatch => {
const { updateProfileItems } = dispatch( 'wc-api' );
const { createNotice } = dispatch( 'core/notices' );
const { addNotice, updateProfileItems } = dispatch( 'wc-api' );
return {
createNotice,
addNotice,
updateProfileItems,
};
} )

View File

@ -27,7 +27,7 @@ class Industry extends Component {
}
async onContinue() {
const { createNotice, goToNextStep, isError, updateProfileItems } = this.props;
const { addNotice, goToNextStep, isError, updateProfileItems } = this.props;
recordEvent( 'storeprofiler_store_industry_continue', { store_industry: this.state.selected } );
await updateProfileItems( { industry: this.state.selected } );
@ -35,10 +35,10 @@ class Industry extends Component {
if ( ! isError ) {
goToNextStep();
} else {
createNotice(
'error',
__( 'There was a problem updating your industries.', 'woocommerce-admin' )
);
addNotice( {
status: 'error',
message: __( 'There was a problem updating your industries.', 'woocommerce-admin' ),
} );
}
}
@ -104,11 +104,10 @@ export default compose(
return { isError };
} ),
withDispatch( dispatch => {
const { updateProfileItems } = dispatch( 'wc-api' );
const { createNotice } = dispatch( 'core/notices' );
const { addNotice, updateProfileItems } = dispatch( 'wc-api' );
return {
createNotice,
addNotice,
updateProfileItems,
};
} )

View File

@ -119,7 +119,10 @@ class Plugins extends Component {
} );
return pluginResponse;
} catch ( err ) {
this.props.createNotice( 'error', this.getErrorMessage( action, plugin ) );
this.props.addNotice( {
status: 'error',
message: this.getErrorMessage( action, plugin ),
} );
this.setState( {
isPending: false,
isError: true,
@ -138,7 +141,10 @@ class Plugins extends Component {
}
throw new Error();
} catch ( err ) {
this.props.createNotice( 'error', this.getErrorMessage( 'activate', 'jetpack' ) );
this.props.addNotice( {
status: 'error',
message: this.getErrorMessage( 'activate', 'jetpack' ),
} );
this.setState( {
isPending: false,
isError: true,
@ -202,9 +208,9 @@ class Plugins extends Component {
export default compose(
withDispatch( dispatch => {
const { createNotice } = dispatch( 'core/notices' );
const { addNotice } = dispatch( 'wc-admin' );
return {
createNotice,
addNotice,
};
} )
)( Plugins );

View File

@ -30,7 +30,7 @@ class ProductTypes extends Component {
}
async onContinue() {
const { createNotice, goToNextStep, isError, updateProfileItems } = this.props;
const { addNotice, goToNextStep, isError, updateProfileItems } = this.props;
recordEvent( 'storeprofiler_store_product_type_continue', {
product_type: this.state.selected,
@ -40,10 +40,10 @@ class ProductTypes extends Component {
if ( ! isError ) {
goToNextStep();
} else {
createNotice(
'error',
__( 'There was a problem updating your product types.', 'woocommerce-admin' )
);
addNotice( {
status: 'error',
message: __( 'There was a problem updating your product types.', 'woocommerce-admin' ),
} );
}
}
@ -137,11 +137,10 @@ export default compose(
return { isError };
} ),
withDispatch( dispatch => {
const { updateProfileItems } = dispatch( 'wc-api' );
const { createNotice } = dispatch( 'core/notices' );
const { addNotice, updateProfileItems } = dispatch( 'wc-api' );
return {
createNotice,
addNotice,
updateProfileItems,
};
} )

View File

@ -76,7 +76,7 @@ class Start extends Component {
}
async skipWizard() {
const { createNotice, isProfileItemsError, updateProfileItems, isSettingsError } = this.props;
const { addNotice, isProfileItemsError, updateProfileItems, isSettingsError } = this.props;
recordEvent( 'storeprofiler_welcome_clicked', { proceed_without_install: true } );
@ -84,15 +84,15 @@ class Start extends Component {
await this.updateTracking();
if ( isProfileItemsError || isSettingsError ) {
createNotice(
'error',
__( 'There was a problem updating your preferences.', 'woocommerce-admin' )
);
addNotice( {
status: 'error',
message: __( 'There was a problem updating your preferences.', 'woocommerce-admin' ),
} );
}
}
async startWizard() {
const { createNotice, isSettingsError } = this.props;
const { addNotice, isSettingsError } = this.props;
recordEvent( 'storeprofiler_welcome_clicked', { get_started: true } );
@ -101,10 +101,10 @@ class Start extends Component {
if ( ! isSettingsError ) {
this.props.goToNextStep();
} else {
createNotice(
'error',
__( 'There was a problem updating your preferences.', 'woocommerce-admin' )
);
addNotice( {
status: 'error',
message: __( 'There was a problem updating your preferences.', 'woocommerce-admin' ),
} );
}
}
@ -217,11 +217,10 @@ export default compose(
return { getSettings, isSettingsError, isProfileItemsError, isSettingsRequesting };
} ),
withDispatch( dispatch => {
const { updateProfileItems, updateSettings } = dispatch( 'wc-api' );
const { createNotice } = dispatch( 'core/notices' );
const { addNotice, updateProfileItems, updateSettings } = dispatch( 'wc-api' );
return {
createNotice,
addNotice,
updateProfileItems,
updateSettings,
};

View File

@ -52,7 +52,7 @@ class StoreDetails extends Component {
return;
}
const { createNotice, goToNextStep, isError, updateSettings } = this.props;
const { addNotice, goToNextStep, isError, updateSettings } = this.props;
const { addressLine1, addressLine2, city, countryState, postCode } = this.state;
recordEvent( 'storeprofiler_store_details_continue', {
@ -72,10 +72,10 @@ class StoreDetails extends Component {
if ( ! isError ) {
goToNextStep();
} else {
createNotice(
'error',
__( 'There was a problem saving your store details.', 'woocommerce-admin' )
);
addNotice( {
status: 'error',
message: __( 'There was a problem saving your store details.', 'woocommerce-admin' ),
} );
}
}
@ -185,11 +185,11 @@ export default compose(
return { getSettings, isError, isRequesting, settings };
} ),
withDispatch( dispatch => {
const { createNotice } = dispatch( 'core/notices' );
const { addNotice } = dispatch( 'wc-api' );
const { updateSettings } = dispatch( 'wc-api' );
return {
createNotice,
addNotice,
updateSettings,
};
} )

View File

@ -40,7 +40,7 @@ class Theme extends Component {
}
async onChoose( theme ) {
const { createNotice, goToNextStep, isError, updateProfileItems } = this.props;
const { addNotice, goToNextStep, isError, updateProfileItems } = this.props;
recordEvent( 'storeprofiler_store_theme_choose', { theme } );
await updateProfileItems( { theme } );
@ -49,10 +49,10 @@ class Theme extends Component {
// @todo This should send profile information to woocommerce.com.
goToNextStep();
} else {
createNotice(
'error',
__( 'There was a problem selecting your store theme.', 'woocommerce-admin' )
);
addNotice( {
status: 'error',
message: __( 'There was a problem selecting your store theme.', 'woocommerce-admin' ),
} );
}
}
@ -206,11 +206,10 @@ export default compose(
return { isError };
} ),
withDispatch( dispatch => {
const { updateProfileItems } = dispatch( 'wc-api' );
const { createNotice } = dispatch( 'core/notices' );
const { addNotice, updateProfileItems } = dispatch( 'wc-api' );
return {
createNotice,
addNotice,
updateProfileItems,
};
} )

View File

@ -2,7 +2,6 @@
/**
* External dependencies
*/
import '@wordpress/notices';
import { render } from '@wordpress/element';
/**
@ -10,6 +9,7 @@ import { render } from '@wordpress/element';
*/
import './stylesheets/_embedded.scss';
import { EmbedLayout, PrimaryLayout as NoticeArea } from './layout';
import 'store';
import 'wc-api/wp-data-store';
const embeddedRoot = document.getElementById( 'woocommerce-embedded-root' );

View File

@ -2,7 +2,6 @@
/**
* External dependencies
*/
import '@wordpress/notices';
import { render } from '@wordpress/element';
/**
@ -10,6 +9,7 @@ import { render } from '@wordpress/element';
*/
import './stylesheets/_index.scss';
import { PageLayout } from './layout';
import 'store';
import 'wc-api/wp-data-store';
render( <PageLayout />, document.getElementById( 'root' ) );

View File

@ -6,25 +6,24 @@ import classnames from 'classnames';
import { Component } from '@wordpress/element';
import { compose } from '@wordpress/compose';
import PropTypes from 'prop-types';
import { SnackbarList } from '@wordpress/components';
import { withDispatch } from '@wordpress/data';
/**
* Internal dependencies
*/
import './style.scss';
import TransientNotice from './transient-notice';
import withSelect from 'wc-api/with-select';
class TransientNotices extends Component {
render() {
const { className, notices, onRemove } = this.props;
const classes = classnames(
'woocommerce-transient-notices',
'components-notices__snackbar',
className
);
const { className, notices } = this.props;
const classes = classnames( 'woocommerce-transient-notices', className );
return <SnackbarList notices={ notices } className={ classes } onRemove={ onRemove } />;
return (
<section className={ classes }>
{ notices && notices.map( ( notice, i ) => <TransientNotice key={ i } { ...notice } /> ) }
</section>
);
}
}
@ -41,11 +40,9 @@ TransientNotices.propTypes = {
export default compose(
withSelect( select => {
const notices = select( 'core/notices' ).getNotices();
const { getNotices } = select( 'wc-admin' );
const notices = getNotices();
return { notices };
} ),
withDispatch( dispatch => ( {
onRemove: dispatch( 'core/notices' ).removeNotice,
} ) )
} )
)( TransientNotices );

View File

@ -5,13 +5,34 @@
bottom: $gap-small;
left: 0;
z-index: 99999;
}
.components-snackbar-list__notice-container {
margin-left: $gap-small;
margin-right: $gap-small;
.woocommerce-transient-notice {
transform: translateX(calc(-100% - #{$gap}));
transition: all 300ms cubic-bezier(0.42, 0, 0.58, 1);
max-height: 300px; // Used to animate sliding down when multiple notices exist on exit.
@media screen and (prefers-reduced-motion: reduce) {
transition: none;
}
.components-snackbar {
margin: 0 auto;
&.slide-enter-active,
&.slide-enter-done {
transform: translateX(0%);
}
&.slide-exit-active {
transform: translateX(calc(-100% - #{$gap}));
}
&.slide-exit-done {
max-height: 0;
margin: 0;
padding: 0;
visibility: hidden;
}
.components-notice {
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
}
}

View File

@ -0,0 +1,104 @@
/** @format */
/**
* External dependencies
*/
import classnames from 'classnames';
import { Component } from '@wordpress/element';
import { CSSTransition } from 'react-transition-group';
import { noop } from 'lodash';
import { Notice } from '@wordpress/components';
import PropTypes from 'prop-types';
import { speak } from '@wordpress/a11y';
class TransientNotice extends Component {
constructor( props ) {
super( props );
this.state = {
visible: false,
timeout: null,
};
}
componentDidMount() {
const exitTime = this.props.exitTime;
const timeout = setTimeout(
() => {
this.setState( { visible: false } );
},
exitTime,
name,
exitTime
);
/* eslint-disable react/no-did-mount-set-state */
this.setState( { visible: true, timeout } );
/* eslint-enable react/no-did-mount-set-state */
speak( this.props.message );
}
componentWillUnmount() {
clearTimeout( this.state.timeout );
}
render() {
const { actions, className, isDismissible, message, onRemove, status } = this.props;
const classes = classnames( 'woocommerce-transient-notice', className );
return (
<CSSTransition in={ this.state.visible } timeout={ 300 } classNames="slide">
<div className={ classes }>
<Notice
status={ status }
isDismissible={ isDismissible }
onRemove={ onRemove }
actions={ actions }
>
{ message }
</Notice>
</div>
</CSSTransition>
);
}
}
TransientNotice.propTypes = {
/**
* Array of action objects.
* See https://wordpress.org/gutenberg/handbook/designers-developers/developers/components/notice/
*/
actions: PropTypes.array,
/**
* Additional class name to style the component.
*/
className: PropTypes.string,
/**
* Determines if the notice dimiss button should be shown.
* See https://wordpress.org/gutenberg/handbook/designers-developers/developers/components/notice/
*/
isDismissible: PropTypes.bool,
/**
* Function called when dismissing the notice.
* See https://wordpress.org/gutenberg/handbook/designers-developers/developers/components/notice/
*/
onRemove: PropTypes.func,
/**
* Type of notice to display.
* See https://wordpress.org/gutenberg/handbook/designers-developers/developers/components/notice/
*/
status: PropTypes.oneOf( [ 'success', 'error', 'warning' ] ),
/**
* Time in milliseconds until exit.
*/
exitTime: PropTypes.number,
};
TransientNotice.defaultProps = {
actions: [],
className: '',
exitTime: 7000,
isDismissible: false,
onRemove: noop,
status: 'warning',
};
export default TransientNotice;

View File

@ -0,0 +1,22 @@
/** @format */
/**
* External dependencies
*/
import { combineReducers, registerStore } from '@wordpress/data';
/**
* Internal dependencies
*/
import notices from './notices';
registerStore( 'wc-admin', {
reducer: combineReducers( {
...notices.reducers,
} ),
actions: {
...notices.actions,
},
selectors: {
...notices.selectors,
},
} );

View File

@ -0,0 +1,9 @@
/** @format */
const addNotice = notice => {
return { type: 'ADD_NOTICE', notice };
};
export default {
addNotice,
};

View File

@ -0,0 +1,13 @@
/** @format */
/**
* Internal dependencies
*/
import reducers from './reducers';
import actions from './actions';
import selectors from './selectors';
export default {
reducers,
actions,
selectors,
};

View File

@ -0,0 +1,15 @@
/** @format */
const DEFAULT_STATE = [];
const notices = ( state = DEFAULT_STATE, action ) => {
if ( action.type === 'ADD_NOTICE' ) {
return [ ...state, action.notice ];
}
return state;
};
export default {
notices,
};

View File

@ -0,0 +1,9 @@
/** @format */
const getNotices = state => {
return state.notices;
};
export default {
getNotices,
};

View File

@ -0,0 +1,7 @@
/** @format */
export const DEFAULT_STATE = {
notices: [],
};
export const testNotice = { message: 'Test notice' };

View File

@ -0,0 +1,55 @@
/** @format */
/**
* Internal dependencies
*/
import actions from '../actions';
import { DEFAULT_STATE, testNotice } from './fixtures';
import reducers from '../reducers';
import selectors from '../selectors';
describe( 'actions', () => {
test( 'should create an add notice action', () => {
const expectedAction = {
type: 'ADD_NOTICE',
notice: testNotice,
};
expect( actions.addNotice( testNotice ) ).toEqual( expectedAction );
} );
} );
describe( 'selectors', () => {
const notices = [ testNotice ];
const updatedState = { ...DEFAULT_STATE, ...{ notices } };
test( 'should return an emtpy initial state', () => {
expect( selectors.getNotices( DEFAULT_STATE ) ).toEqual( [] );
} );
test( 'should have an array length matching number of notices', () => {
expect( selectors.getNotices( updatedState ).length ).toEqual( 1 );
} );
test( 'should return the message content', () => {
expect( selectors.getNotices( updatedState )[ 0 ].message ).toEqual( 'Test notice' );
} );
} );
describe( 'reducers', () => {
test( 'should return an emtpy initial state', () => {
expect( reducers.notices( DEFAULT_STATE.notices, {} ) ).toEqual( [] );
} );
test( 'should return the added notice', () => {
expect(
reducers.notices( DEFAULT_STATE.notices, { type: 'ADD_NOTICE', notice: testNotice } )
).toEqual( [ testNotice ] );
} );
const initialNotices = [ { message: 'Initial notice' } ];
test( 'should return the initial notice and the added notice', () => {
expect(
reducers.notices( initialNotices, { type: 'ADD_NOTICE', notice: testNotice } )
).toEqual( [ ...initialNotices, testNotice ] );
} );
} );

View File

@ -22,15 +22,13 @@ $breakpoints: 320px, 400px, 600px, 782px, 960px, 1280px, 1440px;
@media (max-width: $breakpoint) {
@content;
}
}
@else {
} @else {
@if $size == $and-larger {
$approved-value: 2;
@media (min-width: $breakpoint + 1) {
@content;
}
}
@else {
} @else {
@each $breakpoint-end in $breakpoints {
$range: $breakpoint + '-' + $breakpoint-end;
@if $size == $range {
@ -50,8 +48,7 @@ $breakpoints: 320px, 400px, 600px, 782px, 960px, 1280px, 1440px;
}
@warn 'ERROR in breakpoint( #{ $size } ) : You can only use these sizes[ #{$sizes} ] using the following syntax [ <#{ nth( $breakpoints, 1 ) } >#{ nth( $breakpoints, 1 ) } #{ nth( $breakpoints, 1 ) }-#{ nth( $breakpoints, 2 ) } ]';
}
}
@else {
} @else {
$sizes: '';
@each $breakpoint in $breakpoints {
$sizes: $sizes + ' ' + $breakpoint;

View File

@ -37,7 +37,7 @@
}
}
// Gutenberg mixins. These are temporary until Gutenberg's mixins are exposed.
// Gutenberg Button variables. These are temporary until Gutenberg's variables are exposed.
@mixin button-style__focus-active() {
background-color: $white;
color: $dark-gray-900;
@ -48,31 +48,6 @@
outline-offset: -2px;
}
@mixin reduce-motion($property: '') {
@if $property == 'transition' {
@media (prefers-reduced-motion: reduce) {
transition-duration: 0s;
}
}
@else if $property == 'animation' {
@media (prefers-reduced-motion: reduce) {
animation-duration: 1ms;
}
}
@else {
@media (prefers-reduced-motion: reduce) {
transition-duration: 0s;
animation-duration: 1ms;
}
}
}
@mixin break-small() {
@media (min-width: #{ ($break-small) }) {
@content;
}
}
// Sets positions for children of grid elements
@mixin set-grid-item-position( $wrap-after, $number-of-items ) {
@for $i from 1 through $number-of-items {

View File

@ -19,20 +19,14 @@ $header-height: 56px;
// @todo Remove this spacing variable
$spacing: 16px;
// Gutenberg variables. These are temporary until Gutenberg's variables are exposed.
$default-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell,
'Helvetica Neue', sans-serif;
$default-font-size: 13px;
$default-line-height: 1.4;
$break-small: 600px;
// Gutenberg Button variables. These are temporary until Gutenberg's variables are exposed.
$border-width: 1px;
$default-font-size: 13px;
$blue-medium-focus: #007cba;
$light-gray-500: $core-grey-light-500;
$dark-gray-300: $core-grey-dark-300;
$dark-gray-700: $core-grey-dark-700;
$dark-gray-900: $core-grey-dark-900;
$alert-red: $error-red;
$radius-round-rectangle: 4px;
// WordPress defaults
$adminbar-height: 32px;

View File

@ -5,4 +5,3 @@ Import Gutenberg component SCSS so webpack's postcss process can handle theme-in
allows Woo themed components based on the config found in postcss.config.js
*/
@import 'gutenberg-components/button/style.scss';
@import 'gutenberg-components/snackbar/style.scss';

View File

@ -11,7 +11,7 @@ import { dispatch } from '@wordpress/data';
import { getResourceName } from '../utils';
const updateProductStock = operations => async ( product, newStock ) => {
const { createNotice } = dispatch( 'core/notices' );
const { addNotice } = dispatch( 'wc-admin' );
const oldStockQuantity = product.stock_quantity;
const resourceName = getResourceName( 'items-query-products-item', product.id );
@ -30,16 +30,16 @@ const updateProductStock = operations => async ( product, newStock ) => {
} );
const response = result[ 0 ][ resourceName ];
if ( response && response.data ) {
createNotice(
'success',
sprintf( __( '%s stock updated.', 'woocommerce-admin' ), product.name )
);
addNotice( {
status: 'success',
message: sprintf( __( '%s stock updated.', 'woocommerce-admin' ), product.name ),
} );
}
if ( response && response.error ) {
createNotice(
'error',
sprintf( __( '%s stock could not be updated.', 'woocommerce-admin' ), product.name )
);
addNotice( {
status: 'error',
message: sprintf( __( '%s stock could not be updated.', 'woocommerce-admin' ), product.name ),
} );
// Revert local changes if the operation failed in the server
operations.updateLocally( [ resourceName ], {
[ resourceName ]: { ...product, stock_quantity: oldStockQuantity },

View File

@ -3106,20 +3106,21 @@
"dev": true
},
"@wordpress/components": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@wordpress/components/-/components-8.0.0.tgz",
"integrity": "sha512-8Lo9VHcNME+0s8RGQ0FaTYbSw7UdoIPZYK8+OB+jZgwM88kbVW6SkgCM45QdxSLtaxkCYdWX1IF/DRJzI22WyQ==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@wordpress/components/-/components-7.4.0.tgz",
"integrity": "sha512-riVey0Z5835YdPZLWFSAs/4Hzo0nr7WA/393mRXwGuUtkqdk7ia++5emKfhyaCLYbinVBd6366xFFfiFxxcsCA==",
"requires": {
"@babel/runtime": "^7.4.4",
"@wordpress/a11y": "^2.4.0",
"@wordpress/compose": "^3.4.0",
"@wordpress/a11y": "^2.3.0",
"@wordpress/api-fetch": "^3.2.0",
"@wordpress/compose": "^3.3.0",
"@wordpress/dom": "^2.3.0",
"@wordpress/element": "^2.5.0",
"@wordpress/hooks": "^2.4.0",
"@wordpress/i18n": "^3.5.0",
"@wordpress/is-shallow-equal": "^1.4.0",
"@wordpress/keycodes": "^2.4.0",
"@wordpress/rich-text": "^3.4.0",
"@wordpress/element": "^2.4.0",
"@wordpress/hooks": "^2.3.0",
"@wordpress/i18n": "^3.4.0",
"@wordpress/is-shallow-equal": "^1.3.0",
"@wordpress/keycodes": "^2.3.0",
"@wordpress/rich-text": "^3.3.0",
"@wordpress/url": "^2.6.0",
"classnames": "^2.2.5",
"clipboard": "^2.0.1",
@ -3132,53 +3133,34 @@
"re-resizable": "^4.7.1",
"react-click-outside": "^3.0.0",
"react-dates": "^17.1.1",
"react-spring": "^8.0.20",
"rememo": "^3.0.0",
"tinycolor2": "^1.4.1",
"uuid": "^3.3.2"
},
"dependencies": {
"@wordpress/element": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@wordpress/element/-/element-2.5.0.tgz",
"integrity": "sha512-gqtNcBkVtF//OHKJQAn4c7nwfDqsIy0UMq7ed9l6lpXOKS5ic8cw7BgNtdx4PiicV46ev9s/yHieFKWZNFpfIw==",
"requires": {
"@babel/runtime": "^7.4.4",
"@wordpress/escape-html": "^1.4.0",
"lodash": "^4.17.11",
"react": "^16.8.4",
"react-dom": "^16.8.4"
}
},
"@wordpress/hooks": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@wordpress/hooks/-/hooks-2.4.0.tgz",
"integrity": "sha512-z3+8Yq4IQ3DOvUF4VsXOfntdyk1fJ8RZBYlZTW8WfmHV7VKTDbX3LfHXmC2VCjXhVkeWQVKozi2weoEYopfGKA==",
"requires": {
"@babel/runtime": "^7.4.4"
}
},
"@wordpress/i18n": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-3.5.0.tgz",
"integrity": "sha512-QAYFsHe/raG0MPUX32gCmuSM6UN/5gWCVSFWxOVSuXVuzPP5WnL78CgpuXtUresDZXTJm3FrFcB9IKvh93e1DQ==",
"requires": {
"@babel/runtime": "^7.4.4",
"gettext-parser": "^1.3.1",
"lodash": "^4.17.11",
"memize": "^1.0.5",
"sprintf-js": "^1.1.1",
"tannin": "^1.0.1"
}
},
"@wordpress/keycodes": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-2.4.0.tgz",
"integrity": "sha512-qGRBKcDroYzUffAGMzotyos2k+FA89IjYYFjWlUrDp4TVaadCHK1ESPcmX6Y87ExgcsJKXDkNVZfsCPvh7V7Kw==",
"@wordpress/api-fetch": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-3.3.0.tgz",
"integrity": "sha512-EddkSzj2csdDWhIZueBthue8er5akGDBAnOtUQ5d8cdOQd1RrQbAgHmpKZtNHD8qXbfS40Ay1K42w7Si0uOksw==",
"requires": {
"@babel/runtime": "^7.4.4",
"@wordpress/i18n": "^3.5.0",
"lodash": "^4.17.11"
"@wordpress/url": "^2.6.0"
},
"dependencies": {
"@wordpress/i18n": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-3.5.0.tgz",
"integrity": "sha512-QAYFsHe/raG0MPUX32gCmuSM6UN/5gWCVSFWxOVSuXVuzPP5WnL78CgpuXtUresDZXTJm3FrFcB9IKvh93e1DQ==",
"requires": {
"@babel/runtime": "^7.4.4",
"gettext-parser": "^1.3.1",
"lodash": "^4.17.11",
"memize": "^1.0.5",
"sprintf-js": "^1.1.1",
"tannin": "^1.0.1"
}
}
}
}
}
@ -3394,50 +3376,6 @@
"lodash": "^4.17.11"
}
},
"@wordpress/notices": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@wordpress/notices/-/notices-1.5.0.tgz",
"integrity": "sha512-aKCVDYPVVzYBm2cW4pQzAsshLOZx0f9AZiBZOV+AD9D+eSAscF0SBcvmbduFFQ4KhIgj76IXz5cxXIrafFXaDQ==",
"requires": {
"@babel/runtime": "^7.4.4",
"@wordpress/a11y": "^2.4.0",
"@wordpress/data": "^4.6.0",
"lodash": "^4.17.11"
},
"dependencies": {
"@wordpress/data": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/@wordpress/data/-/data-4.6.0.tgz",
"integrity": "sha512-42BNtWtN0ppnzbnxz0tA72KNtuEKjrIRr4PbVCw3JVrHN2Nfhbo9SiCUutReKAXGQaT4LPnO7gAGmIsdC/mBUw==",
"requires": {
"@babel/runtime": "^7.4.4",
"@wordpress/compose": "^3.4.0",
"@wordpress/deprecated": "^2.4.0",
"@wordpress/element": "^2.5.0",
"@wordpress/is-shallow-equal": "^1.4.0",
"@wordpress/priority-queue": "^1.2.0",
"@wordpress/redux-routine": "^3.4.0",
"equivalent-key-map": "^0.2.2",
"is-promise": "^2.1.0",
"lodash": "^4.17.11",
"redux": "^4.0.0",
"turbo-combine-reducers": "^1.0.2"
}
},
"@wordpress/element": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@wordpress/element/-/element-2.5.0.tgz",
"integrity": "sha512-gqtNcBkVtF//OHKJQAn4c7nwfDqsIy0UMq7ed9l6lpXOKS5ic8cw7BgNtdx4PiicV46ev9s/yHieFKWZNFpfIw==",
"requires": {
"@babel/runtime": "^7.4.4",
"@wordpress/escape-html": "^1.4.0",
"lodash": "^4.17.11",
"react": "^16.8.4",
"react-dom": "^16.8.4"
}
}
}
},
"@wordpress/npm-package-json-lint-config": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@wordpress/npm-package-json-lint-config/-/npm-package-json-lint-config-1.3.0.tgz",
@ -13780,66 +13718,6 @@
"requires": {
"@wordpress/components": "^7.3.1",
"@wordpress/element": "^2.3.0"
},
"dependencies": {
"@wordpress/api-fetch": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-3.3.0.tgz",
"integrity": "sha512-EddkSzj2csdDWhIZueBthue8er5akGDBAnOtUQ5d8cdOQd1RrQbAgHmpKZtNHD8qXbfS40Ay1K42w7Si0uOksw==",
"requires": {
"@babel/runtime": "^7.4.4",
"@wordpress/i18n": "^3.5.0",
"@wordpress/url": "^2.6.0"
},
"dependencies": {
"@wordpress/i18n": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-3.5.0.tgz",
"integrity": "sha512-QAYFsHe/raG0MPUX32gCmuSM6UN/5gWCVSFWxOVSuXVuzPP5WnL78CgpuXtUresDZXTJm3FrFcB9IKvh93e1DQ==",
"requires": {
"@babel/runtime": "^7.4.4",
"gettext-parser": "^1.3.1",
"lodash": "^4.17.11",
"memize": "^1.0.5",
"sprintf-js": "^1.1.1",
"tannin": "^1.0.1"
}
}
}
},
"@wordpress/components": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@wordpress/components/-/components-7.4.0.tgz",
"integrity": "sha512-riVey0Z5835YdPZLWFSAs/4Hzo0nr7WA/393mRXwGuUtkqdk7ia++5emKfhyaCLYbinVBd6366xFFfiFxxcsCA==",
"requires": {
"@babel/runtime": "^7.4.4",
"@wordpress/a11y": "^2.3.0",
"@wordpress/api-fetch": "^3.2.0",
"@wordpress/compose": "^3.3.0",
"@wordpress/dom": "^2.3.0",
"@wordpress/element": "^2.4.0",
"@wordpress/hooks": "^2.3.0",
"@wordpress/i18n": "^3.4.0",
"@wordpress/is-shallow-equal": "^1.3.0",
"@wordpress/keycodes": "^2.3.0",
"@wordpress/rich-text": "^3.3.0",
"@wordpress/url": "^2.6.0",
"classnames": "^2.2.5",
"clipboard": "^2.0.1",
"diff": "^3.5.0",
"dom-scroll-into-view": "^1.2.1",
"lodash": "^4.17.11",
"memize": "^1.0.5",
"moment": "^2.22.1",
"mousetrap": "^1.6.2",
"re-resizable": "^4.7.1",
"react-click-outside": "^3.0.0",
"react-dates": "^17.1.1",
"rememo": "^3.0.0",
"tinycolor2": "^1.4.1",
"uuid": "^3.3.2"
}
}
}
},
"nice-try": {
@ -18675,15 +18553,6 @@
"tiny-warning": "^1.0.0"
}
},
"react-spring": {
"version": "8.0.27",
"resolved": "https://registry.npmjs.org/react-spring/-/react-spring-8.0.27.tgz",
"integrity": "sha512-nDpWBe3ZVezukNRandTeLSPcwwTMjNVu1IDq9qA/AMiUqHuRN4BeSWvKr3eIxxg1vtiYiOLy4FqdfCP5IoP77g==",
"requires": {
"@babel/runtime": "^7.3.1",
"prop-types": "^15.5.8"
}
},
"react-test-renderer": {
"version": "16.8.6",
"resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.8.6.tgz",

View File

@ -67,7 +67,7 @@
"dependencies": {
"@fresh-data/framework": "0.6.1",
"@wordpress/api-fetch": "2.2.8",
"@wordpress/components": "8.0.0",
"@wordpress/components": "7.4.0",
"@wordpress/data": "4.5.0",
"@wordpress/date": "3.3.0",
"@wordpress/element": "2.4.0",
@ -75,7 +75,6 @@
"@wordpress/html-entities": "2.3.0",
"@wordpress/i18n": "3.4.0",
"@wordpress/keycodes": "2.3.0",
"@wordpress/notices": "1.5.0",
"@wordpress/scripts": "3.2.1",
"@wordpress/viewport": "2.4.0",
"browser-filesaver": "1.1.1",

View File

@ -43,7 +43,6 @@ exports[`SearchListControl should render a search box and list of hierarchical o
className="woocommerce-search-list__list components-menu-group"
>
<div
aria-hidden="true"
className="components-menu-group__label"
id="components-menu-group-label-8"
>
@ -51,7 +50,9 @@ exports[`SearchListControl should render a search box and list of hierarchical o
</div>
<div
aria-labelledby="components-menu-group-label-8"
role="group"
aria-orientation="vertical"
onKeyDown={[Function]}
role="menu"
>
<button
aria-checked={false}
@ -344,7 +345,6 @@ exports[`SearchListControl should render a search box and list of options 1`] =
className="woocommerce-search-list__list components-menu-group"
>
<div
aria-hidden="true"
className="components-menu-group__label"
id="components-menu-group-label-0"
>
@ -352,7 +352,9 @@ exports[`SearchListControl should render a search box and list of options 1`] =
</div>
<div
aria-labelledby="components-menu-group-label-0"
role="group"
aria-orientation="vertical"
onKeyDown={[Function]}
role="menu"
>
<button
aria-checked={false}
@ -630,7 +632,6 @@ exports[`SearchListControl should render a search box and list of options with a
className="woocommerce-search-list__list components-menu-group"
>
<div
aria-hidden="true"
className="components-menu-group__label"
id="components-menu-group-label-1"
>
@ -638,7 +639,9 @@ exports[`SearchListControl should render a search box and list of options with a
</div>
<div
aria-labelledby="components-menu-group-label-1"
role="group"
aria-orientation="vertical"
onKeyDown={[Function]}
role="menu"
>
<button
aria-checked={false}
@ -916,7 +919,6 @@ exports[`SearchListControl should render a search box and list of options, with
className="woocommerce-search-list__list components-menu-group"
>
<div
aria-hidden="true"
className="components-menu-group__label"
id="components-menu-group-label-7"
>
@ -924,7 +926,9 @@ exports[`SearchListControl should render a search box and list of options, with
</div>
<div
aria-labelledby="components-menu-group-label-7"
role="group"
aria-orientation="vertical"
onKeyDown={[Function]}
role="menu"
>
<div>
Apricots
@ -998,7 +1002,6 @@ exports[`SearchListControl should render a search box and list of options, with
className="woocommerce-search-list__list components-menu-group"
>
<div
aria-hidden="true"
className="components-menu-group__label"
id="components-menu-group-label-6"
>
@ -1006,7 +1009,9 @@ exports[`SearchListControl should render a search box and list of options, with
</div>
<div
aria-labelledby="components-menu-group-label-6"
role="group"
aria-orientation="vertical"
onKeyDown={[Function]}
role="menu"
>
<button
aria-checked={false}
@ -1428,7 +1433,6 @@ exports[`SearchListControl should render a search box with a search term, and on
className="woocommerce-search-list__list components-menu-group"
>
<div
aria-hidden="true"
className="components-menu-group__label"
id="components-menu-group-label-4"
>
@ -1436,7 +1440,9 @@ exports[`SearchListControl should render a search box with a search term, and on
</div>
<div
aria-labelledby="components-menu-group-label-4"
role="group"
aria-orientation="vertical"
onKeyDown={[Function]}
role="menu"
>
<button
aria-checked={false}
@ -1563,7 +1569,6 @@ exports[`SearchListControl should render a search box with a search term, and on
className="woocommerce-search-list__list components-menu-group"
>
<div
aria-hidden="true"
className="components-menu-group__label"
id="components-menu-group-label-5"
>
@ -1571,7 +1576,9 @@ exports[`SearchListControl should render a search box with a search term, and on
</div>
<div
aria-labelledby="components-menu-group-label-5"
role="group"
aria-orientation="vertical"
onKeyDown={[Function]}
role="menu"
>
<button
aria-checked={false}
@ -1750,7 +1757,6 @@ exports[`SearchListControl should render a search box, a list of options, and 1
className="woocommerce-search-list__list components-menu-group"
>
<div
aria-hidden="true"
className="components-menu-group__label"
id="components-menu-group-label-2"
>
@ -1758,7 +1764,9 @@ exports[`SearchListControl should render a search box, a list of options, and 1
</div>
<div
aria-labelledby="components-menu-group-label-2"
role="group"
aria-orientation="vertical"
onKeyDown={[Function]}
role="menu"
>
<button
aria-checked={false}
@ -2134,7 +2142,6 @@ exports[`SearchListControl should render a search box, a list of options, and 2
className="woocommerce-search-list__list components-menu-group"
>
<div
aria-hidden="true"
className="components-menu-group__label"
id="components-menu-group-label-3"
>
@ -2142,7 +2149,9 @@ exports[`SearchListControl should render a search box, a list of options, and 2
</div>
<div
aria-labelledby="components-menu-group-label-3"
role="group"
aria-orientation="vertical"
onKeyDown={[Function]}
role="menu"
>
<button
aria-checked={false}

View File

@ -26,6 +26,8 @@ const WC_ADMIN_CONFIG = require( path.join( __dirname, 'config', WC_ADMIN_PHASE
const externals = {
'@wordpress/api-fetch': { this: [ 'wp', 'apiFetch' ] },
'@wordpress/blocks': { this: [ 'wp', 'blocks' ] },
'@wordpress/components': { this: [ 'wp', 'components' ] },
'@wordpress/compose': { this: [ 'wp', 'compose' ] },
'@wordpress/data': { this: [ 'wp', 'data' ] },
'@wordpress/editor': { this: [ 'wp', 'editor' ] },
'@wordpress/element': { this: [ 'wp', 'element' ] },