From 58f109e79c48680c199cfe8e37a07af25536943d Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Fri, 22 Nov 2024 16:28:28 +0530 Subject: [PATCH] feat: onboarding steps --- frontend/src/components/DesktopLayout.vue | 2 + .../src/components/Modals/ChapterModal.vue | 5 + frontend/src/components/OnboardingBanner.vue | 151 ++++++++++++++++++ frontend/src/pages/CourseForm.vue | 3 + frontend/src/pages/LessonForm.vue | 5 + frontend/src/stores/settings.js | 7 + lms/lms/utils.py | 3 + 7 files changed, 176 insertions(+) create mode 100644 frontend/src/components/OnboardingBanner.vue diff --git a/frontend/src/components/DesktopLayout.vue b/frontend/src/components/DesktopLayout.vue index 79a4a1dc9..70818bbea 100644 --- a/frontend/src/components/DesktopLayout.vue +++ b/frontend/src/components/DesktopLayout.vue @@ -8,6 +8,7 @@
+
@@ -16,4 +17,5 @@ diff --git a/frontend/src/components/Modals/ChapterModal.vue b/frontend/src/components/Modals/ChapterModal.vue index 0906b72ba..2f02a9e99 100644 --- a/frontend/src/components/Modals/ChapterModal.vue +++ b/frontend/src/components/Modals/ChapterModal.vue @@ -81,9 +81,11 @@ import { defineModel, reactive, watch } from 'vue' import { showToast, getFileSize } from '@/utils/' import { capture } from '@/telemetry' import { FileText, X } from 'lucide-vue-next' +import { useSettings } from '@/stores/settings' const show = defineModel() const outline = defineModel('outline') +const settingsStore = useSettings() const props = defineProps({ course: { @@ -143,6 +145,9 @@ const addChapter = async (close) => { { onSuccess(data) { cleanChapter() + if (!settingsStore.onboardingDetails.data?.is_onboarded) { + settingsStore.onboardingDetails.reload() + } outline.value.reload() showToast( __('Success'), diff --git a/frontend/src/components/OnboardingBanner.vue b/frontend/src/components/OnboardingBanner.vue new file mode 100644 index 000000000..7660e79c7 --- /dev/null +++ b/frontend/src/components/OnboardingBanner.vue @@ -0,0 +1,151 @@ + + diff --git a/frontend/src/pages/CourseForm.vue b/frontend/src/pages/CourseForm.vue index 913a11777..b4de038fa 100644 --- a/frontend/src/pages/CourseForm.vue +++ b/frontend/src/pages/CourseForm.vue @@ -434,6 +434,9 @@ const submitCourse = () => { onSuccess(data) { capture('course_created') showToast('Success', 'Course created successfully', 'check') + if (!settingsStore.onboardingDetails.data?.is_onboarded) { + settingsStore.onboardingDetails.reload() + } router.push({ name: 'CourseForm', params: { courseName: data.name }, diff --git a/frontend/src/pages/LessonForm.vue b/frontend/src/pages/LessonForm.vue index 1b56a3aa1..ed83bf049 100644 --- a/frontend/src/pages/LessonForm.vue +++ b/frontend/src/pages/LessonForm.vue @@ -92,11 +92,13 @@ import LessonHelp from '@/components/LessonHelp.vue' import { ChevronRight } from 'lucide-vue-next' import { updateDocumentTitle, createToast, getEditorTools } from '@/utils' import { capture } from '@/telemetry' +import { useSettings } from '@/stores/settings' const editor = ref(null) const instructorEditor = ref(null) const user = inject('$user') const openInstructorEditor = ref(false) +const settingsStore = useSettings() let autoSaveInterval let showSuccessMessage = false @@ -393,6 +395,9 @@ const createNewLesson = () => { onSuccess() { capture('lesson_created') showToast('Success', 'Lesson created successfully', 'check') + if (!settingsStore.onboardingDetails.data?.is_onboarded) { + settingsStore.onboardingDetails.reload() + } lessonDetails.reload() }, } diff --git a/frontend/src/stores/settings.js b/frontend/src/stores/settings.js index 9844517fa..9aea84760 100644 --- a/frontend/src/stores/settings.js +++ b/frontend/src/stores/settings.js @@ -17,9 +17,16 @@ export const useSettings = defineStore('settings', () => { cache: ['learningPaths'], }) + const onboardingDetails = createResource({ + url: 'lms.lms.utils.is_onboarding_complete', + auto: true, + cache: ['onboardingDetails'], + }) + return { isSettingsOpen, activeTab, learningPaths, + onboardingDetails, } }) diff --git a/lms/lms/utils.py b/lms/lms/utils.py index 3c0ba3c00..0b9733084 100644 --- a/lms/lms/utils.py +++ b/lms/lms/utils.py @@ -855,7 +855,10 @@ def get_telemetry_boot_info(): } +@frappe.whitelist() def is_onboarding_complete(): + if not has_course_moderator_role(): + return {"is_onboarded": False} course_created = frappe.db.a_row_exists("LMS Course") chapter_created = frappe.db.a_row_exists("Course Chapter") lesson_created = frappe.db.a_row_exists("Course Lesson")