WCA Test helper - add remote inbox notification staging importer (#48735)
* Add Remote inbox notifications management
* Remove admin notes section -- replaced by remote inbox notifications
* Add import from staging and production
* Add changefile(s) from automation for the following project(s): woocommerce-beta-tester
* WIP - change test to run
* Display failed rules on error
* Change run to test
* Add changefile(s) from automation for the following project(s): woocommerce-beta-tester, woocommerce
* Retire Remote Spec Ruel Validation -- use test action from Remote Inbox Notifications
* Run spec when all rules have passed
* Fix typo
* Change btn text to Run
* Update copy text
* Place delete all button on the left side
* Update plugins/woocommerce-beta-tester/api/remote-inbox-notifications/class-wca-test-helper-remote-inbox-notifications.php
Co-authored-by: Ilyas Foo <foo.ilyas@gmail.com>
* Update plugins/woocommerce/src/Admin/RemoteSpecs/RuleProcessors/RuleEvaluator.php
Co-authored-by: Ilyas Foo <foo.ilyas@gmail.com>
* Update plugins/woocommerce-beta-tester/api/remote-inbox-notifications/class-wca-test-helper-remote-inbox-notifications.php
Co-authored-by: Ilyas Foo <foo.ilyas@gmail.com>
* Add changefile(s) from automation for the following project(s): woocommerce-beta-tester
* Separate remote inbox notification heler functions into a class and fix DELETE method errors
* Fix typo
* Display all errors
* Fix errors
* Fix error with test
* Add import from URL
* Change func name to importFromUrl
* Rename 48735-feature-remote-notiifcation-importer to 48735-feature-remote-notification-importer
Fix filename typo
* Add changefile(s) from automation for the following project(s): woocommerce-beta-tester
* Fix changelog filename typo
Fix changelog filename typo
* Add changefile(s) from automation for the following project(s): woocommerce-beta-tester
* Revert adding new changelog
It seems the new CI is automatically creating a changelog based on branch name 43d6abe3e7
---------
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Ilyas Foo <foo.ilyas@gmail.com>
This commit is contained in:
parent
655c1436ec
commit
a09522df1c
|
@ -61,3 +61,4 @@ require 'live-branches/manifest.php';
|
|||
require 'live-branches/install.php';
|
||||
require 'tools/set-block-template-logging-threshold.php';
|
||||
require 'remote-spec-validator/class-wca-test-helper-remote-spec-validator.php';
|
||||
require 'remote-inbox-notifications/class-wca-test-helper-remote-inbox-notifications.php';
|
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\SpecRunner;
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsEngine;
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsDataSourcePoller;
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\GetRuleProcessor;
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\RuleEvaluator;
|
||||
|
||||
/**
|
||||
* Helper class for remote inbox notifications.
|
||||
*/
|
||||
class WC_Beta_Tester_Remote_Inbox_Notifications_Helper {
|
||||
|
||||
/**
|
||||
* Get the name of the transient used to store the remote inbox notifications.
|
||||
*
|
||||
* @return string The transient name.
|
||||
*/
|
||||
public static function get_transient_name() {
|
||||
return 'woocommerce_admin_' . RemoteInboxNotificationsDataSourcePoller::ID . '_specs';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the transient data using the transient name.
|
||||
*
|
||||
* @return mixed The transient data.
|
||||
*/
|
||||
public static function get_transient() {
|
||||
return get_transient( static::get_transient_name() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a specific notification by its ID from the database.
|
||||
*
|
||||
* @param int $id The ID of the notification to delete.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
public static function delete_by_id( $id ) {
|
||||
global $wpdb;
|
||||
$wpdb->delete( $wpdb->prefix . 'wc_admin_notes', array( 'note_id' => $id ) );
|
||||
$wpdb->delete( $wpdb->prefix . 'wc_admin_note_actions', array( 'note_id' => $id ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all notifications and their associated actions from the database.
|
||||
*
|
||||
* @global wpdb $wpdb WordPress database abstraction object.
|
||||
* @return array Associative array containing the count of deleted notes and actions.
|
||||
*/
|
||||
public static function delete_all() {
|
||||
global $wpdb;
|
||||
|
||||
$deleted_note_count = $wpdb->query( "DELETE FROM {$wpdb->prefix}wc_admin_notes" );
|
||||
$deleted_action_count = $wpdb->query( "DELETE FROM {$wpdb->prefix}wc_admin_note_actions" );
|
||||
return array(
|
||||
'deleted_note_count' => $deleted_note_count,
|
||||
'deleted_action_count' => $deleted_action_count,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a specific notification by its name and optionally run it.
|
||||
*
|
||||
* @param string $name The name of the notification to test.
|
||||
* @param string|null $locale The locale of the notification. Defaults to the current system locale.
|
||||
* @param bool $run Whether to run the notification if the test passes. Defaults to false.
|
||||
* @return true|WP_Error True on success, WP_Error on failure.
|
||||
*/
|
||||
public static function test( $name, $locale = null, $run = false ) {
|
||||
$notifications = static::get_transient();
|
||||
|
||||
if ( ! $locale ) {
|
||||
$locale = get_locale();
|
||||
}
|
||||
|
||||
if ( ! isset( $notifications[ $locale ][ $name ] ) ) {
|
||||
return new WP_Error(
|
||||
404,
|
||||
"'{$name}' was not found in the latest remote inbox notification transient. Please re-run the import command.",
|
||||
);
|
||||
}
|
||||
|
||||
$spec = $notifications[ $locale ][ $name ];
|
||||
$test = true;
|
||||
$failed_rules = array();
|
||||
$rule_processor = new GetRuleProcessor();
|
||||
foreach ( $spec->rules as $rule ) {
|
||||
if ( ! is_object( $rule ) ) {
|
||||
$test = false;
|
||||
break;
|
||||
}
|
||||
$processor = $rule_processor->get_processor( $rule->type );
|
||||
$processor_result = $processor->process( $rule, null );
|
||||
if ( ! $processor_result ) {
|
||||
$test = false;
|
||||
$failed_rules[] = $rule;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $test && $run ) {
|
||||
$stored_state = RemoteInboxNotificationsEngine::get_stored_state();
|
||||
SpecRunner::run_spec( $spec, $stored_state );
|
||||
}
|
||||
|
||||
if ( ! $test ) {
|
||||
return new WP_Error(
|
||||
400,
|
||||
"Test failed for '{$name}'",
|
||||
array( 'failed_rules' => $failed_rules )
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import specifications and store them in the transient.
|
||||
*
|
||||
* @param array $specs An array of specifications to import.
|
||||
* @return bool True on success.
|
||||
*/
|
||||
public static function import( $specs ) {
|
||||
$stored_state = RemoteInboxNotificationsEngine::get_stored_state();
|
||||
$transient = static::get_transient();
|
||||
|
||||
foreach ( $specs as $spec ) {
|
||||
SpecRunner::run_spec( $spec, $stored_state );
|
||||
if ( isset( $spec->locales ) && is_array( $spec->locales ) ) {
|
||||
foreach ( $spec->locales as $locale ) {
|
||||
$transient[ $locale->locale ][ $spec->slug ] = $spec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_transient( static::get_transient_name(), $transient );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
<?php
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\SpecRunner;
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsEngine;
|
||||
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RemoteInboxNotificationsDataSourcePoller;
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\GetRuleProcessor;
|
||||
use Automattic\WooCommerce\Admin\RemoteSpecs\RuleProcessors\RuleEvaluator;
|
||||
|
||||
require_once dirname( __FILE__ ) . '/class-wc-beta-tester-remote-inbox-notifications-helper.php';
|
||||
|
||||
register_woocommerce_admin_test_helper_rest_route(
|
||||
'/remote-inbox-notifications',
|
||||
array( WCA_Test_Helper_Remote_Inbox_Notifications::class, 'get_items' ),
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
)
|
||||
);
|
||||
|
||||
register_woocommerce_admin_test_helper_rest_route(
|
||||
'/remote-inbox-notifications/(?P<id>\d+)/delete',
|
||||
array( WCA_Test_Helper_Remote_Inbox_Notifications::class, 'delete' ),
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'description' => 'Rest API endpoint.',
|
||||
'type' => 'integer',
|
||||
'required' => true,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_woocommerce_admin_test_helper_rest_route(
|
||||
'/remote-inbox-notifications/(?P<name>(.*)+)/test',
|
||||
array( WCA_Test_Helper_Remote_Inbox_Notifications::class, 'test' ),
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'args' => array(
|
||||
'name' => array(
|
||||
'description' => 'Note name.',
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_woocommerce_admin_test_helper_rest_route(
|
||||
'/remote-inbox-notifications/delete-all',
|
||||
array( WCA_Test_Helper_Remote_Inbox_Notifications::class, 'delete_all_items' ),
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
)
|
||||
);
|
||||
|
||||
register_woocommerce_admin_test_helper_rest_route(
|
||||
'/remote-inbox-notifications/import',
|
||||
array( WCA_Test_Helper_Remote_Inbox_Notifications::class, 'import' ),
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Class WCA_Test_Helper_Remote_Inbox_Notifications.
|
||||
*/
|
||||
class WCA_Test_Helper_Remote_Inbox_Notifications {
|
||||
|
||||
/**
|
||||
* Delete a notification.
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function delete( $request ) {
|
||||
WC_Beta_Tester_Remote_Inbox_Notifications_Helper::delete_by_id( $request->get_param( 'id' ) );
|
||||
|
||||
return new WP_REST_Response(
|
||||
array(
|
||||
'success' => true,
|
||||
'message' => 'Remote inbox notification deleted.',
|
||||
),
|
||||
200
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all notifications.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function delete_all_items() {
|
||||
$deleted = WC_Beta_Tester_Remote_Inbox_Notifications_Helper::delete_all();
|
||||
return new WP_REST_Response( $deleted, 200 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of class-based notes.
|
||||
* These should be excluded from the list of notes to be displayed in the inbox as we don't have control over them.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function get_notes_to_exclude() {
|
||||
$vars = array( 'other_note_classes', 'note_classes_to_added_or_updated' );
|
||||
$note_names = array();
|
||||
$reflection = new ReflectionClass( '\Automattic\WooCommerce\Internal\Admin\Events' );
|
||||
foreach ( $vars as $var ) {
|
||||
$property = $reflection->getProperty( $var );
|
||||
$property->setAccessible( true );
|
||||
$notes = $property->getValue();
|
||||
$note_names = array_merge(
|
||||
$note_names,
|
||||
array_map(
|
||||
function ( $note ) {
|
||||
return $note::NOTE_NAME;
|
||||
},
|
||||
$notes
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $note_names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all notifications.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function get_items() {
|
||||
global $wpdb;
|
||||
$items = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wc_admin_notes ORDER BY note_id desc", ARRAY_A );
|
||||
|
||||
$notes_added_via_classes = self::get_notes_to_exclude();
|
||||
$items = array_filter(
|
||||
$items,
|
||||
function ( $item ) use ( $notes_added_via_classes ) {
|
||||
return ! in_array( $item['name'], $notes_added_via_classes, true );
|
||||
}
|
||||
);
|
||||
|
||||
return new WP_REST_Response( array_values( $items ), 200 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test and run a remote inbox notification.
|
||||
*
|
||||
* @param WP_REST_Request $request The full request data.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function test( $request ) {
|
||||
$name = $request->get_param( 'name' );
|
||||
$result = WC_Beta_Tester_Remote_Inbox_Notifications_Helper::test( $name, null, true );
|
||||
|
||||
if ( $result instanceof WP_Error ) {
|
||||
$message = $result->get_error_data();
|
||||
} else {
|
||||
$message = $name . ': All rules passed successfully';
|
||||
}
|
||||
|
||||
return new WP_REST_Response(
|
||||
array(
|
||||
'success' => true === $result,
|
||||
'message' => $message,
|
||||
),
|
||||
200
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import remote inbox notifications.
|
||||
*
|
||||
* @param WP_REST_Request $request The full request data.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public static function import( $request ) {
|
||||
// Get the JSON data from the request body.
|
||||
$specs = json_decode( wp_json_encode( $request->get_json_params() ) );
|
||||
WC_Beta_Tester_Remote_Inbox_Notifications_Helper::import( $specs );
|
||||
|
||||
return new WP_REST_Response(
|
||||
array(
|
||||
'success' => true,
|
||||
'message' => 'Remote inbox notifications imported.',
|
||||
),
|
||||
200
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Adds a new tool to the WCA Test Helper that helps import remote inbox notifications from staging or production for testing purposes
|
|
@ -14,6 +14,7 @@ import { default as Experiments } from '../experiments';
|
|||
import { default as Features } from '../features';
|
||||
import { default as RestAPIFilters } from '../rest-api-filters';
|
||||
import RemoteSpecValidator from '../remote-spec-validator';
|
||||
import RemoteInboxNotifications from '../remote-inbox-notifications';
|
||||
|
||||
const tabs = applyFilters( 'woocommerce_admin_test_helper_tabs', [
|
||||
{
|
||||
|
@ -21,11 +22,6 @@ const tabs = applyFilters( 'woocommerce_admin_test_helper_tabs', [
|
|||
title: 'Options',
|
||||
content: <Options />,
|
||||
},
|
||||
{
|
||||
name: 'admin-notes',
|
||||
title: 'Admin notes',
|
||||
content: <AdminNotes />,
|
||||
},
|
||||
{
|
||||
name: 'tools',
|
||||
title: 'Tools',
|
||||
|
@ -47,9 +43,9 @@ const tabs = applyFilters( 'woocommerce_admin_test_helper_tabs', [
|
|||
content: <RestAPIFilters />,
|
||||
},
|
||||
{
|
||||
name: 'remote-spec-validator',
|
||||
title: 'Remote Spec Rule Validator',
|
||||
content: <RemoteSpecValidator />,
|
||||
name: 'remote-inbox-notifications',
|
||||
title: 'Remote Inbox Notifications',
|
||||
content: <RemoteInboxNotifications />,
|
||||
},
|
||||
] );
|
||||
|
||||
|
|
|
@ -183,4 +183,44 @@ form.rest-api-filter-new-form {
|
|||
.btn-validate {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
#wc-admin-test-helper-remote-inbox-notifications {
|
||||
pre {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.action-btns {
|
||||
justify-content: end;
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
.btn-danger {
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
.notification-actions {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
justify-content: end;
|
||||
}
|
||||
.components-notice {
|
||||
margin: 0px 0px 10px 0px;
|
||||
}
|
||||
|
||||
.button.staging {
|
||||
background-color: #de9816;
|
||||
color: #fff;
|
||||
border-color: #de9816;
|
||||
}
|
||||
|
||||
.column-status {
|
||||
display: flex;
|
||||
svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
const TYPES = {
|
||||
SET_NOTIFICATIONS: 'SET_NOTIFICATIONS',
|
||||
SET_IS_LOADING: 'SET_IS_LOADING',
|
||||
DELETE_NOTIFICATION: 'DELETE_NOTIFICATION',
|
||||
SET_NOTICE: 'SET_NOTICE',
|
||||
};
|
||||
|
||||
export default TYPES;
|
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { apiFetch } from '@wordpress/data-controls';
|
||||
import { controls } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import TYPES from './action-types';
|
||||
import { API_NAMESPACE, STORE_KEY } from './constants';
|
||||
|
||||
/**
|
||||
* Initialize the state
|
||||
*
|
||||
* @param {Array} notifications
|
||||
*/
|
||||
export function setNotifications( notifications ) {
|
||||
return {
|
||||
type: TYPES.SET_NOTIFICATIONS,
|
||||
notifications,
|
||||
};
|
||||
}
|
||||
|
||||
export function setLoadingState( isLoading ) {
|
||||
return {
|
||||
type: TYPES.SET_IS_LOADING,
|
||||
isLoading,
|
||||
};
|
||||
}
|
||||
|
||||
export function setNotice( notice ) {
|
||||
return {
|
||||
type: TYPES.SET_NOTICE,
|
||||
notice,
|
||||
};
|
||||
}
|
||||
|
||||
export function* importNotifications( notifications ) {
|
||||
try {
|
||||
yield apiFetch( {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
path: `${ API_NAMESPACE }/remote-inbox-notifications/import`,
|
||||
body: JSON.stringify( notifications ),
|
||||
} );
|
||||
|
||||
yield controls.dispatch(
|
||||
STORE_KEY,
|
||||
'invalidateResolutionForStoreSelector',
|
||||
'getNotifications'
|
||||
);
|
||||
} catch ( error ) {
|
||||
setNotice( {
|
||||
message: 'Failed to import notifications',
|
||||
status: 'error',
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
export function* deleteNotification( id ) {
|
||||
try {
|
||||
yield apiFetch( {
|
||||
method: 'POST',
|
||||
path: `${ API_NAMESPACE }/remote-inbox-notifications/${ id }/delete`,
|
||||
} );
|
||||
|
||||
yield {
|
||||
type: TYPES.DELETE_NOTIFICATION,
|
||||
id,
|
||||
};
|
||||
setNotice( {
|
||||
message: 'Notifications deleted successfully.',
|
||||
status: 'success',
|
||||
} );
|
||||
} catch {
|
||||
setNotice( {
|
||||
message: 'Failed to delete notification',
|
||||
status: 'error',
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
export function* testNotification( name ) {
|
||||
try {
|
||||
const response = yield apiFetch( {
|
||||
method: 'GET',
|
||||
path: `${ API_NAMESPACE }/remote-inbox-notifications/${ name }/test`,
|
||||
} );
|
||||
|
||||
if ( response.success ) {
|
||||
yield controls.dispatch(
|
||||
STORE_KEY,
|
||||
'invalidateResolutionForStoreSelector',
|
||||
'getNotifications'
|
||||
);
|
||||
}
|
||||
|
||||
yield setNotice( {
|
||||
message:
|
||||
typeof response.message === 'string'
|
||||
? response.message
|
||||
: 'The following rules have failed.\n\n' +
|
||||
JSON.stringify( response.message, null, 2 ),
|
||||
status: response.success ? 'success' : 'error',
|
||||
} );
|
||||
} catch ( e ) {
|
||||
setNotice( {
|
||||
message: 'Failed to test notification',
|
||||
status: 'error',
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
export function* deleteAllNotifications() {
|
||||
try {
|
||||
yield apiFetch( {
|
||||
method: 'POST',
|
||||
path: `${ API_NAMESPACE }/remote-inbox-notifications/delete-all`,
|
||||
} );
|
||||
|
||||
yield controls.dispatch(
|
||||
STORE_KEY,
|
||||
'invalidateResolutionForStoreSelector',
|
||||
'getNotifications'
|
||||
);
|
||||
|
||||
setNotice( {
|
||||
message: 'All notifications deleted successfully.',
|
||||
status: 'success',
|
||||
} );
|
||||
} catch {
|
||||
setNotice( {
|
||||
message: 'Failed to delete all notifications',
|
||||
status: 'error',
|
||||
} );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export const STORE_KEY = 'wc-admin-helper/remote-inbox-notifications';
|
||||
export const API_NAMESPACE = '/wc-admin-test-helper';
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerStore } from '@wordpress/data';
|
||||
import { controls } from '@wordpress/data-controls';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import * as actions from './actions';
|
||||
import * as resolvers from './resolvers';
|
||||
import * as selectors from './selectors';
|
||||
import reducer from './reducer';
|
||||
import { STORE_KEY } from './constants';
|
||||
|
||||
export default registerStore( STORE_KEY, {
|
||||
actions,
|
||||
selectors,
|
||||
resolvers,
|
||||
controls,
|
||||
reducer,
|
||||
} );
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import TYPES from './action-types';
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
notifications: [],
|
||||
isLoading: true,
|
||||
notice: {
|
||||
status: 'success',
|
||||
message: '',
|
||||
},
|
||||
};
|
||||
|
||||
const reducer = ( state = DEFAULT_STATE, action ) => {
|
||||
switch ( action.type ) {
|
||||
case TYPES.SET_IS_LOADING:
|
||||
return {
|
||||
...state,
|
||||
isLoading: action.isLoading,
|
||||
};
|
||||
case TYPES.SET_NOTIFICATIONS:
|
||||
return {
|
||||
...state,
|
||||
notifications: action.notifications,
|
||||
isLoading: false,
|
||||
};
|
||||
case TYPES.SET_NOTICE:
|
||||
return {
|
||||
...state,
|
||||
notice: {
|
||||
...state.notice,
|
||||
...action.notice,
|
||||
},
|
||||
};
|
||||
case TYPES.DELETE_NOTIFICATION:
|
||||
return {
|
||||
...state,
|
||||
notifications: state.notifications.filter(
|
||||
( item ) => item.note_id !== action.id
|
||||
),
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default reducer;
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { apiFetch } from '@wordpress/data-controls';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { setLoadingState, setNotifications } from './actions';
|
||||
|
||||
export function* getNotifications() {
|
||||
yield setLoadingState( true );
|
||||
|
||||
try {
|
||||
const response = yield apiFetch( {
|
||||
path: 'wc-admin-test-helper/remote-inbox-notifications',
|
||||
} );
|
||||
|
||||
yield setNotifications( response );
|
||||
} catch ( error ) {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export function getNotifications( state ) {
|
||||
return state.notifications;
|
||||
}
|
||||
|
||||
export function isLoading( state ) {
|
||||
return state.isLoading;
|
||||
}
|
||||
|
||||
export function getNotice( state ) {
|
||||
return state.notice;
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { Notice } from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { STORE_KEY } from './data/constants';
|
||||
import './data';
|
||||
|
||||
function RemoteInboxNotifications( {
|
||||
notifications,
|
||||
deleteNotification,
|
||||
importNotifications,
|
||||
deleteAllNotifications,
|
||||
testNotification,
|
||||
isLoading,
|
||||
notice,
|
||||
setNotice,
|
||||
} ) {
|
||||
const importFromUrl = async ( _url ) => {
|
||||
const preDefinedUrls = {
|
||||
staging:
|
||||
'https://staging.woocommerce.com/wp-json/wccom/inbox-notifications/2.0/notifications.json',
|
||||
production:
|
||||
'https://woocommerce.com/wp-json/wccom/inbox-notifications/2.0/notifications.json',
|
||||
};
|
||||
|
||||
const url = preDefinedUrls[ _url ] || _url;
|
||||
|
||||
try {
|
||||
const response = await fetch( url );
|
||||
const data = await response.json();
|
||||
importNotifications( data );
|
||||
setNotice( {
|
||||
message: 'Notifications imported successfully.',
|
||||
status: 'success',
|
||||
} );
|
||||
} catch ( error ) {
|
||||
if ( _url === 'staging' ) {
|
||||
const messages = {
|
||||
staging:
|
||||
'Failed to fetch notifications. Please make sure you are connected to Automattic proxy.',
|
||||
production: error.message,
|
||||
};
|
||||
setNotice( {
|
||||
message: messages[ _url ],
|
||||
status: 'error',
|
||||
} );
|
||||
}
|
||||
}
|
||||
};
|
||||
const renderLoading = () => {
|
||||
return (
|
||||
<tr>
|
||||
<td colSpan="6" align="center">
|
||||
Loading...
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
};
|
||||
|
||||
const renderTableData = () => {
|
||||
if ( notifications.length === 0 ) {
|
||||
return (
|
||||
<tr>
|
||||
<td colSpan="5" align="center">
|
||||
No Notifications Found
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
return notifications.map( ( notification, index ) => {
|
||||
return (
|
||||
<tr key={ index }>
|
||||
<td>{ notification.note_id }</td>
|
||||
<td>{ notification.name }</td>
|
||||
<td>{ notification.type }</td>
|
||||
<td>{ notification.status }</td>
|
||||
<td className="notification-actions">
|
||||
<button
|
||||
className="button btn"
|
||||
onClick={ () => {
|
||||
testNotification( notification.name );
|
||||
} }
|
||||
>
|
||||
Run
|
||||
</button>
|
||||
<button
|
||||
className="button btn-danger"
|
||||
onClick={ () => {
|
||||
if (
|
||||
confirm(
|
||||
'Are you sure you want to delete this notification?'
|
||||
)
|
||||
) {
|
||||
deleteNotification( notification.note_id );
|
||||
}
|
||||
} }
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
} );
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="wc-admin-test-helper-remote-inbox-notifications">
|
||||
<div className="action-btns">
|
||||
<input
|
||||
type="button"
|
||||
className="button btn-danger"
|
||||
value="Delete All"
|
||||
onClick={ () => {
|
||||
if (
|
||||
confirm(
|
||||
'Are you sure you want to delete all notifications?'
|
||||
)
|
||||
) {
|
||||
deleteAllNotifications();
|
||||
}
|
||||
} }
|
||||
/>
|
||||
<input
|
||||
type="button"
|
||||
className="button url"
|
||||
value="Import from URL"
|
||||
onClick={ () => {
|
||||
const url = prompt(
|
||||
'Enter the URL to import notifications from'
|
||||
);
|
||||
if ( url ) {
|
||||
importFromUrl( url );
|
||||
}
|
||||
} }
|
||||
/>
|
||||
<input
|
||||
type="button"
|
||||
className="button btn-primary staging"
|
||||
value="Import from staging"
|
||||
onClick={ () => {
|
||||
if (
|
||||
confirm(
|
||||
'Are you sure you want to import notifications from staging? Existing notifications will be overwritten.'
|
||||
)
|
||||
) {
|
||||
importFromUrl( 'staging' );
|
||||
}
|
||||
} }
|
||||
/>
|
||||
<input
|
||||
type="button"
|
||||
className="button btn-primary"
|
||||
value="Import from production"
|
||||
onClick={ () => {
|
||||
if (
|
||||
confirm(
|
||||
'Are you sure you want to import notifications from production? Existing notifications will be overwritten.'
|
||||
)
|
||||
) {
|
||||
importFromUrl( 'production' );
|
||||
}
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
{ notice.message.length > 0 && (
|
||||
<Notice
|
||||
status={ notice.status }
|
||||
onRemove={ () => {
|
||||
setNotice( { message: '' } );
|
||||
} }
|
||||
>
|
||||
<pre>{ notice.message }</pre>
|
||||
</Notice>
|
||||
) }
|
||||
<table className="wp-list-table striped table-view-list widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<td className="manage-column column-thumb">I.D</td>
|
||||
<td className="manage-column column-thumb">Name</td>
|
||||
<td className="manage-column column-thumb align-center">
|
||||
Type
|
||||
</td>
|
||||
<td className="manage-column column-thumb align-center">
|
||||
Status
|
||||
</td>
|
||||
<td className="manage-column column-thumb align-center"></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{ isLoading ? renderLoading() : renderTableData() }
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getNotifications, isLoading, getNotice } = select( STORE_KEY );
|
||||
const notifications = getNotifications();
|
||||
const notice = getNotice();
|
||||
|
||||
return {
|
||||
notice,
|
||||
notifications,
|
||||
isLoading: isLoading(),
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const {
|
||||
deleteNotification,
|
||||
importNotifications,
|
||||
deleteAllNotifications,
|
||||
testNotification,
|
||||
setNotice,
|
||||
} = dispatch( STORE_KEY );
|
||||
|
||||
return {
|
||||
testNotification,
|
||||
deleteAllNotifications,
|
||||
setNotice,
|
||||
deleteNotification,
|
||||
importNotifications,
|
||||
};
|
||||
} )
|
||||
)( RemoteInboxNotifications );
|
Loading…
Reference in New Issue