diff --git a/includes/class-newspack.php b/includes/class-newspack.php index e626ff304e..4376527fe5 100644 --- a/includes/class-newspack.php +++ b/includes/class-newspack.php @@ -151,6 +151,7 @@ private function includes() { // Audience Wizard. include_once NEWSPACK_ABSPATH . 'includes/wizards/audience/class-audience-wizard.php'; include_once NEWSPACK_ABSPATH . 'includes/wizards/audience/class-audience-campaigns.php'; + include_once NEWSPACK_ABSPATH . 'includes/wizards/audience/class-audience-donations.php'; // Network Wizard. include_once NEWSPACK_ABSPATH . 'includes/wizards/class-network-wizard.php'; diff --git a/includes/class-wizards.php b/includes/class-wizards.php index 3482fd7ad2..b2417dc625 100644 --- a/includes/class-wizards.php +++ b/includes/class-wizards.php @@ -56,6 +56,7 @@ public static function init() { 'advertising-sponsors' => new Advertising_Sponsors(), 'audience' => new Audience_Wizard(), 'audience-campaigns' => new Audience_Campaigns(), + 'audience-donations' => new Audience_Donations(), 'listings' => new Listings_Wizard(), 'network' => new Network_Wizard(), 'newsletters' => new Newsletters_Wizard(), diff --git a/includes/wizards/audience/class-audience-donations.php b/includes/wizards/audience/class-audience-donations.php new file mode 100644 index 0000000000..efe0126540 --- /dev/null +++ b/includes/wizards/audience/class-audience-donations.php @@ -0,0 +1,629 @@ +parent_slug, + $this->get_name(), + esc_html__( 'Donations', 'newspack-plugin' ), + $this->capability, + $this->slug, + [ $this, 'render_wizard' ] + ); + } + + /** + * Enqueue scripts and styles. + */ + public function enqueue_scripts_and_styles() { + if ( ! $this->is_wizard_page() ) { + return; + } + + parent::enqueue_scripts_and_styles(); + + wp_enqueue_script( 'newspack-wizards' ); + + \wp_localize_script( + 'newspack-wizards', + 'newspackAudienceDonations', + [ + 'emails' => Emails::get_emails( [ Reader_Revenue_Emails::EMAIL_TYPES['RECEIPT'] ], false ), + 'email_cpt' => Emails::POST_TYPE, + 'salesforce_redirect_url' => Salesforce::get_redirect_url(), + 'can_use_name_your_price' => Donations::can_use_name_your_price(), + ] + ); + } + + /** + * Prevent rendering of Donate block if Reader Revenue platform is set to 'other. + * + * @param string $block_content The block content about to be rendered. + * @param array $block The data of the block about to be rendered. + */ + public static function prevent_rendering_donate_block( $block_content, $block ) { + if ( + isset( $block['blockName'] ) + && 'newspack-blocks/donate' === $block['blockName'] + && Donations::is_platform_other() + ) { + return ''; + } + return $block_content; + } + + /** + * Register the endpoints needed for the wizard screens. + */ + public function register_api_endpoints() { + // Get all data required to render the Wizard. + \register_rest_route( + NEWSPACK_API_NAMESPACE, + '/wizard/' . $this->slug, + [ + 'methods' => \WP_REST_Server::READABLE, + 'callback' => [ $this, 'api_fetch' ], + 'permission_callback' => [ $this, 'api_permissions_check' ], + ] + ); + // Save basic data about reader revenue platform. + \register_rest_route( + NEWSPACK_API_NAMESPACE, + '/wizard/' . $this->slug, + [ + 'methods' => \WP_REST_Server::EDITABLE, + 'callback' => [ $this, 'api_update' ], + 'permission_callback' => [ $this, 'api_permissions_check' ], + 'args' => [ + 'platform' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + 'validate_callback' => [ $this, 'api_validate_platform' ], + ], + 'nrh_organization_id' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + 'validate_callback' => [ $this, 'api_validate_not_empty' ], + ], + 'nrh_custom_domain' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + ], + 'nrh_salesforce_campaign_id' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + ], + 'donor_landing_page' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + ], + ], + ] + ); + + // Save location info. + register_rest_route( + NEWSPACK_API_NAMESPACE, + '/wizard/' . $this->slug . '/location/', + [ + 'methods' => \WP_REST_Server::EDITABLE, + 'callback' => [ $this, 'api_update_location' ], + 'permission_callback' => [ $this, 'api_permissions_check' ], + 'args' => [ + 'countrystate' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + 'validate_callback' => [ $this, 'api_validate_not_empty' ], + ], + 'address1' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + 'validate_callback' => [ $this, 'api_validate_not_empty' ], + ], + 'address2' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + ], + 'city' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + 'validate_callback' => [ $this, 'api_validate_not_empty' ], + ], + 'postcode' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + 'validate_callback' => [ $this, 'api_validate_not_empty' ], + ], + 'currency' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + 'validate_callback' => [ $this, 'api_validate_not_empty' ], + ], + ], + ] + ); + + // Save Stripe info. + register_rest_route( + NEWSPACK_API_NAMESPACE, + '/wizard/' . $this->slug . '/stripe/', + [ + 'methods' => \WP_REST_Server::EDITABLE, + 'callback' => [ $this, 'api_update_stripe_settings' ], + 'permission_callback' => [ $this, 'api_permissions_check' ], + 'args' => [ + 'activate' => [ + 'sanitize_callback' => 'Newspack\newspack_string_to_bool', + ], + 'enabled' => [ + 'sanitize_callback' => 'Newspack\newspack_string_to_bool', + ], + 'location_code' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + ], + ], + ] + ); + + // Save WooPayments info. + register_rest_route( + NEWSPACK_API_NAMESPACE, + '/wizard/' . $this->slug . '/woopayments/', + [ + 'methods' => \WP_REST_Server::EDITABLE, + 'callback' => [ $this, 'api_update_woopayments_settings' ], + 'permission_callback' => [ $this, 'api_permissions_check' ], + 'args' => [ + 'activate' => [ + 'sanitize_callback' => 'Newspack\newspack_string_to_bool', + ], + 'enabled' => [ + 'sanitize_callback' => 'Newspack\newspack_string_to_bool', + ], + ], + ] + ); + + // Save additional settings info. + register_rest_route( + NEWSPACK_API_NAMESPACE, + '/wizard/' . $this->slug . '/settings/', + [ + 'methods' => \WP_REST_Server::EDITABLE, + 'callback' => [ $this, 'api_update_additional_settings' ], + 'permission_callback' => [ $this, 'api_permissions_check' ], + 'args' => [ + 'fee_multiplier' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + 'validate_callback' => function ( $value ) { + if ( (float) $value > 10 ) { + return new WP_Error( + 'newspack_invalid_param', + __( 'Fee multiplier must be smaller than 10.', 'newspack' ) + ); + } + return true; + }, + ], + 'fee_static' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + ], + 'allow_covering_fees' => [ + 'sanitize_callback' => 'Newspack\newspack_string_to_bool', + ], + 'allow_covering_fees_default' => [ + 'sanitize_callback' => 'Newspack\newspack_string_to_bool', + ], + 'allow_covering_fees_label' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + ], + 'location_code' => [ + 'sanitize_callback' => 'Newspack\newspack_clean', + ], + ], + ] + ); + + // Update Donations settings. + register_rest_route( + NEWSPACK_API_NAMESPACE, + '/wizard/' . $this->slug . '/donations/', + [ + 'methods' => \WP_REST_Server::EDITABLE, + 'callback' => [ $this, 'api_update_donation_settings' ], + 'permission_callback' => [ $this, 'api_permissions_check' ], + 'args' => [ + 'amounts' => [ + 'required' => false, + ], + 'tiered' => [ + 'required' => false, + 'sanitize_callback' => 'Newspack\newspack_string_to_bool', + ], + 'disabledFrequencies' => [ + 'required' => false, + ], + 'platform' => [ + 'required' => false, + 'sanitize_callback' => 'sanitize_text_field', + ], + ], + ] + ); + + // Save Salesforce settings. + register_rest_route( + NEWSPACK_API_NAMESPACE, + '/wizard/' . $this->slug . '/salesforce/', + [ + 'methods' => \WP_REST_Server::EDITABLE, + 'callback' => [ $this, 'api_update_salesforce_settings' ], + 'permission_callback' => [ $this, 'api_permissions_check' ], + 'args' => [ + 'client_id' => [ + 'sanitize_callback' => 'sanitize_text_field', + ], + 'client_secret' => [ + 'sanitize_callback' => 'sanitize_text_field', + ], + 'access_token' => [ + 'sanitize_callback' => 'sanitize_text_field', + ], + 'refresh_token' => [ + 'sanitize_callback' => 'sanitize_text_field', + ], + ], + ] + ); + + register_rest_route( + NEWSPACK_API_NAMESPACE, + '/wizard/' . $this->slug . '/donations/', + [ + 'methods' => \WP_REST_Server::READABLE, + 'callback' => [ $this, 'api_get_donation_settings' ], + 'permission_callback' => [ $this, 'api_permissions_check' ], + ] + ); + } + + /** + * Get all Wizard Data + * + * @return WP_REST_Response containing ad units info. + */ + public function api_fetch() { + return \rest_ensure_response( $this->fetch_all_data() ); + } + + /** + * Save top-level data. + * + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Boolean success. + */ + public function api_update( $request ) { + $params = $request->get_params(); + Donations::set_platform_slug( $params['platform'] ); + + // Update NRH settings. + if ( Donations::is_platform_nrh() ) { + NRH::update_settings( $params ); + } + + // Ensure that any Reader Revenue settings changed while the platform wasn't WC are persisted to WC products. + if ( Donations::is_platform_wc() ) { + Donations::update_donation_product( Donations::get_donation_settings() ); + } + + return \rest_ensure_response( $this->fetch_all_data() ); + } + + /** + * Save location info. + * + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Boolean success. + */ + public function api_update_location( $request ) { + $required_plugins_installed = $this->check_required_plugins_installed(); + if ( is_wp_error( $required_plugins_installed ) ) { + return rest_ensure_response( $required_plugins_installed ); + } + $wc_configuration_manager = Configuration_Managers::configuration_manager_class_for_plugin_slug( 'woocommerce' ); + + $params = $request->get_params(); + + $defaults = [ + 'countrystate' => '', + 'address1' => '', + 'address2' => '', + 'city' => '', + 'postcode' => '', + 'currency' => '', + ]; + + $args = wp_parse_args( $params, $defaults ); + $wc_configuration_manager->update_location( $args ); + + // @todo when is the best time to do this? + $wc_configuration_manager->set_smart_defaults(); + + return \rest_ensure_response( $this->fetch_all_data() ); + } + + /** + * Handler for setting Stripe settings. + * + * @param object $settings Stripe settings. + * @return WP_REST_Response with the latest settings. + */ + public function update_stripe_settings( $settings ) { + if ( ! empty( $settings['activate'] ) ) { + // If activating the Stripe Gateway plugin, let's enable it. + $settings = [ 'enabled' => true ]; + } + $result = Stripe_Connection::update_stripe_data( $settings ); + if ( \is_wp_error( $result ) ) { + return $result; + } + + return $this->fetch_all_data(); + } + + /** + * Handler for setting additional settings. + * + * @param object $settings Settings. + * @return WP_REST_Response with the latest settings. + */ + public function update_additional_settings( $settings ) { + if ( isset( $settings['allow_covering_fees'] ) ) { + update_option( 'newspack_donations_allow_covering_fees', $settings['allow_covering_fees'] ); + } + if ( isset( $settings['allow_covering_fees_default'] ) ) { + update_option( 'newspack_donations_allow_covering_fees_default', $settings['allow_covering_fees_default'] ); + } + + if ( isset( $settings['allow_covering_fees_label'] ) ) { + update_option( 'newspack_donations_allow_covering_fees_label', $settings['allow_covering_fees_label'] ); + } + if ( isset( $settings['fee_multiplier'] ) ) { + update_option( 'newspack_blocks_donate_fee_multiplier', $settings['fee_multiplier'] ); + } + if ( isset( $settings['fee_static'] ) ) { + update_option( 'newspack_blocks_donate_fee_static', $settings['fee_static'] ); + } + return $this->fetch_all_data(); + } + + /** + * Save Stripe settings. + * + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response. + */ + public function api_update_stripe_settings( $request ) { + $params = $request->get_params(); + $result = $this->update_stripe_settings( $params ); + return \rest_ensure_response( $result ); + } + + /** + * Save WooPayments settings. + * + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response. + */ + public function api_update_woopayments_settings( $request ) { + $wc_configuration_manager = Configuration_Managers::configuration_manager_class_for_plugin_slug( 'woocommerce' ); + + $params = $request->get_params(); + $result = $wc_configuration_manager->update_wc_woopayments_settings( $params ); + return \rest_ensure_response( $result ); + } + + /** + * Save additional payment method settings (e.g. transaction fees). + * + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response. + */ + public function api_update_additional_settings( $request ) { + $params = $request->get_params(); + $result = $this->update_additional_settings( $params ); + return \rest_ensure_response( $result ); + } + + /** + * Handler for setting the donation settings. + * + * @param object $settings Donation settings. + * @return WP_REST_Response with the latest settings. + */ + public function update_donation_settings( $settings ) { + $donations_response = Donations::set_donation_settings( $settings ); + if ( is_wp_error( $donations_response ) ) { + return rest_ensure_response( $donations_response ); + } + return \rest_ensure_response( $this->fetch_all_data() ); + } + + /** + * API endpoint for setting the donation settings. + * + * @param WP_REST_Request $request Request containing settings. + * @return WP_REST_Response with the latest settings. + */ + public function api_update_donation_settings( $request ) { + return $this->update_donation_settings( $request->get_params() ); + } + + /** + * API endpoint for setting Salesforce settings. + * + * @param WP_REST_Request $request Request containing settings. + * @return WP_REST_Response with the latest settings. + */ + public function api_update_salesforce_settings( $request ) { + $salesforce_response = Salesforce::set_salesforce_settings( $request->get_params() ); + if ( is_wp_error( $salesforce_response ) ) { + return rest_ensure_response( $salesforce_response ); + } + return \rest_ensure_response( $this->fetch_all_data() ); + } + + /** + * Fetch all data needed to render the Wizard + * + * @return Array + */ + public function fetch_all_data() { + $platform = Donations::get_platform_slug(); + $wc_configuration_manager = Configuration_Managers::configuration_manager_class_for_plugin_slug( 'woocommerce' ); + $wc_installed = 'active' === Plugin_Manager::get_managed_plugin_status( 'woocommerce' ); + $stripe_data = Stripe_Connection::get_stripe_data(); + + $billing_fields = []; + if ( $wc_installed && Donations::is_platform_wc() ) { + $checkout = new \WC_Checkout(); + $fields = $checkout->get_checkout_fields(); + if ( ! empty( $fields['billing'] ) ) { + $billing_fields = $fields['billing']; + } + } + + $args = [ + 'country_state_fields' => newspack_get_countries(), + 'currency_fields' => newspack_get_currencies_options(), + 'location_data' => [], + 'payment_gateways' => [ + 'stripe' => $stripe_data, + 'woopayments' => $wc_configuration_manager->woopayments_data(), + ], + 'additional_settings' => [ + 'allow_covering_fees' => get_option( 'newspack_donations_allow_covering_fees', true ), + 'allow_covering_fees_default' => get_option( 'newspack_donations_allow_covering_fees_default', false ), + 'allow_covering_fees_label' => get_option( 'newspack_donations_allow_covering_fees_label', '' ), + 'fee_multiplier' => get_option( 'newspack_blocks_donate_fee_multiplier', '2.9' ), + 'fee_static' => get_option( 'newspack_blocks_donate_fee_static', '0.3' ), + ], + 'donation_data' => Donations::get_donation_settings(), + 'donation_page' => Donations::get_donation_page_info(), + 'available_billing_fields' => $billing_fields, + 'salesforce_settings' => [], + 'platform_data' => [ + 'platform' => $platform, + ], + 'is_ssl' => is_ssl(), + 'errors' => [], + ]; + if ( 'wc' === $platform ) { + $plugin_status = true; + $managed_plugins = Plugin_Manager::get_managed_plugins(); + $required_plugins = [ + 'woocommerce', + 'woocommerce-subscriptions', + ]; + foreach ( $required_plugins as $required_plugin ) { + if ( 'active' !== $managed_plugins[ $required_plugin ]['Status'] ) { + $plugin_status = false; + } + } + $args = wp_parse_args( + [ + 'salesforce_settings' => Salesforce::get_salesforce_settings(), + 'plugin_status' => $plugin_status, + ], + $args + ); + } elseif ( Donations::is_platform_nrh() ) { + $nrh_config = NRH::get_settings(); + $args['platform_data'] = wp_parse_args( $nrh_config, $args['platform_data'] ); + } + return $args; + } + + /** + * API endpoint for getting donation settings. + * + * @return WP_REST_Response containing info. + */ + public function api_get_donation_settings() { + if ( Donations::is_platform_wc() ) { + $required_plugins_installed = $this->check_required_plugins_installed(); + if ( is_wp_error( $required_plugins_installed ) ) { + return rest_ensure_response( $required_plugins_installed ); + } + } + + return rest_ensure_response( Donations::get_donation_settings() ); + } + + /** + * Check whether WooCommerce is installed and active. + * + * @return bool | WP_Error True on success, WP_Error on failure. + */ + protected function check_required_plugins_installed() { + if ( ! function_exists( 'WC' ) ) { + return new WP_Error( + 'newspack_missing_required_plugin', + esc_html__( 'The WooCommerce plugin is not installed and activated. Install and/or activate it to access this feature.', 'newspack' ), + [ + 'status' => 400, + 'level' => 'fatal', + ] + ); + } + + return true; + } + + /** + * Validate platform ID. + * + * @param mixed $value A param value. + * @return bool + */ + public function api_validate_platform( $value ) { + return in_array( $value, [ 'nrh', 'wc', 'other' ] ); + } +} diff --git a/src/wizards/audience/components/billing-fields/index.tsx b/src/wizards/audience/components/billing-fields/index.tsx new file mode 100644 index 0000000000..e4bc900e88 --- /dev/null +++ b/src/wizards/audience/components/billing-fields/index.tsx @@ -0,0 +1,90 @@ +/** + * WordPress dependencies. + */ +import { useDispatch } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; +import { CheckboxControl } from '@wordpress/components'; + +/** + * Internal dependencies. + */ +import { + Button, + Card, + Grid, + SectionHeader, + Wizard, +} from '../../../../components/src'; + +const BillingFields = () => { + const wizardData = Wizard.useWizardData( 'reader-revenue' ) as ReaderRevenueWizardData; + const { updateWizardSettings, saveWizardSettings } = useDispatch( Wizard.STORE_NAMESPACE ); + + if ( ! wizardData.donation_data || 'errors' in wizardData.donation_data ) { + return null; + } + + const changeHandler = ( path: string[] ) => ( value: any ) => + updateWizardSettings( { + slug: 'newspack-reader-revenue-wizard', + path: [ 'donation_data', ...path ], + value, + } ); + + const onSave = () => + saveWizardSettings( { + slug: 'newspack-reader-revenue-wizard', + section: 'donations', + payloadPath: [ 'donation_data' ], + } ); + + const availableFields = wizardData.available_billing_fields; + if ( ! availableFields || ! Object.keys( availableFields ).length ) { + return null; + } + + const billingFields = wizardData.donation_data.billingFields.length + ? wizardData.donation_data.billingFields + : Object.keys( availableFields ); + + return ( + <> + + + + + { Object.keys( availableFields ).map( fieldKey => ( + { + let newFields = [ ...billingFields ]; + if ( billingFields.includes( fieldKey ) ) { + newFields = newFields.filter( field => field !== fieldKey ); + } else { + newFields = [ ...newFields, fieldKey ]; + } + changeHandler( [ 'billingFields' ] )( newFields ); + } } + /> + ) ) } + +
+ +
+ + ); +}; + +export default BillingFields; diff --git a/src/wizards/readerRevenue/components/money-input/index.js b/src/wizards/audience/components/money-input/index.js similarity index 100% rename from src/wizards/readerRevenue/components/money-input/index.js rename to src/wizards/audience/components/money-input/index.js diff --git a/src/wizards/readerRevenue/components/money-input/style.scss b/src/wizards/audience/components/money-input/style.scss similarity index 100% rename from src/wizards/readerRevenue/components/money-input/style.scss rename to src/wizards/audience/components/money-input/style.scss diff --git a/src/wizards/readerRevenue/views/nrh-settings/index.js b/src/wizards/audience/components/nrh-settings/index.js similarity index 87% rename from src/wizards/readerRevenue/views/nrh-settings/index.js rename to src/wizards/audience/components/nrh-settings/index.js index 8ebeab10dd..d2ed7e624d 100644 --- a/src/wizards/readerRevenue/views/nrh-settings/index.js +++ b/src/wizards/audience/components/nrh-settings/index.js @@ -48,8 +48,8 @@ const NRHSettings = () => { { __( 'Save Settings' ) } @@ -59,20 +59,20 @@ const NRHSettings = () => {
changeHandler( 'nrh_organization_id', value ) } /> changeHandler( 'nrh_custom_domain', value ) } /> changeHandler( 'nrh_salesforce_campaign_id', value ) } @@ -82,7 +82,7 @@ const NRHSettings = () => { { settings.hasOwnProperty( 'donor_landing_page' ) && (

-

{ __( 'Donor Landing Page', 'newspack' ) }

+

{ __( 'Donor Landing Page', 'newspack-plugin' ) }

{ __( 'Set a page on your site as a donor landing page. Once a reader donates and lands on this page, they will be considered a donor.', @@ -90,7 +90,7 @@ const NRHSettings = () => { ) }

{ return changeHandler( 'donor_landing_page', item ); } } postTypes={ [ { slug: 'page', label: 'Page' } ] } - postTypeLabel={ __( 'page', 'newspack' ) } - postTypeLabelPlural={ __( 'pages', 'newspack' ) } + postTypeLabel={ __( 'page', 'newspack-plugin' ) } + postTypeLabelPlural={ __( 'pages', 'newspack-plugin' ) } selectedItems={ selectedPage ? [ selectedPage ] : [] } />
diff --git a/src/wizards/readerRevenue/views/payment-methods/additional-settings.js b/src/wizards/audience/components/payment-methods/additional-settings.js similarity index 100% rename from src/wizards/readerRevenue/views/payment-methods/additional-settings.js rename to src/wizards/audience/components/payment-methods/additional-settings.js diff --git a/src/wizards/readerRevenue/views/payment-methods/index.js b/src/wizards/audience/components/payment-methods/index.js similarity index 100% rename from src/wizards/readerRevenue/views/payment-methods/index.js rename to src/wizards/audience/components/payment-methods/index.js diff --git a/src/wizards/readerRevenue/views/payment-methods/stripe.js b/src/wizards/audience/components/payment-methods/stripe.js similarity index 100% rename from src/wizards/readerRevenue/views/payment-methods/stripe.js rename to src/wizards/audience/components/payment-methods/stripe.js diff --git a/src/wizards/readerRevenue/views/payment-methods/style.scss b/src/wizards/audience/components/payment-methods/style.scss similarity index 100% rename from src/wizards/readerRevenue/views/payment-methods/style.scss rename to src/wizards/audience/components/payment-methods/style.scss diff --git a/src/wizards/readerRevenue/views/payment-methods/woopayments.js b/src/wizards/audience/components/payment-methods/woopayments.js similarity index 100% rename from src/wizards/readerRevenue/views/payment-methods/woopayments.js rename to src/wizards/audience/components/payment-methods/woopayments.js diff --git a/src/wizards/readerRevenue/views/platform/index.js b/src/wizards/audience/components/platform/index.js similarity index 100% rename from src/wizards/readerRevenue/views/platform/index.js rename to src/wizards/audience/components/platform/index.js diff --git a/src/wizards/readerRevenue/views/salesforce/index.js b/src/wizards/audience/components/salesforce/index.js similarity index 93% rename from src/wizards/readerRevenue/views/salesforce/index.js rename to src/wizards/audience/components/salesforce/index.js index 9712b61278..761b473b1c 100644 --- a/src/wizards/readerRevenue/views/salesforce/index.js +++ b/src/wizards/audience/components/salesforce/index.js @@ -19,7 +19,7 @@ import { PluginSettings, Notice, Wizard } from '../../../../components/src'; import { READER_REVENUE_WIZARD_SLUG } from '../../constants'; const Salesforce = () => { - const { salesforce_redirect_url: redirectUrl } = window?.newspack_reader_revenue || {}; + const { salesforce_redirect_url: redirectUrl } = window?.newspackAudienceDonations || {}; const [ hasCopied, setHasCopied ] = useState( false ); const { salesforce_settings: salesforceData = {} } = Wizard.useWizardData( 'reader-revenue' ); const [ isConnected, setIsConnected ] = useState( salesforceData.refresh_token ); @@ -73,7 +73,7 @@ const Salesforce = () => { setError( __( 'We couldn’t establish a connection to Salesforce. Please verify your Consumer Key and Secret and try connecting again.', - 'newspack' + 'newspack-plugin' ) ); } @@ -143,21 +143,21 @@ const Salesforce = () => { } } } pluginSlug="newspack/salesforce" - title={ __( 'Salesforce Settings', 'newspack' ) } + title={ __( 'Salesforce Settings', 'newspack-plugin' ) } description={ () => ( <> { error && } { isConnected && ! error && ( ) } { __( 'Establish a connection to sync WooCommerce order data to Salesforce. To connect with Salesforce, create or choose a Connected App for this site in your Salesforce dashboard. Make sure to paste the full URL for this page (', - 'newspack' + 'newspack-plugin' ) } { onFinishCopy={ () => setHasCopied( false ) } > { hasCopied - ? __( 'copied to clipboard!', 'newspack' ) - : __( 'copy to clipboard', 'newspack' ) } + ? __( 'copied to clipboard!', 'newspack-plugin' ) + : __( 'copy to clipboard', 'newspack-plugin' ) } { __( ') into the “Callback URL” field in the Connected App’s settings. ', - 'newspack' + 'newspack-plugin' ) } - { __( 'Learn how to create a Connected App', 'newspack' ) } + { __( 'Learn how to create a Connected App', 'newspack-plugin' ) } ) } diff --git a/src/wizards/readerRevenue/constants.js b/src/wizards/audience/constants.js similarity index 100% rename from src/wizards/readerRevenue/constants.js rename to src/wizards/audience/constants.js diff --git a/src/wizards/readerRevenue/views/donation/index.tsx b/src/wizards/audience/views/donations/configuration/index.tsx similarity index 62% rename from src/wizards/readerRevenue/views/donation/index.tsx rename to src/wizards/audience/views/donations/configuration/index.tsx index 7a49c143f3..19a3af95a1 100644 --- a/src/wizards/readerRevenue/views/donation/index.tsx +++ b/src/wizards/audience/views/donations/configuration/index.tsx @@ -3,14 +3,13 @@ */ import { useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; -import { ToggleControl, CheckboxControl } from '@wordpress/components'; +import { ToggleControl } from '@wordpress/components'; /** * Internal dependencies. */ -import { MoneyInput } from '../../components'; +import MoneyInput from '../../../components/money-input'; import { - ActionCard, Button, Card, Grid, @@ -19,8 +18,9 @@ import { SelectControl, TextControl, Wizard, -} from '../../../../components/src'; -import { READER_REVENUE_WIZARD_SLUG } from '../../constants'; +} from '../../../../../components/src'; +import WizardsTab from '../../../../wizards-tab'; +import { READER_REVENUE_WIZARD_SLUG } from '../../../constants'; type FrequencySlug = 'once' | 'month' | 'year'; @@ -42,43 +42,8 @@ const FREQUENCIES: { }; const FREQUENCY_SLUGS: FrequencySlug[] = Object.keys( FREQUENCIES ) as FrequencySlug[]; -type WizardData = { - donation_data: - | { errors: { [ key: string ]: string[] } } - | { - amounts: { - [ Key in FrequencySlug as string ]: [ number, number, number, number ]; - }; - disabledFrequencies: { - [ Key in FrequencySlug as string ]: boolean; - }; - currencySymbol: string; - tiered: boolean; - minimumDonation: string; - billingFields: string[]; - }; - platform_data: { - platform: string; - }; - donation_page: { - editUrl: string; - status: string; - }; - available_billing_fields: { - [ key: string ]: { - autocomplete: string; - class: string[]; - label: string; - priority: number; - required: boolean; - type: string; - validate: string[]; - }; - }; -}; - export const DonationAmounts = () => { - const wizardData = Wizard.useWizardData( 'reader-revenue' ) as WizardData; + const wizardData = Wizard.useWizardData( 'reader-revenue' ) as ReaderRevenueWizardData; const { updateWizardSettings } = useDispatch( Wizard.STORE_NAMESPACE ); if ( ! wizardData.donation_data || 'errors' in wizardData.donation_data ) { @@ -104,7 +69,7 @@ export const DonationAmounts = () => { const minimumDonationFloat = parseFloat( minimumDonation ); // Whether we can use the Name Your Price extension. If not, layout is forced to Tiered. - const canUseNameYourPrice = window.newspack_reader_revenue?.can_use_name_your_price; + const canUseNameYourPrice = window.newspackAudienceDonations?.can_use_name_your_price; return ( <> @@ -265,67 +230,8 @@ export const DonationAmounts = () => { ); }; -const BillingFields = () => { - const wizardData = Wizard.useWizardData( 'reader-revenue' ) as WizardData; - const { updateWizardSettings } = useDispatch( Wizard.STORE_NAMESPACE ); - - if ( ! wizardData.donation_data || 'errors' in wizardData.donation_data ) { - return null; - } - - const changeHandler = ( path: string[] ) => ( value: any ) => - updateWizardSettings( { - slug: 'newspack-reader-revenue-wizard', - path: [ 'donation_data', ...path ], - value, - } ); - - const availableFields = wizardData.available_billing_fields; - if ( ! availableFields || ! Object.keys( availableFields ).length ) { - return null; - } - - const billingFields = wizardData.donation_data.billingFields.length - ? wizardData.donation_data.billingFields - : Object.keys( availableFields ); - - return ( - <> - - - - - { Object.keys( availableFields ).map( fieldKey => ( - { - let newFields = [ ...billingFields ]; - if ( billingFields.includes( fieldKey ) ) { - newFields = newFields.filter( field => field !== fieldKey ); - } else { - newFields = [ ...newFields, fieldKey ]; - } - changeHandler( [ 'billingFields' ] )( newFields ); - } } - /> - ) ) } - - - ); -}; - const Donation = () => { - const wizardData = Wizard.useWizardData( 'reader-revenue' ) as WizardData; + const wizardData = Wizard.useWizardData( 'reader-revenue' ) as ReaderRevenueWizardData; const { saveWizardSettings } = useDispatch( Wizard.STORE_NAMESPACE ); const onSaveDonationSettings = () => saveWizardSettings( { @@ -334,71 +240,45 @@ const Donation = () => { payloadPath: [ 'donation_data' ], auxData: { saveDonationProduct: true }, } ); - const onSaveBillingFields = () => - saveWizardSettings( { - slug: READER_REVENUE_WIZARD_SLUG, - section: 'donations', - payloadPath: [ 'donation_data' ], - } ); return ( - <> - - { __( 'Save Donation Settings', 'newspack-plugin' ) } - - } - > - { wizardData.donation_page && ( - <> - - - - - { 'publish' === wizardData.donation_page.status ? ( - - ) : ( - - ) } - - ) } - - - - { __( 'Save Modal Checkout Settings', 'newspack-plugin' ) } - - } - > - - - + + { wizardData.donation_page && ( + <> + + + + + { 'publish' === wizardData.donation_page.status ? ( + + ) : ( + + ) } + + ) } + +
+ +
+
); }; diff --git a/src/wizards/readerRevenue/views/emails/index.js b/src/wizards/audience/views/donations/emails/index.js similarity index 93% rename from src/wizards/readerRevenue/views/emails/index.js rename to src/wizards/audience/views/donations/emails/index.js index e64cb745ae..b9cfed3303 100644 --- a/src/wizards/readerRevenue/views/emails/index.js +++ b/src/wizards/audience/views/donations/emails/index.js @@ -1,4 +1,4 @@ -/* globals newspack_reader_revenue*/ +/* globals newspackAudienceDonations */ /** * WordPress dependencies @@ -15,10 +15,10 @@ import values from 'lodash/values'; /** * Internal dependencies */ -import { PluginInstaller, ActionCard, Notice } from '../../../../components/src'; +import { PluginInstaller, ActionCard, Notice } from '../../../../../components/src'; -const EMAILS = values( newspack_reader_revenue.emails ); -const postType = newspack_reader_revenue.email_cpt; +const EMAILS = values( newspackAudienceDonations.emails ); +const postType = newspackAudienceDonations.email_cpt; const Emails = () => { const [ pluginsReady, setPluginsReady ] = useState( null ); diff --git a/src/wizards/audience/views/donations/index.js b/src/wizards/audience/views/donations/index.js new file mode 100644 index 0000000000..86de8f4f4e --- /dev/null +++ b/src/wizards/audience/views/donations/index.js @@ -0,0 +1,53 @@ +import '../../../../shared/js/public-path'; + +/** + * External dependencies. + */ +import values from 'lodash/values'; + +/** + * WordPress dependencies. + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies. + */ +import { Wizard, Notice, withWizard } from '../../../../components/src'; +import Configuration from './configuration'; +import Emails from './emails'; +import { READER_REVENUE_WIZARD_SLUG, NEWSPACK, OTHER } from '../../constants'; + +const AudienceDonations = () => { + const { platform_data, donation_data } = Wizard.useWizardData( 'reader-revenue' ); + const usedPlatform = platform_data?.platform; + const sections = [ + { + label: __( 'Configuration', 'newspack-plugin' ), + path: '/configuration', + render: Configuration, + isHidden: usedPlatform === OTHER, + }, + { + label: __( 'Emails', 'newspack-plugin' ), + path: '/emails', + render: Emails, + isHidden: usedPlatform !== NEWSPACK, + }, + ]; + return ( + + values( donation_data?.errors ).map( ( error, i ) => ( + + ) ) + } + requiredPlugins={ [ 'newspack-blocks' ] } + /> + ); +}; + +export default withWizard( AudienceDonations ); diff --git a/src/wizards/audience/views/setup/index.js b/src/wizards/audience/views/setup/index.js index ac41ffff83..48d4eac12c 100644 --- a/src/wizards/audience/views/setup/index.js +++ b/src/wizards/audience/views/setup/index.js @@ -19,7 +19,7 @@ import { withWizard } from '../../../../components/src'; import Router from '../../../../components/src/proxied-imports/router'; import ContentGating from './content-gating'; import TransactionalEmails from './transactional-emails'; -import WooCommerce from './woocommerce'; +import Payment from './payment'; const { HashRouter, Redirect, Route, Switch } = Router; @@ -90,7 +90,7 @@ function AudienceWizard( { pluginRequirements, wizardApiFetch } ) { }, { label: __( 'Checkout & Payment', 'newspack-plugin' ), - path: '/woocommerce', + path: '/payment', }, ]; tabs = tabs.filter( tab => tab ); @@ -139,9 +139,9 @@ function AudienceWizard( { pluginRequirements, wizardApiFetch } ) { ) } /> ( - + ) } /> + + { data?.platform_data?.platform === 'wc' && } + { data?.platform_data?.platform === 'nrh' && } +
+ + + ); +} ); diff --git a/src/wizards/audience/views/setup/setup.js b/src/wizards/audience/views/setup/setup.js index b36430d6ad..e6efefa215 100644 --- a/src/wizards/audience/views/setup/setup.js +++ b/src/wizards/audience/views/setup/setup.js @@ -28,6 +28,7 @@ import MetadataFields from '../../components/metadata-fields'; import Mailchimp from '../../components/mailchimp'; import { HANDOFF_KEY } from '../../../../components/src/consts'; import SortableNewsletterListControl from '../../../../components/src/sortable-newsletter-list-control'; +import Salesforce from '../../components/salesforce'; export default withWizardScreen( ( { config, fetchConfig, updateConfig, saveConfig, prerequisites, espSyncErrors, error, inFlight } ) => { const [ allReady, setAllReady ] = useState( false ); @@ -375,6 +376,8 @@ export default withWizardScreen( ( { config, fetchConfig, updateConfig, saveConf ) }
+
+ ) } diff --git a/src/wizards/audience/views/setup/woocommerce.js b/src/wizards/audience/views/setup/woocommerce.js deleted file mode 100644 index 294110c3ce..0000000000 --- a/src/wizards/audience/views/setup/woocommerce.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies. - */ -import { withWizardScreen } from '../../../../components/src'; -import WizardsTab from '../../../wizards-tab'; - -export default withWizardScreen( function () { - return ( - -

In progress.

- {/* TODO: Add Platform from `/wp-admin/admin.php?page=newspack-reader-revenue-wizard#/`*/} - {/* TODO: Add Modal Checkout Billing Fields Settings from `/wp-admin/admin.php?page=newspack-reader-revenue-wizard#/donations`*/} - {/* TODO: Add Stripe Setup from `/wp-admin/admin.php?page=newspack-reader-revenue-wizard#/stripe-setup`*/} - {/* TODO: Add Saleforce Settings from `/wp-admin/admin.php?page=newspack-reader-revenue-wizard#/salesforce`*/} -
- ); -} ); diff --git a/src/wizards/index.tsx b/src/wizards/index.tsx index f33c8dce93..1d6428594b 100644 --- a/src/wizards/index.tsx +++ b/src/wizards/index.tsx @@ -64,6 +64,15 @@ const components: Record< string, any > = { ) ), }, + 'newspack-audience-donations': { + label: __( 'Audience Donations', 'newspack-plugin' ), + component: lazy( + () => + import( + /* webpackChunkName: "audience-wizards" */ './audience/views/donations' + ) + ), + }, } as const; const AdminPageLoader = ( { label }: { label: string } ) => { diff --git a/src/wizards/readerRevenue/components/index.js b/src/wizards/readerRevenue/components/index.js deleted file mode 100644 index cea2a876da..0000000000 --- a/src/wizards/readerRevenue/components/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default as MoneyInput } from './money-input'; diff --git a/src/wizards/readerRevenue/index.js b/src/wizards/readerRevenue/index.js deleted file mode 100644 index 6ecd543329..0000000000 --- a/src/wizards/readerRevenue/index.js +++ /dev/null @@ -1,86 +0,0 @@ -import '../../shared/js/public-path'; - -/** - * External dependencies. - */ -import values from 'lodash/values'; - -/** - * WordPress dependencies. - */ -import { render, createElement } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies. - */ -import { Wizard, Notice } from '../../components/src'; -import * as Views from './views'; -import { READER_REVENUE_WIZARD_SLUG, NEWSPACK, NRH, OTHER } from './constants'; - -const ReaderRevenueWizard = () => { - const { platform_data, plugin_status, donation_data } = Wizard.useWizardData( 'reader-revenue' ); - const usedPlatform = platform_data?.platform; - const platformSection = { - label: __( 'Platform', 'newspack' ), - path: '/', - render: Views.Platform, - }; - - let sections = [ - { - label: __( 'Donations', 'newspack' ), - path: '/donations', - render: Views.Donation, - isHidden: usedPlatform === OTHER, - }, - { - label: __( 'Payment Methods', 'newspack' ), - path: '/payment-methods', - activeTabPaths: [ '/payment-methods' ], - render: Views.StripeSetup, - isHidden: usedPlatform !== NEWSPACK, - }, - { - label: __( 'Emails', 'newspack' ), - path: '/emails', - render: Views.Emails, - isHidden: usedPlatform !== NEWSPACK, - }, - { - label: __( 'Salesforce', 'newspack' ), - path: '/salesforce', - render: Views.Salesforce, - isHidden: usedPlatform !== NEWSPACK, - }, - { - label: __( 'News Revenue Hub Settings', 'newspack' ), - path: '/settings', - render: Views.NRHSettings, - isHidden: usedPlatform !== NRH, - }, - platformSection, - ]; - if ( usedPlatform === NEWSPACK && ! plugin_status ) { - sections = [ platformSection ]; - } - return ( - - values( donation_data?.errors ).map( ( error, i ) => ( - - ) ) - } - requiredPlugins={ [ 'newspack-blocks' ] } - /> - ); -}; - -render( - createElement( ReaderRevenueWizard ), - document.getElementById( 'newspack-reader-revenue-wizard' ) -); diff --git a/src/wizards/readerRevenue/views/index.js b/src/wizards/readerRevenue/views/index.js deleted file mode 100644 index c92ff44a8c..0000000000 --- a/src/wizards/readerRevenue/views/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export { default as Donation } from './donation'; -export { default as NRHSettings } from './nrh-settings'; -export { default as Platform } from './platform'; -export { default as StripeSetup } from './payment-methods'; -export { default as Emails } from './emails'; -export { default as Salesforce } from './salesforce'; diff --git a/src/wizards/setup/views/services/ReaderRevenue.js b/src/wizards/setup/views/services/ReaderRevenue.js index dc48df0436..b6c1b46639 100644 --- a/src/wizards/setup/views/services/ReaderRevenue.js +++ b/src/wizards/setup/views/services/ReaderRevenue.js @@ -12,8 +12,8 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import Platform from '../../../readerRevenue/views/platform'; -import { DonationAmounts } from '../../../readerRevenue/views/donation'; +import Platform from '../../../audience/components/platform'; +import { DonationAmounts } from '../../../audience/views/donations/configuration'; import { Wizard } from '../../../../components/src'; const ReaderRevenue = ( { className } ) => { diff --git a/src/wizards/types/hooks.d.ts b/src/wizards/types/hooks.d.ts index b34eb5f484..1528554702 100644 --- a/src/wizards/types/hooks.d.ts +++ b/src/wizards/types/hooks.d.ts @@ -56,3 +56,41 @@ type WizardData = { type WizardSelector = { getWizardData: ( slug: string ) => WizardData; }; + +/** + * Reader Revenue Wizard Data + */ +type ReaderRevenueWizardData = { + donation_data: + | { errors: { [ key: string ]: string[] } } + | { + amounts: { + [ Key in FrequencySlug as string ]: [ number, number, number, number ]; + }; + disabledFrequencies: { + [ Key in FrequencySlug as string ]: boolean; + }; + currencySymbol: string; + tiered: boolean; + minimumDonation: string; + billingFields: string[]; + }; + platform_data: { + platform: string; + }; + donation_page: { + editUrl: string; + status: string; + }; + available_billing_fields: { + [ key: string ]: { + autocomplete: string; + class: string[]; + label: string; + priority: number; + required: boolean; + type: string; + validate: string[]; + }; + }; +}; \ No newline at end of file diff --git a/src/wizards/types/window.d.ts b/src/wizards/types/window.d.ts index 12f67b0897..c7df99e387 100644 --- a/src/wizards/types/window.d.ts +++ b/src/wizards/types/window.d.ts @@ -45,7 +45,7 @@ declare global { name: string; } >; }; - newspack_reader_revenue: { + newspackAudienceDonations: { can_use_name_your_price: boolean; }; }