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