Skip to content

Commit

Permalink
Merge branch 'epic/campaigns' into fix/campaign-page-back-button-GIVE…
Browse files Browse the repository at this point in the history
…-2142
  • Loading branch information
kjohnson authored Feb 21, 2025
2 parents ffcd43a + 8a5e425 commit f01f3d6
Show file tree
Hide file tree
Showing 55 changed files with 1,064 additions and 547 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,11 @@ public function create( $args ) {
);

give_set_error('stripe_payment_intent_error',
__('There was an issue with your donation transaction. Please check your payment method or contact your card issuer for assistance. If the issue persists, try a different payment method or contact the site administrators.',
'give'));
sprintf(
__('There was an issue with your donation transaction: %s<br>Please check your payment method or contact your card issuer for assistance. If the issue persists, try a different payment method or contact the site administrators.', 'give'),
$e->getMessage()
)
);

return false;
} // End try().
Expand Down
5 changes: 5 additions & 0 deletions includes/payments/actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ function give_record_status_change( $payment_id, $new_status, $old_status ) {
$old_status = isset( $stati[ $old_status ] ) ? $stati[ $old_status ] : $old_status;
$new_status = isset( $stati[ $new_status ] ) ? $stati[ $new_status ] : $new_status;

// Skip recording payment status change if there is no update
if ( $old_status === $new_status ) {
return;
}

// translators: 1: old status 2: new status.
$status_change = sprintf( esc_html__( 'Status changed from %1$s to %2$s.', 'give' ), $old_status, $new_status );

Expand Down
188 changes: 23 additions & 165 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"@fortawesome/free-solid-svg-icons": "^5.15.1",
"@fortawesome/react-fontawesome": "^0.1.12",
"@givewp/design-system-foundation": "^1.2.0",
"@givewp/form-builder-library": "^1.7.0",
"@givewp/form-builder-library": "^1.7.1",
"@hookform/error-message": "^2.0.1",
"@hookform/resolvers": "^2.9.10",
"@paypal/paypal-js": "^5.1.4",
Expand All @@ -91,7 +91,6 @@
"@wordpress/interface": "^5.11.0",
"@wordpress/server-side-render": "^4.2.0",
"accounting": "^0.4.1",
"ajv": "^7.0.4",
"axios": "^1.7.9",
"chart.js": "^2.9.3",
"chartjs-plugin-crosshair": "^1.1.4",
Expand Down Expand Up @@ -120,7 +119,6 @@
"react-a11y-dialog": "^6.1.5",
"react-acceptjs": "^0.3.0",
"react-ace": "^10.1.0",
"react-apexcharts": "^1.4.1",
"react-aria-components": "^1.0.0-alpha.6",
"react-beautiful-dnd": "^13.1.1",
"react-csv": "^2.0.1",
Expand Down
7 changes: 7 additions & 0 deletions src/Campaigns/Actions/LoadCampaignOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,19 @@ public function __invoke()

wp_localize_script('give-campaign-options', 'GiveCampaignOptions',
[
'isAdmin' => is_admin(),
'adminUrl' => admin_url(),
'campaignsAdminUrl' => admin_url('edit.php?post_type=give_forms&page=give-campaigns'),
'currency' => give_get_currency(),
'currencySymbol' => give_currency_symbol(),
'isRecurringEnabled' => defined('GIVE_RECURRING_VERSION')
? GIVE_RECURRING_VERSION
: null,
'admin' => is_admin()
? [
'showCampaignInteractionNotice' => !get_user_meta(get_current_user_id(), 'givewp_show_campaign_interaction_notice', true),
]
: null,
]
);

Expand Down
35 changes: 26 additions & 9 deletions src/Campaigns/Actions/RegisterCampaignBlocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,36 +18,53 @@ public function __invoke()

array_map('register_block_type', $blocks);

if (is_admin()) {
$this->enqueueAdminBlocksAssets();
}

$this->registerSharedStyles();
}

