Add store notice around processing historical data. (https://github.com/woocommerce/woocommerce-admin/pull/1763)
* Add store notice around processing historical data. * Cleanup * Handle PR feedback. * Clean up `add` logic and add empty content_data. Also add logic to get_notes_count so that we can hide unactioned statuses. * Add the ability to update a note, and to also mark a status when an alert is clicked. * Remove mark_actioned call on sync * add missing todo
This commit is contained in:
parent
6c9b96f49a
commit
1348245406
|
@ -37,6 +37,38 @@ const orderStatuses = Object.keys( wcSettings.orderStatuses )
|
||||||
} );
|
} );
|
||||||
|
|
||||||
export const analyticsSettings = applyFilters( SETTINGS_FILTER, [
|
export const analyticsSettings = applyFilters( SETTINGS_FILTER, [
|
||||||
|
{
|
||||||
|
name: 'woocommerce_rebuild_reports_data',
|
||||||
|
label: __( 'Rebuild reports data:', 'wc-admin' ),
|
||||||
|
inputType: 'button',
|
||||||
|
inputText: __( 'Rebuild reports', 'wc-admin' ),
|
||||||
|
helpText: __(
|
||||||
|
'This tool will rebuild all of the information used by the reports. ' +
|
||||||
|
'Data will be processed in the background and may take some time depending on the size of your store.',
|
||||||
|
'wc-admin'
|
||||||
|
),
|
||||||
|
callback: ( resolve, reject, addNotice ) => {
|
||||||
|
const errorMessage = __( 'There was a problem rebuilding your report data.', 'wc-admin' );
|
||||||
|
|
||||||
|
apiFetch( { path: '/wc/v3/system_status/tools/rebuild_stats', method: 'PUT' } )
|
||||||
|
.then( response => {
|
||||||
|
if ( response.success ) {
|
||||||
|
addNotice( { status: 'success', message: response.message } );
|
||||||
|
// @todo This should be changed to detect when the lookup table population is complete.
|
||||||
|
setTimeout( () => resolve(), 300000 );
|
||||||
|
} else {
|
||||||
|
addNotice( { status: 'error', message: errorMessage } );
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
.catch( error => {
|
||||||
|
if ( error && error.message ) {
|
||||||
|
addNotice( { status: 'error', message: error.message } );
|
||||||
|
}
|
||||||
|
reject();
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'woocommerce_excluded_report_order_statuses',
|
name: 'woocommerce_excluded_report_order_statuses',
|
||||||
label: __( 'Excluded Statuses:', 'wc-admin' ),
|
label: __( 'Excluded Statuses:', 'wc-admin' ),
|
||||||
|
@ -89,36 +121,4 @@ export const analyticsSettings = applyFilters( SETTINGS_FILTER, [
|
||||||
initialValue: wcSettings.wcAdminSettings.woocommerce_actionable_order_statuses || [],
|
initialValue: wcSettings.wcAdminSettings.woocommerce_actionable_order_statuses || [],
|
||||||
defaultValue: [ 'processing', 'on-hold' ],
|
defaultValue: [ 'processing', 'on-hold' ],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'woocommerce_rebuild_reports_data',
|
|
||||||
label: __( 'Rebuild reports data:', 'wc-admin' ),
|
|
||||||
inputType: 'button',
|
|
||||||
inputText: __( 'Rebuild reports', 'wc-admin' ),
|
|
||||||
helpText: __(
|
|
||||||
'This tool will rebuild all of the information used by the reports. ' +
|
|
||||||
'Data will be processed in the background and may take some time depending on the size of your store.',
|
|
||||||
'wc-admin'
|
|
||||||
),
|
|
||||||
callback: ( resolve, reject, addNotice ) => {
|
|
||||||
const errorMessage = __( 'There was a problem rebuilding your report data.', 'wc-admin' );
|
|
||||||
|
|
||||||
apiFetch( { path: '/wc/v3/system_status/tools/rebuild_stats', method: 'PUT' } )
|
|
||||||
.then( response => {
|
|
||||||
if ( response.success ) {
|
|
||||||
addNotice( { status: 'success', message: response.message } );
|
|
||||||
// @todo This should be changed to detect when the lookup table population is complete.
|
|
||||||
setTimeout( () => resolve(), 300000 );
|
|
||||||
} else {
|
|
||||||
addNotice( { status: 'error', message: errorMessage } );
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
} )
|
|
||||||
.catch( error => {
|
|
||||||
if ( error && error.message ) {
|
|
||||||
addNotice( { status: 'error', message: error.message } );
|
|
||||||
}
|
|
||||||
reject();
|
|
||||||
} );
|
|
||||||
},
|
|
||||||
},
|
|
||||||
] );
|
] );
|
||||||
|
|
|
@ -8,6 +8,8 @@ import { IconButton, Button, Dashicon } from '@wordpress/components';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import interpolateComponents from 'interpolate-components';
|
import interpolateComponents from 'interpolate-components';
|
||||||
import { compose } from '@wordpress/compose';
|
import { compose } from '@wordpress/compose';
|
||||||
|
import { noop } from 'lodash';
|
||||||
|
import { withDispatch } from '@wordpress/data';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WooCommerce dependencies
|
* WooCommerce dependencies
|
||||||
|
@ -64,7 +66,7 @@ class StoreAlerts extends Component {
|
||||||
const alerts = this.props.alerts || [];
|
const alerts = this.props.alerts || [];
|
||||||
const preloadAlertCount = wcSettings.alertCount && parseInt( wcSettings.alertCount );
|
const preloadAlertCount = wcSettings.alertCount && parseInt( wcSettings.alertCount );
|
||||||
|
|
||||||
if ( preloadAlertCount > 0 && 0 === alerts.length ) {
|
if ( preloadAlertCount > 0 && this.props.isLoading ) {
|
||||||
return <StoreAlertsPlaceholder hasMultipleAlerts={ preloadAlertCount > 1 } />;
|
return <StoreAlertsPlaceholder hasMultipleAlerts={ preloadAlertCount > 1 } />;
|
||||||
} else if ( 0 === alerts.length ) {
|
} else if ( 0 === alerts.length ) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -78,11 +80,22 @@ class StoreAlerts extends Component {
|
||||||
'is-alert-error': 'error' === type,
|
'is-alert-error': 'error' === type,
|
||||||
'is-alert-update': 'update' === type,
|
'is-alert-update': 'update' === type,
|
||||||
} );
|
} );
|
||||||
const actions = alert.actions.map( action => (
|
|
||||||
<Button key={ action.name } isDefault href={ action.url }>
|
const actions = alert.actions.map( action => {
|
||||||
{ action.label }
|
const markStatus = () => {
|
||||||
</Button>
|
this.props.updateNote( alert.id, { status: action.status } );
|
||||||
) );
|
};
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
key={ action.name }
|
||||||
|
isDefault
|
||||||
|
href={ action.url }
|
||||||
|
onClick={ '' === action.status ? noop : markStatus }
|
||||||
|
>
|
||||||
|
{ action.label }
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
|
@ -135,15 +148,29 @@ class StoreAlerts extends Component {
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withSelect( select => {
|
withSelect( select => {
|
||||||
const { getNotes } = select( 'wc-api' );
|
const { getNotes, isGetNotesRequesting } = select( 'wc-api' );
|
||||||
const alertsQuery = {
|
const alertsQuery = {
|
||||||
page: 1,
|
page: 1,
|
||||||
per_page: QUERY_DEFAULTS.pageSize,
|
per_page: QUERY_DEFAULTS.pageSize,
|
||||||
type: 'error,update',
|
type: 'error,update',
|
||||||
|
status: 'unactioned',
|
||||||
};
|
};
|
||||||
|
|
||||||
const alerts = getNotes( alertsQuery );
|
// Filter out notes that may have been marked actioned or not delayed after the initial request
|
||||||
|
const filterNotes = note => 'unactioned' === note.status;
|
||||||
|
const alerts = getNotes( alertsQuery ).filter( filterNotes );
|
||||||
|
|
||||||
return { alerts };
|
const isLoading = isGetNotesRequesting( alertsQuery );
|
||||||
|
|
||||||
|
return {
|
||||||
|
alerts,
|
||||||
|
isLoading,
|
||||||
|
};
|
||||||
|
} ),
|
||||||
|
withDispatch( dispatch => {
|
||||||
|
const { updateNote } = dispatch( 'wc-api' );
|
||||||
|
return {
|
||||||
|
updateNote,
|
||||||
|
};
|
||||||
} )
|
} )
|
||||||
)( StoreAlerts );
|
)( StoreAlerts );
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
*/
|
*/
|
||||||
import operations from './operations';
|
import operations from './operations';
|
||||||
import selectors from './selectors';
|
import selectors from './selectors';
|
||||||
|
import mutations from './mutations';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
operations,
|
operations,
|
||||||
selectors,
|
selectors,
|
||||||
|
mutations,
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
/** @format */
|
||||||
|
|
||||||
|
const updateNote = operations => ( noteId, noteFields ) => {
|
||||||
|
const resourceKey = 'note';
|
||||||
|
operations.update( [ resourceKey ], { [ resourceKey ]: { noteId, ...noteFields } } );
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
updateNote,
|
||||||
|
};
|
|
@ -19,6 +19,10 @@ function read( resourceNames, fetch = apiFetch ) {
|
||||||
return [ ...readNotes( resourceNames, fetch ), ...readNoteQueries( resourceNames, fetch ) ];
|
return [ ...readNotes( resourceNames, fetch ), ...readNoteQueries( resourceNames, fetch ) ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function update( resourceNames, data, fetch = apiFetch ) {
|
||||||
|
return [ ...updateNote( resourceNames, data, fetch ) ];
|
||||||
|
}
|
||||||
|
|
||||||
function readNoteQueries( resourceNames, fetch ) {
|
function readNoteQueries( resourceNames, fetch ) {
|
||||||
const filteredNames = resourceNames.filter( name => isResourcePrefix( name, 'note-query' ) );
|
const filteredNames = resourceNames.filter( name => isResourcePrefix( name, 'note-query' ) );
|
||||||
|
|
||||||
|
@ -71,6 +75,25 @@ function readNote( resourceName, fetch ) {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateNote( resourceNames, data, fetch ) {
|
||||||
|
const resourceName = 'note';
|
||||||
|
if ( resourceNames.includes( resourceName ) ) {
|
||||||
|
const { noteId, ...noteFields } = data[ resourceName ];
|
||||||
|
const url = `${ NAMESPACE }/admin/notes/${ noteId }`;
|
||||||
|
return [
|
||||||
|
fetch( { path: url, method: 'PUT', data: noteFields } )
|
||||||
|
.then( note => {
|
||||||
|
return { [ resourceName + ':' + noteId ]: { data: note } };
|
||||||
|
} )
|
||||||
|
.catch( error => {
|
||||||
|
return { [ resourceName + ':' + noteId ]: { error } };
|
||||||
|
} ),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
read,
|
read,
|
||||||
|
update,
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,7 @@ function createWcApiSpec() {
|
||||||
mutations: {
|
mutations: {
|
||||||
...settings.mutations,
|
...settings.mutations,
|
||||||
...user.mutations,
|
...user.mutations,
|
||||||
|
...notes.mutations,
|
||||||
},
|
},
|
||||||
selectors: {
|
selectors: {
|
||||||
...items.selectors,
|
...items.selectors,
|
||||||
|
@ -42,6 +43,7 @@ function createWcApiSpec() {
|
||||||
return [
|
return [
|
||||||
...settings.operations.update( resourceNames, data ),
|
...settings.operations.update( resourceNames, data ),
|
||||||
...user.operations.update( resourceNames, data ),
|
...user.operations.update( resourceNames, data ),
|
||||||
|
...notes.operations.update( resourceNames, data ),
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -63,6 +63,11 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
|
||||||
'callback' => array( $this, 'get_item' ),
|
'callback' => array( $this, 'get_item' ),
|
||||||
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'methods' => WP_REST_Server::EDITABLE,
|
||||||
|
'callback' => array( $this, 'update_item' ),
|
||||||
|
'permission_callback' => array( $this, 'update_items_permissions_check' ),
|
||||||
|
),
|
||||||
'schema' => array( $this, 'get_public_item_schema' ),
|
'schema' => array( $this, 'get_public_item_schema' ),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -124,6 +129,12 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
|
||||||
$args['type'] = $type;
|
$args['type'] = $type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$status = isset( $request['status'] ) ? $request['status'] : '';
|
||||||
|
$status = sanitize_text_field( $status );
|
||||||
|
if ( ! empty( $status ) ) {
|
||||||
|
$args['status'] = $status;
|
||||||
|
}
|
||||||
|
|
||||||
$notes = WC_Admin_Notes::get_notes( 'edit', $args );
|
$notes = WC_Admin_Notes::get_notes( 'edit', $args );
|
||||||
|
|
||||||
$data = array();
|
$data = array();
|
||||||
|
@ -134,7 +145,7 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = rest_ensure_response( $data );
|
$response = rest_ensure_response( $data );
|
||||||
$response->header( 'X-WP-Total', WC_Admin_Notes::get_notes_count() );
|
$response->header( 'X-WP-Total', WC_Admin_Notes::get_notes_count( $type, $status ) );
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
@ -167,6 +178,49 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a single note.
|
||||||
|
*
|
||||||
|
* @param WP_REST_Request $request Full details about the request.
|
||||||
|
* @return WP_REST_Request|WP_Error
|
||||||
|
*/
|
||||||
|
public function update_item( $request ) {
|
||||||
|
$note = WC_Admin_Notes::get_note( $request->get_param( 'id' ) );
|
||||||
|
|
||||||
|
if ( ! $note ) {
|
||||||
|
return new WP_Error(
|
||||||
|
'woocommerce_admin_notes_invalid_id',
|
||||||
|
__( 'Sorry, there is no resouce with that ID.', 'wc-admin' ),
|
||||||
|
array( 'status' => 404 )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo Status is the only field that can be updated at the moment. We should also implement the "date reminder" setting.
|
||||||
|
$note_changed = false;
|
||||||
|
if ( ! is_null( $request->get_param( 'status' ) ) ) {
|
||||||
|
$note->set_status( $request->get_param( 'status' ) );
|
||||||
|
$note_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $note_changed ) {
|
||||||
|
$note->save();
|
||||||
|
}
|
||||||
|
return $this->get_item( $request );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes sure the current user has access to WRITE the settings APIs.
|
||||||
|
*
|
||||||
|
* @param WP_REST_Request $request Full data about the request.
|
||||||
|
* @return WP_Error|bool
|
||||||
|
*/
|
||||||
|
public function update_items_permissions_check( $request ) {
|
||||||
|
if ( ! wc_rest_check_manager_permissions( 'settings', 'edit' ) ) {
|
||||||
|
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'wc-admin' ), array( 'status' => rest_authorization_required_code() ) );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a path or query for serialization to the client.
|
* Prepare a path or query for serialization to the client.
|
||||||
*
|
*
|
||||||
|
@ -204,8 +258,9 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
|
||||||
$data['title'] = stripslashes( $data['title'] );
|
$data['title'] = stripslashes( $data['title'] );
|
||||||
$data['content'] = stripslashes( $data['content'] );
|
$data['content'] = stripslashes( $data['content'] );
|
||||||
foreach ( (array) $data['actions'] as $key => $value ) {
|
foreach ( (array) $data['actions'] as $key => $value ) {
|
||||||
$data['actions'][ $key ]->label = stripslashes( $data['actions'][ $key ]->label );
|
$data['actions'][ $key ]->label = stripslashes( $data['actions'][ $key ]->label );
|
||||||
$data['actions'][ $key ]->url = $this->prepare_query_for_response( $data['actions'][ $key ]->query );
|
$data['actions'][ $key ]->url = $this->prepare_query_for_response( $data['actions'][ $key ]->query );
|
||||||
|
$data['actions'][ $key ]->status = stripslashes( $data['actions'][ $key ]->status );
|
||||||
}
|
}
|
||||||
$data = $this->filter_response_by_context( $data, $context );
|
$data = $this->filter_response_by_context( $data, $context );
|
||||||
|
|
||||||
|
@ -233,6 +288,29 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
|
||||||
return apply_filters( 'woocommerce_rest_prepare_admin_note', $response, $data, $request );
|
return apply_filters( 'woocommerce_rest_prepare_admin_note', $response, $data, $request );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the query params for collections.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_collection_params() {
|
||||||
|
$params = array();
|
||||||
|
$params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
|
||||||
|
$params['type'] = array(
|
||||||
|
'description' => __( 'Type of note.', 'wc-admin' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'enum' => WC_Admin_Note::get_allowed_types(),
|
||||||
|
'validate_callback' => 'rest_validate_request_arg',
|
||||||
|
);
|
||||||
|
$params['status'] = array(
|
||||||
|
'description' => __( 'Status of note.', 'wc-admin' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'enum' => WC_Admin_Note::get_allowed_statuses(),
|
||||||
|
'validate_callback' => 'rest_validate_request_arg',
|
||||||
|
);
|
||||||
|
return $params;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the note's schema, conforming to JSON Schema.
|
* Get the note's schema, conforming to JSON Schema.
|
||||||
*
|
*
|
||||||
|
@ -296,7 +374,6 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
|
||||||
'description' => __( 'The status of the note (e.g. unactioned, actioned).', 'wc-admin' ),
|
'description' => __( 'The status of the note (e.g. unactioned, actioned).', 'wc-admin' ),
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'context' => array( 'view', 'edit' ),
|
'context' => array( 'view', 'edit' ),
|
||||||
'readonly' => true,
|
|
||||||
),
|
),
|
||||||
'source' => array(
|
'source' => array(
|
||||||
'description' => __( 'Source of the note.', 'wc-admin' ),
|
'description' => __( 'Source of the note.', 'wc-admin' ),
|
||||||
|
@ -320,7 +397,7 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
|
||||||
'description' => __( 'Date after which the user should be reminded of the note, if any.', 'wc-admin' ),
|
'description' => __( 'Date after which the user should be reminded of the note, if any.', 'wc-admin' ),
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'context' => array( 'view', 'edit' ),
|
'context' => array( 'view', 'edit' ),
|
||||||
'readonly' => true,
|
'readonly' => true, // @todo Allow date_reminder to be updated.
|
||||||
),
|
),
|
||||||
'date_reminder_gmt' => array(
|
'date_reminder_gmt' => array(
|
||||||
'description' => __( 'Date after which the user should be reminded of the note, if any (GMT).', 'wc-admin' ),
|
'description' => __( 'Date after which the user should be reminded of the note, if any (GMT).', 'wc-admin' ),
|
||||||
|
|
|
@ -16,7 +16,7 @@ class WC_Admin_Install {
|
||||||
*
|
*
|
||||||
* @todo get this dynamically?
|
* @todo get this dynamically?
|
||||||
*/
|
*/
|
||||||
const VERSION_NUMBER = '0.6.0';
|
const VERSION_NUMBER = '0.8.0';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin version option name.
|
* Plugin version option name.
|
||||||
|
@ -76,6 +76,8 @@ class WC_Admin_Install {
|
||||||
self::create_tables();
|
self::create_tables();
|
||||||
self::update_wc_admin_version();
|
self::update_wc_admin_version();
|
||||||
|
|
||||||
|
WC_Admin_Notes_Historical_Data::add_note();
|
||||||
|
|
||||||
delete_transient( 'wc_admin_installing' );
|
delete_transient( 'wc_admin_installing' );
|
||||||
|
|
||||||
do_action( 'wc_admin_installed' );
|
do_action( 'wc_admin_installed' );
|
||||||
|
@ -174,6 +176,7 @@ class WC_Admin_Install {
|
||||||
name varchar(255) NOT NULL,
|
name varchar(255) NOT NULL,
|
||||||
label varchar(255) NOT NULL,
|
label varchar(255) NOT NULL,
|
||||||
query longtext NOT NULL,
|
query longtext NOT NULL,
|
||||||
|
status varchar(255) NOT NULL,
|
||||||
PRIMARY KEY (action_id),
|
PRIMARY KEY (action_id),
|
||||||
KEY note_id (note_id)
|
KEY note_id (note_id)
|
||||||
) $collate;
|
) $collate;
|
||||||
|
|
|
@ -365,6 +365,7 @@ class WC_Admin_Note extends WC_Data {
|
||||||
/**
|
/**
|
||||||
* Set note data for potential re-localization.
|
* Set note data for potential re-localization.
|
||||||
*
|
*
|
||||||
|
* @todo Set a default empty array? https://github.com/woocommerce/wc-admin/pull/1763#pullrequestreview-212442921.
|
||||||
* @param object $content_data Note data.
|
* @param object $content_data Note data.
|
||||||
*/
|
*/
|
||||||
public function set_content_data( $content_data ) {
|
public function set_content_data( $content_data ) {
|
||||||
|
@ -450,11 +451,13 @@ class WC_Admin_Note extends WC_Data {
|
||||||
* @param string $name Label name (not presented to user).
|
* @param string $name Label name (not presented to user).
|
||||||
* @param string $label Note label (e.g. presented as button label).
|
* @param string $label Note label (e.g. presented as button label).
|
||||||
* @param string $query Note query (for redirect).
|
* @param string $query Note query (for redirect).
|
||||||
|
* @param string $status The status to set for the action should on click.
|
||||||
*/
|
*/
|
||||||
public function add_action( $name, $label, $query ) {
|
public function add_action( $name, $label, $query, $status = '' ) {
|
||||||
$name = wc_clean( $name );
|
$name = wc_clean( $name );
|
||||||
$label = wc_clean( $label );
|
$label = wc_clean( $label );
|
||||||
$query = wc_clean( $query );
|
$query = wc_clean( $query );
|
||||||
|
$status = wc_clean( $status );
|
||||||
|
|
||||||
if ( empty( $name ) ) {
|
if ( empty( $name ) ) {
|
||||||
$this->error( 'admin_note_invalid_data', __( 'The admin note action name prop cannot be empty.', 'wc-admin' ) );
|
$this->error( 'admin_note_invalid_data', __( 'The admin note action name prop cannot be empty.', 'wc-admin' ) );
|
||||||
|
@ -469,9 +472,10 @@ class WC_Admin_Note extends WC_Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
$action = array(
|
$action = array(
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'label' => $label,
|
'label' => $label,
|
||||||
'query' => $query,
|
'query' => $query,
|
||||||
|
'status' => $status,
|
||||||
);
|
);
|
||||||
|
|
||||||
$note_actions = $this->get_prop( 'actions', 'edit' );
|
$note_actions = $this->get_prop( 'actions', 'edit' );
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* WooCommerce Admin: Historical Analytics Data Note.
|
||||||
|
*
|
||||||
|
* Adds a notes to store alerts area concerning the historial analytics data tool.
|
||||||
|
*
|
||||||
|
* @package WooCommerce Admin
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined( 'ABSPATH' ) || exit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WC_Admin_Notes_Historical_Data.
|
||||||
|
*/
|
||||||
|
class WC_Admin_Notes_Historical_Data {
|
||||||
|
const NOTE_NAME = 'wc-admin-historical-data';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a note for regenerating historical data.
|
||||||
|
*/
|
||||||
|
public static function add_note() {
|
||||||
|
$data_store = WC_Data_Store::load( 'admin-note' );
|
||||||
|
|
||||||
|
// First, see if we've already created this kind of note so we don't do it again.
|
||||||
|
$note_ids = $data_store->get_notes_with_name( self::NOTE_NAME );
|
||||||
|
if ( ! empty( $note_ids ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$note = new WC_Admin_Note();
|
||||||
|
$note->set_title( __( 'WooCommerce Admin: Historical Analytics Data', 'wc-admin' ) );
|
||||||
|
$note->set_content( __( 'To view your historical analytics data, you must process your existing orders and customers.', 'wc-admin' ) );
|
||||||
|
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_UPDATE );
|
||||||
|
$note->set_icon( 'info' );
|
||||||
|
$note->set_name( self::NOTE_NAME );
|
||||||
|
$note->set_content_data( (object) array() );
|
||||||
|
$note->set_source( 'woocommerce-admin' );
|
||||||
|
// @todo Add remind me later option. See https://github.com/woocommerce/wc-admin/issues/1756.
|
||||||
|
$note->add_action(
|
||||||
|
'get-started',
|
||||||
|
__( 'Get Started', 'wc-admin' ),
|
||||||
|
'?page=wc-admin#/analytics/settings',
|
||||||
|
'actioned'
|
||||||
|
);
|
||||||
|
|
||||||
|
$note->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new WC_Admin_Notes_Historical_Data();
|
|
@ -94,7 +94,7 @@ class WC_Admin_Notes_New_Sales_Record {
|
||||||
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_INFORMATIONAL );
|
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_INFORMATIONAL );
|
||||||
$note->set_icon( 'trophy' );
|
$note->set_icon( 'trophy' );
|
||||||
$note->set_name( self::NOTE_NAME );
|
$note->set_name( self::NOTE_NAME );
|
||||||
$note->set_source( 'wc-admin' );
|
$note->set_source( 'woocommerce-admin' );
|
||||||
$note->add_action( 'view-report', __( 'View report', 'wc-admin' ), '?page=wc-admin#/analytics' );
|
$note->add_action( 'view-report', __( 'View report', 'wc-admin' ), '?page=wc-admin#/analytics' );
|
||||||
$note->save();
|
$note->save();
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ class WC_Admin_Notes_Settings_Notes {
|
||||||
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_INFORMATIONAL );
|
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_INFORMATIONAL );
|
||||||
$note->set_icon( 'info' );
|
$note->set_icon( 'info' );
|
||||||
$note->set_name( $name );
|
$note->set_name( $name );
|
||||||
$note->set_source( 'wc-admin' );
|
$note->set_source( 'woocommerce-admin' );
|
||||||
$note->add_action(
|
$note->add_action(
|
||||||
'open-customizer',
|
'open-customizer',
|
||||||
__( 'Open Customizer', 'wc-admin' ),
|
__( 'Open Customizer', 'wc-admin' ),
|
||||||
|
|
|
@ -185,7 +185,7 @@ class WC_Admin_Notes_Woo_Subscriptions_Notes {
|
||||||
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_INFORMATIONAL );
|
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_INFORMATIONAL );
|
||||||
$note->set_icon( 'info' );
|
$note->set_icon( 'info' );
|
||||||
$note->set_name( self::CONNECTION_NOTE_NAME );
|
$note->set_name( self::CONNECTION_NOTE_NAME );
|
||||||
$note->set_source( 'wc-admin' );
|
$note->set_source( 'woocommerce-admin' );
|
||||||
$note->add_action(
|
$note->add_action(
|
||||||
'connect',
|
'connect',
|
||||||
__( 'Connect', 'wc-admin' ),
|
__( 'Connect', 'wc-admin' ),
|
||||||
|
@ -334,7 +334,7 @@ class WC_Admin_Notes_Woo_Subscriptions_Notes {
|
||||||
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_WARNING );
|
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_WARNING );
|
||||||
$note->set_icon( 'notice' );
|
$note->set_icon( 'notice' );
|
||||||
$note->set_name( self::SUBSCRIPTION_NOTE_NAME );
|
$note->set_name( self::SUBSCRIPTION_NOTE_NAME );
|
||||||
$note->set_source( 'wc-admin' );
|
$note->set_source( 'woocommerce-admin' );
|
||||||
$note->clear_actions();
|
$note->clear_actions();
|
||||||
$note->add_action(
|
$note->add_action(
|
||||||
'enable-autorenew',
|
'enable-autorenew',
|
||||||
|
@ -398,7 +398,7 @@ class WC_Admin_Notes_Woo_Subscriptions_Notes {
|
||||||
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_WARNING );
|
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_WARNING );
|
||||||
$note->set_icon( 'notice' );
|
$note->set_icon( 'notice' );
|
||||||
$note->set_name( self::SUBSCRIPTION_NOTE_NAME );
|
$note->set_name( self::SUBSCRIPTION_NOTE_NAME );
|
||||||
$note->set_source( 'wc-admin' );
|
$note->set_source( 'woocommerce-admin' );
|
||||||
$note->clear_actions();
|
$note->clear_actions();
|
||||||
$note->add_action(
|
$note->add_action(
|
||||||
'renew-subscription',
|
'renew-subscription',
|
||||||
|
|
|
@ -64,11 +64,12 @@ class WC_Admin_Notes {
|
||||||
* Get the total number of notes
|
* Get the total number of notes
|
||||||
*
|
*
|
||||||
* @param string $type Comma separated list of note types.
|
* @param string $type Comma separated list of note types.
|
||||||
|
* @param string $status Comma separated list of statuses.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public static function get_notes_count( $type = '' ) {
|
public static function get_notes_count( $type = '', $status = '' ) {
|
||||||
$data_store = WC_Data_Store::load( 'admin-note' );
|
$data_store = WC_Data_Store::load( 'admin-note' );
|
||||||
return $data_store->get_notes_count( $type );
|
return $data_store->get_notes_count( $type, $status );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -148,7 +148,6 @@ class WC_Admin_Reports_Sync {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedule an action to process a single Order.
|
* Schedule an action to process a single Order.
|
||||||
*
|
*
|
||||||
|
|
|
@ -197,13 +197,13 @@ class WC_Admin_Notes_Data_Store extends WC_Data_Store_WP implements WC_Object_Da
|
||||||
|
|
||||||
$actions = $wpdb->get_results(
|
$actions = $wpdb->get_results(
|
||||||
$wpdb->prepare(
|
$wpdb->prepare(
|
||||||
"SELECT name, label, query FROM {$wpdb->prefix}wc_admin_note_actions WHERE note_id = %d",
|
"SELECT name, label, query, status FROM {$wpdb->prefix}wc_admin_note_actions WHERE note_id = %d",
|
||||||
$note->get_id()
|
$note->get_id()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if ( $actions ) {
|
if ( $actions ) {
|
||||||
foreach ( $actions as $action ) {
|
foreach ( $actions as $action ) {
|
||||||
$note->add_action( $action->name, $action->label, $action->query );
|
$note->add_action( $action->name, $action->label, $action->query, $action->status );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,6 +232,7 @@ class WC_Admin_Notes_Data_Store extends WC_Data_Store_WP implements WC_Object_Da
|
||||||
'name' => $action->name,
|
'name' => $action->name,
|
||||||
'label' => $action->label,
|
'label' => $action->label,
|
||||||
'query' => $action->query,
|
'query' => $action->query,
|
||||||
|
'status' => $action->status,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -258,6 +259,49 @@ class WC_Admin_Notes_Data_Store extends WC_Data_Store_WP implements WC_Object_Da
|
||||||
|
|
||||||
$offset = $per_page * ( $page - 1 );
|
$offset = $per_page * ( $page - 1 );
|
||||||
|
|
||||||
|
$where_clauses = $this->get_notes_where_clauses( $args );
|
||||||
|
|
||||||
|
$query = $wpdb->prepare(
|
||||||
|
"SELECT note_id, title, content FROM {$wpdb->prefix}wc_admin_notes WHERE 1=1{$where_clauses} ORDER BY note_id DESC LIMIT %d, %d",
|
||||||
|
$offset,
|
||||||
|
$per_page
|
||||||
|
); // WPCS: unprepared SQL ok.
|
||||||
|
|
||||||
|
return $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a count of notes.
|
||||||
|
*
|
||||||
|
* @param string $type Comma separated list of note types.
|
||||||
|
* @param string $status Comma separated list of statuses.
|
||||||
|
* @return array An array of objects containing a note id.
|
||||||
|
*/
|
||||||
|
public function get_notes_count( $type = '', $status = '' ) {
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
$where_clauses = $this->get_notes_where_clauses(
|
||||||
|
array(
|
||||||
|
'type' => $type,
|
||||||
|
'status' => $status,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! empty( $where_clauses ) ) {
|
||||||
|
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||||
|
return $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}wc_admin_notes WHERE 1=1{$where_clauses}" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}wc_admin_notes" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return where clauses for getting notes by status and type. For use in both the count and listing queries.
|
||||||
|
*
|
||||||
|
* @param array $args Array of args to pass.
|
||||||
|
* @return string Where clauses for the query.
|
||||||
|
*/
|
||||||
|
public function get_notes_where_clauses( $args = array() ) {
|
||||||
$allowed_types = WC_Admin_Note::get_allowed_types();
|
$allowed_types = WC_Admin_Note::get_allowed_types();
|
||||||
$where_type_array = array();
|
$where_type_array = array();
|
||||||
if ( isset( $args['type'] ) ) {
|
if ( isset( $args['type'] ) ) {
|
||||||
|
@ -269,54 +313,32 @@ class WC_Admin_Notes_Data_Store extends WC_Data_Store_WP implements WC_Object_Da
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$escaped_where_types = implode( ',', $where_type_array );
|
|
||||||
|
|
||||||
if ( empty( $escaped_where_types ) ) {
|
$allowed_statuses = WC_Admin_Note::get_allowed_statuses();
|
||||||
$query = $wpdb->prepare(
|
$where_status_array = array();
|
||||||
"SELECT note_id, title, content FROM {$wpdb->prefix}wc_admin_notes ORDER BY note_id DESC LIMIT %d, %d",
|
if ( isset( $args['status'] ) ) {
|
||||||
$offset,
|
$args_statuses = explode( ',', $args['status'] );
|
||||||
$per_page
|
foreach ( (array) $args_statuses as $args_status ) {
|
||||||
);
|
$args_status = trim( $args_status );
|
||||||
} else {
|
if ( in_array( $args_status, $allowed_statuses, true ) ) {
|
||||||
$query = $wpdb->prepare(
|
$where_status_array[] = "'" . esc_sql( $args_status ) . "'";
|
||||||
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
|
||||||
"SELECT note_id, title, content FROM {$wpdb->prefix}wc_admin_notes WHERE type IN ($escaped_where_types) ORDER BY note_id DESC LIMIT %d, %d",
|
|
||||||
$offset,
|
|
||||||
$per_page
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a count of notes.
|
|
||||||
*
|
|
||||||
* @param string $type Comma separated list of note types.
|
|
||||||
* @return array An array of objects containing a note id.
|
|
||||||
*/
|
|
||||||
public function get_notes_count( $type = '' ) {
|
|
||||||
global $wpdb;
|
|
||||||
|
|
||||||
$allowed_types = WC_Admin_Note::get_allowed_types();
|
|
||||||
$where_type_array = array();
|
|
||||||
if ( ! empty( $type ) ) {
|
|
||||||
$args_types = explode( ',', $type );
|
|
||||||
foreach ( (array) $args_types as $args_type ) {
|
|
||||||
$args_type = trim( $args_type );
|
|
||||||
if ( in_array( $args_type, $allowed_types, true ) ) {
|
|
||||||
$where_type_array[] = "'" . esc_sql( $args_type ) . "'";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$escaped_where_types = implode( ',', $where_type_array );
|
|
||||||
|
$escaped_where_types = implode( ',', $where_type_array );
|
||||||
|
$escaped_status_types = implode( ',', $where_status_array );
|
||||||
|
$where_clauses = '';
|
||||||
|
|
||||||
if ( ! empty( $escaped_where_types ) ) {
|
if ( ! empty( $escaped_where_types ) ) {
|
||||||
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
$where_clauses .= " AND type IN ($escaped_where_types)";
|
||||||
return $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}wc_admin_notes WHERE type IN ($escaped_where_types)" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}wc_admin_notes" );
|
if ( ! empty( $escaped_status_types ) ) {
|
||||||
|
$where_clauses .= " AND status IN ($escaped_status_types)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $where_clauses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -191,7 +191,7 @@ function wc_admin_print_script_settings() {
|
||||||
'weekdaysShort' => array_values( $wp_locale->weekday_abbrev ),
|
'weekdaysShort' => array_values( $wp_locale->weekday_abbrev ),
|
||||||
),
|
),
|
||||||
'currentUserData' => $current_user_data,
|
'currentUserData' => $current_user_data,
|
||||||
'alertCount' => WC_Admin_Notes::get_notes_count( 'error,update' ),
|
'alertCount' => WC_Admin_Notes::get_notes_count( 'error,update', 'unactioned' ),
|
||||||
);
|
);
|
||||||
$settings = wc_admin_add_custom_settings( $settings );
|
$settings = wc_admin_add_custom_settings( $settings );
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,45 @@ class WC_Tests_API_Admin_Notes extends WC_REST_Unit_Test_Case {
|
||||||
$this->assertEquals( 401, $response->get_status() );
|
$this->assertEquals( 401, $response->get_status() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test updating a single note.
|
||||||
|
*/
|
||||||
|
public function test_update_note() {
|
||||||
|
wp_set_current_user( $this->user );
|
||||||
|
|
||||||
|
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint . '/1' ) );
|
||||||
|
$note = $response->get_data();
|
||||||
|
|
||||||
|
$this->assertEquals( 200, $response->get_status() );
|
||||||
|
$this->assertEquals( 'unactioned', $note['status'] );
|
||||||
|
|
||||||
|
$request = new WP_REST_Request( 'PUT', $this->endpoint . '/1' );
|
||||||
|
$request->set_body_params(
|
||||||
|
array(
|
||||||
|
'status' => 'actioned',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = $this->server->dispatch( $request );
|
||||||
|
$note = $response->get_data();
|
||||||
|
$this->assertEquals( 200, $response->get_status() );
|
||||||
|
$this->assertEquals( 'actioned', $note['status'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test updating a single note without permission. It should fail.
|
||||||
|
*/
|
||||||
|
public function test_update_note_without_permission() {
|
||||||
|
$request = new WP_REST_Request( 'PUT', $this->endpoint . '/1' );
|
||||||
|
$request->set_body_params(
|
||||||
|
array(
|
||||||
|
'status' => 'actioned',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$response = $this->server->dispatch( $request );
|
||||||
|
$this->assertEquals( 401, $response->get_status() );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getting lots of notes.
|
* Test getting lots of notes.
|
||||||
*
|
*
|
||||||
|
@ -139,6 +178,31 @@ class WC_Tests_API_Admin_Notes extends WC_REST_Unit_Test_Case {
|
||||||
$this->assertEquals( $notes[0]['title'], 'PHPUNIT_TEST_NOTE_2_TITLE' );
|
$this->assertEquals( $notes[0]['title'], 'PHPUNIT_TEST_NOTE_2_TITLE' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test getting notes of a certain status.
|
||||||
|
*/
|
||||||
|
public function test_get_actioned_notes() {
|
||||||
|
wp_set_current_user( $this->user );
|
||||||
|
|
||||||
|
$request = new WP_REST_Request( 'GET', $this->endpoint );
|
||||||
|
$request->set_query_params( array( 'status' => 'actioned' ) );
|
||||||
|
$response = $this->server->dispatch( $request );
|
||||||
|
$notes = $response->get_data();
|
||||||
|
|
||||||
|
$this->assertEquals( 200, $response->get_status() );
|
||||||
|
$this->assertEquals( 1, count( $notes ) );
|
||||||
|
$this->assertEquals( $notes[0]['title'], 'PHPUNIT_TEST_NOTE_2_TITLE' );
|
||||||
|
|
||||||
|
$request = new WP_REST_Request( 'GET', $this->endpoint );
|
||||||
|
$request->set_query_params( array( 'status' => 'invalid' ) );
|
||||||
|
$response = $this->server->dispatch( $request );
|
||||||
|
$notes = $response->get_data();
|
||||||
|
|
||||||
|
// get_notes returns all results since 'status' is not one of actioned or unactioned.
|
||||||
|
$this->assertEquals( 2, count( $notes ) );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getting lots of notes without permission. It should fail.
|
* Test getting lots of notes without permission. It should fail.
|
||||||
*
|
*
|
||||||
|
|
|
@ -55,6 +55,7 @@ class WC_Helper_Admin_Notes {
|
||||||
$note_2->set_icon( 'info' );
|
$note_2->set_icon( 'info' );
|
||||||
$note_2->set_name( 'PHPUNIT_TEST_NOTE_NAME' );
|
$note_2->set_name( 'PHPUNIT_TEST_NOTE_NAME' );
|
||||||
$note_2->set_source( 'PHPUNIT_TEST' );
|
$note_2->set_source( 'PHPUNIT_TEST' );
|
||||||
|
$note_2->set_status( WC_Admin_Note::E_WC_ADMIN_NOTE_ACTIONED );
|
||||||
// This note has no actions.
|
// This note has no actions.
|
||||||
$note_2->save();
|
$note_2->save();
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,7 @@ function wc_admin_plugins_loaded() {
|
||||||
require_once WC_ADMIN_ABSPATH . '/includes/class-wc-admin-notes-new-sales-record.php';
|
require_once WC_ADMIN_ABSPATH . '/includes/class-wc-admin-notes-new-sales-record.php';
|
||||||
require_once WC_ADMIN_ABSPATH . '/includes/class-wc-admin-notes-settings-notes.php';
|
require_once WC_ADMIN_ABSPATH . '/includes/class-wc-admin-notes-settings-notes.php';
|
||||||
require_once WC_ADMIN_ABSPATH . '/includes/class-wc-admin-notes-woo-subscriptions-notes.php';
|
require_once WC_ADMIN_ABSPATH . '/includes/class-wc-admin-notes-woo-subscriptions-notes.php';
|
||||||
|
require_once WC_ADMIN_ABSPATH . '/includes/class-wc-admin-notes-historical-data.php';
|
||||||
|
|
||||||
// Verify we have a proper build.
|
// Verify we have a proper build.
|
||||||
if ( ! wc_admin_build_file_exists() ) {
|
if ( ! wc_admin_build_file_exists() ) {
|
||||||
|
|
Loading…
Reference in New Issue