added additional plugins
This commit is contained in:
parent
c85895d306
commit
00e60ec1b7
132 changed files with 27514 additions and 0 deletions
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
// Silence is golden.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
// Silence is golden.
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
import { useState, useEffect } from '@wordpress/element';
|
||||
import { Button, Spinner } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import StepOne from './components/StepOne';
|
||||
import StepTwo from './components/StepTwo';
|
||||
import StepThree from './components/StepThree';
|
||||
import StepFour from './components/StepFour';
|
||||
import StepFive from './components/StepFive';
|
||||
import StepSix from './components/StepSix';
|
||||
import { fetchAutomation } from './utils/api';
|
||||
|
||||
const WizardApp = () => {
|
||||
const [currentStep, setCurrentStep] = useState(1);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [formData, setFormData] = useState({
|
||||
title: '',
|
||||
form_id: '',
|
||||
field_mapping: {
|
||||
email: '',
|
||||
firstname: '',
|
||||
lastname: ''
|
||||
},
|
||||
trigger_field_id: '',
|
||||
api_key: '',
|
||||
api_secret: '',
|
||||
list_mappings: {},
|
||||
activate: false
|
||||
});
|
||||
const [forms, setForms] = useState([]);
|
||||
const [fields, setFields] = useState([]);
|
||||
const [triggerChoices, setTriggerChoices] = useState([]);
|
||||
const [mailjetLists, setMailjetLists] = useState([]);
|
||||
|
||||
const totalSteps = 6;
|
||||
const editId = window.wpfmjData?.editId || 0;
|
||||
|
||||
// Load automation if editing
|
||||
useEffect(() => {
|
||||
if (!editId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
setLoading(true);
|
||||
|
||||
fetchAutomation(editId)
|
||||
.then(data => {
|
||||
if (!cancelled) {
|
||||
setFormData({
|
||||
title: data.title,
|
||||
...data.config,
|
||||
activate: data.status === 'publish'
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (!cancelled) {
|
||||
alert('Error loading automation: ' + error.message);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [editId]);
|
||||
|
||||
const updateFormData = (field, value) => {
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
[field]: value
|
||||
}));
|
||||
};
|
||||
|
||||
const nextStep = () => {
|
||||
if (currentStep < totalSteps) {
|
||||
setCurrentStep(currentStep + 1);
|
||||
}
|
||||
};
|
||||
|
||||
const prevStep = () => {
|
||||
if (currentStep > 1) {
|
||||
setCurrentStep(currentStep - 1);
|
||||
}
|
||||
};
|
||||
|
||||
const renderStep = () => {
|
||||
const stepProps = {
|
||||
formData,
|
||||
updateFormData,
|
||||
forms,
|
||||
setForms,
|
||||
fields,
|
||||
setFields,
|
||||
triggerChoices,
|
||||
setTriggerChoices,
|
||||
mailjetLists,
|
||||
setMailjetLists,
|
||||
nextStep,
|
||||
setLoading
|
||||
};
|
||||
|
||||
switch (currentStep) {
|
||||
case 1:
|
||||
return <StepOne {...stepProps} />;
|
||||
case 2:
|
||||
return <StepTwo {...stepProps} />;
|
||||
case 3:
|
||||
return <StepThree {...stepProps} />;
|
||||
case 4:
|
||||
return <StepFour {...stepProps} />;
|
||||
case 5:
|
||||
return <StepFive {...stepProps} />;
|
||||
case 6:
|
||||
return <StepSix {...stepProps} editId={editId} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const renderProgress = () => {
|
||||
const steps = [
|
||||
__('Choose Form', 'wpforms-mailjet-automation'),
|
||||
__('Map Fields', 'wpforms-mailjet-automation'),
|
||||
__('Trigger Field', 'wpforms-mailjet-automation'),
|
||||
__('Connect Mailjet', 'wpforms-mailjet-automation'),
|
||||
__('Map Lists', 'wpforms-mailjet-automation'),
|
||||
__('Review', 'wpforms-mailjet-automation')
|
||||
];
|
||||
|
||||
return (
|
||||
<ul className="wpfmj-wizard-progress">
|
||||
{steps.map((step, index) => {
|
||||
const stepNumber = index + 1;
|
||||
const isActive = currentStep === stepNumber;
|
||||
const isCompleted = currentStep > stepNumber;
|
||||
const className = isActive ? 'active' : isCompleted ? 'completed' : '';
|
||||
|
||||
return (
|
||||
<li key={stepNumber} className={className}>
|
||||
{step}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div style={{ padding: '40px', textAlign: 'center' }}>
|
||||
<Spinner />
|
||||
<p>{__('Loading...', 'wpforms-mailjet-automation')}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="wpfmj-wizard-container">
|
||||
<div className="wpfmj-wizard-header">
|
||||
{renderProgress()}
|
||||
</div>
|
||||
<div className="wpfmj-wizard-body">
|
||||
{renderStep()}
|
||||
</div>
|
||||
<div className="wpfmj-wizard-footer">
|
||||
<div>
|
||||
{currentStep > 1 && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={prevStep}
|
||||
disabled={loading}
|
||||
>
|
||||
{__('Previous', 'wpforms-mailjet-automation')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
{currentStep < totalSteps && (
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={nextStep}
|
||||
disabled={loading}
|
||||
>
|
||||
{__('Next', 'wpforms-mailjet-automation')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Mount the app
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const rootElement = document.getElementById('wpfmj-wizard-root');
|
||||
if (rootElement) {
|
||||
wp.element.render(<WizardApp />, rootElement);
|
||||
}
|
||||
});
|
||||
|
||||
export default WizardApp;
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
import { SelectControl, Button } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const StepFive = ({ formData, updateFormData, triggerChoices, mailjetLists, nextStep }) => {
|
||||
|
||||
const handleNext = () => {
|
||||
const hasMapping = Object.keys(formData.list_mappings).length > 0;
|
||||
if (!hasMapping) {
|
||||
alert(__('Please map at least one answer to a Mailjet list', 'wpforms-mailjet-automation'));
|
||||
return;
|
||||
}
|
||||
nextStep();
|
||||
};
|
||||
|
||||
const updateListMapping = (choiceValue, listId) => {
|
||||
const newMappings = { ...formData.list_mappings };
|
||||
|
||||
if (listId === '') {
|
||||
// Remove mapping if empty
|
||||
delete newMappings[choiceValue];
|
||||
} else {
|
||||
newMappings[choiceValue] = listId;
|
||||
}
|
||||
|
||||
updateFormData('list_mappings', newMappings);
|
||||
};
|
||||
|
||||
// Get list of already selected lists to prevent duplicates
|
||||
const getAvailableLists = (currentChoiceValue) => {
|
||||
const usedListIds = Object.entries(formData.list_mappings)
|
||||
.filter(([key]) => key !== currentChoiceValue)
|
||||
.map(([, listId]) => listId);
|
||||
|
||||
return mailjetLists.filter(list => !usedListIds.includes(list.id.toString()));
|
||||
};
|
||||
|
||||
const listOptions = (choiceValue) => {
|
||||
const available = getAvailableLists(choiceValue);
|
||||
return [
|
||||
{ label: __('Select a list...', 'wpforms-mailjet-automation'), value: '' },
|
||||
...available.map(list => ({
|
||||
label: list.name,
|
||||
value: list.id.toString()
|
||||
}))
|
||||
];
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="wpfmj-step">
|
||||
<h2>{__('Map Answers to Mailjet Lists', 'wpforms-mailjet-automation')}</h2>
|
||||
<p className="description">
|
||||
{__('Map each answer from your trigger field to a Mailjet list. When someone selects an answer, they\'ll be added to the corresponding list. Each list can only be used once.', 'wpforms-mailjet-automation')}
|
||||
</p>
|
||||
|
||||
<div className="wpfmj-two-column">
|
||||
<div className="wpfmj-column">
|
||||
<h3>{__('Form Answers', 'wpforms-mailjet-automation')}</h3>
|
||||
{triggerChoices.map((choice) => (
|
||||
<div key={choice.value} className="wpfmj-mapping-row">
|
||||
<div className="wpfmj-answer">{choice.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="wpfmj-column">
|
||||
<h3>{__('Mailjet Lists', 'wpforms-mailjet-automation')}</h3>
|
||||
{triggerChoices.map((choice) => (
|
||||
<div key={choice.value} className="wpfmj-mapping-row">
|
||||
<SelectControl
|
||||
value={formData.list_mappings[choice.value] || ''}
|
||||
options={listOptions(choice.value)}
|
||||
onChange={(value) => updateListMapping(choice.value, value)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{mailjetLists.length === 0 && (
|
||||
<div className="wpfmj-alert wpfmj-alert-error">
|
||||
{__('No Mailjet lists found. Please create lists in your Mailjet account first.', 'wpforms-mailjet-automation')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="wpfmj-alert wpfmj-alert-info" style={{ marginTop: '20px' }}>
|
||||
<strong>{__('Note:', 'wpforms-mailjet-automation')}</strong> {__('For checkbox fields, users can select multiple answers, and they will be added to multiple lists accordingly.', 'wpforms-mailjet-automation')}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleNext}
|
||||
disabled={mailjetLists.length === 0}
|
||||
style={{ marginTop: '20px' }}
|
||||
>
|
||||
{__('Next', 'wpforms-mailjet-automation')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StepFive;
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
import { useState } from '@wordpress/element';
|
||||
import { TextControl, Button } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { testMailjetConnection, fetchMailjetLists } from '../utils/api';
|
||||
|
||||
const StepFour = ({ formData, updateFormData, setMailjetLists, setLoading, nextStep }) => {
|
||||
const [testing, setTesting] = useState(false);
|
||||
const [tested, setTested] = useState(false);
|
||||
const [testSuccess, setTestSuccess] = useState(false);
|
||||
|
||||
const handleTest = async () => {
|
||||
if (!formData.api_key || !formData.api_secret) {
|
||||
alert(__('Please enter both API Key and API Secret', 'wpforms-mailjet-automation'));
|
||||
return;
|
||||
}
|
||||
|
||||
setTesting(true);
|
||||
try {
|
||||
await testMailjetConnection(formData.api_key, formData.api_secret);
|
||||
setTestSuccess(true);
|
||||
setTested(true);
|
||||
|
||||
// Automatically fetch lists after successful connection
|
||||
const lists = await fetchMailjetLists(formData.api_key, formData.api_secret);
|
||||
setMailjetLists(lists);
|
||||
|
||||
} catch (error) {
|
||||
setTestSuccess(false);
|
||||
setTested(true);
|
||||
alert(__('Connection failed: ', 'wpforms-mailjet-automation') + error.message);
|
||||
} finally {
|
||||
setTesting(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleNext = () => {
|
||||
if (!tested || !testSuccess) {
|
||||
alert(__('Please test your API connection first', 'wpforms-mailjet-automation'));
|
||||
return;
|
||||
}
|
||||
nextStep();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="wpfmj-step">
|
||||
<h2>{__('Connect to Mailjet', 'wpforms-mailjet-automation')}</h2>
|
||||
<p className="description">
|
||||
{__('Enter your Mailjet API credentials. You can find these in your Mailjet account under Account Settings > REST API.', 'wpforms-mailjet-automation')}
|
||||
</p>
|
||||
|
||||
<div className="wpfmj-field-group">
|
||||
<TextControl
|
||||
label={__('API Key', 'wpforms-mailjet-automation')}
|
||||
value={formData.api_key}
|
||||
onChange={(value) => {
|
||||
updateFormData('api_key', value);
|
||||
setTested(false);
|
||||
}}
|
||||
type="text"
|
||||
placeholder={__('Enter your Mailjet API Key', 'wpforms-mailjet-automation')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="wpfmj-field-group">
|
||||
<TextControl
|
||||
label={__('API Secret', 'wpforms-mailjet-automation')}
|
||||
value={formData.api_secret}
|
||||
onChange={(value) => {
|
||||
updateFormData('api_secret', value);
|
||||
setTested(false);
|
||||
}}
|
||||
type="password"
|
||||
placeholder={__('Enter your Mailjet API Secret', 'wpforms-mailjet-automation')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '20px' }}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={handleTest}
|
||||
isBusy={testing}
|
||||
disabled={testing || !formData.api_key || !formData.api_secret}
|
||||
>
|
||||
{testing ? __('Testing...', 'wpforms-mailjet-automation') : __('Test Connection', 'wpforms-mailjet-automation')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{tested && testSuccess && (
|
||||
<div className="wpfmj-alert wpfmj-alert-success">
|
||||
{__('✓ Connection successful! Your Mailjet account is connected.', 'wpforms-mailjet-automation')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tested && !testSuccess && (
|
||||
<div className="wpfmj-alert wpfmj-alert-error">
|
||||
{__('✗ Connection failed. Please check your credentials and try again.', 'wpforms-mailjet-automation')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleNext}
|
||||
disabled={!tested || !testSuccess}
|
||||
style={{ marginTop: '20px' }}
|
||||
>
|
||||
{__('Next', 'wpforms-mailjet-automation')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StepFour;
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
import { useEffect } from '@wordpress/element';
|
||||
import { SelectControl, TextControl, Button } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { fetchForms } from '../utils/api';
|
||||
|
||||
const StepOne = ({ formData, updateFormData, forms, setForms, setLoading, nextStep }) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (forms.length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
setLoading(true);
|
||||
|
||||
fetchForms()
|
||||
.then(data => {
|
||||
if (!cancelled) {
|
||||
setForms(data);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (!cancelled) {
|
||||
alert('Error loading forms: ' + error.message);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [forms.length, setForms, setLoading]);
|
||||
|
||||
const handleNext = () => {
|
||||
if (!formData.title) {
|
||||
alert(__('Please enter an automation title', 'wpforms-mailjet-automation'));
|
||||
return;
|
||||
}
|
||||
if (!formData.form_id) {
|
||||
alert(__('Please select a form', 'wpforms-mailjet-automation'));
|
||||
return;
|
||||
}
|
||||
nextStep();
|
||||
};
|
||||
|
||||
const formOptions = [
|
||||
{ label: __('Select a form...', 'wpforms-mailjet-automation'), value: '' },
|
||||
...forms.map(form => ({
|
||||
label: form.title,
|
||||
value: form.id.toString()
|
||||
}))
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="wpfmj-step">
|
||||
<h2>{__('Create Your Automation', 'wpforms-mailjet-automation')}</h2>
|
||||
<p className="description">
|
||||
{__('Give your automation a name and select which WPForms form you want to connect to Mailjet.', 'wpforms-mailjet-automation')}
|
||||
</p>
|
||||
|
||||
<div className="wpfmj-field-group">
|
||||
<TextControl
|
||||
label={__('Automation Title', 'wpforms-mailjet-automation')}
|
||||
value={formData.title}
|
||||
onChange={(value) => updateFormData('title', value)}
|
||||
placeholder={__('e.g., Newsletter Signup Automation', 'wpforms-mailjet-automation')}
|
||||
help={__('This is only for your reference and won\'t be shown to users.', 'wpforms-mailjet-automation')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="wpfmj-field-group">
|
||||
<SelectControl
|
||||
label={__('Select WPForm', 'wpforms-mailjet-automation')}
|
||||
value={formData.form_id}
|
||||
options={formOptions}
|
||||
onChange={(value) => updateFormData('form_id', value)}
|
||||
help={__('Choose the form that will trigger this automation.', 'wpforms-mailjet-automation')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleNext}
|
||||
style={{ marginTop: '20px' }}
|
||||
>
|
||||
{__('Next', 'wpforms-mailjet-automation')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StepOne;
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
import { useState } from '@wordpress/element';
|
||||
import { Button, CheckboxControl } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { saveAutomation } from '../utils/api';
|
||||
|
||||
const StepSix = ({ formData, updateFormData, forms, fields, triggerChoices, mailjetLists, editId }) => {
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
const handleSave = async (activate) => {
|
||||
setSaving(true);
|
||||
updateFormData('activate', activate);
|
||||
|
||||
try {
|
||||
const result = await saveAutomation({ ...formData, activate }, editId);
|
||||
alert(__('Automation saved successfully!', 'wpforms-mailjet-automation'));
|
||||
window.location.href = 'admin.php?page=wpfmj-dashboard';
|
||||
} catch (error) {
|
||||
alert(__('Error saving automation: ', 'wpforms-mailjet-automation') + error.message);
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
const getFormName = () => {
|
||||
const form = forms.find(f => f.id.toString() === formData.form_id);
|
||||
return form ? form.title : formData.form_id;
|
||||
};
|
||||
|
||||
const getFieldName = (fieldId) => {
|
||||
const field = fields.find(f => f.id.toString() === fieldId);
|
||||
return field ? field.label : fieldId;
|
||||
};
|
||||
|
||||
const getTriggerFieldName = () => {
|
||||
return getFieldName(formData.trigger_field_id);
|
||||
};
|
||||
|
||||
const getListName = (listId) => {
|
||||
const list = mailjetLists.find(l => l.id.toString() === listId);
|
||||
return list ? list.name : listId;
|
||||
};
|
||||
|
||||
const getChoiceLabel = (choiceValue) => {
|
||||
const choice = triggerChoices.find(c => c.value === choiceValue);
|
||||
return choice ? choice.label : choiceValue;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="wpfmj-step">
|
||||
<h2>{__('Review & Save', 'wpforms-mailjet-automation')}</h2>
|
||||
<p className="description">
|
||||
{__('Review your automation settings below. Once you\'re happy with everything, choose whether to save as a draft or save and activate immediately.', 'wpforms-mailjet-automation')}
|
||||
</p>
|
||||
|
||||
<div className="wpfmj-review-section">
|
||||
<h3>{__('Basic Information', 'wpforms-mailjet-automation')}</h3>
|
||||
<div className="wpfmj-review-item">
|
||||
<div className="wpfmj-review-label">{__('Automation Title:', 'wpforms-mailjet-automation')}</div>
|
||||
<div className="wpfmj-review-value">{formData.title}</div>
|
||||
</div>
|
||||
<div className="wpfmj-review-item">
|
||||
<div className="wpfmj-review-label">{__('Form:', 'wpforms-mailjet-automation')}</div>
|
||||
<div className="wpfmj-review-value">{getFormName()}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="wpfmj-review-section">
|
||||
<h3>{__('Field Mapping', 'wpforms-mailjet-automation')}</h3>
|
||||
<div className="wpfmj-review-item">
|
||||
<div className="wpfmj-review-label">{__('Email Field:', 'wpforms-mailjet-automation')}</div>
|
||||
<div className="wpfmj-review-value">{getFieldName(formData.field_mapping.email)}</div>
|
||||
</div>
|
||||
{formData.field_mapping.firstname && (
|
||||
<div className="wpfmj-review-item">
|
||||
<div className="wpfmj-review-label">{__('First Name Field:', 'wpforms-mailjet-automation')}</div>
|
||||
<div className="wpfmj-review-value">{getFieldName(formData.field_mapping.firstname)}</div>
|
||||
</div>
|
||||
)}
|
||||
{formData.field_mapping.lastname && (
|
||||
<div className="wpfmj-review-item">
|
||||
<div className="wpfmj-review-label">{__('Last Name Field:', 'wpforms-mailjet-automation')}</div>
|
||||
<div className="wpfmj-review-value">{getFieldName(formData.field_mapping.lastname)}</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="wpfmj-review-item">
|
||||
<div className="wpfmj-review-label">{__('Trigger Field:', 'wpforms-mailjet-automation')}</div>
|
||||
<div className="wpfmj-review-value">{getTriggerFieldName()}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="wpfmj-review-section">
|
||||
<h3>{__('List Mappings', 'wpforms-mailjet-automation')}</h3>
|
||||
{Object.entries(formData.list_mappings).map(([choiceValue, listId]) => (
|
||||
<div key={choiceValue} className="wpfmj-review-item">
|
||||
<div className="wpfmj-review-label">{getChoiceLabel(choiceValue)}:</div>
|
||||
<div className="wpfmj-review-value">{getListName(listId)}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="wpfmj-alert wpfmj-alert-info">
|
||||
<strong>{__('What happens next?', 'wpforms-mailjet-automation')}</strong>
|
||||
<ul style={{ margin: '10px 0 0 20px' }}>
|
||||
<li>{__('When someone submits the selected form, the automation will check their answers', 'wpforms-mailjet-automation')}</li>
|
||||
<li>{__('Based on their selections in the trigger field, they\'ll be added to the corresponding Mailjet list(s)', 'wpforms-mailjet-automation')}</li>
|
||||
<li>{__('If the API call fails, the system will retry up to 3 times with exponential backoff', 'wpforms-mailjet-automation')}</li>
|
||||
<li>{__('If all retries fail, you\'ll receive an email notification', 'wpforms-mailjet-automation')}</li>
|
||||
<li>{__('You can view all automation activity and errors in the dashboard', 'wpforms-mailjet-automation')}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: '30px', display: 'flex', gap: '10px' }}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => handleSave(false)}
|
||||
isBusy={saving}
|
||||
disabled={saving}
|
||||
>
|
||||
{__('Save as Draft', 'wpforms-mailjet-automation')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => handleSave(true)}
|
||||
isBusy={saving}
|
||||
disabled={saving}
|
||||
>
|
||||
{__('Save & Activate', 'wpforms-mailjet-automation')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StepSix;
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
import { SelectControl, Button } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const StepThree = ({ formData, updateFormData, fields, setTriggerChoices, nextStep }) => {
|
||||
|
||||
const handleNext = () => {
|
||||
if (!formData.trigger_field_id) {
|
||||
alert(__('Please select a trigger field', 'wpforms-mailjet-automation'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the selected field and extract its choices
|
||||
const triggerField = fields.find(f => f.id.toString() === formData.trigger_field_id);
|
||||
if (triggerField && triggerField.choices) {
|
||||
setTriggerChoices(triggerField.choices);
|
||||
}
|
||||
|
||||
nextStep();
|
||||
};
|
||||
|
||||
// Filter fields to only show those with choices (checkbox, radio, select, etc.)
|
||||
const triggerFieldOptions = [
|
||||
{ label: __('Select a field...', 'wpforms-mailjet-automation'), value: '' },
|
||||
...fields
|
||||
.filter(field => field.choices && field.choices.length > 0)
|
||||
.map(field => ({
|
||||
label: `${field.label} (${field.type})`,
|
||||
value: field.id.toString()
|
||||
}))
|
||||
];
|
||||
|
||||
const selectedField = fields.find(f => f.id.toString() === formData.trigger_field_id);
|
||||
|
||||
return (
|
||||
<div className="wpfmj-step">
|
||||
<h2>{__('Choose Trigger Field', 'wpforms-mailjet-automation')}</h2>
|
||||
<p className="description">
|
||||
{__('Select the field that will determine which Mailjet lists the contact is added to. This should be a field with multiple choice options like checkboxes, radio buttons, or dropdowns.', 'wpforms-mailjet-automation')}
|
||||
</p>
|
||||
|
||||
<div className="wpfmj-field-group">
|
||||
<SelectControl
|
||||
label={__('Trigger Field', 'wpforms-mailjet-automation')}
|
||||
value={formData.trigger_field_id}
|
||||
options={triggerFieldOptions}
|
||||
onChange={(value) => updateFormData('trigger_field_id', value)}
|
||||
help={__('The answers to this field will determine which Mailjet lists the contact is added to.', 'wpforms-mailjet-automation')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{selectedField && selectedField.choices && (
|
||||
<div className="wpfmj-alert wpfmj-alert-info">
|
||||
<strong>{__('Field Preview:', 'wpforms-mailjet-automation')}</strong>
|
||||
<ul style={{ margin: '10px 0 0 20px' }}>
|
||||
{selectedField.choices.map((choice, index) => (
|
||||
<li key={index}>{choice.label}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{triggerFieldOptions.length === 1 && (
|
||||
<div className="wpfmj-alert wpfmj-alert-error">
|
||||
{__('This form doesn\'t have any fields with multiple choice options. Please add checkbox, radio, or dropdown fields to your form first.', 'wpforms-mailjet-automation')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleNext}
|
||||
disabled={triggerFieldOptions.length === 1}
|
||||
style={{ marginTop: '20px' }}
|
||||
>
|
||||
{__('Next', 'wpforms-mailjet-automation')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StepThree;
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
import { useEffect } from '@wordpress/element';
|
||||
import { SelectControl, Button } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { fetchFormFields } from '../utils/api';
|
||||
|
||||
const StepTwo = ({ formData, updateFormData, fields, setFields, setLoading, nextStep }) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (!formData.form_id || fields.length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
setLoading(true);
|
||||
|
||||
fetchFormFields(formData.form_id)
|
||||
.then(data => {
|
||||
if (!cancelled) {
|
||||
setFields(data);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (!cancelled) {
|
||||
alert('Error loading form fields: ' + error.message);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [formData.form_id, fields.length, setFields, setLoading]);
|
||||
|
||||
const handleNext = () => {
|
||||
if (!formData.field_mapping.email) {
|
||||
alert(__('Please select an email field', 'wpforms-mailjet-automation'));
|
||||
return;
|
||||
}
|
||||
nextStep();
|
||||
};
|
||||
|
||||
const updateFieldMapping = (field, value) => {
|
||||
updateFormData('field_mapping', {
|
||||
...formData.field_mapping,
|
||||
[field]: value
|
||||
});
|
||||
};
|
||||
|
||||
const fieldOptions = [
|
||||
{ label: __('Select a field...', 'wpforms-mailjet-automation'), value: '' },
|
||||
...fields.map(field => ({
|
||||
label: field.label,
|
||||
value: field.id.toString()
|
||||
}))
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="wpfmj-step">
|
||||
<h2>{__('Map Contact Fields', 'wpforms-mailjet-automation')}</h2>
|
||||
<p className="description">
|
||||
{__('Map your form fields to Mailjet contact properties. Email is required, while first name and last name are optional.', 'wpforms-mailjet-automation')}
|
||||
</p>
|
||||
|
||||
<div className="wpfmj-field-group">
|
||||
<SelectControl
|
||||
label={__('Email Field', 'wpforms-mailjet-automation') + ' *'}
|
||||
value={formData.field_mapping.email}
|
||||
options={fieldOptions}
|
||||
onChange={(value) => updateFieldMapping('email', value)}
|
||||
help={__('Required. This field will be used as the contact email address.', 'wpforms-mailjet-automation')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="wpfmj-field-group">
|
||||
<SelectControl
|
||||
label={__('First Name Field', 'wpforms-mailjet-automation')}
|
||||
value={formData.field_mapping.firstname}
|
||||
options={fieldOptions}
|
||||
onChange={(value) => updateFieldMapping('firstname', value)}
|
||||
help={__('Optional. If selected, this will populate the contact\'s first name in Mailjet.', 'wpforms-mailjet-automation')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="wpfmj-field-group">
|
||||
<SelectControl
|
||||
label={__('Last Name Field', 'wpforms-mailjet-automation')}
|
||||
value={formData.field_mapping.lastname}
|
||||
options={fieldOptions}
|
||||
onChange={(value) => updateFieldMapping('lastname', value)}
|
||||
help={__('Optional. If selected, this will populate the contact\'s last name in Mailjet.', 'wpforms-mailjet-automation')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleNext}
|
||||
style={{ marginTop: '20px' }}
|
||||
>
|
||||
{__('Next', 'wpforms-mailjet-automation')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StepTwo;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
// Silence is golden.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
// Silence is golden.
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* API utility functions for AJAX calls
|
||||
*/
|
||||
|
||||
const { ajaxUrl, ajaxNonce } = window.wpfmjData || {};
|
||||
|
||||
/**
|
||||
* Make AJAX request
|
||||
*/
|
||||
const makeRequest = async (action, data = {}) => {
|
||||
const formData = new FormData();
|
||||
formData.append('action', action);
|
||||
formData.append('nonce', ajaxNonce);
|
||||
|
||||
Object.keys(data).forEach(key => {
|
||||
if (typeof data[key] === 'object') {
|
||||
formData.append(key, JSON.stringify(data[key]));
|
||||
} else {
|
||||
formData.append(key, data[key]);
|
||||
}
|
||||
});
|
||||
|
||||
const response = await fetch(ajaxUrl, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.data || 'Request failed');
|
||||
}
|
||||
|
||||
return result.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch all WPForms
|
||||
*/
|
||||
export const fetchForms = async () => {
|
||||
return await makeRequest('wpfmj_get_forms');
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch form fields
|
||||
*/
|
||||
export const fetchFormFields = async (formId) => {
|
||||
return await makeRequest('wpfmj_get_form_fields', { form_id: formId });
|
||||
};
|
||||
|
||||
/**
|
||||
* Test Mailjet connection
|
||||
*/
|
||||
export const testMailjetConnection = async (apiKey, apiSecret) => {
|
||||
return await makeRequest('wpfmj_test_mailjet', {
|
||||
api_key: apiKey,
|
||||
api_secret: apiSecret
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch Mailjet lists
|
||||
*/
|
||||
export const fetchMailjetLists = async (apiKey, apiSecret) => {
|
||||
return await makeRequest('wpfmj_get_mailjet_lists', {
|
||||
api_key: apiKey,
|
||||
api_secret: apiSecret
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Save automation
|
||||
*/
|
||||
export const saveAutomation = async (data, editId = 0) => {
|
||||
return await makeRequest('wpfmj_save_automation', {
|
||||
data: data,
|
||||
edit_id: editId
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch automation
|
||||
*/
|
||||
export const fetchAutomation = async (id) => {
|
||||
return await makeRequest('wpfmj_get_automation', { id });
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle automation status
|
||||
*/
|
||||
export const toggleAutomation = async (id) => {
|
||||
return await makeRequest('wpfmj_toggle_automation', { id });
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete automation
|
||||
*/
|
||||
export const deleteAutomation = async (id) => {
|
||||
return await makeRequest('wpfmj_delete_automation', { id });
|
||||
};
|
||||
|
||||
/**
|
||||
* Get dashboard data
|
||||
*/
|
||||
export const fetchDashboardData = async () => {
|
||||
return await makeRequest('wpfmj_get_dashboard_data');
|
||||
};
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
// Silence is golden.
|
||||
Loading…
Add table
Add a link
Reference in a new issue