diff --git a/.github/workflows/plugin-check.yml b/.github/workflows/plugin-check.yml index 2c9c4e956..b195c7b11 100644 --- a/.github/workflows/plugin-check.yml +++ b/.github/workflows/plugin-check.yml @@ -75,7 +75,7 @@ jobs: wp-env start - name: WordPress Plugin Check - uses: wordpress/plugin-check-action@v1 + uses: wordpress/plugin-check-action@v1.1.7 with: build-dir: './build/${{ env.PLUGIN_SLUG }}' exclude-directories: | diff --git a/backend/Actions/MasterStudyLms/MasterStudyLmsHelper.php b/backend/Actions/MasterStudyLms/MasterStudyLmsHelper.php index fb6e9c0cf..28cc69523 100644 --- a/backend/Actions/MasterStudyLms/MasterStudyLmsHelper.php +++ b/backend/Actions/MasterStudyLms/MasterStudyLmsHelper.php @@ -6,59 +6,37 @@ class MasterStudyLmsHelper { public static function getLessonByCourse($courseId) { - global $wpdb; - - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Direct query needed for MasterStudy lessons - $lesson = $wpdb->get_results( - $wpdb->prepare( - "SELECT ID, post_title,post_content - FROM {$wpdb->posts} - WHERE FIND_IN_SET( - ID, - (SELECT meta_value FROM wp_postmeta WHERE post_id = %d AND meta_key = 'curriculum') - ) - AND post_type = 'stm-lessons' - ORDER BY post_title ASC - ", - absint($courseId) - ) - ); - - return $lesson; - - // if ($courseId == 'any') { - // $lesson = $wpdb->get_results( - // $wpdb->prepare( - // "SELECT ID, post_title,post_content - // FROM $wpdb->posts - // WHERE post_type = 'stm-lesson' - // ORDER BY post_title ASC - // " - // ) - // ); - // return $quizzes; - // } + return self::getCourseMaterialsByIdAndType($courseId, 'stm-lessons'); } public static function getQuizByCourse($courseId) { - global $wpdb; - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Direct query needed for MasterStudy quizzes - $quizzes = $wpdb->get_results( - $wpdb->prepare( - "SELECT ID, post_title,post_content - FROM {$wpdb->posts} - WHERE FIND_IN_SET( - ID, - (SELECT meta_value FROM wp_postmeta WHERE post_id = %d AND meta_key = 'curriculum') - ) - AND post_type = 'stm-quizzes' - ORDER BY post_title ASC - ", - absint($courseId) - ) - ); + return self::getCourseMaterialsByIdAndType($courseId, 'stm-quizzes'); + } + + public static function getCourseMaterialsByIdAndType($courseId, $postType) + { + if (!class_exists('\MasterStudy\Lms\Repositories\CurriculumRepository')) { + return []; + } + + $CurriculumRepository = new \MasterStudy\Lms\Repositories\CurriculumRepository(); + + $curriculum = $CurriculumRepository->get_curriculum(absint($courseId)); + + if (empty($curriculum) || !isset($curriculum['materials'])) { + return []; + } + + foreach ($curriculum['materials'] as $material) { + if ($material['post_type'] === $postType) { + $posts[] = [ + 'ID' => $material['post_id'], + 'post_title' => $material['title'], + ]; + } + } - return $quizzes; + return $posts ?? []; } } diff --git a/backend/Actions/MasterStudyLms/RecordApiHelper.php b/backend/Actions/MasterStudyLms/RecordApiHelper.php index c94f03751..c49cc970a 100644 --- a/backend/Actions/MasterStudyLms/RecordApiHelper.php +++ b/backend/Actions/MasterStudyLms/RecordApiHelper.php @@ -2,6 +2,9 @@ namespace BitApps\Integrations\Actions\MasterStudyLms; +use BitApps\Integrations\Config; +use BitApps\Integrations\Core\Util\Common; +use BitApps\Integrations\Core\Util\Hooks; use BitApps\Integrations\Log\LogHandler; use STM_LMS_Course; use STM_LMS_Helpers; @@ -12,6 +15,24 @@ class RecordApiHelper { + private const COMPLETE_COURSE = 1; + + private const COMPLETE_LESSON = 2; + + private const COMPLETE_QUIZ = 3; + + private const RESET_COURSE = 4; + + private const RESET_LESSON = 5; + + private const ENROLL_USER = 6; + + private const UNENROLL_USER = 7; + + private const MARK_COURSE_COMPLETE = 8; + + private const MARK_LESSON_COMPLETE = 9; + private $integrationID; private $_integrationDetails; @@ -305,9 +326,15 @@ public function execute( $integrationData ) { $response = []; - $fieldData = []; + $fieldData = static::generateReqDataFromFieldMap($integrationDetails->field_map ?? [], $fieldValues); + + $defaultResponse = [ + 'success' => false, + // translators: %s: Plugin name + 'message' => wp_sprintf(__('%s plugin is not installed or activate', 'bit-integrations'), 'Bit Integrations Pro'), + ]; - if ($mainAction == 1) { + if ((int) $mainAction === self::COMPLETE_COURSE) { $courseId = $integrationDetails->courseId; $response = self::complete_course($courseId); if ($response) { @@ -315,7 +342,7 @@ public function execute( } else { LogHandler::save($this->integrationID, wp_json_encode(['type' => 'course-complete', 'type_name' => 'user-course-complete']), 'error', __('Failed to completed course', 'bit-integrations')); } - } elseif ($mainAction == 2) { + } elseif ((int) $mainAction === self::COMPLETE_LESSON) { $courseId = $integrationDetails->courseId; $lessonId = $integrationDetails->lessonId; $response = self::complete_lesson($courseId, $lessonId); @@ -324,7 +351,7 @@ public function execute( } else { LogHandler::save($this->integrationID, wp_json_encode(['type' => 'lesson-complete', 'type_name' => 'user-lesson-complete']), 'error', __('Failed to completed lesson', 'bit-integrations')); } - } elseif ($mainAction == 3) { + } elseif ((int) $mainAction === self::COMPLETE_QUIZ) { $courseId = $integrationDetails->courseId; $quizId = $integrationDetails->quizId; $response = self::complete_quiz($courseId, $quizId); @@ -333,7 +360,7 @@ public function execute( } else { LogHandler::save($this->integrationID, wp_json_encode(['type' => 'quiz-complete', 'type_name' => 'user-quiz-complete']), 'error', __('Failed to completed quiz', 'bit-integrations')); } - } elseif ($mainAction == 4) { + } elseif ((int) $mainAction === self::RESET_COURSE) { $courseId = $integrationDetails->courseId; $response = self::reset_course($courseId); if ($response) { @@ -341,7 +368,7 @@ public function execute( } else { LogHandler::save($this->integrationID, wp_json_encode(['type' => 'course-reset', 'type_name' => 'user-course-reset']), 'error', __('Failed to reset course', 'bit-integrations')); } - } elseif ($mainAction == 5) { + } elseif ((int) $mainAction === self::RESET_LESSON) { $course_id = $integrationDetails->courseId; $lesson_id = $integrationDetails->lessonId; $response = self::reset_lesson($course_id, $lesson_id); @@ -350,8 +377,66 @@ public function execute( } else { LogHandler::save($this->integrationID, wp_json_encode(['type' => 'lesson-reset', 'type_name' => 'user-lesson-reset']), 'error', __('Failed to reset lesson', 'bit-integrations')); } + } elseif ((int) $mainAction === self::ENROLL_USER) { + if (empty($fieldData['user_email'])) { + return new WP_Error('REQ_FIELD_EMPTY', __('User email is required', 'bit-integrations')); + } + $response = Hooks::apply(Config::withPrefix('master_study_lms_enroll_user'), $defaultResponse, [ + 'course_id' => $integrationDetails->courseId ?? null, + 'email' => $fieldData['user_email'], + ]); + LogHandler::save($this->integrationID, wp_json_encode(['type' => 'enroll-user', 'type_name' => 'enroll-user-to-course']), (\is_array($response) && !empty($response['success'])) ? 'success' : 'error', \is_array($response) ? ($response['message'] ?? '') : ''); + } elseif ((int) $mainAction === self::UNENROLL_USER) { + if (empty($fieldData['user_email'])) { + return new WP_Error('REQ_FIELD_EMPTY', __('User email is required', 'bit-integrations')); + } + $response = Hooks::apply(Config::withPrefix('master_study_lms_unenroll_user'), $defaultResponse, [ + 'course_id' => $integrationDetails->courseId ?? null, + 'email' => $fieldData['user_email'], + ]); + LogHandler::save($this->integrationID, wp_json_encode(['type' => 'unenroll-user', 'type_name' => 'unenroll-user-from-course']), (\is_array($response) && !empty($response['success'])) ? 'success' : 'error', \is_array($response) ? ($response['message'] ?? '') : ''); + } elseif ((int) $mainAction === self::MARK_COURSE_COMPLETE) { + if (empty($fieldData['user_email'])) { + return new WP_Error('REQ_FIELD_EMPTY', __('User email is required', 'bit-integrations')); + } + $response = Hooks::apply(Config::withPrefix('master_study_lms_mark_course_complete'), $defaultResponse, [ + 'course_id' => $integrationDetails->courseId ?? null, + 'email' => $fieldData['user_email'], + ]); + LogHandler::save($this->integrationID, wp_json_encode(['type' => 'mark-course-complete', 'type_name' => 'mark-course-complete-for-user']), (\is_array($response) && !empty($response['success'])) ? 'success' : 'error', \is_array($response) ? ($response['message'] ?? '') : ''); + } elseif ((int) $mainAction === self::MARK_LESSON_COMPLETE) { + if (empty($fieldData['user_email'])) { + return new WP_Error('REQ_FIELD_EMPTY', __('User email is required', 'bit-integrations')); + } + $response = Hooks::apply(Config::withPrefix('master_study_lms_mark_lesson_complete'), $defaultResponse, [ + 'course_id' => $integrationDetails->courseId ?? null, + 'lesson_id' => $integrationDetails->lessonId ?? null, + 'email' => $fieldData['user_email'], + ]); + LogHandler::save($this->integrationID, wp_json_encode(['type' => 'mark-lesson-complete', 'type_name' => 'mark-lesson-complete-for-user']), (\is_array($response) && !empty($response['success'])) ? 'success' : 'error', \is_array($response) ? ($response['message'] ?? '') : ''); } return $response; } + + protected static function generateReqDataFromFieldMap($fieldMap, $fieldValues) + { + $data = []; + + foreach ($fieldMap as $map) { + if (empty($map->msLmsFormField)) { + continue; + } + + $formField = $map->formField ?? ''; + + if ($formField === 'custom' && isset($map->customValue)) { + $data[$map->msLmsFormField] = Common::replaceFieldWithValue($map->customValue, $fieldValues); + } else { + $data[$map->msLmsFormField] = $fieldValues[$formField] ?? ''; + } + } + + return $data; + } } diff --git a/frontend/src/components/AllIntegrations/MasterStudyLms/EditMasterStudyLms.jsx b/frontend/src/components/AllIntegrations/MasterStudyLms/EditMasterStudyLms.jsx index 0e2972bfe..2c1295b52 100644 --- a/frontend/src/components/AllIntegrations/MasterStudyLms/EditMasterStudyLms.jsx +++ b/frontend/src/components/AllIntegrations/MasterStudyLms/EditMasterStudyLms.jsx @@ -10,7 +10,7 @@ import SetEditIntegComponents from '../IntegrationHelpers/SetEditIntegComponents import EditWebhookInteg from '../EditWebhookInteg' import { saveActionConf } from '../IntegrationHelpers/IntegrationHelpers' import IntegrationStepThree from '../IntegrationHelpers/IntegrationStepThree' -import { handleInput } from './MasterStudyLmsCommonFunc' +import { handleInput, isActionConfigIncomplete } from './MasterStudyLmsCommonFunc' import MasterStudyLmsIntegLayout from './MasterStudyLmsIntegLayout' function EditMasterStudyLms({ allIntegURL }) { @@ -66,7 +66,7 @@ function EditMasterStudyLms({ allIntegURL }) { setSnackbar }) } - disabled={msLmsConf.mainAction === '' || isLoading} + disabled={msLmsConf.mainAction === '' || isLoading || isActionConfigIncomplete(msLmsConf)} isLoading={isLoading} dataConf={msLmsConf} setDataConf={setMsLmsConf} diff --git a/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLms.jsx b/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLms.jsx index fb8967705..5fa5f3af8 100644 --- a/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLms.jsx +++ b/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLms.jsx @@ -8,7 +8,7 @@ import SnackMsg from '../../Utilities/SnackMsg' import Steps from '../../Utilities/Steps' import { saveActionConf } from '../IntegrationHelpers/IntegrationHelpers' import IntegrationStepThree from '../IntegrationHelpers/IntegrationStepThree' -import { handleInput, checkMappedFields } from './MasterStudyLmsCommonFunc' +import { isActionConfigIncomplete } from './MasterStudyLmsCommonFunc' import MasterStudyLmsAuthorization from './MasterStudyLmsAuthorization' import MasterStudyLmsIntegLayout from './MasterStudyLmsIntegLayout' import TutorialLink from '../../Utilities/TutorialLink' @@ -21,20 +21,11 @@ function MasterStudyLms({ formFields, setFlow, flow, allIntegURL, isInfo, edit } const [step, setStep] = useState(1) const [snack, setSnackbar] = useState({ show: false }) - const allActions = [ - { key: '1', label: __('Course complete for the user', 'bit-integrations') }, - { key: '2', label: __('Lesson complete for the user', 'bit-integrations') }, - { key: '3', label: __('Quiz complete for the user', 'bit-integrations') }, - { key: '4', label: __('Reset user course', 'bit-integrations') }, - { key: '5', label: __('Reset user lesson', 'bit-integrations') } - ] - const [msLmsConf, setMsLmsConf] = useState({ name: 'MasterStudyLms', type: 'MasterStudyLms', mainAction: '', field_map: [{ formField: '', msLmsFormField: '' }], - allActions, actions: {} }) @@ -49,20 +40,7 @@ function MasterStudyLms({ formFields, setFlow, flow, allIntegURL, isInfo, edit } } function isDisabled() { - switch (msLmsConf.mainAction) { - case '1': - return msLmsConf.courseId === undefined - case '4': - return msLmsConf.courseId === undefined - case '2': - return msLmsConf.lessonId === undefined - case '5': - return msLmsConf.lessonId === undefined - case '3': - return msLmsConf.quizId === undefined - default: - return false - } + return isActionConfigIncomplete(msLmsConf) } return ( @@ -90,7 +68,6 @@ function MasterStudyLms({ formFields, setFlow, flow, allIntegURL, isInfo, edit } style={{ ...(step === 2 && { width: 900, height: 'auto', overflow: 'visible' }) }}> handleInput(e, msLmsConf, setMsLmsConf, setIsLoading, setSnackbar, formID)} msLmsConf={msLmsConf} setMsLmsConf={setMsLmsConf} isLoading={isLoading} diff --git a/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLmsCommonFunc.js b/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLmsCommonFunc.js index 60f418f1f..664f266fe 100644 --- a/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLmsCommonFunc.js +++ b/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLmsCommonFunc.js @@ -3,6 +3,89 @@ import bitsFetch from '../../../Utils/bitsFetch' import { deepCopy } from '../../../Utils/Helpers' import { sprintf, __ } from '../../../Utils/i18nwrap' +export const MS_LMS_ACTIONS = { + COMPLETE_COURSE: '1', + COMPLETE_LESSON: '2', + COMPLETE_QUIZ: '3', + RESET_COURSE: '4', + RESET_LESSON: '5', + ENROLL_USER: '6', + UNENROLL_USER: '7', + MARK_COURSE_COMPLETE: '8', + MARK_LESSON_COMPLETE: '9' +} + +// Field-map definition for the email-based (Pro) actions. +export const msLmsUserFields = [ + { key: 'user_email', label: __('User Email', 'bit-integrations'), required: true } +] + +export const generateMappedField = (fields = msLmsUserFields) => { + const requiredFlds = fields.filter(fld => fld.required === true) + return requiredFlds.length > 0 + ? requiredFlds.map(field => ({ formField: '', msLmsFormField: field.key })) + : [{ formField: '', msLmsFormField: '' }] +} + +export const isUserEmailMapped = conf => + Boolean( + conf?.field_map?.some( + f => + f.msLmsFormField === 'user_email' && + (f.formField === 'custom' ? f.customValue : f.formField) + ) + ) + +export const allActions = [ + { key: MS_LMS_ACTIONS.COMPLETE_COURSE, label: __('Course complete for the user', 'bit-integrations') }, + { key: MS_LMS_ACTIONS.COMPLETE_LESSON, label: __('Lesson complete for the user', 'bit-integrations') }, + { key: MS_LMS_ACTIONS.COMPLETE_QUIZ, label: __('Quiz complete for the user', 'bit-integrations') }, + { key: MS_LMS_ACTIONS.RESET_COURSE, label: __('Reset user course', 'bit-integrations') }, + { key: MS_LMS_ACTIONS.RESET_LESSON, label: __('Reset user lesson', 'bit-integrations') }, + { + key: MS_LMS_ACTIONS.ENROLL_USER, + label: __('Enroll user in a course', 'bit-integrations'), + is_pro: true + }, + { + key: MS_LMS_ACTIONS.UNENROLL_USER, + label: __('Unenroll user from a course', 'bit-integrations'), + is_pro: true + }, + { + key: MS_LMS_ACTIONS.MARK_COURSE_COMPLETE, + label: __('Mark a course complete for the user', 'bit-integrations'), + is_pro: true + }, + { + key: MS_LMS_ACTIONS.MARK_LESSON_COMPLETE, + label: __('Mark a lesson complete for the user', 'bit-integrations'), + is_pro: true + } +] + +// Per-action required-field validation shared by the New wizard and Edit screen. +export const isActionConfigIncomplete = conf => { + switch (conf?.mainAction) { + case MS_LMS_ACTIONS.COMPLETE_COURSE: + case MS_LMS_ACTIONS.RESET_COURSE: + return !conf.courseId + case MS_LMS_ACTIONS.COMPLETE_LESSON: + case MS_LMS_ACTIONS.RESET_LESSON: + return !conf.lessonId + case MS_LMS_ACTIONS.COMPLETE_QUIZ: + return !conf.quizId + case MS_LMS_ACTIONS.ENROLL_USER: + case MS_LMS_ACTIONS.UNENROLL_USER: + case MS_LMS_ACTIONS.MARK_COURSE_COMPLETE: + return !conf.courseId || !isUserEmailMapped(conf) + case MS_LMS_ACTIONS.MARK_LESSON_COMPLETE: + return !conf.courseId || !conf.lessonId || !isUserEmailMapped(conf) + default: + return false + } +} + export const handleInput = (e, msLmsConf, setMsLmsConf, setIsLoading, setSnackbar, formID) => { const newConf = { ...msLmsConf } const { name } = e.target diff --git a/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLmsFieldMap.jsx b/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLmsFieldMap.jsx new file mode 100644 index 000000000..6499b9e99 --- /dev/null +++ b/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLmsFieldMap.jsx @@ -0,0 +1,110 @@ +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 MasterStudyLmsFieldMap({ + i, + formFields, + field, + msLmsFields = [], + msLmsConf, + setMsLmsConf +}) { + const { isPro } = useRecoilValue($appConfigState) + + const requiredFlds = msLmsFields.filter(fld => fld.required === true) + const nonRequiredFlds = msLmsFields.filter(fld => fld.required === false) + + return ( +
+
+
+ + + {field.formField === 'custom' && ( + handleCustomValue(e, i, msLmsConf, setMsLmsConf)} + 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/MasterStudyLms/MasterStudyLmsIntegLayout.jsx b/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLmsIntegLayout.jsx index ff70f9a38..c9b583452 100644 --- a/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLmsIntegLayout.jsx +++ b/frontend/src/components/AllIntegrations/MasterStudyLms/MasterStudyLmsIntegLayout.jsx @@ -1,14 +1,24 @@ 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 { addFieldMap } from '../IntegrationHelpers/IntegrationHelpers' -import { fetchAllLesson, fetchAllMsLmsCourse, fetchAllQuiz } from './MasterStudyLmsCommonFunc' +import { checkIsPro, getProLabel } from '../../Utilities/ProUtilHelpers' +import { + allActions, + fetchAllLesson, + fetchAllMsLmsCourse, + fetchAllQuiz, + generateMappedField, + MS_LMS_ACTIONS, + msLmsUserFields +} from './MasterStudyLmsCommonFunc' +import MasterStudyLmsFieldMap from './MasterStudyLmsFieldMap' import Note from '../../Utilities/Note' export default function MasterStudyLmsIntegLayout({ formFields, - handleInput, msLmsConf, setMsLmsConf, isLoading, @@ -18,8 +28,37 @@ export default function MasterStudyLmsIntegLayout({ isInfo, edit }) { + const { isPro } = useRecoilValue($appConfigState) + + const { + COMPLETE_COURSE, + COMPLETE_LESSON, + COMPLETE_QUIZ, + RESET_COURSE, + RESET_LESSON, + ENROLL_USER, + UNENROLL_USER, + MARK_COURSE_COMPLETE, + MARK_LESSON_COMPLETE + } = MS_LMS_ACTIONS + + const courseActions = [ + COMPLETE_COURSE, + COMPLETE_LESSON, + COMPLETE_QUIZ, + RESET_COURSE, + RESET_LESSON, + ENROLL_USER, + UNENROLL_USER, + MARK_COURSE_COMPLETE, + MARK_LESSON_COMPLETE + ] + const lessonActions = [COMPLETE_LESSON, RESET_LESSON, MARK_LESSON_COMPLETE] + const emailActions = [ENROLL_USER, UNENROLL_USER, MARK_COURSE_COMPLETE, MARK_LESSON_COMPLETE] + const loggedInActions = [COMPLETE_COURSE, COMPLETE_LESSON, COMPLETE_QUIZ, RESET_COURSE, RESET_LESSON] + useEffect(() => { - if (['1', '2', '3', '4', '5'].includes(msLmsConf.mainAction)) { + if (courseActions.includes(msLmsConf.mainAction)) { fetchAllMsLmsCourse(msLmsConf, setMsLmsConf, setIsLoading, setSnackbar) } }, [msLmsConf.mainAction]) @@ -28,10 +67,10 @@ export default function MasterStudyLmsIntegLayout({ const newConf = { ...msLmsConf } if (val !== '') { newConf[status] = val - if (msLmsConf.mainAction === '2' || msLmsConf.mainAction === '5') { + if (lessonActions.includes(msLmsConf.mainAction)) { fetchAllLesson(newConf, setMsLmsConf, setIsLoading, setSnackbar) } - if (msLmsConf.mainAction === '3') { + if (msLmsConf.mainAction === COMPLETE_QUIZ) { fetchAllQuiz(newConf, setMsLmsConf, setIsLoading, setSnackbar) } } else { @@ -39,26 +78,39 @@ export default function MasterStudyLmsIntegLayout({ } setMsLmsConf({ ...newConf }) } + + const handleMainAction = val => { + const newConf = { ...msLmsConf, mainAction: val } + const hasEmailRow = newConf.field_map?.some(f => f.msLmsFormField === 'user_email') + if (emailActions.includes(val)) { + // Keep an existing user_email mapping when switching between email actions. + if (!hasEmailRow) newConf.field_map = generateMappedField(msLmsUserFields) + } else { + newConf.field_map = [{ formField: '', msLmsFormField: '' }] + } + setMsLmsConf(newConf) + } return ( <>
- {__('Actions:', 'bit-integrations')} - +
+ {__('Actions:', 'bit-integrations')} + ({ + label: checkIsPro(isPro, action.is_pro) ? action.label : getProLabel(action.label), + value: action.key, + disabled: !checkIsPro(isPro, action.is_pro) + }))} + onChange={handleMainAction} + /> +


- {['1', '2', '3', '4', '5'].includes(msLmsConf.mainAction) && ( + {courseActions.includes(msLmsConf.mainAction) && (
{__('Select a Course:', 'bit-integrations')} changeHandler(val, 'courseId')} />
)} - {(msLmsConf.mainAction === '2' || msLmsConf.mainAction === '5') && msLmsConf?.courseId && ( + {lessonActions.includes(msLmsConf.mainAction) && msLmsConf?.courseId && (
{__('Select Lesson:', 'bit-integrations')}
)} - {msLmsConf.mainAction === '3' && msLmsConf?.courseId && ( + {msLmsConf.mainAction === COMPLETE_QUIZ && msLmsConf?.courseId && (
{__('Select Quiz:', 'bit-integrations')} )} + {emailActions.includes(msLmsConf.mainAction) && ( +
+ {__('Map User Email', 'bit-integrations')} +
+
+
+ {__('Form Fields', 'bit-integrations')} +
+
+ {__('MasterStudy LMS Fields', 'bit-integrations')} +
+
+ {msLmsConf?.field_map?.map((itm, idx) => ( + + ))} +
+ )} +

{isLoading && ( @@ -150,7 +228,17 @@ export default function MasterStudyLmsIntegLayout({ }} /> )} - + {loggedInActions.includes(msLmsConf.mainAction) && ( + + )} + {emailActions.includes(msLmsConf.mainAction) && ( + + )} ) } diff --git a/frontend/src/components/AllIntegrations/WishlistMember/WishlistMemberIntegLayout.jsx b/frontend/src/components/AllIntegrations/WishlistMember/WishlistMemberIntegLayout.jsx index 13b9dfacc..fd770409a 100644 --- a/frontend/src/components/AllIntegrations/WishlistMember/WishlistMemberIntegLayout.jsx +++ b/frontend/src/components/AllIntegrations/WishlistMember/WishlistMemberIntegLayout.jsx @@ -38,6 +38,7 @@ export default function WishlistMemberIntegLayout({ } return ( + <>