Skip to content

Commit

Permalink
Refactor: Separate "Design Selector" from design tour (#6983)
Browse files Browse the repository at this point in the history
  • Loading branch information
kjohnson authored Oct 3, 2023
1 parent d894691 commit 5fb9b39
Show file tree
Hide file tree
Showing 18 changed files with 344 additions and 191 deletions.
2 changes: 1 addition & 1 deletion src/DonationForms/Properties/FormSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public static function fromArray(array $array): self
$self->enableDonationGoal = $array['enableDonationGoal'] ?? false;
$self->enableAutoClose = $array['enableAutoClose'] ?? false;
$self->goalType = !empty($array['goalType']) ? new GoalType($array['goalType']) : GoalType::AMOUNT();
$self->designId = $array['designId'] ?? ClassicFormDesign::id();
$self->designId = $array['designId'] ?? null;
$self->primaryColor = $array['primaryColor'] ?? '#69b86b';
$self->secondaryColor = $array['secondaryColor'] ?? '#f49420';
$self->goalAmount = $array['goalAmount'] ?? 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import cx from 'classnames';
import CheckCircleIcon from "../icons/check-circle"
import {setFormSettings, useFormState, useFormStateDispatch} from "@givewp/form-builder/stores/form-state";

const DesignCard = ({title, description, image, alt, selected, onSelected}) => {
return <div
className={cx('givewp-design-selector--card', {selected: selected})}
onClick={onSelected}
>
<img src={image} alt={alt} />
<strong>{title}</strong>
<p>{description}</p>
{selected && <CheckCircleIcon />}
</div>
}

export default DesignCard;
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {useState, useContext} from 'react';
import {Button, Modal} from "@wordpress/components"
import {ShepherdTourContext} from "react-shepherd"
import {__} from "@wordpress/i18n";
import DesignCard from "./components/DesignCard";

// @ts-ignore
import classDesignScreenshot from "./images/classic-design-screenshot.png";

// @ts-ignore
import multiStepDesignScreenshot from "./images/multi-step-design-screenshot.png";
import {setFormSettings, useFormState, useFormStateDispatch} from "@givewp/form-builder/stores/form-state";

export default ({onContinue}) => {
const tour = useContext(ShepherdTourContext);

const dispatch = useFormStateDispatch();

const onProceed = () => {
onContinue()
window.onboardingTourData.autoStartDesignTour && tour.start()
}

const [selectedDesign, setSelectedDesign] = useState(null)

const onDesignSelected = (design) => {
setSelectedDesign(design)
dispatch(setFormSettings({designId: design}))
}

return <Modal
bodyOpenClassName={'show-design-selector-modal'}
title={null}
isDismissible={false}
shouldCloseOnEsc={false}
shouldCloseOnClickOutside={false}
onRequestClose={() => null}
>
<div className={'givewp-design-selector--container'}>
<header className={'givewp-design-selector--header'}>
<h3>
{__('Choose your form design', 'give')}
</h3>
<p>
{__('Select one that suits your taste and requirements for your cause.', 'give')}
</p>
</header>

<div className={'givewp-design-selector--cards'}>
<DesignCard
selected={selectedDesign === 'classic'}
onSelected={() => onDesignSelected('classic')}
image={classDesignScreenshot}
alt={__('Classic form design', 'give')}
title={__('Classic', 'give')}
description={__('This displays all form fields on one page. Donors fill out the form as they scroll down the page', 'give')}
/>
<DesignCard
selected={selectedDesign === 'multi-step'}
onSelected={() => onDesignSelected('multi-step')}
image={multiStepDesignScreenshot}
alt={__('Multi-Step form design', 'give')}
title={__('Multi-step', 'give')}
description={__('This walks the donor through a number of steps to the donation process. The sections are broken into steps in the form', 'give')}
/>
</div>

<Button disabled={!selectedDesign} className={'givewp-design-selector--button'} variant={'primary'} onClick={onProceed}>
{__('Proceed', 'give')}
</Button>
</div>
</Modal>
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {useContext, useEffect} from 'react';
import {useContext, useEffect, useState} from 'react';
import {useFormState} from '@givewp/form-builder/stores/form-state';
import {useDispatch} from '@wordpress/data';
import {ShepherdTour, ShepherdTourContext} from 'react-shepherd';
Expand All @@ -8,6 +8,8 @@ import {useEditorState} from "@givewp/form-builder/stores/editor-state";
import {setFormSettings, useFormStateDispatch} from "@givewp/form-builder/stores/form-state";

import 'shepherd.js/dist/css/shepherd.css';
import DesignSelector from "@givewp/form-builder/components/onboarding/DesignSelector";
import SchemaWelcome from "@givewp/form-builder/components/onboarding/SchemaWelcome";

declare global {
interface Window {
Expand Down Expand Up @@ -39,29 +41,6 @@ function TourEffectsAndEvents() {
const dispatch = useFormStateDispatch();
const {selectBlock} = useDispatch('core/block-editor');

// @ts-ignore
window.onboardingResetDesign = window.onboardingResetDesign || function() {
dispatch(setFormSettings({designId: 'classic'}))
}

useEffect(() => {

const clickDelegationCallback = (e) => {
if(e.target.closest(".js-onboarding-set-design-classic")){
dispatch(setFormSettings({designId: 'classic'}))
}
if(e.target.closest(".js-onboarding-set-design-multi-step")){
dispatch(setFormSettings({designId: 'multi-step'}))
}
}

document.addEventListener("click", clickDelegationCallback);

return () => {
window.removeEventListener('click', clickDelegationCallback);
}
}, [mode])

useEffect(() => {
const selectAmountBlockCallback = () => {
const amountBlock = document.querySelector('[data-type="givewp/donation-amount"]');
Expand Down Expand Up @@ -114,25 +93,28 @@ function TourEffectsAndEvents() {
}
}, [mode])

useEffect(() => {
mode === 'design' && window.onboardingTourData.autoStartDesignTour && (tour.isActive() || tour.start());
mode === 'schema' && window.onboardingTourData.autoStartSchemaTour && (tour.isActive() || tour.start());
}, [mode])

return <></>
}

const Onboarding = () => {
const {transfer} = useFormState();
const {transfer, settings: {designId}} = useFormState();
const {mode} = useEditorState();
const [showDesignSelector, setShowDesignSelector] = useState(!designId);
const [showSchemaWelcome, setShowSchemaWelcome] = useState(!!window.onboardingTourData.autoStartSchemaTour);

if (transfer.showUpgradeModal) {
return null;
}

return <ShepherdTour steps={mode === 'schema' ? schemaSteps : designSteps} tourOptions={options}>
<TourEffectsAndEvents />
</ShepherdTour>
const steps = mode === 'schema' ? schemaSteps : designSteps;

return <>
<ShepherdTour steps={steps} tourOptions={options}>
<TourEffectsAndEvents />
{mode === 'design' && showDesignSelector && <DesignSelector onContinue={() => setShowDesignSelector(false)} />}
{mode === 'schema' && showSchemaWelcome && <SchemaWelcome onContinue={() => setShowSchemaWelcome(false)} />}
</ShepherdTour>
</>
}

export default Onboarding;
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {useContext} from 'react';
import {__} from "@wordpress/i18n";
import {ShepherdTourContext} from "react-shepherd"
import {Button, Modal} from "@wordpress/components"
import Logo from '@givewp/form-builder/components/icons/logo';

export default ({onContinue}) => {
const tour = useContext(ShepherdTourContext);

const onProceed = () => {
onContinue()
tour.start()
}

return <Modal
bodyOpenClassName={'show-schema-welcome-modal'}
title={null}
isDismissible={false}
shouldCloseOnEsc={false}
shouldCloseOnClickOutside={false}
onRequestClose={() => null}
>
<div className={'givewp-schema-welcome--container'}>
<div>
<div style={{display: 'flex', justifyContent: 'center', margin: '0 auto var(--givewp-spacing-4)'}}>
<Logo />
</div>

<h3>
{__('Welcome to the visual donation form builder!', 'give')}
</h3>

<p>
{__('The following is a quick (less than a minute) tour of the visual donation form builder, to introduce the tools for creating engaging donation forms.', 'give')}
</p>
</div>

<Button className={'givewp-schema-welcome--button'} variant={'primary'} onClick={onProceed}>
{__('Get started', 'give')}
</Button>
</div>
</Modal>
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
import {__} from "@wordpress/i18n";
import Placement from "./types/placement";
import DesignWelcome from "./components/DesignWelcome";

export default [
{
id: 'design-welcome',
title: __('Choose your form design', 'give'),
text: __('Select one that suits your taste and requirements for your cause.', 'give'),
component: <DesignWelcome />,
beforeShowPromise: function () {
return new Promise<void>(function (resolve) {
// @ts-ignore
window.onboardingResetDesign();
resolve();
});
},
},
{
id: 'design-edit-settings',
attachTo: { element: '#sidebar-primary', on: 'left-start' as Placement },
Expand All @@ -24,7 +10,7 @@ export default [
},
{
id: 'design-edit-form',
attachTo: { element: '#editor-state-toggle', on: 'bottom' as Placement },
attachTo: { element: '#editor-state-toggle', on: 'bottom-end' as Placement },
title: __('Edit form', 'give'),
text: __('This is where you add and edit various blocks and sections to make up your form.', 'give'),
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
const withButtons = (steps) => {
const start = {
classes: 'shepherd-button-primary',
text: 'Get started',
type: 'next'
}
const previous = {
classes: 'shepherd-button-secondary',
text: 'Previous',
Expand All @@ -23,7 +18,7 @@ const withButtons = (steps) => {

if(index === 0) {
return {...step, ...{
buttons: [start]
buttons: [next]
}}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {offset} from '@floating-ui/dom';

const withDefaults = (steps) => {
return steps.map((step) => {
return {...step,...{
Expand All @@ -7,6 +9,9 @@ const withDefaults = (steps) => {
enabled: false,
},
arrow: false,
floatingUIOptions: {
middleware: [offset(20)],
}
}}
})
}
Expand Down
Loading

0 comments on commit 5fb9b39

Please sign in to comment.