Merge pull request #1490 from frappe/develop

chore: merge 'develop' into 'main'
This commit is contained in:
Jannat Patel
2025-05-07 12:56:56 +05:30
committed by GitHub
30 changed files with 3607 additions and 3522 deletions

Submodule frappe-ui deleted from 175be05a92

View File

@@ -3,7 +3,7 @@
<template #target="{ togglePopover }"> <template #target="{ togglePopover }">
<button <button
:class="[ :class="[
'group w-full flex h-7 items-center justify-between rounded px-2 text-base text-ink-gray-8 hover:bg-surface-gray-2', 'group w-full flex h-7 items-center justify-between rounded px-2 text-base text-ink-gray-7 hover:bg-surface-gray-2',
]" ]"
@click.prevent="togglePopover()" @click.prevent="togglePopover()"
> >

View File

@@ -28,9 +28,7 @@
</template> </template>
<template #body="{ isOpen }"> <template #body="{ isOpen }">
<div v-show="isOpen"> <div v-show="isOpen">
<div <div class="mt-1 rounded-lg bg-surface-white py-1 text-base border-2">
class="mt-1 rounded-lg bg-surface-white py-1 text-base shadow-2xl"
>
<div class="relative px-1.5 pt-0.5"> <div class="relative px-1.5 pt-0.5">
<ComboboxInput <ComboboxInput
ref="search" ref="search"
@@ -49,7 +47,7 @@
class="absolute right-1.5 inline-flex h-7 w-7 items-center justify-center" class="absolute right-1.5 inline-flex h-7 w-7 items-center justify-center"
@click="selectedValue = null" @click="selectedValue = null"
> >
<X class="h-4 w-4 stroke-1.5" /> <X class="h-4 w-4 stroke-1.5 text-ink-gray-7" />
</button> </button>
</div> </div>
<ComboboxOptions <ComboboxOptions
@@ -89,7 +87,7 @@
name="item-label" name="item-label"
v-bind="{ active, selected, option }" v-bind="{ active, selected, option }"
> >
<div class="flex flex-col space-y-1"> <div class="flex flex-col space-y-1 text-ink-gray-8">
<div> <div>
{{ option.label }} {{ option.label }}
</div> </div>

View File

@@ -4,7 +4,7 @@
{{ label }} {{ label }}
<span class="text-ink-red-3" v-if="required">*</span> <span class="text-ink-red-3" v-if="required">*</span>
</label> </label>
<div class="grid grid-cols-3 gap-1"> <div class="grid grid-cols-3 gap-2">
<Button <Button
ref="emails" ref="emails"
v-for="value in values" v-for="value in values"
@@ -12,7 +12,7 @@
:label="value" :label="value"
theme="gray" theme="gray"
variant="subtle" variant="subtle"
class="rounded-md" class="rounded-md word-break-all"
@keydown.delete.capture.stop="removeLastValue" @keydown.delete.capture.stop="removeLastValue"
> >
<template #suffix> <template #suffix>
@@ -42,7 +42,7 @@
<template #body="{ isOpen }"> <template #body="{ isOpen }">
<div v-show="isOpen"> <div v-show="isOpen">
<div <div
class="mt-1 rounded-lg bg-surface-white py-1 text-base shadow-2xl" class="mt-1 rounded-lg bg-surface-white py-1 text-base border-2"
> >
<ComboboxOptions <ComboboxOptions
class="my-1 max-h-[12rem] overflow-y-auto px-1.5" class="my-1 max-h-[12rem] overflow-y-auto px-1.5"
@@ -61,7 +61,7 @@
]" ]"
> >
<div class="flex flex-col gap-1 p-1"> <div class="flex flex-col gap-1 p-1">
<div class="text-base font-medium"> <div class="text-base font-medium text-ink-gray-8">
{{ option.description }} {{ option.description }}
</div> </div>
<div class="text-sm text-ink-gray-5"> <div class="text-sm text-ink-gray-5">

View File

@@ -2,57 +2,73 @@
<Dialog <Dialog
v-model="show" v-model="show"
:options="{ :options="{
title:
assignmentID === 'new'
? __('Create an Assignment')
: __('Edit Assignment'),
size: 'lg', size: 'lg',
actions: [
{
label: __('Save'),
variant: 'solid',
onClick: (close) => saveAssignment(close),
},
],
}" }"
> >
<template #body-content> <template #body>
<div class="space-y-4 text-base max-h-[65vh] overflow-y-auto"> <div class="p-5 text-base max-h-[75vh] overflow-y-auto">
<FormControl <div class="text-lg text-ink-gray-9 font-semibold mb-5">
v-model="assignment.title" {{
:label="__('Title')" assignmentID === 'new'
:required="true" ? __('Create an Assignment')
/> : __('Edit Assignment')
<FormControl }}
v-model="assignment.type" </div>
type="select" <div class="space-y-4">
:options="assignmentOptions" <FormControl
:label="__('Submission Type')" v-model="assignment.title"
:required="true" :label="__('Title')"
/> :required="true"
<div>
<div class="text-xs text-ink-gray-5 mb-2">
{{ __('Question') }}
<span class="text-ink-red-3">*</span>
</div>
<TextEditor
:content="assignment.question"
@change="(val) => (assignment.question = val)"
:editable="true"
:fixedMenu="true"
editorClass="prose-sm max-w-none border-b border-x bg-surface-gray-2 rounded-b-md py-1 px-2 min-h-[7rem]"
/> />
<FormControl
v-model="assignment.type"
type="select"
:options="assignmentOptions"
:label="__('Submission Type')"
:required="true"
/>
<div>
<div class="text-xs text-ink-gray-5 mb-2">
{{ __('Question') }}
<span class="text-ink-red-3">*</span>
</div>
<TextEditor
:content="assignment.question"
@change="(val) => (assignment.question = val)"
:editable="true"
:fixedMenu="true"
editorClass="prose-sm max-w-none border-b border-x bg-surface-gray-2 rounded-b-md py-1 px-2 min-h-[7rem]"
/>
</div>
</div>
<div class="flex justify-end space-x-2 mt-5">
<router-link
:to="{
name: 'AssignmentSubmissionList',
query: {
assignmentID: assignmentID,
},
}"
>
<Button v-if="assignmentID !== 'new'" variant="subtle">
{{ __('Check Submissions') }}
</Button>
</router-link>
<Button variant="solid" @click="saveAssignment">
{{ __('Save') }}
</Button>
</div> </div>
</div> </div>
</template> </template>
</Dialog> </Dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Dialog, FormControl, TextEditor } from 'frappe-ui' import { Button, Dialog, FormControl, TextEditor } from 'frappe-ui'
import { computed, reactive, watch } from 'vue' import { computed, reactive, watch } from 'vue'
import { showToast } from '@/utils' import { showToast } from '@/utils'
const show = defineModel('show') const show = defineModel()
const assignments = defineModel<Assignments>('assignments') const assignments = defineModel<Assignments>('assignments')
interface Assignment { interface Assignment {
@@ -98,7 +114,7 @@ watch(
{ flush: 'post' } { flush: 'post' }
) )
const saveAssignment = (close) => { const saveAssignment = () => {
if (props.assignmentID == 'new') { if (props.assignmentID == 'new') {
assignments.value.insert.submit( assignments.value.insert.submit(
{ {
@@ -106,7 +122,7 @@ const saveAssignment = (close) => {
}, },
{ {
onSuccess() { onSuccess() {
close() show.value = false
showToast( showToast(
__('Success'), __('Success'),
__('Assignment created successfully'), __('Assignment created successfully'),
@@ -123,7 +139,7 @@ const saveAssignment = (close) => {
}, },
{ {
onSuccess() { onSuccess() {
close() show.value = false
showToast( showToast(
__('Success'), __('Success'),
__('Assignment updated successfully'), __('Assignment updated successfully'),

View File

@@ -1,38 +1,27 @@
<template> <template>
<Dialog v-model="show" :options="dialogOptions"> <Dialog
<template #body-content> v-model="show"
<div class="space-y-4"> :options="{
size: '3xl',
}"
>
<template #body>
<div class="p-5 space-y-5">
<div class="text-lg font-semibold text-ink-gray-9 mb-5">
{{ __(props.title) }}
</div>
<div <div
v-if="!editMode" v-if="!editMode"
class="flex items-center text-xs text-ink-gray-7 space-x-5" class="flex items-center text-xs text-ink-gray-7 space-x-5"
> >
<div class="flex items-center space-x-2"> <Switch
<input size="sm"
type="radio" :label="__('Choose an existing question')"
id="existing" v-model="chooseFromExisting"
value="existing" class="!p-0"
v-model="questionType" />
class="w-3 h-3 cursor-pointer"
/>
<label for="existing" class="cursor-pointer">
{{ __('Add an existing question') }}
</label>
</div>
<div class="flex items-center space-x-2">
<input
type="radio"
id="new"
value="new"
v-model="questionType"
class="w-3 h-3 cursor-pointer"
/>
<label for="new" class="cursor-pointer">
{{ __('Create a new question') }}
</label>
</div>
</div> </div>
<div v-if="questionType == 'new' || editMode" class="space-y-2"> <div v-if="!chooseFromExisting || editMode" class="space-y-2">
<div> <div>
<label class="block text-xs text-ink-gray-5 mb-1"> <label class="block text-xs text-ink-gray-5 mb-1">
{{ __('Question') }} {{ __('Question') }}
@@ -45,20 +34,34 @@
editorClass="prose-sm max-w-none border-b border-x bg-surface-gray-2 rounded-b-md py-1 px-2 min-h-[7rem]" editorClass="prose-sm max-w-none border-b border-x bg-surface-gray-2 rounded-b-md py-1 px-2 min-h-[7rem]"
/> />
</div> </div>
<FormControl <div class="grid grid-cols-2 gap-4">
v-model="question.marks" <FormControl
:label="__('Marks')" v-model="question.marks"
type="number" :label="__('Marks')"
/> type="number"
<FormControl />
:label="__('Type')" <FormControl
v-model="question.type" :label="__('Type')"
type="select" v-model="question.type"
:options="['Choices', 'User Input', 'Open Ended']" type="select"
class="pb-2" :options="['Choices', 'User Input', 'Open Ended']"
:required="true" class="pb-2"
/> :required="true"
<div v-if="question.type == 'Choices'" class="divide-y border-t"> />
</div>
<div
v-if="question.type == 'Choices'"
class="text-base font-semibold text-ink-gray-9 mb-5 mt-5"
>
{{ __('Options') }}
</div>
<div
v-else-if="question.type == 'User Input'"
class="text-base font-semibold text-ink-gray-9 mb-5 mt-5"
>
{{ __('Possibilities') }}
</div>
<div v-if="question.type == 'Choices'" class="grid grid-cols-2 gap-4">
<div v-for="n in 4" class="space-y-4 py-2"> <div v-for="n in 4" class="space-y-4 py-2">
<FormControl <FormControl
:label="__('Option') + ' ' + n" :label="__('Option') + ' ' + n"
@@ -78,17 +81,18 @@
</div> </div>
<div <div
v-else-if="question.type == 'User Input'" v-else-if="question.type == 'User Input'"
v-for="n in 4" class="grid grid-cols-2 gap-4 py-2"
class="space-y-2"
> >
<FormControl <div v-for="n in 4">
:label="__('Possibility') + ' ' + n" <FormControl
v-model="question[`possibility_${n}`]" :label="__('Possibility') + ' ' + n"
:required="n == 1 ? true : false" v-model="question[`possibility_${n}`]"
/> :required="n == 1 ? true : false"
/>
</div>
</div> </div>
</div> </div>
<div v-else-if="questionType == 'existing'" class="space-y-2"> <div v-else-if="chooseFromExisting" class="space-y-2">
<Link <Link
v-model="existingQuestion.question" v-model="existingQuestion.question"
:label="__('Select a question')" :label="__('Select a question')"
@@ -100,12 +104,24 @@
type="number" type="number"
/> />
</div> </div>
<div class="flex items-center justify-end space-x-2 mt-5">
<Button variant="solid" @click="submitQuestion()">
{{ __('Submit') }}
</Button>
</div>
</div> </div>
</template> </template>
</Dialog> </Dialog>
</template> </template>
<script setup> <script setup>
import { Dialog, FormControl, TextEditor, createResource } from 'frappe-ui' import {
Dialog,
FormControl,
TextEditor,
createResource,
Switch,
Button,
} from 'frappe-ui'
import { computed, watch, reactive, ref, inject } from 'vue' import { computed, watch, reactive, ref, inject } from 'vue'
import Link from '@/components/Controls/Link.vue' import Link from '@/components/Controls/Link.vue'
import { showToast } from '@/utils' import { showToast } from '@/utils'
@@ -113,7 +129,7 @@ import { useOnboarding } from 'frappe-ui/frappe'
const show = defineModel() const show = defineModel()
const quiz = defineModel('quiz') const quiz = defineModel('quiz')
const questionType = ref(null) const chooseFromExisting = ref(false)
const editMode = ref(false) const editMode = ref(false)
const user = inject('$user') const user = inject('$user')
const { updateOnboardingStep } = useOnboarding('learning') const { updateOnboardingStep } = useOnboarding('learning')
@@ -182,11 +198,12 @@ watch(show, () => {
editMode.value = false editMode.value = false
if (props.questionDetail.question) questionData.fetch() if (props.questionDetail.question) questionData.fetch()
else { else {
;(question.question = ''), (question.marks = 0) question.question = ''
question.marks = 1
question.type = 'Choices' question.type = 'Choices'
existingQuestion.question = '' existingQuestion.question = ''
existingQuestion.marks = 0 existingQuestion.marks = 1
questionType.value = null chooseFromExisting.value = false
populateFields() populateFields()
} }
@@ -221,32 +238,26 @@ const questionCreation = createResource({
}, },
}) })
const submitQuestion = (close) => { const submitQuestion = () => {
if (props.questionDetail?.question) updateQuestion(close) if (props.questionDetail?.question) updateQuestion()
else addQuestion(close) else addQuestion()
} }
const addQuestion = (close) => { const addQuestion = () => {
if (questionType.value == 'existing') { if (chooseFromExisting.value) {
addQuestionRow( addQuestionRow({
{ question: existingQuestion.question,
question: existingQuestion.question, marks: existingQuestion.marks,
marks: existingQuestion.marks, })
},
close
)
} else { } else {
questionCreation.submit( questionCreation.submit(
{}, {},
{ {
onSuccess(data) { onSuccess(data) {
addQuestionRow( addQuestionRow({
{ question: data.name,
question: data.name, marks: question.marks,
marks: question.marks, })
},
close
)
}, },
onError(err) { onError(err) {
showToast(__('Error'), __(err.messages?.[0] || err), 'x') showToast(__('Error'), __(err.messages?.[0] || err), 'x')
@@ -256,7 +267,7 @@ const addQuestion = (close) => {
} }
} }
const addQuestionRow = (question, close) => { const addQuestionRow = (question) => {
questionRow.submit( questionRow.submit(
{ {
...question, ...question,
@@ -269,11 +280,11 @@ const addQuestionRow = (question, close) => {
show.value = false show.value = false
showToast(__('Success'), __('Question added successfully'), 'check') showToast(__('Success'), __('Question added successfully'), 'check')
quiz.value.reload() quiz.value.reload()
close() show.value = false
}, },
onError(err) { onError(err) {
showToast(__('Error'), __(err.messages?.[0] || err), 'x') showToast(__('Error'), __(err.messages?.[0] || err), 'x')
close() show.value = false
}, },
} }
) )
@@ -307,7 +318,7 @@ const marksUpdate = createResource({
}, },
}) })
const updateQuestion = (close) => { const updateQuestion = () => {
questionUpdate.submit( questionUpdate.submit(
{}, {},
{ {
@@ -323,7 +334,6 @@ const updateQuestion = (close) => {
'check' 'check'
) )
quiz.value.reload() quiz.value.reload()
close()
}, },
} }
) )
@@ -334,22 +344,6 @@ const updateQuestion = (close) => {
} }
) )
} }
const dialogOptions = computed(() => {
return {
title: __(props.title),
size: 'xl',
actions: [
{
label: __('Submit'),
variant: 'solid',
onClick: (close) => {
submitQuestion(close)
},
},
],
}
})
</script> </script>
<style> <style>
input[type='radio']:checked { input[type='radio']:checked {

View File

@@ -10,11 +10,11 @@
</header> </header>
<div class="w-3/4 mx-auto py-5"> <div class="w-3/4 mx-auto py-5">
<div class=""> <div class="">
<div class="text-lg font-semibold mb-4"> <div class="text-lg text-ink-gray-9 font-semibold mb-4">
{{ __('Details') }} {{ __('Details') }}
</div> </div>
<div class="space-y-10 mb-4"> <div class="space-y-10 mb-4">
<div class="grid grid-cols-2 gap-10"> <div class="space-y-4">
<FormControl <FormControl
v-model="batch.title" v-model="batch.title"
:label="__('Title')" :label="__('Title')"
@@ -107,7 +107,7 @@
</div> </div>
<div class="my-10"> <div class="my-10">
<div class="text-lg font-semibold mb-4"> <div class="text-lg text-ink-gray-9 font-semibold mb-4">
{{ __('Date and Time') }} {{ __('Date and Time') }}
</div> </div>
<div class="grid grid-cols-3 gap-10"> <div class="grid grid-cols-3 gap-10">
@@ -157,7 +157,7 @@
</div> </div>
<div class="mb-10"> <div class="mb-10">
<div class="text-lg font-semibold mb-4"> <div class="text-lg text-ink-gray-9 font-semibold mb-4">
{{ __('Settings') }} {{ __('Settings') }}
</div> </div>
<div class="grid grid-cols-3 gap-10"> <div class="grid grid-cols-3 gap-10">
@@ -210,7 +210,7 @@
</div> </div>
<div class=""> <div class="">
<div class="text-lg font-semibold mb-4"> <div class="text-lg text-ink-gray-9 font-semibold mb-4">
{{ __('Payment') }} {{ __('Payment') }}
</div> </div>
<FormControl <FormControl
@@ -234,7 +234,7 @@
</div> </div>
<div class="my-10"> <div class="my-10">
<div class="text-lg font-semibold mb-4"> <div class="text-lg text-ink-gray-9 font-semibold mb-4">
{{ __('Description') }} {{ __('Description') }}
</div> </div>
<FormControl <FormControl

View File

@@ -10,56 +10,32 @@
</span> </span>
</div> </div>
<div <div
class="mx-auto space-y-5 w-full h-fit bg-white px-4 py-8 sm:mt-6 sm:w-96 sm:rounded-lg sm:px-8 sm:shadow-xl" class="mx-auto w-full h-fit bg-white py-8 sm:mt-6 sm:w-96 sm:rounded-lg sm:px-8 sm:shadow-xl"
> >
<div> <div class="font-medium text-center mb-8">
{{ __('Help us understand your needs') }}
</div>
<div class="mb-5">
<div class="text-sm text-gray-700 mb-2"> <div class="text-sm text-gray-700 mb-2">
{{ __('1. What best describes your role?') }} {{ __('What is your main use case for Frappe Learning?') }}
</div> </div>
<FormControl <FormControl
v-model="persona.role" v-model="persona.useCase"
type="select" type="select"
:options="roleOptions" :options="useCaseOptions"
/> />
</div> </div>
<div> <div class="mb-5">
<div> <div class="text-sm text-gray-700 mb-2">
<div class="text-sm text-gray-700 mb-2"> {{ __('How many students are you planning to teach?') }}
{{ __('2. How many students are you planning to teach?') }}
</div>
<FormControl
v-model="persona.noOfStudents"
type="select"
:options="noOfStudentsOptions"
/>
</div>
</div>
<div>
<div>
<div class="text-sm text-gray-700 mb-2">
{{ __('3. What is your main use case for Frappe Learning?') }}
</div>
<FormControl
v-model="persona.useCase"
type="select"
:options="useCaseOptions"
/>
</div>
</div>
<div>
<div>
<div class="text-sm text-gray-700 mb-2">
{{ __('4. Are you currently using any Frappe products?') }}
</div>
<FormControl
v-model="persona.frappeProducts"
type="select"
:options="frappeProductsOptions"
/>
</div> </div>
<FormControl
v-model="persona.noOfStudents"
type="select"
:options="noOfStudentsOptions"
/>
</div> </div>
<div class="flex w-full"> <div class="flex w-full">
@@ -89,19 +65,15 @@ const router = useRouter()
const { brand } = sessionStore() const { brand } = sessionStore()
const persona = reactive({ const persona = reactive({
role: null,
noOfStudents: null, noOfStudents: null,
useCase: null, useCase: null,
frappeProducts: null,
}) })
const submitPersona = () => { const submitPersona = () => {
let responses = { let responses = {
site: user.data?.sitename, site: user.data?.sitename,
role: persona.role,
no_of_students: persona.noOfStudents, no_of_students: persona.noOfStudents,
use_case: persona.useCase, use_case: persona.useCase,
frappe_products: persona.frappeProducts,
} }
call('lms.lms.api.capture_user_persona', { call('lms.lms.api.capture_user_persona', {
responses: JSON.stringify(responses), responses: JSON.stringify(responses),
@@ -125,24 +97,6 @@ const skipPersonaForm = () => {
}) })
} }
const roleOptions = computed(() => {
const options = [
'Trainer / Instructor',
'Freelancer / Consultant',
'HR / L&D Professional',
'School / University Admin',
'Software Developer',
'Community Manager',
'Business Owner / Team Lead',
'Other',
]
return options.map((option) => ({
label: option,
value: option,
}))
})
const noOfStudentsOptions = computed(() => { const noOfStudentsOptions = computed(() => {
const options = [ const options = [
'Less than 50', 'Less than 50',
@@ -173,22 +127,6 @@ const useCaseOptions = computed(() => {
})) }))
}) })
const frappeProductsOptions = computed(() => {
const options = [
'Frappe Framework',
'ERPNext / Frappe HR',
'Frappe CRM / Helpdesk',
'Custom Frappe App',
'Other',
'Not using any Frappe product',
]
return options.map((option) => ({
label: option,
value: option,
}))
})
usePageMeta(() => { usePageMeta(() => {
return { return {
title: 'Persona', title: 'Persona',

View File

@@ -13,7 +13,7 @@
<!-- Courses --> <!-- Courses -->
<div> <div>
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<div class="text-lg font-semibold"> <div class="text-lg text-ink-gray-9 font-semibold">
{{ __('Program Courses') }} {{ __('Program Courses') }}
</div> </div>
<Button <Button
@@ -75,7 +75,7 @@
<!-- Members --> <!-- Members -->
<div> <div>
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<div class="text-lg font-semibold"> <div class="text-lg text-ink-gray-9 font-semibold">
{{ __('Program Members') }} {{ __('Program Members') }}
</div> </div>
<Button <Button

View File

@@ -38,7 +38,7 @@
<div class="w-3/4 mx-auto py-5"> <div class="w-3/4 mx-auto py-5">
<!-- Details --> <!-- Details -->
<div class="mb-8"> <div class="mb-8">
<div class="font-semibold mb-4"> <div class="font-semibold text-ink-gray-9 mb-4">
{{ __('Details') }} {{ __('Details') }}
</div> </div>
<FormControl <FormControl
@@ -75,7 +75,7 @@
<!-- Settings --> <!-- Settings -->
<div class="mb-8"> <div class="mb-8">
<div class="font-semibold mb-4"> <div class="font-semibold text-ink-gray-9 mb-4">
{{ __('Settings') }} {{ __('Settings') }}
</div> </div>
<div class="grid grid-cols-3 gap-5 my-4"> <div class="grid grid-cols-3 gap-5 my-4">
@@ -93,7 +93,7 @@
</div> </div>
<div class="mb-8"> <div class="mb-8">
<div class="font-semibold mb-4"> <div class="font-semibold text-ink-gray-9 mb-4">
{{ __('Shuffle Settings') }} {{ __('Shuffle Settings') }}
</div> </div>
<div class="grid grid-cols-3"> <div class="grid grid-cols-3">
@@ -113,7 +113,7 @@
<!-- Questions --> <!-- Questions -->
<div> <div>
<div class="flex items-center justify-between mb-4"> <div class="flex items-center justify-between mb-4">
<div class="font-semibold"> <div class="font-semibold text-ink-gray-9">
{{ __('Questions') }} {{ __('Questions') }}
</div> </div>
<Button v-if="!readOnlyMode" @click="openQuestionModal()"> <Button v-if="!readOnlyMode" @click="openQuestionModal()">
@@ -445,11 +445,7 @@ const breadcrumbs = computed(() => {
}, },
}, },
] ]
/* if (quizDetails.data) {
crumbs.push({
label: quiz.title,
})
} */
crumbs.push({ crumbs.push({
label: props.quizID == 'new' ? __('New Quiz') : quizDetails.data?.title, label: props.quizID == 'new' ? __('New Quiz') : quizDetails.data?.title,
route: { name: 'QuizForm', params: { quizID: props.quizID } }, route: { name: 'QuizForm', params: { quizID: props.quizID } },

View File

@@ -312,7 +312,7 @@ def get_lesson_index(lesson_name):
def get_lesson_url(course, lesson_number): def get_lesson_url(course, lesson_number):
if not lesson_number: if not lesson_number:
return return
return f"/courses/{course}/learn/{lesson_number}" return f"/lms/courses/{course}/learn/{lesson_number}"
def get_batch(course, batch_name): def get_batch(course, batch_name):

View File

@@ -128,7 +128,7 @@
<a class="stretched-link" href="{{ get_lesson_url(course.name, lesson_index) }}{{ query_parameter }}"></a> <a class="stretched-link" href="{{ get_lesson_url(course.name, lesson_index) }}{{ query_parameter }}"></a>
{% else %} {% else %}
<a class="stretched-link" href="/courses/{{ course.name }}"></a> <a class="stretched-link" href="/lms/courses/{{ course.name }}"></a>
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff