diff --git a/frappe-ui b/frappe-ui
index c795670f..704a098e 160000
--- a/frappe-ui
+++ b/frappe-ui
@@ -1 +1 @@
-Subproject commit c795670f395748c0d68761c710d29141fa20b113
+Subproject commit 704a098eb1982410678cb12e6764c3d4087ea8fb
diff --git a/frontend/components.d.ts b/frontend/components.d.ts
index 085dc343..4389972d 100644
--- a/frontend/components.d.ts
+++ b/frontend/components.d.ts
@@ -16,7 +16,6 @@ declare module 'vue' {
AssessmentPlugin: typeof import('./src/components/AssessmentPlugin.vue')['default']
Assessments: typeof import('./src/components/Assessments.vue')['default']
Assignment: typeof import('./src/components/Assignment.vue')['default']
- AssignmentBlock: typeof import('./src/components/AssignmentBlock.vue')['default']
AudioBlock: typeof import('./src/components/AudioBlock.vue')['default']
Autocomplete: typeof import('./src/components/Controls/Autocomplete.vue')['default']
BatchCard: typeof import('./src/components/BatchCard.vue')['default']
@@ -24,7 +23,6 @@ declare module 'vue' {
BatchCourses: typeof import('./src/components/BatchCourses.vue')['default']
BatchDashboard: typeof import('./src/components/BatchDashboard.vue')['default']
BatchFeedback: typeof import('./src/components/BatchFeedback.vue')['default']
- BatchIcon: typeof import('./src/components/Icons/BatchIcon.vue')['default']
BatchOverlay: typeof import('./src/components/BatchOverlay.vue')['default']
BatchStudentProgress: typeof import('./src/components/Modals/BatchStudentProgress.vue')['default']
BatchStudents: typeof import('./src/components/BatchStudents.vue')['default']
@@ -49,11 +47,13 @@ declare module 'vue' {
EditCoverImage: typeof import('./src/components/Modals/EditCoverImage.vue')['default']
EditProfile: typeof import('./src/components/Modals/EditProfile.vue')['default']
EvaluationModal: typeof import('./src/components/Modals/EvaluationModal.vue')['default']
+ Evaluators: typeof import('./src/components/Evaluators.vue')['default']
Event: typeof import('./src/components/Modals/Event.vue')['default']
ExplanationVideos: typeof import('./src/components/Modals/ExplanationVideos.vue')['default']
FrappeCloudIcon: typeof import('./src/components/Icons/FrappeCloudIcon.vue')['default']
IconPicker: typeof import('./src/components/Controls/IconPicker.vue')['default']
IndicatorIcon: typeof import('./src/components/Icons/IndicatorIcon.vue')['default']
+ InviteIcon: typeof import('./src/components/Icons/InviteIcon.vue')['default']
JobApplicationModal: typeof import('./src/components/Modals/JobApplicationModal.vue')['default']
JobCard: typeof import('./src/components/JobCard.vue')['default']
LessonContent: typeof import('./src/components/LessonContent.vue')['default']
diff --git a/frontend/package.json b/frontend/package.json
index 57752299..7990f221 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -26,13 +26,13 @@
"codemirror-editor-vue3": "^2.8.0",
"dayjs": "^1.11.6",
"feather-icons": "^4.28.0",
- "frappe-ui": "^0.1.118",
+ "frappe-ui": "^0.1.122",
"highlight.js": "^11.11.1",
"lucide-vue-next": "^0.383.0",
"markdown-it": "^14.0.0",
"pinia": "^2.0.33",
"socket.io-client": "^4.7.2",
- "tailwindcss": "^3.3.3",
+ "tailwindcss": "3.4.15",
"typescript": "^5.7.2",
"vue": "^3.4.23",
"vue-chartjs": "^5.3.0",
diff --git a/frontend/src/components/AppSidebar.vue b/frontend/src/components/AppSidebar.vue
index 79d05006..8b18c389 100644
--- a/frontend/src/components/AppSidebar.vue
+++ b/frontend/src/components/AppSidebar.vue
@@ -62,25 +62,48 @@
-
+
+
+ {
+ showHelpModal = minimize ? true : !showHelpModal
+ minimize = !showHelpModal
+ }
+ "
+ >
+
+
+
+
+
+
+
+
{
+ addNotifications()
+ setSidebarLinks()
socket.on('publish_lms_notifications', (data) => {
unreadNotifications.reload()
})
- addNotifications()
+})
+
+const setSidebarLinks = () => {
sidebarSettings.reload(
{},
{
@@ -144,7 +221,7 @@ onMounted(() => {
},
}
)
-})
+}
const unreadNotifications = createResource({
cache: 'Unread Notifications Count',
@@ -272,16 +349,6 @@ const getSidebarFromStorage = () => {
return useStorage('sidebar_is_collapsed', false)
}
-watch(userResource, () => {
- if (userResource.data) {
- isModerator.value = userResource.data.is_moderator
- isInstructor.value = userResource.data.is_instructor
- addPrograms()
- addQuizzes()
- addAssignments()
- }
-})
-
const toggleSidebar = () => {
sidebarStore.isSidebarCollapsed = !sidebarStore.isSidebarCollapsed
localStorage.setItem(
@@ -297,4 +364,218 @@ const toggleWebPages = () => {
JSON.stringify(sidebarStore.isWebpagesCollapsed)
)
}
+
+const getFirstCourse = async () => {
+ let firstCourse = localStorage.getItem('firstCourse')
+ if (firstCourse) return firstCourse
+ return await call('lms.lms.onboarding.get_first_course')
+}
+
+const getFirstBatch = async () => {
+ let firstBatch = localStorage.getItem('firstBatch')
+ if (firstBatch) return firstBatch
+ return await call('lms.lms.onboarding.get_first_batch')
+}
+
+const steps = reactive([
+ {
+ name: 'create_first_course',
+ title: __('Create your first course'),
+ icon: markRaw(h(BookOpen, iconProps)),
+ completed: false,
+ onClick: () => {
+ minimize.value = true
+ router.push({
+ name: 'Courses',
+ })
+ },
+ },
+ {
+ name: 'create_first_chapter',
+ title: __('Add your first chapter'),
+ icon: markRaw(h(FolderTree, iconProps)),
+ completed: false,
+ onClick: async () => {
+ minimize.value = true
+ let course = await getFirstCourse()
+ if (course) {
+ router.push({ name: 'CourseForm', params: { courseName: course } })
+ } else {
+ router.push({ name: 'CourseForm' })
+ }
+ },
+ },
+ {
+ name: 'create_first_lesson',
+ title: __('Add your first lesson'),
+ icon: markRaw(h(FileText, iconProps)),
+ completed: false,
+ onClick: async () => {
+ minimize.value = true
+ let course = await getFirstCourse()
+ if (course) {
+ router.push({
+ name: 'CourseForm',
+ params: { courseName: course },
+ })
+ } else {
+ router.push({ name: 'Courses' })
+ }
+ },
+ },
+ {
+ name: 'create_first_quiz',
+ title: __('Create your first quiz'),
+ icon: markRaw(h(CircleHelp, iconProps)),
+ completed: false,
+ onClick: () => {
+ minimize.value = true
+ router.push({ name: 'Quizzes' })
+ },
+ },
+ {
+ name: 'invite_students',
+ title: __('Invite your team and students'),
+ icon: markRaw(h(InviteIcon, iconProps)),
+ completed: false,
+ onClick: () => {
+ minimize.value = true
+ settingsStore.activeTab = 'Members'
+ settingsStore.isSettingsOpen = true
+ },
+ },
+ {
+ name: 'create_first_batch',
+ title: __('Create your first batch'),
+ icon: markRaw(h(Users, iconProps)),
+ completed: false,
+ onClick: () => {
+ minimize.value = true
+ router.push({ name: 'Batches' })
+ },
+ },
+ {
+ name: 'add_batch_student',
+ title: __('Add students to your batch'),
+ icon: markRaw(h(UserPlus, iconProps)),
+ completed: false,
+ onClick: async () => {
+ minimize.value = true
+ let batch = await getFirstBatch()
+ if (batch) {
+ router.push({
+ name: 'Batch',
+ params: {
+ batchName: batch,
+ },
+ })
+ } else {
+ router.push({ name: 'Batch' })
+ }
+ },
+ },
+ {
+ name: 'add_batch_course',
+ title: __('Add courses to your batch'),
+ icon: markRaw(h(BookText, iconProps)),
+ completed: false,
+ onClick: async () => {
+ minimize.value = true
+ let batch = await getFirstBatch()
+ if (batch) {
+ router.push({
+ name: 'Batch',
+ params: {
+ batchName: batch,
+ },
+ hash: '#courses',
+ })
+ } else {
+ router.push({ name: 'Batch' })
+ }
+ },
+ },
+])
+
+const articles = ref([
+ {
+ title: __('Introduction'),
+ opened: false,
+ subArticles: [
+ { name: 'introduction', title: __('Introduction') },
+ { name: 'setting-up', title: __('Setting up') },
+ ],
+ },
+ {
+ title: __('Creating a course'),
+ opened: false,
+ subArticles: [
+ { name: 'create-a-course', title: __('Create a course') },
+ { name: 'add-a-chapter', title: __('Add a chapter') },
+ { name: 'add-a-lesson', title: __('Add a lesson') },
+ ],
+ },
+ {
+ title: __('Creating a batch'),
+ opened: false,
+ subArticles: [
+ { name: 'create-a-batch', title: __('Create a batch') },
+ { name: 'create-a-live-class', title: __('Create a live class') },
+ ],
+ },
+ {
+ title: __('Assessments'),
+ opened: false,
+ subArticles: [
+ { name: 'quizzes', title: __('Quizzes') },
+ { name: 'assignments', title: __('Assignments') },
+ ],
+ },
+ {
+ title: __('Certification'),
+ opened: false,
+ subArticles: [
+ { name: 'issue-a-certificate', title: __('Issue a Certificate') },
+ {
+ name: 'custom-certificate-templates',
+ title: __('Custom Certificate Templates'),
+ },
+ ],
+ },
+ {
+ title: __('Monetization'),
+ opened: false,
+ subArticles: [
+ {
+ name: 'setting-up-payment-gateway',
+ title: __('Setting up payment gateway'),
+ },
+ ],
+ },
+ {
+ title: __('Settings'),
+ opened: false,
+ subArticles: [{ name: 'roles', title: __('Roles') }],
+ },
+])
+
+const setUpOnboarding = () => {
+ if (userResource.data?.is_system_manager) {
+ onboardingDetails = useOnboarding('learning')
+ onboardingDetails.setUp(steps)
+ isOnboardingStepsCompleted = onboardingDetails.isOnboardingStepsCompleted
+ showOnboarding.value = true
+ }
+}
+
+watch(userResource, () => {
+ if (userResource.data) {
+ isModerator.value = userResource.data.is_moderator
+ isInstructor.value = userResource.data.is_instructor
+ addPrograms()
+ addQuizzes()
+ addAssignments()
+ setUpOnboarding()
+ }
+})
diff --git a/frontend/src/components/BatchCourses.vue b/frontend/src/components/BatchCourses.vue
index ebf2f8af..37972a72 100644
--- a/frontend/src/components/BatchCourses.vue
+++ b/frontend/src/components/BatchCourses.vue
@@ -63,6 +63,9 @@
+
+ {{ __('No courses added') }}
+
-
+
-
+
{{ __(title) }}
-
+