From b014781640c7c76efca8f12d450d5f6f7c408cfb Mon Sep 17 00:00:00 2001 From: Rishad Alam Date: Thu, 30 Jul 2026 18:37:17 +0600 Subject: [PATCH 1/4] feat(popup-maker): add Popup Maker action integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Popup Maker existed as a trigger only. Add the free side of its action integration: a controller exposing the popup and theme dropdowns, a RecordApiHelper routing ten write actions to their pro hooks, and the wizard, layout, field map and utilities components. Actions cover popups (create, update, delete, change status, show, reset counts, track event) and subscribers (create, update, delete). Read actions are deliberately absent — fetched data belongs in a dropdown, not a flow step. Each action's target identifier stays in the field map so it can be mapped from trigger data, while fixed option sets and fetchable config choices are selects. --- .../PopupMaker/PopupMakerController.php | 86 +++++ .../Actions/PopupMaker/RecordApiHelper.php | 164 ++++++++++ backend/Actions/PopupMaker/Routes.php | 11 + .../components/AllIntegrations/EditInteg.jsx | 3 + .../components/AllIntegrations/IntegInfo.jsx | 3 + .../components/AllIntegrations/NewInteg.jsx | 10 + .../PopupMaker/EditPopupMaker.jsx | 76 +++++ .../AllIntegrations/PopupMaker/PopupMaker.jsx | 126 ++++++++ .../PopupMaker/PopupMakerActions.jsx | 166 ++++++++++ .../PopupMaker/PopupMakerAuthorization.jsx | 36 +++ .../PopupMaker/PopupMakerCommonFunc.js | 81 +++++ .../PopupMaker/PopupMakerFieldMap.jsx | 104 ++++++ .../PopupMaker/PopupMakerIntegLayout.jsx | 297 ++++++++++++++++++ .../AllIntegrations/PopupMaker/staticData.js | 131 ++++++++ .../src/components/Flow/New/SelectAction.jsx | 1 + 15 files changed, 1295 insertions(+) create mode 100644 backend/Actions/PopupMaker/PopupMakerController.php create mode 100644 backend/Actions/PopupMaker/RecordApiHelper.php create mode 100644 backend/Actions/PopupMaker/Routes.php create mode 100644 frontend/src/components/AllIntegrations/PopupMaker/EditPopupMaker.jsx create mode 100644 frontend/src/components/AllIntegrations/PopupMaker/PopupMaker.jsx create mode 100644 frontend/src/components/AllIntegrations/PopupMaker/PopupMakerActions.jsx create mode 100644 frontend/src/components/AllIntegrations/PopupMaker/PopupMakerAuthorization.jsx create mode 100644 frontend/src/components/AllIntegrations/PopupMaker/PopupMakerCommonFunc.js create mode 100644 frontend/src/components/AllIntegrations/PopupMaker/PopupMakerFieldMap.jsx create mode 100644 frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx create mode 100644 frontend/src/components/AllIntegrations/PopupMaker/staticData.js diff --git a/backend/Actions/PopupMaker/PopupMakerController.php b/backend/Actions/PopupMaker/PopupMakerController.php new file mode 100644 index 000000000..bb4655de9 --- /dev/null +++ b/backend/Actions/PopupMaker/PopupMakerController.php @@ -0,0 +1,86 @@ +flow_details; + $integId = $integrationData->id; + $fieldMap = $integrationDetails->field_map; + $utilities = isset($integrationDetails->utilities) ? $integrationDetails->utilities : []; + + if (empty($fieldMap)) { + return new WP_Error('field_map_empty', __('Field map is empty', 'bit-integrations')); + } + + $recordApiHelper = new RecordApiHelper($integrationDetails, $integId); + + return $recordApiHelper->execute($fieldValues, $fieldMap, $utilities); + } + + private static function postDropdown($postType) + { + $options = []; + + $posts = get_posts( + [ + 'post_type' => $postType, + 'post_status' => ['publish', 'draft', 'pending', 'private'], + 'orderby' => 'title', + 'order' => 'ASC', + 'posts_per_page' => -1, + ] + ); + + foreach ($posts as $post) { + $options[] = (object) [ + 'id' => $post->ID, + 'title' => $post->post_title !== '' ? $post->post_title : \sprintf('#%d', $post->ID), + ]; + } + + return $options; + } +} diff --git a/backend/Actions/PopupMaker/RecordApiHelper.php b/backend/Actions/PopupMaker/RecordApiHelper.php new file mode 100644 index 000000000..6abc8dd7c --- /dev/null +++ b/backend/Actions/PopupMaker/RecordApiHelper.php @@ -0,0 +1,164 @@ +_integrationDetails = $integrationDetails; + $this->_integrationID = $integId; + } + + /** + * Execute the integration + * + * @param array $fieldValues Field values from trigger + * @param array $fieldMap Field mapping + * @param array $utilities Optional actions to perform + * + * @return array + */ + public function execute($fieldValues, $fieldMap, $utilities) + { + if (!\defined('POPMAKE_VERSION')) { + return [ + 'success' => false, + 'message' => __('Popup Maker is not installed or activated', 'bit-integrations') + ]; + } + + $fieldData = static::generateReqDataFromFieldMap($fieldMap, $fieldValues); + + $mainAction = $this->_integrationDetails->mainAction ?? 'create_popup'; + + $defaultResponse = [ + 'success' => false, + // translators: %s: Plugin name + 'message' => wp_sprintf(__('%s plugin is not installed or activate', 'bit-integrations'), 'Bit Integrations Pro') + ]; + + switch ($mainAction) { + case 'create_popup': + $response = Hooks::apply(Config::withPrefix('popup_maker_create_popup'), $defaultResponse, $fieldData, $utilities, $this->_integrationDetails); + $type = 'popup'; + $actionType = 'create_popup'; + + break; + + case 'update_popup': + $response = Hooks::apply(Config::withPrefix('popup_maker_update_popup'), $defaultResponse, $fieldData, $utilities, $this->_integrationDetails); + $type = 'popup'; + $actionType = 'update_popup'; + + break; + + case 'delete_popup': + $response = Hooks::apply(Config::withPrefix('popup_maker_delete_popup'), $defaultResponse, $fieldData, $utilities); + $type = 'popup'; + $actionType = 'delete_popup'; + + break; + + case 'change_popup_status': + $response = Hooks::apply(Config::withPrefix('popup_maker_change_popup_status'), $defaultResponse, $fieldData, $this->_integrationDetails); + $type = 'popup'; + $actionType = 'change_popup_status'; + + break; + + case 'reset_popup_counts': + $response = Hooks::apply(Config::withPrefix('popup_maker_reset_popup_counts'), $defaultResponse, $fieldData); + $type = 'popup'; + $actionType = 'reset_popup_counts'; + + break; + + case 'track_popup_event': + $response = Hooks::apply(Config::withPrefix('popup_maker_track_popup_event'), $defaultResponse, $fieldData, $this->_integrationDetails); + $type = 'popup'; + $actionType = 'track_popup_event'; + + break; + + case 'show_popup': + $response = Hooks::apply(Config::withPrefix('popup_maker_show_popup'), $defaultResponse, $fieldData); + $type = 'popup'; + $actionType = 'show_popup'; + + break; + + case 'create_subscriber': + $response = Hooks::apply(Config::withPrefix('popup_maker_create_subscriber'), $defaultResponse, $fieldData, $utilities, $this->_integrationDetails); + $type = 'subscriber'; + $actionType = 'create_subscriber'; + + break; + + case 'update_subscriber': + $response = Hooks::apply(Config::withPrefix('popup_maker_update_subscriber'), $defaultResponse, $fieldData, $utilities, $this->_integrationDetails); + $type = 'subscriber'; + $actionType = 'update_subscriber'; + + break; + + case 'delete_subscriber': + $response = Hooks::apply(Config::withPrefix('popup_maker_delete_subscriber'), $defaultResponse, $fieldData); + $type = 'subscriber'; + $actionType = 'delete_subscriber'; + + break; + + default: + $response = [ + 'success' => false, + 'message' => __('Invalid action', 'bit-integrations') + ]; + $type = 'PopupMaker'; + $actionType = 'unknown'; + + break; + } + + $responseType = isset($response['success']) && $response['success'] ? 'success' : 'error'; + LogHandler::save($this->_integrationID, ['type' => $type, 'type_name' => $actionType], $responseType, $response); + + return $response; + } + + protected static function generateReqDataFromFieldMap($fieldMap, $fieldValues) + { + $dataFinal = []; + + foreach ($fieldMap as $item) { + $triggerValue = $item->formField; + $actionValue = $item->popupMakerField; + + if (empty($actionValue)) { + continue; + } + + $dataFinal[$actionValue] = $triggerValue === 'custom' && isset($item->customValue) + ? Common::replaceFieldWithValue($item->customValue, $fieldValues) + : $fieldValues[$triggerValue] ?? ''; + } + + return $dataFinal; + } +} diff --git a/backend/Actions/PopupMaker/Routes.php b/backend/Actions/PopupMaker/Routes.php new file mode 100644 index 000000000..dfef415fa --- /dev/null +++ b/backend/Actions/PopupMaker/Routes.php @@ -0,0 +1,11 @@ + import('./CreatorLms/EditCreatorLms')) const EditUltimateAffiliatePro = lazy(() => import('./UltimateAffiliatePro/EditUltimateAffiliatePro')) const EditBookly = lazy(() => import('./Bookly/EditBookly')) const EditFluentCart = lazy(() => import('./FluentCart/EditFluentCart')) +const EditPopupMaker = lazy(() => import('./PopupMaker/EditPopupMaker')) const EditFluentPlayer = lazy(() => import('./FluentPlayer/EditFluentPlayer')) const EditBitCrm = lazy(() => import('./BitCrm/EditBitCrm')) const EditWsms = lazy(() => import('./Wsms/EditWsms')) @@ -631,6 +632,8 @@ const IntegType = memo(({ allIntegURL, flow }) => { return case 'FluentCart': return + case 'PopupMaker': + return case 'FluentPlayer': return case 'BitCrm': diff --git a/frontend/src/components/AllIntegrations/IntegInfo.jsx b/frontend/src/components/AllIntegrations/IntegInfo.jsx index 057cbd6b0..2edf6576c 100644 --- a/frontend/src/components/AllIntegrations/IntegInfo.jsx +++ b/frontend/src/components/AllIntegrations/IntegInfo.jsx @@ -186,6 +186,7 @@ const UltimateAffiliateProAuthorization = lazy( ) const BooklyAuthorization = lazy(() => import('./Bookly/BooklyAuthorization')) const FluentCartAuthorization = lazy(() => import('./FluentCart/FluentCartAuthorization')) +const PopupMakerAuthorization = lazy(() => import('./PopupMaker/PopupMakerAuthorization')) const FluentPlayerAuthorization = lazy(() => import('./FluentPlayer/FluentPlayerAuthorization')) const BitCrmAuthorization = lazy(() => import('./BitCrm/BitCrmAuthorization')) const WsmsAuthorization = lazy(() => import('./Wsms/WsmsAuthorization')) @@ -671,6 +672,8 @@ const IntegrationInfo = memo(({ integrationConf, location, editUrl }) => { return case 'FluentCart': return + case 'PopupMaker': + return case 'FluentPlayer': return case 'BitCrm': diff --git a/frontend/src/components/AllIntegrations/NewInteg.jsx b/frontend/src/components/AllIntegrations/NewInteg.jsx index ab927ddcc..b6cbe6e54 100644 --- a/frontend/src/components/AllIntegrations/NewInteg.jsx +++ b/frontend/src/components/AllIntegrations/NewInteg.jsx @@ -179,6 +179,7 @@ const CreatorLms = lazy(() => import('./CreatorLms/CreatorLms')) const UltimateAffiliatePro = lazy(() => import('./UltimateAffiliatePro/UltimateAffiliatePro')) const Bookly = lazy(() => import('./Bookly/Bookly')) const FluentCart = lazy(() => import('./FluentCart/FluentCart')) +const PopupMaker = lazy(() => import('./PopupMaker/PopupMaker')) const FluentPlayer = lazy(() => import('./FluentPlayer/FluentPlayer')) const BitCrm = lazy(() => import('./BitCrm/BitCrm')) const Wsms = lazy(() => import('./Wsms/Wsms')) @@ -1750,6 +1751,15 @@ const NewIntegs = memo(({ integUrlName, allIntegURL, flow, setFlow }) => { setFlow={setFlow} /> ) + case 'PopupMaker': + return ( + + ) case 'FluentPlayer': return ( + + +
+ {__('Integration Name:', 'bit-integrations')} + handleInput(e, popupMakerConf, setPopupMakerConf)} + name="name" + value={popupMakerConf.name} + type="text" + placeholder={__('Integration Name...', 'bit-integrations')} + /> +
+
+ + + + + + + saveActionConf({ + flow, + setFlow, + allIntegURL, + conf: popupMakerConf, + navigate, + id, + edit: 1, + setIsLoading, + setSnackbar + }) + } + disabled={!checkMappedFields(popupMakerConf)} + isLoading={isLoading} + dataConf={popupMakerConf} + setDataConf={setPopupMakerConf} + formFields={formFields} + /> +
+ + ) +} diff --git a/frontend/src/components/AllIntegrations/PopupMaker/PopupMaker.jsx b/frontend/src/components/AllIntegrations/PopupMaker/PopupMaker.jsx new file mode 100644 index 000000000..98d7f71ad --- /dev/null +++ b/frontend/src/components/AllIntegrations/PopupMaker/PopupMaker.jsx @@ -0,0 +1,126 @@ +import { useState } from 'react' +import 'react-multiple-select-dropdown-lite/dist/index.css' +import { useNavigate, useParams } from 'react-router' +import BackIcn from '../../../Icons/BackIcn' +import { __ } from '../../../Utils/i18nwrap' +import SnackMsg from '../../Utilities/SnackMsg' +import { saveIntegConfig } from '../IntegrationHelpers/IntegrationHelpers' +import IntegrationStepThree from '../IntegrationHelpers/IntegrationStepThree' +import PopupMakerAuthorization from './PopupMakerAuthorization' +import { checkMappedFields } from './PopupMakerCommonFunc' +import PopupMakerIntegLayout from './PopupMakerIntegLayout' +import { needsEvent, needsStatus } from './staticData' + +export default function PopupMaker({ formFields, setFlow, flow, allIntegURL }) { + const navigate = useNavigate() + const { formID } = useParams() + const [isLoading, setIsLoading] = useState(false) + const [step, setStep] = useState(1) + const [snack, setSnackbar] = useState({ show: false }) + const [popupMakerConf, setPopupMakerConf] = useState({ + name: 'PopupMaker', + type: 'PopupMaker', + field_map: [{ formField: '', popupMakerField: '' }], + actions: {}, + mainAction: '' + }) + + const nextPage = val => { + setTimeout(() => { + document.getElementById('btcd-settings-wrp').scrollTop = 0 + }, 300) + + if (val === 3) { + if (needsStatus.includes(popupMakerConf.mainAction) && !popupMakerConf?.selectedStatus) { + setSnackbar({ + show: true, + msg: __('Please select a status to continue.', 'bit-integrations') + }) + return + } + + if (needsEvent.includes(popupMakerConf.mainAction) && !popupMakerConf?.selectedEvent) { + setSnackbar({ + show: true, + msg: __('Please select an event to continue.', 'bit-integrations') + }) + return + } + + if (!checkMappedFields(popupMakerConf)) { + setSnackbar({ + show: true, + msg: __('Please map all required fields to continue.', 'bit-integrations') + }) + return + } + + if (popupMakerConf.name !== '' && popupMakerConf.field_map.length > 0) { + setStep(val) + } + } else { + setStep(val) + } + } + + return ( +
+ +
+ + {/* STEP 1 */} + + + {/* STEP 2 */} +
+ +
+
+
+ +
+ + {/* STEP 3 */} + + saveIntegConfig(flow, setFlow, allIntegURL, popupMakerConf, navigate, '', '', setIsLoading) + } + isLoading={isLoading} + dataConf={popupMakerConf} + setDataConf={setPopupMakerConf} + formFields={formFields} + /> +
+ ) +} diff --git a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerActions.jsx b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerActions.jsx new file mode 100644 index 000000000..7813c2c14 --- /dev/null +++ b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerActions.jsx @@ -0,0 +1,166 @@ +/* eslint-disable no-param-reassign */ + +import { useState } from 'react' +import { create } from 'mutative' +import MultiSelect from 'react-multiple-select-dropdown-lite' +import { __ } from '../../../Utils/i18nwrap' +import ConfirmModal from '../../Utilities/ConfirmModal' +import TableCheckBox from '../../Utilities/TableCheckBox' +import 'react-multiple-select-dropdown-lite/dist/index.css' +import { + animationOptions, + consentOptions, + forceDeleteOptions, + sizeOptions, + statusOptions +} from './staticData' + +export default function PopupMakerActions({ popupMakerConf, setPopupMakerConf }) { + const [actionMdl, setActionMdl] = useState({ show: false, action: () => {} }) + + const actionHandler = type => { + setPopupMakerConf(prevConf => + create(prevConf, draftConf => { + if (!draftConf.utilities) { + draftConf.utilities = {} + } + }) + ) + + setActionMdl({ show: type }) + } + + const clsActionMdl = () => { + setActionMdl({ show: false }) + } + + const setAction = (val, name) => { + setPopupMakerConf(prevConf => + create(prevConf, draftConf => { + if (!draftConf.utilities) { + draftConf.utilities = {} + } + draftConf.utilities[name] = val + }) + ) + } + + const renderActionModal = (type, title, options, valueName) => ( + +
+
{title}
+
+ setAction(val, valueName)} + /> +
+ + ) + + const isPopupWrite = ['create_popup', 'update_popup'].includes(popupMakerConf?.mainAction) + const isSubscriberWrite = ['create_subscriber', 'update_subscriber'].includes( + popupMakerConf?.mainAction + ) + + return ( +
+ {isPopupWrite && ( + <> + actionHandler('status')} + className="wdt-200 mt-4 mr-2" + value="status" + title={__('Popup Status', 'bit-integrations')} + subTitle={__('Set the popup status', 'bit-integrations')} + /> + + actionHandler('size')} + className="wdt-200 mt-4 mr-2" + value="size" + title={__('Size', 'bit-integrations')} + subTitle={__('Set the popup size', 'bit-integrations')} + /> + + actionHandler('animation_type')} + className="wdt-200 mt-4 mr-2" + value="animation_type" + title={__('Animation Type', 'bit-integrations')} + subTitle={__('Set the popup animation', 'bit-integrations')} + /> + + {renderActionModal( + 'status', + __('Popup Status', 'bit-integrations'), + statusOptions, + 'selected_status' + )} + {renderActionModal('size', __('Size', 'bit-integrations'), sizeOptions, 'selected_size')} + {renderActionModal( + 'animation_type', + __('Animation Type', 'bit-integrations'), + animationOptions, + 'selected_animation_type' + )} + + )} + + {popupMakerConf?.mainAction === 'delete_popup' && ( + <> + actionHandler('force_delete')} + className="wdt-200 mt-4 mr-2" + value="force_delete" + title={__('Force Delete', 'bit-integrations')} + subTitle={__('Delete permanently instead of trashing', 'bit-integrations')} + /> + + {renderActionModal( + 'force_delete', + __('Force Delete', 'bit-integrations'), + forceDeleteOptions, + 'selected_force_delete' + )} + + )} + + {isSubscriberWrite && ( + <> + actionHandler('consent')} + className="wdt-200 mt-4 mr-2" + value="consent" + title={__('Consent', 'bit-integrations')} + subTitle={__('Set the subscriber consent', 'bit-integrations')} + /> + + {renderActionModal( + 'consent', + __('Consent', 'bit-integrations'), + consentOptions, + 'selected_consent' + )} + + )} +
+ ) +} diff --git a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerAuthorization.jsx b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerAuthorization.jsx new file mode 100644 index 000000000..f9ab0cc86 --- /dev/null +++ b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerAuthorization.jsx @@ -0,0 +1,36 @@ +import { useCallback } from 'react' +import { AUTH_TYPES } from '../../../Utils/connectionAuth' +import { __ } from '../../../Utils/i18nwrap' +import tutorialLinks from '../../../Utils/StaticData/tutorialLinks' +import Authorization from '../../Connections/Authorization' + +export default function PopupMakerAuthorization({ + popupMakerConf, + setPopupMakerConf, + step, + nextPage, + isInfo +}) { + const setStep = useCallback(value => nextPage(value), [nextPage]) + return ( + + ) +} diff --git a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerCommonFunc.js b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerCommonFunc.js new file mode 100644 index 000000000..3ceb1782b --- /dev/null +++ b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerCommonFunc.js @@ -0,0 +1,81 @@ +import { create } from 'mutative' +import toast from 'react-hot-toast' +import bitsFetch from '../../../Utils/bitsFetch' +import { __ } from '../../../Utils/i18nwrap' + +export const handleInput = (e, popupMakerConf, setPopupMakerConf) => { + const { name, value } = e.target + + setPopupMakerConf(prevConf => + create(prevConf, draftConf => { + draftConf[name] = value + }) + ) +} + +export const refreshPopupMakerPopups = (setPopupMakerConf, setIsLoading) => { + setIsLoading(true) + bitsFetch(null, 'refresh_popup_maker_popups') + .then(result => { + if (result && result?.success && result?.data?.popups) { + setPopupMakerConf(prevConf => + create(prevConf, draftConf => { + draftConf.allPopups = result.data.popups + }) + ) + + setIsLoading(false) + toast.success(__('All popups fetched successfully', 'bit-integrations')) + return + } + setIsLoading(false) + toast.error(__('Popup Maker popups fetch failed. Please try again', 'bit-integrations')) + }) + .catch(() => setIsLoading(false)) +} + +export const refreshPopupMakerThemes = (setPopupMakerConf, setIsLoading) => { + setIsLoading(true) + bitsFetch(null, 'refresh_popup_maker_themes') + .then(result => { + if (result && result?.success && result?.data?.themes) { + setPopupMakerConf(prevConf => + create(prevConf, draftConf => { + draftConf.allThemes = result.data.themes + }) + ) + + setIsLoading(false) + toast.success(__('All popup themes fetched successfully', 'bit-integrations')) + return + } + setIsLoading(false) + toast.error(__('Popup Maker themes fetch failed. Please try again', 'bit-integrations')) + }) + .catch(() => setIsLoading(false)) +} + +export const checkMappedFields = popupMakerConf => { + const mappedFields = popupMakerConf?.field_map + ? popupMakerConf.field_map.filter( + mappedField => + !mappedField.formField || + !mappedField.popupMakerField || + (mappedField.formField === 'custom' && !mappedField.customValue) + ) + : [] + if (mappedFields.length > 0) { + return false + } + return true +} + +export const generateMappedField = fields => { + const requiredFlds = fields.filter(fld => fld.required === true) + return requiredFlds.length > 0 + ? requiredFlds.map(field => ({ + formField: '', + popupMakerField: field.key + })) + : [{ formField: '', popupMakerField: '' }] +} diff --git a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerFieldMap.jsx b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerFieldMap.jsx new file mode 100644 index 000000000..bffd46985 --- /dev/null +++ b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerFieldMap.jsx @@ -0,0 +1,104 @@ +import { useRecoilValue } from 'recoil' +import { $appConfigState } from '../../../GlobalStates' +import { __, sprintf } from '../../../Utils/i18nwrap' +import { SmartTagField } from '../../../Utils/StaticData/SmartTagField' +import TagifyInput from '../../Utilities/TagifyInput' +import { + addFieldMap, + delFieldMap, + handleCustomValue, + handleFieldMapping +} from '../GlobalIntegrationHelper' + +export default function PopupMakerFieldMap({ i, formFields, field, popupMakerConf, setPopupMakerConf }) { + const btcbi = useRecoilValue($appConfigState) + const { isPro } = btcbi + + const requiredFlds = popupMakerConf?.popupMakerFields?.filter(fld => fld.required === true) || [] + const nonRequiredFlds = popupMakerConf?.popupMakerFields?.filter(fld => fld.required === false) || [] + + return ( +
+
+
+ + + {field.formField === 'custom' && ( + handleCustomValue(e, i, popupMakerConf, setPopupMakerConf)} + label={__('Custom Value', 'bit-integrations')} + className="mr-2" + type="text" + value={field.customValue} + placeholder={__('Custom Value', 'bit-integrations')} + formFields={formFields} + /> + )} + + +
+ {i >= requiredFlds.length && ( + <> + + + + )} +
+
+ ) +} diff --git a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx new file mode 100644 index 000000000..4954aadc9 --- /dev/null +++ b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx @@ -0,0 +1,297 @@ +import { create } from 'mutative' +import MultiSelect from 'react-multiple-select-dropdown-lite' +import { useRecoilValue } from 'recoil' +import { $appConfigState } from '../../../GlobalStates' +import { __ } from '../../../Utils/i18nwrap' +import Loader from '../../Loaders/Loader' +import Note from '../../Utilities/Note' +import { checkIsPro, getProLabel } from '../../Utilities/ProUtilHelpers' +import { addFieldMap } from '../IntegrationHelpers/IntegrationHelpers' +import PopupMakerActions from './PopupMakerActions' +import { + generateMappedField, + refreshPopupMakerPopups, + refreshPopupMakerThemes +} from './PopupMakerCommonFunc' +import PopupMakerFieldMap from './PopupMakerFieldMap' +import { + changeStatusOptions, + eventOptions, + hasUtilities, + modules, + needsEvent, + needsPopup, + needsStatus, + needsTheme, + PopupFields, + PopupIdField, + PopupUpdateFields, + ShowPopupFields, + SubscriberFields, + SubscriberIdField, + SubscriberUpdateFields +} from './staticData' + +export default function PopupMakerIntegLayout({ + formID, + formFields, + popupMakerConf, + setPopupMakerConf, + isLoading, + setIsLoading, + setSnackbar +}) { + const btcbi = useRecoilValue($appConfigState) + const { isPro } = btcbi + + const setField = (key, val) => + setPopupMakerConf(prevConf => + create(prevConf, draftConf => { + draftConf[key] = val + }) + ) + + const handleMainAction = value => { + setPopupMakerConf(prevConf => + create(prevConf, draftConf => { + draftConf.mainAction = value + + switch (value) { + case 'create_popup': + draftConf.popupMakerFields = PopupFields + break + case 'update_popup': + draftConf.popupMakerFields = PopupUpdateFields + break + case 'delete_popup': + case 'change_popup_status': + case 'reset_popup_counts': + case 'track_popup_event': + draftConf.popupMakerFields = PopupIdField + break + case 'show_popup': + draftConf.popupMakerFields = ShowPopupFields + break + case 'create_subscriber': + draftConf.popupMakerFields = SubscriberFields + break + case 'update_subscriber': + draftConf.popupMakerFields = SubscriberUpdateFields + break + case 'delete_subscriber': + draftConf.popupMakerFields = SubscriberIdField + break + default: + draftConf.popupMakerFields = [] + } + + draftConf.field_map = generateMappedField(draftConf.popupMakerFields) + }) + ) + + if (needsTheme.includes(value)) { + refreshPopupMakerThemes(setPopupMakerConf, setIsLoading) + } + + if (needsPopup.includes(value)) { + refreshPopupMakerPopups(setPopupMakerConf, setIsLoading) + } + } + + return ( + <> +
+
+ {__('Action:', 'bit-integrations')} + handleMainAction(value)} + options={modules?.map(action => ({ + label: checkIsPro(isPro, action.is_pro) ? action.label : getProLabel(action.label), + value: action.name, + disabled: !checkIsPro(isPro, action.is_pro) + }))} + singleSelect + closeOnSelect + /> +
+ + {needsStatus.includes(popupMakerConf?.mainAction) && ( + <> +
+
+ {__('Status:', 'bit-integrations')} + setField('selectedStatus', val)} + singleSelect + closeOnSelect + /> +
+ + )} + + {needsEvent.includes(popupMakerConf?.mainAction) && ( + <> +
+
+ {__('Event:', 'bit-integrations')} + setField('selectedEvent', val)} + singleSelect + closeOnSelect + /> +
+ + )} + + {needsTheme.includes(popupMakerConf?.mainAction) && ( + <> +
+
+ {__('Popup Theme:', 'bit-integrations')} + ({ + label: theme.title, + value: theme.id.toString() + })) + } + onChange={val => setField('selectedTheme', val)} + singleSelect + closeOnSelect + /> + +
+ + )} + + {needsPopup.includes(popupMakerConf?.mainAction) && ( + <> +
+
+ {__('Popup:', 'bit-integrations')} + ({ + label: popup.title, + value: popup.id.toString() + })) + } + onChange={val => setField('selectedPopup', val)} + singleSelect + closeOnSelect + /> + +
+ + )} + + {isLoading && ( + + )} + + {popupMakerConf?.mainAction && popupMakerConf.popupMakerFields && ( +
+ {__('Map Fields', 'bit-integrations')} +
+
+
+ {__('Form Fields', 'bit-integrations')} +
+
+ {__('Popup Maker Fields', 'bit-integrations')} +
+
+ + {popupMakerConf?.field_map?.map((itm, i) => ( + + ))} +
+ +
+
+
+ )} + + {popupMakerConf?.mainAction === 'show_popup' && ( + + )} + + {popupMakerConf?.mainAction && + popupMakerConf.popupMakerFields && + hasUtilities.includes(popupMakerConf?.mainAction) && ( +
+ {__('Utilities', 'bit-integrations')} +
+ +
+ )} + + ) +} diff --git a/frontend/src/components/AllIntegrations/PopupMaker/staticData.js b/frontend/src/components/AllIntegrations/PopupMaker/staticData.js new file mode 100644 index 000000000..2ca9c5105 --- /dev/null +++ b/frontend/src/components/AllIntegrations/PopupMaker/staticData.js @@ -0,0 +1,131 @@ +import { __ } from '../../../Utils/i18nwrap' + +export const modules = [ + { name: 'create_popup', label: __('Create Popup', 'bit-integrations'), is_pro: true }, + { name: 'update_popup', label: __('Update Popup', 'bit-integrations'), is_pro: true }, + { name: 'delete_popup', label: __('Delete Popup', 'bit-integrations'), is_pro: true }, + { + name: 'change_popup_status', + label: __('Change Popup Status', 'bit-integrations'), + is_pro: true + }, + { name: 'show_popup', label: __('Show Popup', 'bit-integrations'), is_pro: true }, + { + name: 'reset_popup_counts', + label: __('Reset Popup Counts', 'bit-integrations'), + is_pro: true + }, + { name: 'track_popup_event', label: __('Track Popup Event', 'bit-integrations'), is_pro: true }, + { name: 'create_subscriber', label: __('Create Subscriber', 'bit-integrations'), is_pro: true }, + { name: 'update_subscriber', label: __('Update Subscriber', 'bit-integrations'), is_pro: true }, + { name: 'delete_subscriber', label: __('Delete Subscriber', 'bit-integrations'), is_pro: true } +] + +export const PopupFields = [ + { key: 'title', label: __('Popup Name', 'bit-integrations'), required: true }, + { key: 'popup_title', label: __('Popup Title', 'bit-integrations'), required: false }, + { key: 'content', label: __('Content', 'bit-integrations'), required: false } +] + +export const PopupUpdateFields = [ + { key: 'popup_id', label: __('Popup ID', 'bit-integrations'), required: true }, + { key: 'title', label: __('Popup Name', 'bit-integrations'), required: false }, + { key: 'popup_title', label: __('Popup Title', 'bit-integrations'), required: false }, + { key: 'content', label: __('Content', 'bit-integrations'), required: false } +] + +export const PopupIdField = [ + { key: 'popup_id', label: __('Popup ID', 'bit-integrations'), required: true } +] + +export const ShowPopupFields = [ + { key: 'popup_id', label: __('Popup ID', 'bit-integrations'), required: true }, + { key: 'user_email', label: __('User Email', 'bit-integrations'), required: false }, + { key: 'expires_in', label: __('Expires In (Minutes)', 'bit-integrations'), required: false } +] + +export const SubscriberFields = [ + { key: 'email', label: __('Email', 'bit-integrations'), required: true }, + { key: 'name', label: __('Name', 'bit-integrations'), required: false }, + { key: 'fname', label: __('First Name', 'bit-integrations'), required: false }, + { key: 'lname', label: __('Last Name', 'bit-integrations'), required: false }, + { key: 'consent_args', label: __('Consent Args', 'bit-integrations'), required: false } +] + +export const SubscriberUpdateFields = [ + { key: 'subscriber_id', label: __('Subscriber ID', 'bit-integrations'), required: true }, + { key: 'email', label: __('Email', 'bit-integrations'), required: false }, + { key: 'name', label: __('Name', 'bit-integrations'), required: false }, + { key: 'fname', label: __('First Name', 'bit-integrations'), required: false }, + { key: 'lname', label: __('Last Name', 'bit-integrations'), required: false } +] + +export const SubscriberIdField = [ + { key: 'subscriber_id', label: __('Subscriber ID', 'bit-integrations'), required: true } +] + +export const statusOptions = [ + { label: __('Publish', 'bit-integrations'), value: 'publish' }, + { label: __('Draft', 'bit-integrations'), value: 'draft' }, + { label: __('Pending', 'bit-integrations'), value: 'pending' }, + { label: __('Private', 'bit-integrations'), value: 'private' } +] + +export const changeStatusOptions = [ + ...statusOptions, + { label: __('Trash', 'bit-integrations'), value: 'trash' } +] + +export const eventOptions = [ + { label: __('Open', 'bit-integrations'), value: 'open' }, + { label: __('Conversion', 'bit-integrations'), value: 'conversion' } +] + +export const sizeOptions = [ + { label: __('Nano - 10%', 'bit-integrations'), value: 'nano' }, + { label: __('Micro - 20%', 'bit-integrations'), value: 'micro' }, + { label: __('Tiny - 30%', 'bit-integrations'), value: 'tiny' }, + { label: __('Small - 40%', 'bit-integrations'), value: 'small' }, + { label: __('Medium - 60%', 'bit-integrations'), value: 'medium' }, + { label: __('Normal - 70%', 'bit-integrations'), value: 'normal' }, + { label: __('Large - 80%', 'bit-integrations'), value: 'large' }, + { label: __('X Large - 95%', 'bit-integrations'), value: 'xlarge' }, + { label: __('Auto', 'bit-integrations'), value: 'auto' }, + { label: __('Custom', 'bit-integrations'), value: 'custom' } +] + +export const animationOptions = [ + { label: __('None', 'bit-integrations'), value: 'none' }, + { label: __('Slide', 'bit-integrations'), value: 'slide' }, + { label: __('Fade', 'bit-integrations'), value: 'fade' }, + { label: __('Fade and Slide', 'bit-integrations'), value: 'fadeAndSlide' } +] + +export const consentOptions = [ + { label: __('Yes', 'bit-integrations'), value: 'yes' }, + { label: __('No', 'bit-integrations'), value: 'no' } +] + +export const forceDeleteOptions = [ + { label: __('Yes, delete permanently', 'bit-integrations'), value: 'yes' }, + { label: __('No, move to trash', 'bit-integrations'), value: 'no' } +] + +// Actions that need a fetched theme dropdown +export const needsTheme = ['create_popup', 'update_popup'] + +// Actions that need a fetched popup dropdown (subscriber attribution) +export const needsPopup = ['create_subscriber', 'update_subscriber'] + +// Actions with a required select rendered in the layout +export const needsStatus = ['change_popup_status'] +export const needsEvent = ['track_popup_event'] + +// Actions with optional selects rendered under Utilities +export const hasUtilities = [ + 'create_popup', + 'update_popup', + 'delete_popup', + 'create_subscriber', + 'update_subscriber' +] diff --git a/frontend/src/components/Flow/New/SelectAction.jsx b/frontend/src/components/Flow/New/SelectAction.jsx index f2efc8ff1..85029dd93 100644 --- a/frontend/src/components/Flow/New/SelectAction.jsx +++ b/frontend/src/components/Flow/New/SelectAction.jsx @@ -185,6 +185,7 @@ export default function SelectAction() { { type: 'CreatorLms', is_pro: true }, { type: 'Bookly', is_pro: true }, { type: 'FluentCart', is_pro: true }, + { type: 'PopupMaker', name: 'Popup Maker', logo: 'popupMaker', is_pro: true }, { type: 'FluentPlayer', is_pro: true }, { type: 'BitCrm', name: 'Bit CRM', logo: 'bitCrm', is_pro: false }, { type: 'MoreConvert Wishlist', logo: 'moreConvertWishlist', is_pro: true }, From cfb8aa1196dfb7fb9c68d9142de2c499861acb1a Mon Sep 17 00:00:00 2001 From: Rishad Alam Date: Thu, 30 Jul 2026 18:46:10 +0600 Subject: [PATCH 2/4] refactor(popup-maker): trim redundant work and dead wiring Review cleanups on the free side of the integration. The popup and theme dropdowns primed the post meta and term caches for a list that renders ids and titles only, pulling every popup's serialized settings along the way. Switching actions also refetched lists already held in state, even though the refresh buttons cover that. PopupMakerActions received formFields and setSnackbar it never destructured, opened its modal through a state write whose only effect was an empty utilities object, and restated the action lists that staticData already exports. --- .../PopupMaker/PopupMakerController.php | 4 ++++ .../PopupMaker/PopupMakerActions.jsx | 20 +++++-------------- .../PopupMaker/PopupMakerIntegLayout.jsx | 12 ++++------- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/backend/Actions/PopupMaker/PopupMakerController.php b/backend/Actions/PopupMaker/PopupMakerController.php index bb4655de9..af08adc35 100644 --- a/backend/Actions/PopupMaker/PopupMakerController.php +++ b/backend/Actions/PopupMaker/PopupMakerController.php @@ -71,6 +71,10 @@ private static function postDropdown($postType) 'orderby' => 'title', 'order' => 'ASC', 'posts_per_page' => -1, + // The dropdown renders ids and titles only, so skip priming the meta cache + // with every popup's serialized settings, and the term cache with taxonomies. + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, ] ); diff --git a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerActions.jsx b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerActions.jsx index 7813c2c14..397f2c827 100644 --- a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerActions.jsx +++ b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerActions.jsx @@ -11,6 +11,8 @@ import { animationOptions, consentOptions, forceDeleteOptions, + needsPopup, + needsTheme, sizeOptions, statusOptions } from './staticData' @@ -18,17 +20,7 @@ import { export default function PopupMakerActions({ popupMakerConf, setPopupMakerConf }) { const [actionMdl, setActionMdl] = useState({ show: false, action: () => {} }) - const actionHandler = type => { - setPopupMakerConf(prevConf => - create(prevConf, draftConf => { - if (!draftConf.utilities) { - draftConf.utilities = {} - } - }) - ) - - setActionMdl({ show: type }) - } + const actionHandler = type => setActionMdl({ show: type }) const clsActionMdl = () => { setActionMdl({ show: false }) @@ -70,10 +62,8 @@ export default function PopupMakerActions({ popupMakerConf, setPopupMakerConf }) ) - const isPopupWrite = ['create_popup', 'update_popup'].includes(popupMakerConf?.mainAction) - const isSubscriberWrite = ['create_subscriber', 'update_subscriber'].includes( - popupMakerConf?.mainAction - ) + const isPopupWrite = needsTheme.includes(popupMakerConf?.mainAction) + const isSubscriberWrite = needsPopup.includes(popupMakerConf?.mainAction) return (
diff --git a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx index 4954aadc9..040ec62ed 100644 --- a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx +++ b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx @@ -89,11 +89,12 @@ export default function PopupMakerIntegLayout({ }) ) - if (needsTheme.includes(value)) { + // The refresh buttons cover re-fetching, so only load a list we do not have yet. + if (needsTheme.includes(value) && !popupMakerConf?.allThemes?.length) { refreshPopupMakerThemes(setPopupMakerConf, setIsLoading) } - if (needsPopup.includes(value)) { + if (needsPopup.includes(value) && !popupMakerConf?.allPopups?.length) { refreshPopupMakerPopups(setPopupMakerConf, setIsLoading) } } @@ -284,12 +285,7 @@ export default function PopupMakerIntegLayout({
{__('Utilities', 'bit-integrations')}
- +
)} From 1858f9310741d23c782e583bbbe3dbf27bdc6f6c Mon Sep 17 00:00:00 2001 From: Rishad Alam Date: Sun, 2 Aug 2026 10:36:17 +0600 Subject: [PATCH 3/4] refactor(popup-maker): drop Show Popup action The Show Popup action queued a popup in user meta and opened it on the user's next front-end page view, which needed a logged-in WordPress user and only ever fired client side. Remove it along with its field set and the explanatory note in the layout. --- backend/Actions/PopupMaker/RecordApiHelper.php | 7 ------- .../PopupMaker/PopupMakerIntegLayout.jsx | 14 -------------- .../AllIntegrations/PopupMaker/staticData.js | 7 ------- 3 files changed, 28 deletions(-) diff --git a/backend/Actions/PopupMaker/RecordApiHelper.php b/backend/Actions/PopupMaker/RecordApiHelper.php index 6abc8dd7c..1b741ff79 100644 --- a/backend/Actions/PopupMaker/RecordApiHelper.php +++ b/backend/Actions/PopupMaker/RecordApiHelper.php @@ -97,13 +97,6 @@ public function execute($fieldValues, $fieldMap, $utilities) break; - case 'show_popup': - $response = Hooks::apply(Config::withPrefix('popup_maker_show_popup'), $defaultResponse, $fieldData); - $type = 'popup'; - $actionType = 'show_popup'; - - break; - case 'create_subscriber': $response = Hooks::apply(Config::withPrefix('popup_maker_create_subscriber'), $defaultResponse, $fieldData, $utilities, $this->_integrationDetails); $type = 'subscriber'; diff --git a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx index 040ec62ed..4c07ef34b 100644 --- a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx +++ b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx @@ -4,7 +4,6 @@ import { useRecoilValue } from 'recoil' import { $appConfigState } from '../../../GlobalStates' import { __ } from '../../../Utils/i18nwrap' import Loader from '../../Loaders/Loader' -import Note from '../../Utilities/Note' import { checkIsPro, getProLabel } from '../../Utilities/ProUtilHelpers' import { addFieldMap } from '../IntegrationHelpers/IntegrationHelpers' import PopupMakerActions from './PopupMakerActions' @@ -26,7 +25,6 @@ import { PopupFields, PopupIdField, PopupUpdateFields, - ShowPopupFields, SubscriberFields, SubscriberIdField, SubscriberUpdateFields @@ -69,9 +67,6 @@ export default function PopupMakerIntegLayout({ case 'track_popup_event': draftConf.popupMakerFields = PopupIdField break - case 'show_popup': - draftConf.popupMakerFields = ShowPopupFields - break case 'create_subscriber': draftConf.popupMakerFields = SubscriberFields break @@ -270,15 +265,6 @@ export default function PopupMakerIntegLayout({
)} - {popupMakerConf?.mainAction === 'show_popup' && ( - - )} - {popupMakerConf?.mainAction && popupMakerConf.popupMakerFields && hasUtilities.includes(popupMakerConf?.mainAction) && ( diff --git a/frontend/src/components/AllIntegrations/PopupMaker/staticData.js b/frontend/src/components/AllIntegrations/PopupMaker/staticData.js index 2ca9c5105..1b9f1c99d 100644 --- a/frontend/src/components/AllIntegrations/PopupMaker/staticData.js +++ b/frontend/src/components/AllIntegrations/PopupMaker/staticData.js @@ -9,7 +9,6 @@ export const modules = [ label: __('Change Popup Status', 'bit-integrations'), is_pro: true }, - { name: 'show_popup', label: __('Show Popup', 'bit-integrations'), is_pro: true }, { name: 'reset_popup_counts', label: __('Reset Popup Counts', 'bit-integrations'), @@ -38,12 +37,6 @@ export const PopupIdField = [ { key: 'popup_id', label: __('Popup ID', 'bit-integrations'), required: true } ] -export const ShowPopupFields = [ - { key: 'popup_id', label: __('Popup ID', 'bit-integrations'), required: true }, - { key: 'user_email', label: __('User Email', 'bit-integrations'), required: false }, - { key: 'expires_in', label: __('Expires In (Minutes)', 'bit-integrations'), required: false } -] - export const SubscriberFields = [ { key: 'email', label: __('Email', 'bit-integrations'), required: true }, { key: 'name', label: __('Name', 'bit-integrations'), required: false }, From 79c20c26d22e5019434b4f5198cbe5981f40d009 Mon Sep 17 00:00:00 2001 From: Rishad Alam Date: Sun, 2 Aug 2026 11:04:25 +0600 Subject: [PATCH 4/4] fix(popup-maker): fail on a missing action and trim comments mainAction no longer falls back to create_popup, so a flow that lost its action reports "Invalid action" instead of publishing a popup. Also drop the comments that only restated the code they sat above. --- backend/Actions/PopupMaker/PopupMakerController.php | 2 -- backend/Actions/PopupMaker/RecordApiHelper.php | 2 +- .../AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx | 1 - .../src/components/AllIntegrations/PopupMaker/staticData.js | 5 +---- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/backend/Actions/PopupMaker/PopupMakerController.php b/backend/Actions/PopupMaker/PopupMakerController.php index af08adc35..891a994c1 100644 --- a/backend/Actions/PopupMaker/PopupMakerController.php +++ b/backend/Actions/PopupMaker/PopupMakerController.php @@ -71,8 +71,6 @@ private static function postDropdown($postType) 'orderby' => 'title', 'order' => 'ASC', 'posts_per_page' => -1, - // The dropdown renders ids and titles only, so skip priming the meta cache - // with every popup's serialized settings, and the term cache with taxonomies. 'update_post_meta_cache' => false, 'update_post_term_cache' => false, ] diff --git a/backend/Actions/PopupMaker/RecordApiHelper.php b/backend/Actions/PopupMaker/RecordApiHelper.php index 1b741ff79..1315e1dd4 100644 --- a/backend/Actions/PopupMaker/RecordApiHelper.php +++ b/backend/Actions/PopupMaker/RecordApiHelper.php @@ -46,7 +46,7 @@ public function execute($fieldValues, $fieldMap, $utilities) $fieldData = static::generateReqDataFromFieldMap($fieldMap, $fieldValues); - $mainAction = $this->_integrationDetails->mainAction ?? 'create_popup'; + $mainAction = $this->_integrationDetails->mainAction ?? ''; $defaultResponse = [ 'success' => false, diff --git a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx index 4c07ef34b..30047517e 100644 --- a/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx +++ b/frontend/src/components/AllIntegrations/PopupMaker/PopupMakerIntegLayout.jsx @@ -84,7 +84,6 @@ export default function PopupMakerIntegLayout({ }) ) - // The refresh buttons cover re-fetching, so only load a list we do not have yet. if (needsTheme.includes(value) && !popupMakerConf?.allThemes?.length) { refreshPopupMakerThemes(setPopupMakerConf, setIsLoading) } diff --git a/frontend/src/components/AllIntegrations/PopupMaker/staticData.js b/frontend/src/components/AllIntegrations/PopupMaker/staticData.js index 1b9f1c99d..60e39b672 100644 --- a/frontend/src/components/AllIntegrations/PopupMaker/staticData.js +++ b/frontend/src/components/AllIntegrations/PopupMaker/staticData.js @@ -104,17 +104,14 @@ export const forceDeleteOptions = [ { label: __('No, move to trash', 'bit-integrations'), value: 'no' } ] -// Actions that need a fetched theme dropdown export const needsTheme = ['create_popup', 'update_popup'] -// Actions that need a fetched popup dropdown (subscriber attribution) export const needsPopup = ['create_subscriber', 'update_subscriber'] -// Actions with a required select rendered in the layout export const needsStatus = ['change_popup_status'] + export const needsEvent = ['track_popup_event'] -// Actions with optional selects rendered under Utilities export const hasUtilities = [ 'create_popup', 'update_popup',