/**
* @unreleased
*/
private function enqueueAdminBlocksAssets(): void
public function loadBlockEditorAssets(): void
{
$handleName = 'givewp-campaign-blocks';
global $post;

$scriptAsset = ScriptAsset::get(GIVE_PLUGIN_DIR . 'build/campaignBlocks.asset.php');

wp_register_script(
$handleName,
'givewp-campaign-blocks',
GIVE_PLUGIN_URL . 'build/campaignBlocks.js',
$scriptAsset['dependencies'],
$scriptAsset['version'],
true
);

wp_enqueue_script($handleName);
wp_enqueue_script('givewp-campaign-blocks');
wp_enqueue_style(
$handleName,
'givewp-campaign-blocks',
GIVE_PLUGIN_URL . 'build/campaignBlocks.css',
['wp-components'],
$scriptAsset['version']
);

if ($post && $post->post_type === 'give_campaign_page') {
$scriptAsset = ScriptAsset::get(GIVE_PLUGIN_DIR . 'build/campaignBlocksLandingPage.asset.php');

wp_register_script(
'givewp-campaign-landing-page-blocks',
GIVE_PLUGIN_URL . 'build/campaignBlocksLandingPage.js',
$scriptAsset['dependencies'],
$scriptAsset['version'],
true
);

wp_enqueue_script('givewp-campaign-landing-page-blocks');
wp_enqueue_style(
'givewp-campaign-landing-page-blocks',
GIVE_PLUGIN_URL . 'build/campaignBlocksLandingPage.css',
['wp-components'],
$scriptAsset['version']
);
}
}

/**
Expand Down
36 changes: 36 additions & 0 deletions src/Campaigns/Blocks/Campaign/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {createRoot} from '@wordpress/element';
import {CampaignBlockType} from './types';
import useCampaign from '../shared/hooks/useCampaign';
import CampaignCard from '../shared/components/CampaignCard';

const BlockApp = ({attributes}: { attributes: CampaignBlockType }) => {
const {campaign, hasResolved} = useCampaign(attributes?.campaignId);

if (!hasResolved) {
return null;
}

return (
<CampaignCard
campaign={campaign}
showImage={attributes?.showImage}
showDescription={attributes?.showDescription}
showGoal={attributes?.showGoal}
/>
);
}

/**
* @unreleased
*/
const nodeList = document.querySelectorAll('[data-givewp-campaign-block]');

if (nodeList) {
const containers = Array.from(nodeList);

containers.map((container: any) => {
const attributes: CampaignBlockType = JSON.parse(container.dataset?.attributes);
const root = createRoot(container);
return root.render(<BlockApp attributes={attributes} />)
});
}
39 changes: 39 additions & 0 deletions src/Campaigns/Blocks/Campaign/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"$schema": "https://json.schemastore.org/block.json",
"apiVersion": 2,
"name": "givewp/campaign-block",
"version": "1.0.0",
"title": "Campaign Block",
"category": "give",
"description": "Insert an existing campaign into the page.",
"supports": {
"align": [
"wide",
"full",
"left",
"center",
"right"
]
},
"attributes": {
"campaignId": {
"type": "number"
},
"showImage": {
"type": "boolean",
"default": true
},
"showDescription": {
"type": "boolean",
"default": true
},
"showGoal": {
"type": "boolean",
"default": true
}
},
"textdomain": "give",
"viewScript": "file:../../../../build/campaignBlockApp.js",
"viewStyle": "file:../../../../build/campaignBlockApp.css",
"render": "file:./render.php"
}
148 changes: 148 additions & 0 deletions src/Campaigns/Blocks/Campaign/edit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import {__} from '@wordpress/i18n';
import React, {CSSProperties, useState} from 'react';
import {InspectorControls, useBlockProps} from '@wordpress/block-editor';
import {BlockEditProps} from '@wordpress/blocks';
import {PanelBody, ToggleControl} from '@wordpress/components';
import {CampaignBlockType} from './types';
import CampaignSelector from '../shared/components/CampaignSelector';
import CampaignCard from '../shared/components/CampaignCard';
import {BlockNotice} from '@givewp/form-builder-library';
import {getCampaignOptionsWindowData, useCampaignEntityRecord} from '@givewp/campaigns/utils';


