diff --git a/src/Campaigns/Blocks/CampaignCover/Icon.tsx b/src/Campaigns/Blocks/CampaignCover/Icon.tsx new file mode 100644 index 0000000000..6c893fba1c --- /dev/null +++ b/src/Campaigns/Blocks/CampaignCover/Icon.tsx @@ -0,0 +1,16 @@ +import {Path, SVG} from "@wordpress/components"; + +export function GalleryIcon() { + return ( + + ); +} diff --git a/src/Campaigns/Blocks/CampaignCover/block.json b/src/Campaigns/Blocks/CampaignCover/block.json new file mode 100644 index 0000000000..a3f58c4d89 --- /dev/null +++ b/src/Campaigns/Blocks/CampaignCover/block.json @@ -0,0 +1,88 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "givewp/campaign-cover-block", + "version": "1.0.0", + "title": "Campaign Cover", + "category": "give", + "description": "Displays the cover image of the campaign.", + "attributes": { + "campaignId": { + "type": "integer" + }, + "alt": { + "type": "string" + }, + "width": { + "type": "number", + "default": 645 + }, + "height": { + "type": "number", + "default": 865 + }, + "align": { + "type": "string", + "default": "" + } + }, + "supports": { + "align": [ + "wide", + "full", + "left", + "center", + "right" + ], + "filter": { + "duotone": true + }, + "selectors": { + "filter": { + "duotone": ".wp-block-givewp-campaign-cover-block img" + } + }, + "anchor": true, + "className": true, + "splitting": true, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true + }, + "color": { + "gradients": true, + "link": true, + "__experimentalDefaultControls": { + "background": true, + "text": true + } + }, + "spacing": { + "margin": true, + "padding": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontStyle": true, + "__experimentalFontWeight": true, + "__experimentalLetterSpacing": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalWritingMode": true, + "__experimentalDefaultControls": { + "fontSize": true + } + } + }, + "textdomain": "give", + "render": "file:./render.php", + "style": "file:./style.css" +} diff --git a/src/Campaigns/Blocks/CampaignCover/edit.tsx b/src/Campaigns/Blocks/CampaignCover/edit.tsx new file mode 100644 index 0000000000..99e1a3d539 --- /dev/null +++ b/src/Campaigns/Blocks/CampaignCover/edit.tsx @@ -0,0 +1,143 @@ +import {InspectorControls, useBlockProps} from '@wordpress/block-editor'; +import {__} from '@wordpress/i18n'; +import {useSelect} from '@wordpress/data'; +import {external} from '@wordpress/icons'; +import {BaseControl, Icon, PanelBody, Placeholder, ResizableBox, TextareaControl} from '@wordpress/components'; +import {BlockEditProps} from '@wordpress/blocks'; +import {CampaignSelector} from '../shared/components/CampaignSelector'; +import useCampaign from '../shared/hooks/useCampaign'; +import {GalleryIcon} from "./Icon"; + +import './editor.scss'; + +interface EditProps extends BlockEditProps<{ + campaignId: number; + alt: string; + width: number; + height: number; + align: string; +}> { + toggleSelection: (isSelected: boolean) => void; +} + +export default function Edit({attributes, setAttributes, toggleSelection}: EditProps) { + const blockProps = useBlockProps(); + const {campaign, hasResolved} = useCampaign(attributes.campaignId); + + const adminBaseUrl = useSelect( + // @ts-ignore + (select) => select('core').getSite()?.url + '/wp-admin/edit.php?post_type=give_forms&page=give-campaigns', + [] + ); + const editCampaignUrl = `${adminBaseUrl}&id=${attributes.campaignId}&tab=settings`; + + const handleResizeStop = (event: MouseEvent | TouchEvent, direction, refToElement: HTMLDivElement, delta: { + height: number, + width: number + }) => { + setAttributes({ + height: attributes.height + delta.height, + width: attributes.width + delta.width, + }); + toggleSelection(true); + }; + + const isSizeAligned = attributes.align === 'full' || attributes.align === 'wide'; + + return ( +
+ + {hasResolved && !campaign?.image && ( + } + label={__('Campaign Cover Image', 'give')} + instructions={__('Upload a cover image for your campaign.', 'give')} + /> + + )} + + {hasResolved && campaign?.image && + (!isSizeAligned ? ( + { + toggleSelection(false); + }} + onResizeStop={handleResizeStop} + enable={{ + bottom: true, + right: true, + bottomRight: false, + top: false, + left: false, + topLeft: false, + topRight: true, + bottomLeft: false, + }} + > + {attributes.alt + + ) : ( + {attributes.alt + ))} + + + {hasResolved && campaign && ( + + + + {campaign?.image && ( + {attributes.alt + )} +

+ {__('Shows the cover image of the campaign.', 'give')} +

+ + {__('Change campaign cover', 'give')} + + +
+ setAttributes({alt: value})} + /> +
+
+ )} +
+ ); +} diff --git a/src/Campaigns/Blocks/CampaignCover/editor.scss b/src/Campaigns/Blocks/CampaignCover/editor.scss new file mode 100644 index 0000000000..223da9c73a --- /dev/null +++ b/src/Campaigns/Blocks/CampaignCover/editor.scss @@ -0,0 +1,61 @@ +.givewp-campaign-cover-block { + &__button { + display: flex; + align-items: center; + justify-content: center; + min-height: 32px; + width: 100%; + margin-bottom: .5rem; + color: #2271b1; + border: 1px solid #2271b1; + border-radius: 2px; + } + + &__image { + flex-grow: 1; + display: flex; + max-height: 4.44rem; + width: 100%; + object-fit: cover; + margin-bottom: .5rem; + border-radius: 2px; + } + + &__help-text { + font-size: 0.75rem; + font-weight: normal; + font-stretch: normal; + font-style: normal; + line-height: 1.4; + letter-spacing: normal; + text-align: left; + color: #4b5563; + } + + &__edit-campaign-link { + display: inline-flex; + align-items: center; + gap: 0.125rem; + font-size: 0.75rem; + font-weight: normal; + font-stretch: normal; + font-style: normal; + line-height: 1.4; + + svg { + fill: currentColor; + height: 1.25rem; + width: 1.25rem; + } + } +} + +.givewp-campaign-cover-block-preview { + &__image { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + } +} diff --git a/src/Campaigns/Blocks/CampaignCover/index.tsx b/src/Campaigns/Blocks/CampaignCover/index.tsx new file mode 100644 index 0000000000..f83ac0465b --- /dev/null +++ b/src/Campaigns/Blocks/CampaignCover/index.tsx @@ -0,0 +1,14 @@ +import metadata from './block.json'; +import Edit from './edit'; +import initBlock from '../shared/utils/init-block'; +import {GalleryIcon} from './Icon'; + +const {name} = metadata; + +export {metadata, name}; +export const settings = { + edit: Edit, + icon: , +}; + +export const init = () => initBlock({name, metadata, settings}); diff --git a/src/Campaigns/Blocks/CampaignCover/render.php b/src/Campaigns/Blocks/CampaignCover/render.php new file mode 100644 index 0000000000..b1d9a300b3 --- /dev/null +++ b/src/Campaigns/Blocks/CampaignCover/render.php @@ -0,0 +1,42 @@ +getById($attributes['campaignId']); + +if ( ! $campaign) { + return; +} + +$campaignMediaSetting = $campaign->image; + +$altText = $attributes['alt'] ?? __('Campaign cover image', 'give'); +$alignment = isset($attributes['align']) ? 'align' . $attributes['align'] : ''; + +// Only assign width and height if the alignment is NOT "full" or "wide" +if ($attributes['align'] !== 'full' && $attributes['align'] !== 'wide') { + $width = isset($attributes['width']) ? $attributes['width'] : '100%'; + $height = isset($attributes['height']) ? $attributes['height'] : '100%'; +} else { + $width = 'auto'; + $height = 'auto'; +} +?> + + +
+ <?php echo esc_attr($altText); ?> +
diff --git a/src/Campaigns/Blocks/blocks.ts b/src/Campaigns/Blocks/blocks.ts index a42f34ca1d..137a02e5cd 100644 --- a/src/Campaigns/Blocks/blocks.ts +++ b/src/Campaigns/Blocks/blocks.ts @@ -1,7 +1,8 @@ import * as campaignTitleBlock from './CampaignTitleBlock'; +import * as campaignCover from './CampaignCover'; const getAllBlocks = () => { - return [campaignTitleBlock]; + return [campaignTitleBlock, campaignCover]; }; getAllBlocks().forEach((block) => { diff --git a/src/Campaigns/resources/admin/components/CampaignDetailsPage/Tabs/Settings.tsx b/src/Campaigns/resources/admin/components/CampaignDetailsPage/Tabs/Settings.tsx index 214b23eedc..9eb9d1b32c 100644 --- a/src/Campaigns/resources/admin/components/CampaignDetailsPage/Tabs/Settings.tsx +++ b/src/Campaigns/resources/admin/components/CampaignDetailsPage/Tabs/Settings.tsx @@ -126,10 +126,10 @@ export default () => {
- {__('Add a cover image or video for your campaign.', 'give')} + {__('Add a cover image for your campaign.', 'give')}
- {__('Upload an image or video to represent and inspire your campaign.', 'give')} + {__('Upload an image to represent and inspire your campaign.', 'give')}
- + - {__('Upload an image or video to represent and inspire your campaign.', 'give')} + {__('Upload an image to represent and inspire your campaign.', 'give')} {actionLabel} -

{__('or drag your image or video here', 'give')}

+

{__('or drag your image here', 'give')}

)}
diff --git a/src/Campaigns/resources/admin/components/Inputs/Upload/styles.scss b/src/Campaigns/resources/admin/components/Inputs/Upload/styles.scss index c81bae5329..84e0e563e2 100644 --- a/src/Campaigns/resources/admin/components/Inputs/Upload/styles.scss +++ b/src/Campaigns/resources/admin/components/Inputs/Upload/styles.scss @@ -4,19 +4,23 @@ div.media-modal.wp-core-ui { .givewp-media-library-drop-area { text-align: center; - padding: 1rem 0 0 0; + padding: var(--givewp-spacing-8) 0; border: 1px dotted; - border-radius: 4px; + border-radius: var(--givewp-rounded-4); button { cursor: pointer; width: fit-content; - margin: 8px auto; - background: #E5E7EB; + margin: var(--givewp-spacing-4) auto var(--givewp-spacing-2); + background: var(--givewp-neutral-100); height: initial; border: initial; - padding: 4px 8px 4px 8px; - border-radius: 4px + padding: var(--givewp-spacing-1) var(--givewp-spacing-2); + border-radius: var(--givewp-rounded-4); + } + + p, svg { + margin: 0; } } @@ -66,7 +70,7 @@ div.media-modal.wp-core-ui { object-fit: cover; object-position: center; transition: filter 0.3s ease; - border-radius: 4px; + border-radius: var(--givewp-rounded-4); cursor: pointer; &:hover { @@ -96,7 +100,7 @@ div.media-modal.wp-core-ui { align-items: center; gap: 0.5rem; cursor: pointer; - border-radius: 4px; + border-radius: var(--givewp-rounded-4); button { margin-top: var(--givewp-spacing-2);