Merge pull request #1490 from frappe/develop
chore: merge 'develop' into 'main'
This commit is contained in:
Submodule frappe-ui deleted from 175be05a92
@@ -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()"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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'),
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 } },
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
372
lms/locale/ar.po
372
lms/locale/ar.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/bs.po
372
lms/locale/bs.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/de.po
372
lms/locale/de.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/eo.po
372
lms/locale/eo.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/es.po
372
lms/locale/es.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/fa.po
372
lms/locale/fa.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/fr.po
372
lms/locale/fr.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/hr.po
372
lms/locale/hr.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/hu.po
372
lms/locale/hu.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/pl.po
372
lms/locale/pl.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/pt.po
372
lms/locale/pt.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
372
lms/locale/ru.po
372
lms/locale/ru.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
372
lms/locale/sv.po
372
lms/locale/sv.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/th.po
372
lms/locale/th.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/tr.po
372
lms/locale/tr.po
File diff suppressed because it is too large
Load Diff
372
lms/locale/zh.po
372
lms/locale/zh.po
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user