Skip to content

Commit

Permalink
Merge pull request #1151 from frappe/develop
Browse files Browse the repository at this point in the history
chore: merge 'develop' into 'main'
  • Loading branch information
pateljannat authored Nov 25, 2024
2 parents db38099 + 1ecdbd9 commit 95e9087
Show file tree
Hide file tree
Showing 43 changed files with 2,416 additions and 963 deletions.
25 changes: 25 additions & 0 deletions frontend/src/components/AppSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ import { getSidebarLinks } from '../utils'
import { usersStore } from '@/stores/user'
import { sessionStore } from '@/stores/session'
import { useSidebar } from '@/stores/sidebar'
import { useSettings } from '@/stores/settings'
import { ChevronRight, Plus } from 'lucide-vue-next'
import { createResource, Button } from 'frappe-ui'
import PageModal from '@/components/Modals/PageModal.vue'
Expand All @@ -114,6 +115,7 @@ const isModerator = ref(false)
const isInstructor = ref(false)
const pageToEdit = ref(null)
const showWebPages = ref(false)
const settingsStore = useSettings()
onMounted(() => {
socket.on('publish_lms_notifications', (data) => {
Expand Down Expand Up @@ -183,6 +185,28 @@ const addQuizzes = () => {
}
}
const addPrograms = () => {
if (settingsStore.learningPaths.data) {
let activeFor = ['Programs', 'ProgramForm']
let index = 1
if (!isInstructor.value && !isModerator.value) {
sidebarLinks.value = sidebarLinks.value.filter(
(link) => link.label !== 'Courses'
)
activeFor.push('CourseDetail')
activeFor.push('Lesson')
index = 0
}
sidebarLinks.value.splice(index, 0, {
label: 'Programs',
icon: 'Route',
to: 'Programs',
activeFor: activeFor,
})
}
}
const openPageModal = (link) => {
showPageModal.value = true
pageToEdit.value = link
Expand Down Expand Up @@ -215,6 +239,7 @@ watch(userResource, () => {
isModerator.value = userResource.data.is_moderator
isInstructor.value = userResource.data.is_instructor
addQuizzes()
addPrograms()
}
})
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Controls/Autocomplete.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
{{ option.label }}
</div>
<div
v-if="option.label != option.description"
v-if="option.description"
class="text-xs text-gray-700"
v-html="option.description"
></div>
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/components/Controls/Link.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
</div>
</template>
</Autocomplete>
<p v-if="description" class="text-sm text-gray-600">{{ description }}</p>
</div>
</template>

Expand All @@ -67,6 +68,10 @@ const props = defineProps({
type: String,
default: '',
},
description: {
type: String,
default: '',
},
})
const emit = defineEmits(['update:modelValue', 'change'])
Expand Down Expand Up @@ -118,7 +123,7 @@ const options = createResource({
transform: (data) => {
return data.map((option) => {
return {
label: option.value,
label: option.label || option.value,
value: option.value,
description: option.description,
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/CourseOutline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,9 @@ const trashChapter = (chapterName) => {
}
const redirectToChapter = (chapter) => {
if (!chapter.is_scorm_package) return
event.preventDefault()
if (props.allowEdit) return
if (!chapter.is_scorm_package) return
if (!user.data) {
showToast(
__('You are not enrolled'),
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/components/DesktopLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<AppSidebar />
</div>
<div class="w-full overflow-auto" id="scrollContainer">
<OnboardingBanner />
<slot />
</div>
</div>
Expand All @@ -16,4 +17,5 @@
</template>
<script setup>
import AppSidebar from './AppSidebar.vue'
import OnboardingBanner from '@/components/OnboardingBanner.vue'
</script>
19 changes: 15 additions & 4 deletions frontend/src/components/Modals/ChapterModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@
<template #body-content>
<div class="space-y-4 text-base">
<FormControl label="Title" v-model="chapter.title" :required="true" />
<FormControl
:label="__('Is SCORM Package')"
<Switch
size="sm"
:label="__('SCORM Package')"
:description="
__(
'Enable this only if you want to upload a SCORM package as a chapter.'
)
"
v-model="chapter.is_scorm_package"
type="checkbox"
/>
<div v-if="chapter.is_scorm_package">
<FileUploader
Expand Down Expand Up @@ -70,14 +75,17 @@ import {
Dialog,
FileUploader,
FormControl,
Switch,
} from 'frappe-ui'
import { defineModel, reactive, watch, ref } from 'vue'
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: {
Expand Down Expand Up @@ -137,6 +145,9 @@ const addChapter = async (close) => {
{
onSuccess(data) {
cleanChapter()
if (!settingsStore.onboardingDetails.data?.is_onboarded) {
settingsStore.onboardingDetails.reload()
}
outline.value.reload()
showToast(
__('Success'),
Expand Down
37 changes: 32 additions & 5 deletions frontend/src/components/Modals/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,31 @@ const tabsStructure = computed(() => {
hideLabel: true,
items: [
{
label: 'Members',
description: 'Manage the members of your learning system',
icon: 'UserRoundPlus',
label: 'General',
icon: 'Wrench',
fields: [
{
label: 'Enable Learning Paths',
name: 'enable_learning_paths',
description:
'This will enforce students to go through programs assigned to them in the correct order.',
type: 'checkbox',
},
{
label: 'Send calendar invite for evaluations',
name: 'send_calendar_invite_for_evaluations',
description:
'If enabled, it sends google calendar invite to the student for evaluations.',
type: 'checkbox',
},
{
label: 'Unsplash Access Key',
name: 'unsplash_access_key',
description:
'Optional. If this is set, students can pick a cover image from the unsplash library for their profile page. https://unsplash.com/documentation#getting-started.',
type: 'text',
},
],
},
],
},
Expand Down Expand Up @@ -156,9 +178,14 @@ const tabsStructure = computed(() => {
],
},
{
label: 'Settings',
hideLabel: true,
label: 'Lists',
hideLabel: false,
items: [
{
label: 'Members',
description: 'Manage the members of your learning system',
icon: 'UserRoundPlus',
},
{
label: 'Categories',
description: 'Manage the members of your learning system',
Expand Down
151 changes: 151 additions & 0 deletions frontend/src/components/OnboardingBanner.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<template>
<div v-if="showOnboardingBanner && onboardingDetails.data">
<Tooltip :text="__('Skip Onboarding')" placement="left">
<X
class="w-4 h-4 stroke-1 absolute top-2 right-2 cursor-pointer mr-1"
@click="skipOnboarding.reload()"
/>
</Tooltip>
<div class="flex items-center justify-evenly bg-gray-100 p-10">
<div
@click="redirectToCourseForm()"
class="flex items-center space-x-2"
:class="{
'cursor-pointer': !onboardingDetails.data.course_created.length,
}"
>
<span
v-if="onboardingDetails.data.course_created.length"
class="py-1 px-1 bg-white rounded-full"
>
<Check class="h-4 w-4 stroke-2 text-green-600" />
</span>
<span v-else class="font-semibold bg-white px-2 py-1 rounded-full">
1
</span>
<span class="text-lg font-semibold">
{{ __('Create a course') }}
</span>
</div>
<div
@click="redirectToChapterForm()"
class="flex items-center space-x-2"
:class="{
'cursor-pointer':
onboardingDetails.data.course_created.length &&
!onboardingDetails.data.chapter_created.length,
'text-gray-400': !onboardingDetails.data.course_created.length,
}"
>
<span
v-if="onboardingDetails.data.chapter_created.length"
class="py-1 px-1 bg-white rounded-full"
>
<Check class="h-4 w-4 stroke-2 text-green-600" />
</span>
<span v-else class="font-semibold bg-white px-2 py-1 rounded-full">
2
</span>
<span class="text-lg font-semibold">
{{ __('Add a chapter') }}
</span>
</div>
<div
@click="redirectToLessonForm()"
class="flex items-center space-x-2"
:class="{
'cursor-pointer':
onboardingDetails.data.course_created.length &&
onboardingDetails.data.chapter_created.length,
'text-gray-400':
!onboardingDetails.data.course_created.length ||
!onboardingDetails.data.chapter_created.length,
}"
>
<span
v-if="onboardingDetails.data.lesson_created.length"
class="py-1 px-1 bg-white rounded-full"
>
<Check class="h-4 w-4 stroke-2 text-green-600" />
</span>
<span class="font-semibold bg-white px-2 py-1 rounded-full"> 3 </span>
<span class="text-lg font-semibold">
{{ __('Add a lesson') }}
</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { Check, X } from 'lucide-vue-next'
import { useRouter } from 'vue-router'
import { useSettings } from '@/stores/settings'
import { createResource, Tooltip } from 'frappe-ui'
const showOnboardingBanner = ref(false)
const settings = useSettings()
const onboardingDetails = settings.onboardingDetails
const router = useRouter()
watch(onboardingDetails, () => {
if (!onboardingDetails.data?.is_onboarded) {
showOnboardingBanner.value = true
} else {
showOnboardingBanner.value = false
}
})
const redirectToCourseForm = () => {
if (onboardingDetails.data?.course_created.length) {
return
} else {
router.push({ name: 'CourseForm', params: { courseName: 'new' } })
}
}
const redirectToChapterForm = () => {
if (!onboardingDetails.data?.course_created.length) {
return
} else {
router.push({
name: 'CourseForm',
params: {
courseName: onboardingDetails.data?.first_course,
},
})
}
}
const redirectToLessonForm = () => {
if (!onboardingDetails.data?.course_created.length) {
return
} else if (!onboardingDetails.data?.chapter_created.length) {
return
} else {
router.push({
name: 'LessonForm',
params: {
courseName: onboardingDetails.data?.first_course,
chapterNumber: 1,
lessonNumber: 1,
},
})
}
}
const skipOnboarding = createResource({
url: 'frappe.client.set_value',
makeParams() {
return {
doctype: 'LMS Settings',
name: 'LMS Settings',
fieldname: 'is_onboarding_complete',
value: 1,
}
},
onSuccess(data) {
onboardingDetails.reload()
},
})
</script>
3 changes: 3 additions & 0 deletions frontend/src/components/Quiz.vue
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,9 @@ const attempts = createResource({
watch(
() => quiz.data,
() => {
if (quiz.data) {
populateQuestions()
}
if (quiz.data && quiz.data.max_attempts) {
attempts.reload()
resetQuiz()
Expand Down
Loading

0 comments on commit 95e9087

Please sign in to comment.