Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: merge 'develop' into 'main' #1151

Merged
merged 30 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
be66c56
Add Chinese locale
yarin-zhang Nov 11, 2024
5e61601
Update Revision Date
yarin-zhang Nov 11, 2024
0fb18f9
Update Chinese locale
yarin-zhang Nov 14, 2024
ee6685e
Update Chinese locale
yarin-zhang Nov 14, 2024
fac0038
Update Chinese locale
yarin-zhang Nov 14, 2024
b5551fd
Merge branch 'develop' into develop
yarin-zhang Nov 14, 2024
1ba63a2
Update Chinese locale
yarin-zhang Nov 14, 2024
4ee1693
Merge branch 'develop' into develop
yarin-zhang Nov 17, 2024
e1a7838
feat: learning paths
pateljannat Nov 18, 2024
582c7af
feat: reorder courses and students view for programs
pateljannat Nov 20, 2024
460edc7
fix: changed SCORM input from checkbox to switch with better description
pateljannat Nov 20, 2024
29e356f
Merge pull request #1144 from pateljannat/issues-52
pateljannat Nov 20, 2024
fcaaee9
chore: Persian translations
pateljannat Nov 20, 2024
64ed0b3
feat: program restrictions
pateljannat Nov 21, 2024
68e87f2
feat: added progress column in program members list
pateljannat Nov 22, 2024
a394952
Merge pull request #1146 from frappe/l10n_develop2
pateljannat Nov 22, 2024
7cafaf5
Merge pull request #1145 from pateljannat/learning-paths
pateljannat Nov 22, 2024
cb324f6
Merge branch 'develop' into develop
yarin-zhang Nov 22, 2024
58f109e
feat: onboarding steps
pateljannat Nov 22, 2024
40bcc4d
Merge pull request #1147 from pateljannat/onboarding-steps
pateljannat Nov 22, 2024
1c52979
chore: update POT file
frappe-pr-bot Nov 22, 2024
de0675f
chore: Persian translations
pateljannat Nov 23, 2024
0ac32ee
chore: Swedish translations
pateljannat Nov 24, 2024
cfa1aa8
Merge pull request #1115 from yarin-zhang/develop
pateljannat Nov 25, 2024
044907e
Merge pull request #1148 from frappe/pot_develop_2024-11-22
pateljannat Nov 25, 2024
562020d
Merge pull request #1149 from frappe/l10n_develop2
pateljannat Nov 25, 2024
83338a5
fix: disable desk_access for lms roles
pateljannat Nov 25, 2024
d49d638
fix: amount validation for course
pateljannat Nov 25, 2024
a90e3d6
Merge pull request #1150 from pateljannat/roles-desk-access-issue
pateljannat Nov 25, 2024
1ecdbd9
chore(release): Bumped to Version 2.13.0
frappe-bot Nov 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading