-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: Add getScriptParameters helper function * feat: Add shouldEnableFormOnlyMode helper function * feat: Add form-only donation flow
- Loading branch information
1 parent
9dabc4a
commit cdc6922
Showing
6 changed files
with
210 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import {render} from 'preact'; | ||
import EmbedButton from 'src/components/embed-button'; | ||
import {CreateButtonInSelectorProps} from 'src/components/embed-button/types'; | ||
import {CreateWidgetInSelectorProps} from 'src/components/widget/types'; | ||
import {WidgetConfig} from 'src/components/widget/types/WidgetConfig'; | ||
import {loadFonts} from 'src/loadFonts'; | ||
import {FormLoader} from 'src/loaders/FormLoader'; | ||
import {WidgetLoader} from 'src/loaders/Widgetloader'; | ||
import resetcss from 'src/resetCss'; | ||
|
||
interface GlobalExport { | ||
createButton: (options: CreateButtonInSelectorProps) => void; | ||
createWidget: (options: CreateWidgetInSelectorProps) => void; | ||
setOptions: (options: Partial<WidgetConfig>) => void; | ||
showWidget: () => void; | ||
} | ||
|
||
declare const window: Window & { | ||
everyDotOrgDonateButton?: GlobalExport; | ||
}; | ||
|
||
export default function formOnlyMode() { | ||
const DEFAULT_HASH_OPEN_WIDGET = 'donate'; | ||
|
||
const baseOptions: Partial<WidgetConfig> = {}; | ||
const options = { | ||
show: false, | ||
openAt: DEFAULT_HASH_OPEN_WIDGET | ||
}; | ||
const instanceOptions: Partial<WidgetConfig> = {}; | ||
|
||
const getNode = (element?: Element, selector?: string) => | ||
element ? element : selector ? document.querySelector(selector) : null; | ||
|
||
loadFonts(); | ||
|
||
/** | ||
* Helper function to debug donate button issues | ||
*/ | ||
function log(...messages: unknown[]): void { | ||
console.info('Every.org Donate Button:', ...messages); | ||
} | ||
|
||
let formContainer: HTMLElement; | ||
let formMountPoint: HTMLElement; | ||
|
||
const mountWidget = () => { | ||
const shadowWidgetWrapper = document.createElement('div'); | ||
shadowWidgetWrapper.id = 'shadow-wrapper'; | ||
formContainer.append(shadowWidgetWrapper); | ||
|
||
formMountPoint = document.createElement('div'); | ||
shadowWidgetWrapper.attachShadow({mode: 'open'}).append(formMountPoint); | ||
|
||
const everyStyles: HTMLStyleElement | null = | ||
document.querySelector('#every-styles'); | ||
|
||
if (everyStyles) { | ||
const rules = Object.values(everyStyles.sheet?.cssRules ?? {}) | ||
.map((rule) => rule.cssText) | ||
.join('\n'); | ||
|
||
const everyShadowStyles = document.createElement('style'); | ||
everyShadowStyles.id = 'every-shadow-styles'; | ||
everyShadowStyles.innerHTML = resetcss + rules; | ||
|
||
formMountPoint.append(everyShadowStyles); | ||
} | ||
}; | ||
|
||
const renderWidget = () => { | ||
if (!formMountPoint) { | ||
mountWidget(); | ||
} | ||
|
||
const finalOptions: Partial<WidgetConfig> = { | ||
...options, | ||
...baseOptions, | ||
...instanceOptions | ||
}; | ||
|
||
render(<FormLoader options={finalOptions} />, formMountPoint); | ||
}; | ||
|
||
function setOptions(newOptions: Partial<WidgetConfig>) { | ||
Object.assign(baseOptions, newOptions); | ||
renderWidget(); | ||
} | ||
|
||
const createWidgetInSelector = ({ | ||
element, | ||
selector, | ||
...options | ||
}: CreateWidgetInSelectorProps) => { | ||
if (!element && !selector) { | ||
log('createWidget():', 'must provide element or selector'); | ||
} | ||
|
||
const node = getNode(element, selector); | ||
if (!node) { | ||
log('createWidget():', 'element or selector not found'); | ||
return; | ||
} | ||
|
||
if (!options.nonprofitSlug) { | ||
log('createWidget():', 'must provide nonprofitSlug'); | ||
return; | ||
} | ||
|
||
formContainer = node as HTMLElement; | ||
|
||
Object.assign(baseOptions, options); | ||
renderWidget(); | ||
}; | ||
|
||
window.everyDotOrgDonateButton = { | ||
createButton: () => { | ||
log( | ||
'createButton function is not available in formOnlyMode. Use createWidget instead.' | ||
); | ||
}, | ||
showWidget: () => { | ||
log( | ||
'showWidget function is not available in formOnlyMode. Use createWidget instead.' | ||
); | ||
}, | ||
setOptions, | ||
createWidget: createWidgetInSelector | ||
}; | ||
} |
15 changes: 15 additions & 0 deletions
15
packages/donate-button-v4/src/helpers/getScriptParameters.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
export default function getScriptParameters() { | ||
const parametersString = document.currentScript | ||
?.getAttribute('src') | ||
?.split('?')[1]; | ||
const parametersArray = parametersString | ||
?.split('&') | ||
.map((parameterString) => { | ||
const [key, value] = parameterString.split('='); | ||
return [key, value]; | ||
}); | ||
const parametersObject = | ||
parametersArray && Object.fromEntries(parametersArray); | ||
|
||
return parametersObject; | ||
} |
18 changes: 5 additions & 13 deletions
18
packages/donate-button-v4/src/helpers/shouldEnableAutoPlay.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
packages/donate-button-v4/src/helpers/shouldEnableFormOnlyMode.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import getScriptParameters from 'src/helpers/getScriptParameters'; | ||
|
||
const FORM_ONLY_PARAM = 'formOnly'; | ||
|
||
export function shouldEnableFormOnlyMode() { | ||
const parameters = getScriptParameters(); | ||
|
||
if (parameters) { | ||
return parameters[FORM_ONLY_PARAM] === '1'; | ||
} | ||
|
||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import {PaymentProcess} from 'src/components/widget/components/PaymentProcess'; | ||
import {ContextProvider} from 'src/components/widget/context'; | ||
import {useConfigContext} from 'src/components/widget/hooks/useConfigContext'; | ||
import {useFundraiser} from 'src/components/widget/hooks/useFundraiser'; | ||
import {useNonprofit} from 'src/components/widget/hooks/useNonprofit'; | ||
import {LoadingIcon} from 'src/components/widget/icons/LoadingIcon'; | ||
import {FundraiserFetching} from 'src/components/widget/types/Fundraiser'; | ||
import {NonprofitFetching} from 'src/components/widget/types/Nonprofit'; | ||
import {WidgetConfig} from 'src/components/widget/types/WidgetConfig'; | ||
|
||
interface FormLoaderProps { | ||
options: Partial<WidgetConfig>; | ||
} | ||
|
||
export const FormLoader = ({options = {}}: FormLoaderProps) => { | ||
return ( | ||
<ContextProvider | ||
options={options} | ||
hide={() => { | ||
// do nothing | ||
}} | ||
> | ||
<Form /> | ||
</ContextProvider> | ||
); | ||
}; | ||
|
||
const Form = () => { | ||
const {fundraiserSlug} = useConfigContext(); | ||
const findraiser = useFundraiser(); | ||
const nonprofit = useNonprofit(); | ||
|
||
if ( | ||
nonprofit === NonprofitFetching || | ||
(fundraiserSlug && findraiser === FundraiserFetching) | ||
) { | ||
return <LoadingIcon size={24} />; | ||
} | ||
|
||
return <PaymentProcess />; | ||
}; |