Add loading indicators, error state, and EmptyContent to the revenue report. (#347, woocommerce/woocommerce-admin#348)
* Add loading indiciators for the revenue report. * Improve accessibility, and fix up some documentation comments. * Fix top border on mobile * Add EmptyContent Component and revenue error/empty states. (https://github.com/woocommerce/woocommerce-admin/pull/348) * Add EmptyContent Component and revenue error/empty states. * Move relative image handling to ImageAsset, combine secondary and primary action rendering, add some missing isRequired proptypes, add empty error handling. * Handle PR Feedback: Clean up button css, set a default for illustration, fix deprecation typo, some code cleanup.
This commit is contained in:
parent
9183756a70
commit
f5479e1c18
|
@ -11,6 +11,7 @@ import { find } from 'lodash';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
import ExampleReport from './example';
|
||||
import Header from 'layout/header';
|
||||
import OrdersReport from './orders';
|
||||
|
|
|
@ -16,10 +16,14 @@ import { withSelect } from '@wordpress/data';
|
|||
import {
|
||||
Card,
|
||||
Chart,
|
||||
ChartPlaceholder,
|
||||
EmptyContent,
|
||||
ReportFilters,
|
||||
SummaryList,
|
||||
SummaryListPlaceholder,
|
||||
SummaryNumber,
|
||||
TableCard,
|
||||
TablePlaceholder,
|
||||
} from '@woocommerce/components';
|
||||
import { downloadCSVFile, generateCSVDataFromTable, generateCSVFileName } from 'lib/csv';
|
||||
import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency';
|
||||
|
@ -328,7 +332,11 @@ export class RevenueReport extends Component {
|
|||
|
||||
const headers = this.getHeadersContent();
|
||||
|
||||
const tableQuery = { ...query, orderby: query.orderby || 'date_start', order: query.order || 'asc' };
|
||||
const tableQuery = {
|
||||
...query,
|
||||
orderby: query.orderby || 'date_start',
|
||||
order: query.order || 'asc',
|
||||
};
|
||||
return (
|
||||
<TableCard
|
||||
title={ __( 'Revenue', 'wc-admin' ) }
|
||||
|
@ -344,30 +352,63 @@ export class RevenueReport extends Component {
|
|||
);
|
||||
}
|
||||
|
||||
renderPlaceholder() {
|
||||
const { path, query } = this.props;
|
||||
const headers = this.getHeadersContent();
|
||||
const charts = this.getCharts();
|
||||
return (
|
||||
<Fragment>
|
||||
<ReportFilters query={ query } path={ path } />
|
||||
|
||||
<span className="screen-reader-text">
|
||||
{ __( 'Your requested data is loading', 'wc-admin' ) }
|
||||
</span>
|
||||
|
||||
<SummaryListPlaceholder numberOfItems={ charts.length } />
|
||||
<ChartPlaceholder />
|
||||
<Card
|
||||
title={ __( 'Revenue', 'wc-admin' ) }
|
||||
className="woocommerce-analytics__table-placeholder"
|
||||
>
|
||||
<TablePlaceholder caption={ __( 'Revenue', 'wc-admin' ) } headers={ headers } />
|
||||
</Card>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { path, query, primaryData, secondaryData } = this.props;
|
||||
|
||||
// TODO The loading, error, and empty messages below are all temporary.
|
||||
// So we need to use an actual EmptyState components and add in a loading indicator.
|
||||
const tempMessage = message => {
|
||||
return (
|
||||
<div>
|
||||
<ReportFilters query={ query } path={ path } />
|
||||
<p>{ message }</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
if ( isReportDataEmpty( primaryData ) ) {
|
||||
return tempMessage( 'Empty Data' );
|
||||
}
|
||||
|
||||
if ( primaryData.isRequesting || secondaryData.isRequesting ) {
|
||||
return tempMessage( 'Loading...' );
|
||||
return this.renderPlaceholder();
|
||||
}
|
||||
|
||||
if ( primaryData.isError || secondaryData.isError ) {
|
||||
return tempMessage( 'Error' );
|
||||
if ( isReportDataEmpty( primaryData ) || primaryData.isError || secondaryData.isError ) {
|
||||
let title, actionLabel, actionURL, actionCallback;
|
||||
if ( primaryData.isError || secondaryData.isError ) {
|
||||
title = __( 'There was an error getting your stats. Please try again.', 'wc-admin' );
|
||||
actionLabel = __( 'Reload', 'wc-admin' );
|
||||
actionCallback = () => {
|
||||
// TODO Add tracking for how often an error is displayed, and the reload action is clicked.
|
||||
window.location.reload();
|
||||
};
|
||||
} else {
|
||||
title = __( 'No results could be found for this date range.', 'wc-admin' );
|
||||
actionLabel = __( 'View Orders', 'wc-admin' );
|
||||
actionURL = getAdminLink( 'edit.php?post_type=shop_order' );
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<ReportFilters query={ query } path={ path } />
|
||||
<EmptyContent
|
||||
title={ title }
|
||||
actionLabel={ actionLabel }
|
||||
actionURL={ actionURL }
|
||||
actionCallback={ actionCallback }
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/** @format */
|
||||
.woocommerce-analytics__table-placeholder {
|
||||
.woocommerce-card__body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.woocommerce-table__table {
|
||||
margin-bottom: 0;
|
||||
|
||||
tr:last-child {
|
||||
border-bottom-style: none;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/** @format */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Component } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* `ChartPlaceholder` displays a large loading indiciator for use in place of a `Chart` while data is loading.
|
||||
*/
|
||||
class ChartPlaceholder extends Component {
|
||||
render() {
|
||||
return <div className="woocommerce-chart is-placeholder" aria-hidden="true" />;
|
||||
}
|
||||
}
|
||||
|
||||
export default ChartPlaceholder;
|
|
@ -123,6 +123,17 @@
|
|||
stroke-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-placeholder {
|
||||
@include placeholder();
|
||||
display: inline-block;
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-bottom: $gap;
|
||||
border: 1px solid $core-grey-light-700;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-chart__container {
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/** @format */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Button } from '@wordpress/components';
|
||||
import { Component } from '@wordpress/element';
|
||||
import classnames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
import { H } from 'layout/section';
|
||||
import ImageAsset from 'components/image-asset';
|
||||
|
||||
/**
|
||||
* A component to be used when there is no data to show.
|
||||
* It can be used as an opportunity to provide explanation or guidance to help a user progress.
|
||||
*/
|
||||
class EmptyContent extends Component {
|
||||
renderIllustration() {
|
||||
const { illustrationWidth, illustrationHeight, illustration } = this.props;
|
||||
return (
|
||||
<ImageAsset
|
||||
alt=""
|
||||
src={ illustration }
|
||||
width={ illustrationWidth }
|
||||
height={ illustrationHeight }
|
||||
className="woocommerce-empty-content__illustration"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderActionButtons( type ) {
|
||||
const actionLabel =
|
||||
'secondary' === type ? this.props.secondaryActionLabel : this.props.actionLabel;
|
||||
const actionURL = 'secondary' === type ? this.props.secondaryActionURL : this.props.actionURL;
|
||||
const actionCallback =
|
||||
'secondary' === type ? this.props.secondaryActionCallback : this.props.actionCallback;
|
||||
|
||||
const isPrimary = 'secondary' === type ? false : true;
|
||||
|
||||
if ( actionURL && actionCallback ) {
|
||||
return (
|
||||
<Button
|
||||
className="woocommerce-empty-content__action"
|
||||
isPrimary={ isPrimary }
|
||||
onClick={ actionCallback }
|
||||
href={ actionURL }
|
||||
>
|
||||
{ actionLabel }
|
||||
</Button>
|
||||
);
|
||||
} else if ( actionURL ) {
|
||||
return (
|
||||
<Button
|
||||
className="woocommerce-empty-content__action"
|
||||
isPrimary={ isPrimary }
|
||||
href={ actionURL }
|
||||
>
|
||||
{ actionLabel }
|
||||
</Button>
|
||||
);
|
||||
} else if ( actionCallback ) {
|
||||
return (
|
||||
<Button
|
||||
className="woocommerce-empty-content__action"
|
||||
isPrimary={ isPrimary }
|
||||
onClick={ actionCallback }
|
||||
>
|
||||
{ actionLabel }
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
renderActions() {
|
||||
const { actionLabel, secondaryActionLabel } = this.props;
|
||||
return (
|
||||
<div className="woocommerce-empty-content__actions">
|
||||
{ actionLabel && this.renderActionButtons( 'primary' ) }
|
||||
{ secondaryActionLabel && this.renderActionButtons( 'secondary' ) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { title, message, illustration } = this.props;
|
||||
return (
|
||||
<div className={ classnames( 'woocommerce-empty-content', this.props.className ) }>
|
||||
{ illustration && this.renderIllustration() }
|
||||
{ title ? <H className="woocommerce-empty-content__title">{ title }</H> : null }
|
||||
{ message ? <p className="woocommerce-empty-content__message">{ message }</p> : null }
|
||||
|
||||
{ this.renderActions() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EmptyContent.propTypes = {
|
||||
/**
|
||||
* The title to be displayed.
|
||||
*/
|
||||
title: PropTypes.string.isRequired,
|
||||
/**
|
||||
* An additional message to be displayed.
|
||||
*/
|
||||
message: PropTypes.string,
|
||||
/**
|
||||
* The url string of an image path. Prefix with `/` to load an image relative to the plugin directory.
|
||||
*/
|
||||
illustration: PropTypes.string,
|
||||
/**
|
||||
* Height to use for the illustration.
|
||||
*/
|
||||
illustrationHeight: PropTypes.number,
|
||||
/**
|
||||
* Width to use for the illustration.
|
||||
*/
|
||||
illustrationWidth: PropTypes.number,
|
||||
/**
|
||||
* Label to be used for the primary action button.
|
||||
*/
|
||||
actionLabel: PropTypes.string.isRequired,
|
||||
/**
|
||||
* URL to be used for the primary action button.
|
||||
*/
|
||||
actionURL: PropTypes.string,
|
||||
/**
|
||||
* Callback to be used for the primary action button.
|
||||
*/
|
||||
actionCallback: PropTypes.func,
|
||||
/**
|
||||
* Label to be used for the secondary action button.
|
||||
*/
|
||||
secondaryActionLabel: PropTypes.string,
|
||||
/**
|
||||
* URL to be used for the secondary action button.
|
||||
*/
|
||||
secondaryActionURL: PropTypes.string,
|
||||
/**
|
||||
* Callback to be used for the secondary action button.
|
||||
*/
|
||||
secondaryActionCallback: PropTypes.func,
|
||||
/**
|
||||
* Additional CSS classes.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
EmptyContent.defaultProps = {
|
||||
illustration: '/empty-content.svg',
|
||||
illustrationHeight: 400,
|
||||
illustrationWidth: 400,
|
||||
};
|
||||
|
||||
export default EmptyContent;
|
|
@ -0,0 +1,11 @@
|
|||
/** @format */
|
||||
|
||||
.woocommerce-empty-content {
|
||||
text-align: center;
|
||||
|
||||
.woocommerce-empty-content__actions {
|
||||
.components-button + .components-button {
|
||||
margin-left: $gap;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/** @format */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Component } from '@wordpress/element';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* A component that loads an image, allowing images to be loaded relative to the main asset/plugin folder.
|
||||
* Props are passed through to `<img />`
|
||||
*/
|
||||
class ImageAsset extends Component {
|
||||
render() {
|
||||
const { src, alt, ...restOfProps } = this.props;
|
||||
let illustrationSrc = src;
|
||||
|
||||
if ( illustrationSrc.indexOf( '/' ) === 0 ) {
|
||||
illustrationSrc = illustrationSrc.substring( 1 );
|
||||
illustrationSrc = wcSettings.wcAdminAssetUrl + illustrationSrc;
|
||||
}
|
||||
|
||||
return <img src={ illustrationSrc } alt={ alt || '' } { ...restOfProps } />;
|
||||
}
|
||||
}
|
||||
|
||||
ImageAsset.propTypes = {
|
||||
/**
|
||||
* Image location to pass through to `<img />`.
|
||||
*/
|
||||
src: PropTypes.string.isRequired,
|
||||
/**
|
||||
* Alt text to pass through to `<img />`.
|
||||
*/
|
||||
alt: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default ImageAsset;
|
|
@ -11,15 +11,18 @@ export { default as AnimationSlider } from './animation-slider';
|
|||
export { default as Card } from './card';
|
||||
export { default as Chart } from './chart';
|
||||
export { default as ChartLegend } from './chart/legend';
|
||||
export { default as ChartPlaceholder } from './chart/placeholder';
|
||||
export { default as Count } from './count';
|
||||
export { default as D3Chart } from './chart/charts';
|
||||
export { default as DatePicker } from './filters/date';
|
||||
export { default as DateRange } from './calendar';
|
||||
export { default as DropdownButton } from './dropdown-button';
|
||||
export { default as EllipsisMenu } from './ellipsis-menu';
|
||||
export { default as EmptyContent } from './empty-content';
|
||||
export { default as Flag } from './flag';
|
||||
export { default as FilterPicker } from './filters/filter';
|
||||
export { default as Gravatar } from './gravatar';
|
||||
export { default as ImageAsset } from './image-asset';
|
||||
export { default as Link } from './link';
|
||||
export { default as MenuItem } from './ellipsis-menu/menu-item';
|
||||
export { default as MenuTitle } from './ellipsis-menu/menu-title';
|
||||
|
@ -34,6 +37,7 @@ export { default as Search } from './search';
|
|||
export { default as SegmentedSelection } from './segmented-selection';
|
||||
export { default as SplitButton } from './split-button';
|
||||
export { default as SummaryList } from './summary';
|
||||
export { default as SummaryListPlaceholder } from './summary/placeholder';
|
||||
export { default as SummaryNumber } from './summary/item';
|
||||
export { default as Table } from './table/table';
|
||||
export { default as TableCard } from './table';
|
||||
|
|
|
@ -10,7 +10,7 @@ import { isUndefined } from 'lodash';
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
* Internal dependencies
|
||||
*/
|
||||
import Link from 'components/link';
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/** @format */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Component } from '@wordpress/element';
|
||||
import classnames from 'classnames';
|
||||
import { range } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { isMobileViewport, isTabletViewport } from 'lib/ui';
|
||||
|
||||
/**
|
||||
* `SummaryListPlaceholder` behaves like `SummaryList` but displays placeholder summary items instead of data.
|
||||
* This can be used while loading data.
|
||||
*/
|
||||
class SummaryListPlaceholder extends Component {
|
||||
render() {
|
||||
const isDropdownBreakpoint = isTabletViewport() || isMobileViewport();
|
||||
const numberOfItems = isDropdownBreakpoint ? 1 : this.props.numberOfItems;
|
||||
|
||||
const hasItemsClass = numberOfItems < 10 ? `has-${ numberOfItems }-items` : 'has-10-items';
|
||||
const classes = classnames( 'woocommerce-summary', {
|
||||
[ hasItemsClass ]: ! isDropdownBreakpoint,
|
||||
'is-placeholder': true,
|
||||
} );
|
||||
|
||||
const rows = range( numberOfItems ).map( i => {
|
||||
return (
|
||||
<li className="woocommerce-summary__item-container is-placeholder" key={ i }>
|
||||
<span className="woocommerce-summary__item">
|
||||
<span className="woocommerce-summary__item-label" />
|
||||
<span className="woocommerce-summary__item-data">
|
||||
<span className="woocommerce-summary__item-value" />
|
||||
<div className="woocommerce-summary__item-delta">
|
||||
<span className="woocommerce-summary__item-delta-value" />
|
||||
</div>
|
||||
</span>
|
||||
<span className="woocommerce-summary__item-prev-label" />
|
||||
<span className="woocommerce-summary__item-prev-value" />
|
||||
</span>
|
||||
</li>
|
||||
);
|
||||
} );
|
||||
|
||||
return (
|
||||
<ul className={ classes } aria-hidden="true">
|
||||
{ rows }
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SummaryListPlaceholder.propTypes = {
|
||||
/**
|
||||
* An integer with the number of summary items to display.
|
||||
*/
|
||||
numberOfItems: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
SummaryListPlaceholder.defaultProps = {
|
||||
numberOfRows: 5,
|
||||
};
|
||||
|
||||
export default SummaryListPlaceholder;
|
|
@ -46,6 +46,16 @@ $inner-border: $core-grey-light-500;
|
|||
background-color: $core-grey-light-300;
|
||||
box-shadow: inset -1px -1px 0 $outer-border;
|
||||
|
||||
@include breakpoint( '<782px' ) {
|
||||
&.is-placeholder {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.woocommerce-summary__item-container.is-placeholder {
|
||||
border-top: 1px solid $outer-border;
|
||||
}
|
||||
}
|
||||
|
||||
// Specificity
|
||||
.components-popover.components-popover {
|
||||
// !important to override element-level styles
|
||||
|
@ -214,6 +224,36 @@ $inner-border: $core-grey-light-500;
|
|||
border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-placeholder {
|
||||
.woocommerce-summary__item-label {
|
||||
@include placeholder();
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
max-width: 110px;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.woocommerce-summary__item-data {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.woocommerce-summary__item-value,
|
||||
.woocommerce-summary__item-prev-value {
|
||||
@include placeholder();
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
max-width: 140px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.woocommerce-summary__item-delta-value {
|
||||
@include placeholder();
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-summary__item {
|
||||
|
|
|
@ -11,6 +11,9 @@ import PropTypes from 'prop-types';
|
|||
*/
|
||||
import Table from './table';
|
||||
|
||||
/**
|
||||
* `TablePlaceholder` behaves like `Table` but displays placeholder boxes instead of data. This can be used while loading.
|
||||
*/
|
||||
class TablePlaceholder extends Component {
|
||||
render() {
|
||||
const { caption, headers, numberOfRows } = this.props;
|
||||
|
@ -32,7 +35,13 @@ class TablePlaceholder extends Component {
|
|||
}
|
||||
|
||||
TablePlaceholder.propTypes = {
|
||||
/**
|
||||
* A label for the content in this table.
|
||||
*/
|
||||
caption: PropTypes.string.isRequired,
|
||||
/**
|
||||
* An array of column headers (see `Table` props).
|
||||
*/
|
||||
headers: PropTypes.arrayOf(
|
||||
PropTypes.shape( {
|
||||
defaultSort: PropTypes.bool,
|
||||
|
@ -42,6 +51,9 @@ TablePlaceholder.propTypes = {
|
|||
required: PropTypes.bool,
|
||||
} )
|
||||
),
|
||||
/**
|
||||
* An integer with the number of rows to display.
|
||||
*/
|
||||
numberOfRows: PropTypes.number,
|
||||
};
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ describe( 'isReportDataEmpty()', () => {
|
|||
describe( 'getAllReportData()', () => {
|
||||
const select = jest.fn().mockReturnValue( {} );
|
||||
const response = {
|
||||
isEmpty: false,
|
||||
isError: false,
|
||||
isRequesting: false,
|
||||
data: {
|
||||
|
@ -208,4 +209,22 @@ describe( 'getAllReportData()', () => {
|
|||
const result = getAllReportData( 'revenue', {}, select );
|
||||
expect( result ).toEqual( { ...response, isError: true } );
|
||||
} );
|
||||
|
||||
it( 'returns empty state if a query returns no data', () => {
|
||||
setIsReportStatsRequesting( () => {
|
||||
return false;
|
||||
} );
|
||||
setIsReportStatsError( () => {
|
||||
return false;
|
||||
} );
|
||||
setGetReportStats( () => {
|
||||
return {
|
||||
totalResults: undefined,
|
||||
data: {},
|
||||
};
|
||||
} );
|
||||
|
||||
const result = getAllReportData( 'revenue', {}, select );
|
||||
expect( result ).toEqual( { ...response, isEmpty: true } );
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -45,6 +45,7 @@ export function getAllReportData( endpoint, query, select ) {
|
|||
const { getReportStats, isReportStatsRequesting, isReportStatsError } = select( 'wc-admin' );
|
||||
|
||||
const response = {
|
||||
isEmpty: false,
|
||||
isError: false,
|
||||
isRequesting: false,
|
||||
data: {
|
||||
|
@ -62,6 +63,8 @@ export function getAllReportData( endpoint, query, select ) {
|
|||
return { ...response, isRequesting: true };
|
||||
} else if ( isReportStatsError( endpoint, query ) ) {
|
||||
return { ...response, isError: true };
|
||||
} else if ( isReportDataEmpty( stats ) ) {
|
||||
return { ...response, isEmpty: true };
|
||||
}
|
||||
|
||||
const totals = ( stats && stats.data && stats.data.totals ) || null;
|
||||
|
|
|
@ -49,4 +49,14 @@
|
|||
a:focus {
|
||||
box-shadow: 0 0 0 1px $woocommerce-300, 0 0 2px 1px rgba($woocommerce-300, 0.8);
|
||||
}
|
||||
|
||||
.components-button.is-button.is-primary {
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.components-button.is-button.is-primary:hover,
|
||||
.components-button.is-button.is-primary:active,
|
||||
.components-button.is-button.is-primary:focus {
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 14 KiB |
|
@ -57,10 +57,16 @@ function wc_admin_register_script() {
|
|||
|
||||
wp_enqueue_script( 'wp-api' );
|
||||
|
||||
/**
|
||||
* TODO: On merge, once plugin images are added to core WooCommerce, `wcAdminAssetUrl` can be retired, and
|
||||
* `wcAssetUrl` can be used in its place throughout the codebase.
|
||||
*/
|
||||
|
||||
// Settings and variables can be passed here for access in the app.
|
||||
$settings = array(
|
||||
'adminUrl' => admin_url(),
|
||||
'wcAssetUrl' => plugins_url( 'assets/', WC_PLUGIN_FILE ),
|
||||
'wcAdminAssetUrl' => plugins_url( 'images/', wc_admin_dir_path( 'wc-admin.php' ) ), // Temporary for plugin. See above.
|
||||
'embedBreadcrumbs' => wc_admin_get_embed_breadcrumbs(),
|
||||
'siteLocale' => esc_attr( get_bloginfo( 'language' ) ),
|
||||
'currency' => wc_admin_currency_settings(),
|
||||
|
|
Loading…
Reference in New Issue