const styles = {
title: {
fontWeight: 600
},
notice: {
position: 'relative',
display: 'flex',
flexDirection: 'column',
gap: 8,
padding: 16,
borderRadius: 2,
color: '#0e0e0e',
background: '#f2f2f2',
fontSize: 12,
lineHeight: 1.33,
},
close: {
position: 'absolute',
cursor: 'pointer',
right: 16,
top: 16,
},
link: {
color: '#0e0e0e',
}
} as CSSProperties;

const CloseIcon = () => (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M11.805 5.138a.667.667 0 1 0-.943-.943L8 7.057 5.138 4.195a.667.667 0 1 0-.943.943L7.057 8l-2.862 2.862a.667.667 0 1 0 .943.943L8 8.943l2.862 2.862a.667.667 0 1 0 .943-.943L8.943 8l2.862-2.862z"
fill="#0E0E0E" />
</svg>
)

export default function Edit({attributes, setAttributes}: BlockEditProps<CampaignBlockType>) {
const blockProps = useBlockProps();
const campaignWindowData = getCampaignOptionsWindowData();
const [showNotification, setShowNotification] = useState(campaignWindowData.admin.showCampaignInteractionNotice);
const {campaign, hasResolved, edit, save} = useCampaignEntityRecord(attributes.campaignId);


const enableCampaignPage = (e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault()
edit({enableCampaignPage: true});
save();
}

const Notices = () => {
if (!attributes.campaignId) {
return null;
}

if (campaign.enableCampaignPage) {
if (!showNotification) {
return null;
}

return (
<p style={styles['notice']}>
<span
style={styles['close']}
onClick={() => {
fetch(campaignWindowData.adminUrl + '/admin-ajax.php?action=givewp_campaign_interaction_notice', {method: 'POST'})
.then(() => setShowNotification(false))
}}>
<CloseIcon />
</span>
<span style={styles['title']}>
{__('Campaign interaction', 'give ')}
</span>
<span>
{__('Users will be redirected to campaign page.', 'give')}
</span>
</p>
)
}

return (
<BlockNotice
title={__('Campaign page has been disabled for this campaign.', 'give ')}
description={__('For this campaign block to work properly, enable the campaign page for this campaign.', 'give')}
>
<a
href="#"
onClick={(e) => enableCampaignPage(e)}
style={styles['link']}
>
{__('Enable campaign page.', 'give')}
</a>
</BlockNotice>
)
};

return (
<div {...blockProps}>
{hasResolved && (
<>
<CampaignSelector
campaignId={attributes.campaignId}
handleSelect={(campaignId: number) => setAttributes({campaignId})}
showInspectorControl={true}
inspectorControls={<Notices />}
>
<CampaignCard
campaign={campaign}
showImage={attributes.showImage}
showDescription={attributes.showDescription}
showGoal={attributes.showGoal}
/>
</CampaignSelector>

<InspectorControls>
<PanelBody title={__('Display Elements', 'give')} initialOpen={true}>
<ToggleControl
label={__('Show campaign image', 'give')}
checked={attributes.showImage}
onChange={(showImage) => setAttributes({showImage})}
/>
<ToggleControl
label={__('Show description', 'give')}
checked={attributes.showDescription}
onChange={(showDescription) => setAttributes({showDescription})}
/>
<ToggleControl
label={__('Show goal', 'give')}
checked={attributes.showGoal}
onChange={(showGoal) => setAttributes({showGoal})}
/>
</PanelBody>
</InspectorControls>
</>
)}
</div>
)
}
15 changes: 15 additions & 0 deletions src/Campaigns/Blocks/Campaign/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import edit from './edit';
import GiveIcon from '@givewp/components/GiveIcon';
import schema from './block.json';

/**
* @unreleased
*/
export default {
schema,
settings: {
icon: <GiveIcon color="grey" />,
edit,
},
};

18 changes: 18 additions & 0 deletions src/Campaigns/Blocks/Campaign/render.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

use Give\Campaigns\Models\Campaign;

/**
* @var array $attributes
* @var Campaign $campaign
*/

if (
! isset($attributes['campaignId'])
|| ! Campaign::find($attributes['campaignId'])
) {
return;
}

?>
<div data-givewp-campaign-block data-attributes=<?= json_encode($attributes) ?>></div>
Loading

0 comments on commit f01f3d6

Please sign in to comment.