PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 4.9.0
GiveWP – Donation Plugin and Fundraising Platform v4.9.0
4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / src / Campaigns / resources / admin / components / MergeCampaign / Form / index.tsx
give / src / Campaigns / resources / admin / components / MergeCampaign / Form Last commit date
Form.module.scss 1 year ago index.tsx 1 year ago types.ts 1 year ago
index.tsx
295 lines
1 import {FormProvider, SubmitHandler, useForm} from 'react-hook-form';
2 import {__} from '@wordpress/i18n';
3 import styles from './Form.module.scss';
4 import FormModal from '../../FormModal';
5 import {MergeCampaignFormInputs, MergeCampaignFormProps} from './types';
6 import {useState} from 'react';
7 import apiFetch from '@wordpress/api-fetch';
8 import {addQueryArgs} from '@wordpress/url';
9 import {getGiveCampaignsListTableWindowData} from '../../CampaignsListTable';
10
11 /**
12 * Campaign Form Modal component
13 *
14 * @since 4.0.0
15 */
16 export default function MergeCampaignsForm({isOpen, handleClose, title, campaigns}: MergeCampaignFormProps) {
17 const [step, setStep] = useState<number>(1);
18
19 const methods = useForm<MergeCampaignFormInputs>({
20 defaultValues: {
21 destinationCampaignId: '',
22 },
23 });
24
25 const {
26 register,
27 handleSubmit,
28 formState: {isDirty, isSubmitting},
29 watch,
30 } = methods;
31
32 const destinationCampaignId = watch('destinationCampaignId');
33
34 const requiredAsterisk = <span className={`givewp-field-required ${styles.fieldRequired}`}>*</span>;
35
36 const onSubmit: SubmitHandler<MergeCampaignFormInputs> = async (inputs, event) => {
37 event.preventDefault();
38
39 if (step !== 2) {
40 return;
41 }
42
43 const campaignsToMergeIds = campaigns.selected.filter((id) => id != inputs.destinationCampaignId);
44
45 try {
46 const response = await apiFetch({
47 path: addQueryArgs('/givewp/v3/campaigns/' + destinationCampaignId + '/merge', {
48 campaignsToMergeIds: campaignsToMergeIds,
49 }),
50 method: 'PATCH',
51 });
52
53 console.log('Merge campaigns response: ', response);
54
55 // Go to success page
56 setStep(3);
57
58 //Reset bulk actions selector
59 const selects = document.querySelectorAll('#give-admin-campaigns-root select');
60 selects.forEach((select) => {
61 const selectElement = select as HTMLSelectElement;
62 selectElement.selectedIndex = 0;
63 });
64
65 // Uncheck all checkboxes
66 const checkboxes = document.querySelectorAll(".giveListTable input[type='checkbox']");
67 checkboxes.forEach((checkbox) => {
68 const input = checkbox as HTMLInputElement;
69 input.checked = false;
70 });
71 // @ts-ignore
72 document.querySelector('.giveListTable #giveListTableSelectAll').checked = false;
73
74 //Remove campaignsToMergeIds from the list table.
75 const adminFormsListViewItems = document.querySelectorAll('tr');
76 if (adminFormsListViewItems.length > 0) {
77 adminFormsListViewItems.forEach((itemElement) => {
78 const select = itemElement.querySelector('.giveListTableSelect');
79
80 if (!select) {
81 return;
82 }
83
84 const campaignId = select.getAttribute('data-id');
85 if (campaignsToMergeIds.includes(campaignId)) {
86 itemElement.remove();
87 }
88 });
89 }
90 //handleClose(response);
91 } catch (error) {
92 // Go to error page
93 setStep(4);
94 console.error('Error merging campaigns: ', error);
95 }
96 };
97
98 const extractTextFromLink = (link) => {
99 const parser = new DOMParser();
100 const doc = parser.parseFromString(link, 'text/html');
101 return doc.querySelector('a')?.textContent || link;
102 };
103
104 return (
105 <FormProvider {...methods}>
106 <FormModal
107 isOpen={isOpen}
108 handleClose={handleClose}
109 title={title}
110 handleSubmit={handleSubmit(onSubmit)}
111 errors={[]}
112 className={styles.campaignForm}
113 >
114 {step === 1 && (
115 <>
116 <div className="givewp-campaigns__form-row">
117 <p className={styles.intro}>
118 {__(
119 'All selected campaigns will be merged into the destination campaign. This means that forms, donors, donations, and all related data will be added to the destination campaign, and the merged campaigns will cease to exist.',
120 'give'
121 )}
122 </p>
123 </div>
124 <button
125 type="submit"
126 onClick={() => setStep(2)}
127 className={`button button-primary ${styles.button}`}
128 aria-disabled={false}
129 disabled={false}
130 >
131 {__('Proceed', 'give')}
132 </button>
133 </>
134 )}
135 {step === 2 && (
136 <>
137 <div className="givewp-campaigns__form-row">
138 <label htmlFor="title">
139 {__('Select your destination campaign', 'give')} {requiredAsterisk}
140 </label>
141 <span>{__('All selected campaigns will be merged into this campaign.', 'give')}</span>
142 <select {...register('destinationCampaignId', {valueAsNumber: true})} defaultValue="">
143 <option value="" disabled hidden>
144 {__('Choose from selected campaigns', 'give')}
145 </option>
146 {campaigns.selected.map((id, index) => (
147 <option key={id} value={id}>
148 {extractTextFromLink(campaigns.names[index])}
149 </option>
150 ))}
151 </select>
152 </div>
153 <button
154 type="submit"
155 className={`button button-primary ${styles.button} ${isSubmitting ? 'disabled' : ''}`}
156 aria-disabled={!isDirty}
157 disabled={!isDirty}
158 >
159 {isSubmitting ? __('Merging in progress...', 'give') : __('Merge', 'give')}
160 </button>
161 {isDirty && (
162 <div className={styles.notice}>
163 <svg
164 width="20"
165 height="20"
166 viewBox="0 0 20 20"
167 fill="none"
168 xmlns="http://www.w3.org/2000/svg"
169 >
170 <path
171 fillRule="evenodd"
172 clipRule="evenodd"
173 d="M10 .836a9.167 9.167 0 1 0 0 18.333A9.167 9.167 0 0 0 10 .836zm0 5a.833.833 0 1 0 0 1.667h.009a.833.833 0 0 0 0-1.667h-.008zm.834 4.167a.833.833 0 0 0-1.667 0v3.333a.833.833 0 1 0 1.667 0v-3.333z"
174 fill="#0C7FF2"
175 />
176 </svg>
177
178 <p>{__('Once completed, this action is irreversible.', 'give')}</p>
179 </div>
180 )}
181 </>
182 )}
183 {step === 3 && (
184 <>
185 <div className="givewp-campaigns__form-row">
186 <div className={styles.returnMessage}>
187 <svg
188 width="40"
189 height="40"
190 viewBox="0 0 40 40"
191 fill="none"
192 xmlns="http://www.w3.org/2000/svg"
193 >
194 <path
195 fillRule="evenodd"
196 clipRule="evenodd"
197 d="M20 1.664c-10.126 0-18.334 8.208-18.334 18.333 0 10.126 8.208 18.334 18.333 18.334 10.126 0 18.334-8.208 18.334-18.334 0-10.125-8.208-18.333-18.334-18.333zm8.678 14.512a1.667 1.667 0 0 0-2.357-2.357l-8.822 8.821-3.821-3.821a1.667 1.667 0 0 0-2.357 2.357l5 5c.65.65 1.706.65 2.357 0l10-10z"
198 fill="#459948"
199 />
200 </svg>
201
202 <label htmlFor="title">{__('Campaigns have been successfully merged', 'give')}</label>
203 <span>
204 {__(
205 'All donations, donors, and forms from selected campaigns now belong to your destination campaign.',
206 'give'
207 )}
208 </span>
209 </div>
210 </div>
211 <div
212 className="givewp-campaigns__form-row givewp-campaigns__form-row--half"
213 style={{marginBottom: 0}}
214 >
215 <button
216 type="submit"
217 onClick={() => handleClose()}
218 className={`button button-secondary ${styles.button} ${styles.previousButton}`}
219 >
220 {__('Back to campaign list', 'give')}
221 </button>
222
223 <button
224 type="submit"
225 onClick={() =>
226 (window.location.href =
227 getGiveCampaignsListTableWindowData().adminUrl +
228 'edit.php?post_type=give_forms&page=give-campaigns&id=' +
229 destinationCampaignId)
230 }
231 className={`button button-primary ${styles.button}`}
232 aria-disabled={false}
233 disabled={false}
234 >
235 {__('View destination campaign', 'give')}
236 </button>
237 </div>
238 </>
239 )}
240 {step === 4 && (
241 <>
242 <div className="givewp-campaigns__form-row">
243 <div className={styles.returnMessage}>
244 <svg
245 width="40"
246 height="40"
247 viewBox="0 0 40 40"
248 fill="none"
249 xmlns="http://www.w3.org/2000/svg"
250 >
251 <path
252 fillRule="evenodd"
253 clipRule="evenodd"
254 d="M20 1.668c-10.125 0-18.333 8.208-18.333 18.333 0 10.125 8.208 18.334 18.333 18.334 10.125 0 18.333-8.209 18.333-18.334S30.125 1.668 20 1.668zm1.667 11.667a1.667 1.667 0 0 0-3.334 0V20a1.667 1.667 0 1 0 3.334 0v-6.666zM20 25a1.667 1.667 0 1 0 0 3.334h.017a1.667 1.667 0 0 0 0-3.334H20z"
255 fill="#D92D0B"
256 />
257 </svg>
258 <label htmlFor="title">{__("Campaigns couldn't be merged", 'give')}</label>
259 <span>
260 {__(
261 'An error occurred during the merging process. Please try again, or contact our support team if the issue persists.',
262 'give'
263 )}
264 </span>
265 </div>
266 </div>
267 <div
268 className="givewp-campaigns__form-row givewp-campaigns__form-row--half"
269 style={{marginBottom: 0}}
270 >
271 <button
272 type="submit"
273 onClick={() => handleClose()}
274 className={`button button-secondary ${styles.button} ${styles.previousButton}`}
275 >
276 {__('Back to campaign list', 'give')}
277 </button>
278
279 <button
280 type="submit"
281 onClick={() => setStep(2)}
282 className={`button button-primary ${styles.button}`}
283 aria-disabled={false}
284 disabled={false}
285 >
286 {__('Try again', 'give')}
287 </button>
288 </div>
289 </>
290 )}
291 </FormModal>
292 </FormProvider>
293 );
294 }
295