diff --git a/backend/Actions/WeDocs/RecordApiHelper.php b/backend/Actions/WeDocs/RecordApiHelper.php new file mode 100644 index 00000000..94ca66d0 --- /dev/null +++ b/backend/Actions/WeDocs/RecordApiHelper.php @@ -0,0 +1,119 @@ +_integrationDetails = $integrationDetails; + $this->_integrationID = $integId; + } + + public function execute($fieldValues, $fieldMap) + { + if (!class_exists('WeDocs')) { + $response = [ + 'success' => false, + 'message' => __('weDocs is not installed or activated', 'bit-integrations'), + ]; + + LogHandler::save($this->_integrationID, ['type' => 'weDocs', 'type_name' => 'check'], 'error', $response); + + return $response; + } + + $mainAction = $this->_integrationDetails->mainAction ?? ''; + $fieldData = $this->generateReqDataFromFieldMap($fieldMap, $fieldValues); + $payload = $this->buildPayload($fieldData); + + $defaultResponse = [ + 'success' => false, + // translators: %s is the plugin name. + 'message' => wp_sprintf(__('%s plugin is not installed or activated', 'bit-integrations'), 'Bit Integrations Pro'), + ]; + + switch ($mainAction) { + case 'create_documentation': + $response = Hooks::apply(Config::withPrefix('wedocs_create_documentation'), $defaultResponse, $payload); + $actionType = 'create_documentation'; + + break; + + case 'create_section': + $response = Hooks::apply(Config::withPrefix('wedocs_create_section'), $defaultResponse, $payload); + $actionType = 'create_section'; + + break; + + case 'create_article': + $response = Hooks::apply(Config::withPrefix('wedocs_create_article'), $defaultResponse, $payload); + $actionType = 'create_article'; + + break; + + default: + $response = [ + 'success' => false, + 'message' => __('Invalid action', 'bit-integrations'), + ]; + $actionType = 'unknown'; + + break; + } + + $responseType = !empty($response['success']) ? 'success' : 'error'; + LogHandler::save($this->_integrationID, ['type' => 'weDocs', 'type_name' => $actionType], $responseType, $response); + + return $response; + } + + private function buildPayload($payload) + { + if (!isset($payload['documentation_id']) && isset($this->_integrationDetails->selectedDocumentationId)) { + $payload['documentation_id'] = $this->_integrationDetails->selectedDocumentationId; + } + + if (!isset($payload['section_id']) && isset($this->_integrationDetails->selectedSectionId)) { + $payload['section_id'] = $this->_integrationDetails->selectedSectionId; + } + + return $payload; + } + + private function generateReqDataFromFieldMap($fieldMap, $fieldValues) + { + $dataFinal = []; + + if (!\is_array($fieldMap)) { + return $dataFinal; + } + + foreach ($fieldMap as $item) { + $triggerValue = $item->formField ?? ''; + $actionValue = $item->weDocsField ?? ''; + + 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/WeDocs/Routes.php b/backend/Actions/WeDocs/Routes.php new file mode 100644 index 00000000..ba462e97 --- /dev/null +++ b/backend/Actions/WeDocs/Routes.php @@ -0,0 +1,12 @@ + self::DOC_POST_TYPE, + 'post_status' => self::ALLOWED_POST_STATUSES, + 'posts_per_page' => -1, + 'post_parent' => 0, + 'orderby' => 'title', + 'order' => 'ASC', + ] + ); + + $documentations = array_map( + function ($doc) { + return (object) [ + 'value' => (string) $doc->ID, + 'label' => $doc->post_title, + ]; + }, + $allDocumentations + ); + + wp_send_json_success(['documentations' => $documentations], 200); + } + + public static function getSections($request) + { + self::checkPluginExists(); + + $documentationId = self::sanitizeId($request->documentation_id ?? ''); + + if ($documentationId > 0) { + $documentation = get_post($documentationId); + + if (!self::isValidDocumentation($documentation)) { + wp_send_json_error(__('Selected documentation is invalid.', 'bit-integrations'), 400); + } + } + + $queryArgs = [ + 'post_type' => self::DOC_POST_TYPE, + 'post_status' => self::ALLOWED_POST_STATUSES, + 'posts_per_page' => -1, + 'orderby' => 'title', + 'order' => 'ASC', + ]; + + if ($documentationId > 0) { + $queryArgs['post_parent'] = $documentationId; + } + + $sections = get_posts($queryArgs); + + if ($documentationId <= 0) { + $sections = array_values(array_filter($sections, [__CLASS__, 'isValidSection'])); + } + + $options = array_map( + function ($section) { + return (object) [ + 'value' => (string) $section->ID, + 'label' => $section->post_title, + ]; + }, + $sections + ); + + wp_send_json_success(['sections' => $options], 200); + } + + public function execute($integrationData, $fieldValues) + { + $integrationDetails = $integrationData->flow_details; + $fieldMap = $integrationDetails->field_map ?? []; + + $recordApiHelper = new RecordApiHelper($integrationDetails, $integrationData->id); + + return $recordApiHelper->execute($fieldValues, $fieldMap); + } + + private static function checkPluginExists() + { + if (!class_exists('WeDocs')) { + wp_send_json_error(__('weDocs is not activated or not installed', 'bit-integrations'), 400); + } + } + + private static function sanitizeId($value) + { + if (empty($value)) { + return 0; + } + + return absint($value); + } + + private static function isValidDocsPost($post) + { + return $post instanceof WP_Post && $post->post_type === self::DOC_POST_TYPE; + } + + private static function isValidDocumentation($post) + { + return self::isValidDocsPost($post) && (int) $post->post_parent === 0; + } + + private static function isValidSection($post) + { + if (!self::isValidDocsPost($post)) { + return false; + } + + $parentId = (int) $post->post_parent; + + if ($parentId <= 0) { + return false; + } + + return (int) wp_get_post_parent_id($parentId) === 0; + } +} diff --git a/backend/Core/Util/AllTriggersName.php b/backend/Core/Util/AllTriggersName.php index a6fc95c5..fce2979b 100644 --- a/backend/Core/Util/AllTriggersName.php +++ b/backend/Core/Util/AllTriggersName.php @@ -144,6 +144,7 @@ public static function allTriggersName() 'WCSubscriptions' => ['name' => 'WooCommerce Subscriptions', 'isPro' => true, 'is_active' => false], 'Webhook' => ['name' => 'Webhook', 'isPro' => true, 'is_active' => false], 'WeForms' => ['name' => 'WeForms', 'isPro' => true, 'is_active' => false], + 'WeDocs' => ['name' => 'weDocs', 'isPro' => true, 'is_active' => false], 'WPCourseware' => ['name' => 'WP Courseware', 'isPro' => true, 'is_active' => false], 'WPEF' => ['name' => 'eForm', 'isPro' => true, 'is_active' => false], 'WPForo' => ['name' => 'wpForo Forum', 'isPro' => true, 'is_active' => false], diff --git a/frontend/src/Utils/StaticData/webhookIntegrations.js b/frontend/src/Utils/StaticData/webhookIntegrations.js index ffc2c6c7..69b3101d 100644 --- a/frontend/src/Utils/StaticData/webhookIntegrations.js +++ b/frontend/src/Utils/StaticData/webhookIntegrations.js @@ -91,6 +91,7 @@ export const customFormIntegrations = [ 'SeoPress', 'ThriveLeads', 'NotificationX', + 'WeDocs', 'UserRegistrationMembership', 'UltimateAffiliatePro', ] diff --git a/frontend/src/components/AllIntegrations/EditInteg.jsx b/frontend/src/components/AllIntegrations/EditInteg.jsx index 21d5fb6d..a2306ec7 100644 --- a/frontend/src/components/AllIntegrations/EditInteg.jsx +++ b/frontend/src/components/AllIntegrations/EditInteg.jsx @@ -175,8 +175,9 @@ const EditFluentCart = lazy(() => import('./FluentCart/EditFluentCart')) const EditWCAffiliate = lazy(() => import('./WCAffiliate/EditWCAffiliate')) const EditWPCafe = lazy(() => import('./WPCafe/EditWPCafe')) const EditNotificationX = lazy(() => import('./NotificationX/EditNotificationX')) -const EditTeamsForWooCommerceMemberships = lazy(() => - import('./TeamsForWooCommerceMemberships/EditTeamsForWooCommerceMemberships') +const EditWeDocs = lazy(() => import('./WeDocs/EditWeDocs')) +const EditTeamsForWooCommerceMemberships = lazy( + () => import('./TeamsForWooCommerceMemberships/EditTeamsForWooCommerceMemberships') ) const EditAsgarosForum = lazy(() => import('./AsgarosForum/EditAsgarosForum')) const EditSeoPress = lazy(() => import('./SeoPress/EditSeoPress')) @@ -597,6 +598,9 @@ const IntegType = memo(({ allIntegURL, flow }) => { return case 'NotificationX': return + case 'weDocs': + case 'WeDocs': + return case 'Asgaros Forum': case 'AsgarosForum': return diff --git a/frontend/src/components/AllIntegrations/IntegInfo.jsx b/frontend/src/components/AllIntegrations/IntegInfo.jsx index 1147190d..aea430c5 100644 --- a/frontend/src/components/AllIntegrations/IntegInfo.jsx +++ b/frontend/src/components/AllIntegrations/IntegInfo.jsx @@ -182,6 +182,7 @@ const TeamsForWooCommerceMembershipsAuthorization = lazy( ) const SeoPressAuthorization = lazy(() => import('./SeoPress/SeoPressAuthorization')) const NotificationXAuthorization = lazy(() => import('./NotificationX/NotificationXAuthorization')) +const WeDocsAuthorization = lazy(() => import('./WeDocs/WeDocsAuthorization')) const AsgarosForumAuthorization = lazy(() => import('./AsgarosForum/AsgarosForumAuthorization')) const UserRegistrationMembershipAuthorization = lazy( () => import('./UserRegistrationMembership/UserRegistrationMembershipAuthorization') @@ -650,6 +651,9 @@ export default function IntegInfo() { return case 'NotificationX': return + case 'weDocs': + case 'WeDocs': + return case 'Asgaros Forum': case 'AsgarosForum': return diff --git a/frontend/src/components/AllIntegrations/NewInteg.jsx b/frontend/src/components/AllIntegrations/NewInteg.jsx index 50b6a117..1f965ee0 100644 --- a/frontend/src/components/AllIntegrations/NewInteg.jsx +++ b/frontend/src/components/AllIntegrations/NewInteg.jsx @@ -174,8 +174,9 @@ const FluentCart = lazy(() => import('./FluentCart/FluentCart')) const WCAffiliate = lazy(() => import('./WCAffiliate/WCAffiliate')) const WPCafe = lazy(() => import('./WPCafe/WPCafe')) const NotificationX = lazy(() => import('./NotificationX/NotificationX')) -const TeamsForWooCommerceMemberships = lazy(() => - import('./TeamsForWooCommerceMemberships/TeamsForWooCommerceMemberships') +const WeDocs = lazy(() => import('./WeDocs/WeDocs')) +const TeamsForWooCommerceMemberships = lazy( + () => import('./TeamsForWooCommerceMemberships/TeamsForWooCommerceMemberships') ) const AsgarosForum = lazy(() => import('./AsgarosForum/AsgarosForum')) const SeoPress = lazy(() => import('./SeoPress/SeoPress')) @@ -1693,6 +1694,16 @@ export default function NewInteg({ allIntegURL }) { setFlow={setFlow} /> ) + case 'weDocs': + case 'WeDocs': + return ( + + ) case 'Asgaros Forum': case 'AsgarosForum': return ( diff --git a/frontend/src/components/AllIntegrations/WeDocs/EditWeDocs.jsx b/frontend/src/components/AllIntegrations/WeDocs/EditWeDocs.jsx new file mode 100644 index 00000000..abb45d86 --- /dev/null +++ b/frontend/src/components/AllIntegrations/WeDocs/EditWeDocs.jsx @@ -0,0 +1,76 @@ +import { useState } from 'react' +import { useNavigate, useParams } from 'react-router' +import { useRecoilState, useRecoilValue } from 'recoil' +import { $actionConf, $formFields, $newFlow } from '../../../GlobalStates' +import { __ } from '../../../Utils/i18nwrap' +import SnackMsg from '../../Utilities/SnackMsg' +import { saveActionConf } from '../IntegrationHelpers/IntegrationHelpers' +import IntegrationStepThree from '../IntegrationHelpers/IntegrationStepThree' +import SetEditIntegComponents from '../IntegrationHelpers/SetEditIntegComponents' +import { checkMappedFields, handleInput } from './WeDocsCommonFunc' +import WeDocsIntegLayout from './WeDocsIntegLayout' + +export default function EditWeDocs({ allIntegURL }) { + const navigate = useNavigate() + const { id, formID } = useParams() + + const [weDocsConf, setWeDocsConf] = useRecoilState($actionConf) + const [flow, setFlow] = useRecoilState($newFlow) + const formFields = useRecoilValue($formFields) + const [isLoading, setIsLoading] = useState(false) + const [snack, setSnackbar] = useState({ show: false }) + + return ( +
+ + +
+ {__('Integration Name:', 'bit-integrations')} + handleInput(e, weDocsConf, setWeDocsConf)} + name="name" + value={weDocsConf.name} + type="text" + placeholder={__('Integration Name...', 'bit-integrations')} + /> +
+
+ + + + + + + saveActionConf({ + flow, + setFlow, + allIntegURL, + conf: weDocsConf, + navigate, + id, + edit: 1, + setIsLoading, + setSnackbar + }) + } + disabled={!checkMappedFields(weDocsConf)} + isLoading={isLoading} + dataConf={weDocsConf} + setDataConf={setWeDocsConf} + formFields={formFields} + /> +
+
+ ) +} diff --git a/frontend/src/components/AllIntegrations/WeDocs/WeDocs.jsx b/frontend/src/components/AllIntegrations/WeDocs/WeDocs.jsx new file mode 100644 index 00000000..833e38c4 --- /dev/null +++ b/frontend/src/components/AllIntegrations/WeDocs/WeDocs.jsx @@ -0,0 +1,109 @@ +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 WeDocsAuthorization from './WeDocsAuthorization' +import { checkMappedFields } from './WeDocsCommonFunc' +import WeDocsIntegLayout from './WeDocsIntegLayout' + +export default function WeDocs({ 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 [weDocsConf, setWeDocsConf] = useState({ + name: 'weDocs', + type: 'weDocs', + field_map: [], + weDocsFields: [], + actions: {}, + mainAction: '', + selectedDocumentationId: '', + selectedSectionId: '', + documentations: [], + sections: [] + }) + + const nextPage = val => { + setTimeout(() => { + document.getElementById('btcd-settings-wrp').scrollTop = 0 + }, 300) + + if (val === 3) { + if (!checkMappedFields(weDocsConf)) { + setSnackbar({ + show: true, + msg: __('Please complete all required fields to continue.', 'bit-integrations') + }) + return + } + + if (weDocsConf.name !== '') { + setStep(val) + } + return + } + + setStep(val) + } + + return ( +
+ +
+ + + +
+ +
+
+
+ +
+ + + saveIntegConfig(flow, setFlow, allIntegURL, weDocsConf, navigate, '', '', setIsLoading) + } + isLoading={isLoading} + /> +
+ ) +} diff --git a/frontend/src/components/AllIntegrations/WeDocs/WeDocsAuthorization.jsx b/frontend/src/components/AllIntegrations/WeDocs/WeDocsAuthorization.jsx new file mode 100644 index 00000000..2f31349a --- /dev/null +++ b/frontend/src/components/AllIntegrations/WeDocs/WeDocsAuthorization.jsx @@ -0,0 +1,81 @@ +import { useState } from 'react' +import { __ } from '../../../Utils/i18nwrap' +import tutorialLinks from '../../../Utils/StaticData/tutorialLinks' +import LoaderSm from '../../Loaders/LoaderSm' +import Note from '../../Utilities/Note' +import TutorialLink from '../../Utilities/TutorialLink' +import { weDocsAuthentication } from './WeDocsCommonFunc' + +export default function WeDocsAuthorization({ + weDocsConf, + setWeDocsConf, + step, + nextPage, + isLoading, + setIsLoading, + isInfo +}) { + const [isAuthorized, setIsAuthorized] = useState(false) + const [error, setError] = useState({ name: '' }) + const { weDocs } = tutorialLinks + + const handleInput = e => { + const newConf = { ...weDocsConf } + newConf[e.target.name] = e.target.value + setWeDocsConf(newConf) + } + + return ( +
+ {weDocs?.youTubeLink && } + {weDocs?.docLink && } + +
+ {__('Integration Name:', 'bit-integrations')} +
+ +
{error.name}
+ + + + {!isInfo && ( + <> + +
+ + + )} +
+ ) +} diff --git a/frontend/src/components/AllIntegrations/WeDocs/WeDocsCommonFunc.js b/frontend/src/components/AllIntegrations/WeDocs/WeDocsCommonFunc.js new file mode 100644 index 00000000..3300db20 --- /dev/null +++ b/frontend/src/components/AllIntegrations/WeDocs/WeDocsCommonFunc.js @@ -0,0 +1,167 @@ +import { create } from 'mutative' +import bitsFetch from '../../../Utils/bitsFetch' +import { __ } from '../../../Utils/i18nwrap' +import { + requiredDocumentationSelectionActions, + requiredSectionSelectionActions, + weDocsActionFields +} from './staticData' + +export const handleInput = (e, weDocsConf, setWeDocsConf) => { + const newConf = create(weDocsConf, draftConf => { + draftConf[e.target.name] = e.target.value + }) + setWeDocsConf(newConf) +} + +export const generateMappedField = () => { + const requiredFlds = weDocsActionFields.filter(fld => fld.required === true) + return requiredFlds.length > 0 + ? requiredFlds.map(field => ({ formField: '', weDocsField: field.key })) + : [{ formField: '', weDocsField: '' }] +} + +export const checkMappedFields = weDocsConf => { + const { mainAction, field_map: fieldMap = [] } = weDocsConf || {} + + if (!mainAction) { + return false + } + + if ( + requiredDocumentationSelectionActions.includes(mainAction) && + (!weDocsConf?.selectedDocumentationId) + ) { + return false + } + + if ( + requiredSectionSelectionActions.includes(mainAction) && + (!weDocsConf?.selectedSectionId) + ) { + return false + } + + const requiredFields = weDocsActionFields.filter(field => field.required) + if (!requiredFields.length) { + return true + } + + return requiredFields.every(requiredField => + fieldMap.some( + mappedField => + mappedField?.weDocsField === requiredField.key && + mappedField?.formField && + (mappedField.formField !== 'custom' || mappedField?.customValue) + ) + ) +} + +export const refreshDocumentations = (setWeDocsConf, setIsLoading, setSnackbar) => { + setIsLoading(true) + + bitsFetch({}, 'wedocs_get_documentations') + .then(result => { + if (result?.success) { + setWeDocsConf(prevConf => + create(prevConf, draftConf => { + draftConf.documentations = result?.data?.documentations || [] + }) + ) + } else { + setSnackbar({ + show: true, + msg: result?.data || __('Failed to fetch documentations', 'bit-integrations') + }) + } + }) + .catch(() => { + setSnackbar({ + show: true, + msg: __('Failed to fetch documentations', 'bit-integrations') + }) + }) + .finally(() => { + setIsLoading(false) + }) +} + +export const refreshSections = (documentationId, setWeDocsConf, setIsLoading, setSnackbar) => { + if (!documentationId) { + setWeDocsConf(prevConf => + create(prevConf, draftConf => { + draftConf.sections = [] + }) + ) + return + } + + setIsLoading(true) + + bitsFetch({ documentation_id: documentationId }, 'wedocs_get_sections') + .then(result => { + if (result?.success) { + setWeDocsConf(prevConf => + create(prevConf, draftConf => { + draftConf.sections = result?.data?.sections || [] + }) + ) + } else { + setSnackbar({ + show: true, + msg: result?.data || __('Failed to fetch sections', 'bit-integrations') + }) + } + }) + .catch(() => { + setSnackbar({ + show: true, + msg: __('Failed to fetch sections', 'bit-integrations') + }) + }) + .finally(() => { + setIsLoading(false) + }) +} + +export const weDocsAuthentication = ( + confTmp, + setWeDocsConf, + setError, + setIsAuthorized, + setIsLoading +) => { + if (!confTmp?.name) { + setError({ + name: __("Integration name can't be empty", 'bit-integrations') + }) + return + } + + setError({}) + setIsLoading(true) + + bitsFetch({ name: confTmp.name }, 'wedocs_authorize') + .then(result => { + if (result?.success) { + setIsAuthorized(true) + setWeDocsConf(prevConf => + create(prevConf, draftConf => { + draftConf.name = confTmp.name + }) + ) + } else { + setError({ + name: result?.data || __('Authorization failed', 'bit-integrations') + }) + } + }) + .catch(() => { + setError({ + name: __('Authorization failed', 'bit-integrations') + }) + }) + .finally(() => { + setIsLoading(false) + }) +} diff --git a/frontend/src/components/AllIntegrations/WeDocs/WeDocsFieldMap.jsx b/frontend/src/components/AllIntegrations/WeDocs/WeDocsFieldMap.jsx new file mode 100644 index 00000000..0bbcfbd2 --- /dev/null +++ b/frontend/src/components/AllIntegrations/WeDocs/WeDocsFieldMap.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 WeDocsFieldMap({ i, formFields, field, weDocsConf, setWeDocsConf }) { + const btcbi = useRecoilValue($appConfigState) + const { isPro } = btcbi + + const requiredFlds = weDocsConf?.weDocsFields?.filter(fld => fld.required === true) || [] + const nonRequiredFlds = weDocsConf?.weDocsFields?.filter(fld => fld?.required === false) || [] + + return ( +
+
+
+ + + {field.formField === 'custom' && ( + handleCustomValue(e, i, weDocsConf, setWeDocsConf)} + 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/WeDocs/WeDocsIntegLayout.jsx b/frontend/src/components/AllIntegrations/WeDocs/WeDocsIntegLayout.jsx new file mode 100644 index 00000000..4925dc53 --- /dev/null +++ b/frontend/src/components/AllIntegrations/WeDocs/WeDocsIntegLayout.jsx @@ -0,0 +1,281 @@ +import { create } from 'mutative' +import { useEffect } from 'react' +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 { + checkMappedFields, + generateMappedField, + refreshDocumentations, + refreshSections +} from './WeDocsCommonFunc' +import WeDocsFieldMap from './WeDocsFieldMap' +import { + documentationSelectionActions, + modules, + requiredDocumentationSelectionActions, + requiredSectionSelectionActions, + sectionSelectionActions, + weDocsActionFields +} from './staticData' + +export default function WeDocsIntegLayout({ + formFields, + weDocsConf, + setWeDocsConf, + setIsLoading, + isLoading, + setSnackbar +}) { + const btcbi = useRecoilValue($appConfigState) + const { isPro } = btcbi + + useEffect(() => { + if (!weDocsConf?.mainAction) { + return + } + + if (documentationSelectionActions.includes(weDocsConf.mainAction)) { + refreshDocumentations(setWeDocsConf, setIsLoading, setSnackbar) + } + + if ( + sectionSelectionActions.includes(weDocsConf.mainAction) && + weDocsConf?.selectedDocumentationId + ) { + refreshSections(weDocsConf.selectedDocumentationId, setWeDocsConf, setIsLoading, setSnackbar) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + const handleMainAction = value => { + setWeDocsConf(prevConf => + create(prevConf, draftConf => { + draftConf.mainAction = value + draftConf.weDocsFields = weDocsActionFields + draftConf.field_map = generateMappedField() + + if (!documentationSelectionActions.includes(value)) { + draftConf.selectedDocumentationId = '' + draftConf.selectedSectionId = '' + draftConf.documentations = [] + draftConf.sections = [] + return + } + + if ( + requiredDocumentationSelectionActions.includes(value) + ) { + draftConf.selectedDocumentationId = '' + } + + if (!sectionSelectionActions.includes(value)) { + draftConf.selectedSectionId = '' + draftConf.sections = [] + } else if ( + requiredSectionSelectionActions.includes(value) + ) { + draftConf.selectedSectionId = '' + } + }) + ) + + if (documentationSelectionActions.includes(value)) { + refreshDocumentations(setWeDocsConf, setIsLoading, setSnackbar) + } + } + + const handleDocumentationSelection = value => { + setWeDocsConf(prevConf => + create(prevConf, draftConf => { + draftConf.selectedDocumentationId = value + draftConf.selectedSectionId = '' + draftConf.sections = [] + }) + ) + + if (sectionSelectionActions.includes(weDocsConf.mainAction)) { + refreshSections(value, setWeDocsConf, setIsLoading, setSnackbar) + } + } + + const docOptions = requiredDocumentationSelectionActions.includes(weDocsConf?.mainAction) + ? (weDocsConf?.documentations || []).filter(option => option.value !== 'any') + : weDocsConf?.documentations || [] + + const sectionOptions = requiredSectionSelectionActions.includes(weDocsConf?.mainAction) + ? (weDocsConf?.sections || []).filter(option => option.value !== 'any') + : weDocsConf?.sections || [] + + 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 + /> +
+ + {documentationSelectionActions.includes(weDocsConf?.mainAction) && ( +
+ + {requiredDocumentationSelectionActions.includes(weDocsConf?.mainAction) + ? __('Documentation:', 'bit-integrations') + : __('Documentation (Optional):', 'bit-integrations')} + + handleDocumentationSelection(value)} + options={docOptions.map(option => ({ + label: option.label, + value: option.value + }))} + singleSelect + closeOnSelect + /> + +
+ )} + + {sectionSelectionActions.includes(weDocsConf?.mainAction) && ( +
+ + {requiredSectionSelectionActions.includes(weDocsConf?.mainAction) + ? __('Section:', 'bit-integrations') + : __('Section (Optional):', 'bit-integrations')} + + + setWeDocsConf(prevConf => + create(prevConf, draftConf => { + draftConf.selectedSectionId = value + }) + ) + } + options={sectionOptions.map(option => ({ + label: option.label, + value: option.value + }))} + singleSelect + closeOnSelect + /> + +
+ )} + + {isLoading && ( + + )} + + {!!weDocsConf?.weDocsFields?.length && !!weDocsConf?.field_map?.length && ( +
+ {__('Map Fields', 'bit-integrations')} +
+
+
+ {__('Form Fields', 'bit-integrations')} +
+
+ {__('weDocs Fields', 'bit-integrations')} +
+
+ + {weDocsConf?.field_map?.map((itm, i) => ( + + ))} + +
+ +
+
+ )} + + {['create_documentation', 'create_section', 'create_article'].includes(weDocsConf?.mainAction) && ( + <> +
+ + + )} + + {!checkMappedFields(weDocsConf) && !!weDocsConf?.mainAction && ( + <> +
+ + + )} + + ) +} diff --git a/frontend/src/components/AllIntegrations/WeDocs/staticData.js b/frontend/src/components/AllIntegrations/WeDocs/staticData.js new file mode 100644 index 00000000..16a55a3e --- /dev/null +++ b/frontend/src/components/AllIntegrations/WeDocs/staticData.js @@ -0,0 +1,33 @@ +import { __ } from '../../../Utils/i18nwrap' + +export const modules = [ + { + label: __('Create Documentation', 'bit-integrations'), + name: 'create_documentation', + is_pro: true + }, + { + label: __('Create Section', 'bit-integrations'), + name: 'create_section', + is_pro: true + }, + { + label: __('Create Article', 'bit-integrations'), + name: 'create_article', + is_pro: true + } +] + +export const weDocsActionFields = [ + { key: 'post_title', label: __('Title', 'bit-integrations'), required: true }, + { key: 'post_content', label: __('Content', 'bit-integrations'), required: false }, + { key: 'post_status', label: __('Status', 'bit-integrations'), required: false } + ] + +export const documentationSelectionActions = ['create_section', 'create_article'] + +export const sectionSelectionActions = ['create_article'] + +export const requiredDocumentationSelectionActions = ['create_section', 'create_article'] + +export const requiredSectionSelectionActions = ['create_article'] diff --git a/frontend/src/components/Flow/New/SelectAction.jsx b/frontend/src/components/Flow/New/SelectAction.jsx index 78976716..76ceeea9 100644 --- a/frontend/src/components/Flow/New/SelectAction.jsx +++ b/frontend/src/components/Flow/New/SelectAction.jsx @@ -181,6 +181,7 @@ export default function SelectAction() { { type: 'Teams For WooCommerce Memberships' }, { type: 'SeoPress' }, { type: 'NotificationX' }, + { type: 'weDocs' }, { type: 'Asgaros Forum', logo: 'asgaros' }, { type: 'User Registration & Membership', logo: 'userRegistrationMembership' } ] diff --git a/frontend/src/resource/img/integ/weDocs.webp b/frontend/src/resource/img/integ/weDocs.webp new file mode 100644 index 00000000..d18086a8 Binary files /dev/null and b/frontend/src/resource/img/integ/weDocs.webp differ