chore: fixed conflicts
This commit is contained in:
@@ -125,7 +125,7 @@
|
||||
@click="redirectToWebsite()"
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip :text="__('Help')">
|
||||
<Tooltip v-if="showOnboarding" :text="__('Help')">
|
||||
<CircleHelp
|
||||
class="size-4 stroke-1.5 text-ink-gray-7 cursor-pointer"
|
||||
@click="
|
||||
|
||||
@@ -191,10 +191,11 @@ import {
|
||||
FileUploader,
|
||||
FormControl,
|
||||
TextEditor,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { computed, inject, onMounted, onBeforeUnmount, ref, watch } from 'vue'
|
||||
import { FileText, X } from 'lucide-vue-next'
|
||||
import { showToast, getFileSize } from '@/utils'
|
||||
import { getFileSize } from '@/utils'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const submissionFile = ref(null)
|
||||
@@ -284,7 +285,7 @@ const submissionResource = createDocumentResource({
|
||||
doctype: 'LMS Assignment Submission',
|
||||
name: props.submissionName,
|
||||
onError(err) {
|
||||
showToast(__('Error'), __(err.messages?.[0] || err), 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
auto: false,
|
||||
cache: [user.data?.name, props.assignmentID],
|
||||
@@ -338,7 +339,7 @@ const submitAssignment = () => {
|
||||
},
|
||||
{
|
||||
onSuccess(data) {
|
||||
showToast(__('Success'), __('Changes saved successfully'), 'check')
|
||||
toast.success(__('Changes saved successfully'))
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -352,7 +353,7 @@ const addNewSubmission = () => {
|
||||
{},
|
||||
{
|
||||
onSuccess(data) {
|
||||
showToast('Success', 'Assignment submitted successfully.', 'check')
|
||||
toast.success(__('Assignment submitted successfully'))
|
||||
if (router.currentRoute.value.name == 'AssignmentSubmission') {
|
||||
router.push({
|
||||
name: 'AssignmentSubmission',
|
||||
@@ -370,7 +371,7 @@ const addNewSubmission = () => {
|
||||
submissionResource.reload()
|
||||
},
|
||||
onError(err) {
|
||||
showToast('Error', err.messages?.[0] || err, 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -86,9 +86,9 @@ import {
|
||||
ListRows,
|
||||
ListView,
|
||||
ListRowItem,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { Plus, Trash2 } from 'lucide-vue-next'
|
||||
import { showToast } from '@/utils'
|
||||
const readOnlyMode = window.read_only_mode
|
||||
|
||||
const showCourseModal = ref(false)
|
||||
@@ -152,7 +152,7 @@ const removeCourses = (selections, unselectAll) => {
|
||||
{
|
||||
onSuccess(data) {
|
||||
courses.reload()
|
||||
showToast(__('Success'), __('Courses deleted successfully'), 'check')
|
||||
toast.success(__('Courses deleted successfully'))
|
||||
unselectAll()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
<div v-if="batch.data" class="border-2 rounded-md p-5 lg:w-72">
|
||||
<div
|
||||
v-if="batch.data.seat_count && seats_left > 0"
|
||||
class="text-xs bg-green-100 text-green-700 float-right px-2 py-0.5 rounded-md"
|
||||
class="text-sm bg-green-100 text-green-700 px-2 py-1 rounded-md"
|
||||
:class="
|
||||
batch.data.amount || batch.data.courses.length
|
||||
? 'float-right'
|
||||
: 'w-fit mb-4'
|
||||
"
|
||||
>
|
||||
{{ seats_left }}
|
||||
<span v-if="seats_left > 1">
|
||||
@@ -117,9 +122,9 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import { inject, computed } from 'vue'
|
||||
import { Badge, Button, createResource } from 'frappe-ui'
|
||||
import { Badge, Button, createResource, toast } from 'frappe-ui'
|
||||
import { BookOpen, Clock, Globe } from 'lucide-vue-next'
|
||||
import { formatNumberIntoCurrency, formatTime, showToast } from '@/utils'
|
||||
import { formatNumberIntoCurrency, formatTime } from '@/utils'
|
||||
import DateRange from '@/components/Common/DateRange.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
@@ -151,11 +156,7 @@ const enrollInBatch = () => {
|
||||
{},
|
||||
{
|
||||
onSuccess(data) {
|
||||
showToast(
|
||||
__('Success'),
|
||||
__('You have been enrolled in this batch'),
|
||||
'check'
|
||||
)
|
||||
toast.success(__('You have been enrolled in this batch'))
|
||||
router.push({
|
||||
name: 'Batch',
|
||||
params: {
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<template>
|
||||
<div class="">
|
||||
<div v-if="batch.data" class="">
|
||||
<div class="w-full flex items-center justify-between pb-4">
|
||||
<div class="font-medium text-ink-gray-7">
|
||||
{{ __('Statistics') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 gap-5 mb-8">
|
||||
|
||||
<NumberChart
|
||||
class="border rounded-md"
|
||||
:config="{ title: __('Students'), value: students.data?.length || 0 }"
|
||||
@@ -14,7 +13,10 @@
|
||||
|
||||
<NumberChart
|
||||
class="border rounded-md"
|
||||
:config="{ title: __('Certified'), value: certificationCount.data || 0 }"
|
||||
:config="{
|
||||
title: __('Certified'),
|
||||
value: certificationCount.data || 0,
|
||||
}"
|
||||
/>
|
||||
|
||||
<NumberChart
|
||||
@@ -79,26 +81,26 @@
|
||||
product: 'HomePod',
|
||||
sales: 200,
|
||||
},
|
||||
],
|
||||
title: __('Batch Summary'),
|
||||
subtitle: __('Progress of students in courses and assessments'),
|
||||
xAxis: {
|
||||
key: 'product',
|
||||
title: 'Product',
|
||||
type: 'category',
|
||||
],
|
||||
title: __('Batch Summary'),
|
||||
subtitle: __('Progress of students in courses and assessments'),
|
||||
xAxis: {
|
||||
key: 'product',
|
||||
title: 'Product',
|
||||
type: 'category',
|
||||
},
|
||||
yAxis: {
|
||||
title: __('Number of Students'),
|
||||
},
|
||||
swapXY: true,
|
||||
series: [
|
||||
{
|
||||
name: 'sales',
|
||||
type: 'bar',
|
||||
},
|
||||
yAxis: {
|
||||
title: __('Number of Students'),
|
||||
},
|
||||
swapXY: true,
|
||||
series: [
|
||||
{
|
||||
name: 'sales',
|
||||
type: 'bar',
|
||||
},
|
||||
],
|
||||
}"
|
||||
/>
|
||||
],
|
||||
}"
|
||||
/>
|
||||
|
||||
<div v-if="showProgressChart" class="mb-8">
|
||||
<div class="text-ink-gray-7 font-medium">
|
||||
@@ -231,9 +233,10 @@
|
||||
</div>
|
||||
|
||||
<StudentModal
|
||||
:batch="props.batch.name"
|
||||
:batch="props.batch.data.name"
|
||||
v-model="showStudentModal"
|
||||
v-model:reloadStudents="students"
|
||||
v-model:batchModal="props.batch"
|
||||
/>
|
||||
<BatchStudentProgress
|
||||
:student="selectedStudent"
|
||||
@@ -255,6 +258,7 @@ import {
|
||||
ListView,
|
||||
ListRowItem,
|
||||
NumberChart,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import {
|
||||
BookOpen,
|
||||
@@ -266,7 +270,6 @@ import {
|
||||
} from 'lucide-vue-next'
|
||||
import { ref, watch } from 'vue'
|
||||
import StudentModal from '@/components/Modals/StudentModal.vue'
|
||||
import { showToast } from '@/utils'
|
||||
import ProgressBar from '@/components/ProgressBar.vue'
|
||||
import BatchStudentProgress from '@/components/Modals/BatchStudentProgress.vue'
|
||||
import ApexChart from 'vue3-apexcharts'
|
||||
@@ -290,15 +293,15 @@ const props = defineProps({
|
||||
|
||||
const students = createResource({
|
||||
url: 'lms.lms.utils.get_batch_students',
|
||||
cache: ['students', props.batch.name],
|
||||
params: {
|
||||
batch: props.batch?.name,
|
||||
batch: props.batch?.data?.name,
|
||||
},
|
||||
auto: true,
|
||||
onSuccess(data) {
|
||||
chartData.value = getChartData()
|
||||
showProgressChart.value =
|
||||
data.length && (props.batch?.courses?.length || assessmentCount.value)
|
||||
data.length &&
|
||||
(props.batch?.data?.courses?.length || assessmentCount.value)
|
||||
},
|
||||
})
|
||||
|
||||
@@ -355,7 +358,8 @@ const removeStudents = (selections, unselectAll) => {
|
||||
{
|
||||
onSuccess(data) {
|
||||
students.reload()
|
||||
showToast(__('Success'), __('Students deleted successfully'), 'check')
|
||||
props.batch.reload()
|
||||
toast.success(__('Students deleted successfully'))
|
||||
unselectAll()
|
||||
},
|
||||
}
|
||||
@@ -366,10 +370,8 @@ const getChartData = () => {
|
||||
let data = []
|
||||
console.log(students.data)
|
||||
|
||||
students.data.forEach(row => {
|
||||
row.assessments.forEach(assessment => {
|
||||
|
||||
})
|
||||
students.data.forEach((row) => {
|
||||
row.assessments.forEach((assessment) => {})
|
||||
})
|
||||
|
||||
/* let categories = {}
|
||||
@@ -476,7 +478,7 @@ const certificationCount = createResource({
|
||||
params: {
|
||||
doctype: 'LMS Certificate',
|
||||
filters: {
|
||||
batch_name: props.batch.name,
|
||||
batch_name: props.batch?.data?.name,
|
||||
},
|
||||
},
|
||||
auto: true,
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
{{ label }}
|
||||
</div>
|
||||
<Button @click="() => showCategoryForm()">
|
||||
<template #icon>
|
||||
<template #prefix>
|
||||
<Plus v-if="!showForm" class="h-3 w-3 stroke-1.5" />
|
||||
<X v-else class="h-3 w-3 stroke-1.5" />
|
||||
</template>
|
||||
{{ showForm ? __('Close') : __('New') }}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -28,12 +29,11 @@
|
||||
</div>
|
||||
|
||||
<div class="overflow-y-scroll">
|
||||
<div class="text-base divide-y space-y-2">
|
||||
<div class="text-base space-y-2">
|
||||
<FormControl
|
||||
:value="cat.category"
|
||||
type="text"
|
||||
v-for="cat in categories.data"
|
||||
class=""
|
||||
@change.stop="(e) => update(cat.name, e.target.value)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -92,7 +92,10 @@
|
||||
{{ option.label }}
|
||||
</div>
|
||||
<div
|
||||
v-if="option.description"
|
||||
v-if="
|
||||
option.description &&
|
||||
option.description != option.label
|
||||
"
|
||||
class="text-xs text-ink-gray-7"
|
||||
v-html="option.description"
|
||||
></div>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<Button
|
||||
variant="ghost"
|
||||
class="w-full !justify-start"
|
||||
label="Create New"
|
||||
:label="__('Create New')"
|
||||
@click="attrs.onCreate(value, close)"
|
||||
>
|
||||
<template #prefix>
|
||||
|
||||
@@ -4,78 +4,91 @@
|
||||
{{ label }}
|
||||
<span class="text-ink-red-3" v-if="required">*</span>
|
||||
</label>
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
<Button
|
||||
ref="emails"
|
||||
v-for="value in values"
|
||||
:key="value"
|
||||
:label="value"
|
||||
theme="gray"
|
||||
variant="subtle"
|
||||
class="rounded-md word-break-all"
|
||||
@keydown.delete.capture.stop="removeLastValue"
|
||||
>
|
||||
<template #suffix>
|
||||
<X @click="removeValue(value)" class="h-4 w-4 stroke-1.5" />
|
||||
</template>
|
||||
</Button>
|
||||
<div class="">
|
||||
<Combobox v-model="selectedValue" nullable>
|
||||
<Popover class="w-full" v-model:show="showOptions">
|
||||
<template #target="{ togglePopover }">
|
||||
<ComboboxInput
|
||||
ref="search"
|
||||
class="search-input form-input w-full focus-visible:!ring-0"
|
||||
type="text"
|
||||
:value="query"
|
||||
@change="
|
||||
(e) => {
|
||||
query = e.target.value
|
||||
showOptions = true
|
||||
}
|
||||
"
|
||||
autocomplete="off"
|
||||
@focus="() => togglePopover()"
|
||||
@keydown.delete.capture.stop="removeLastValue"
|
||||
/>
|
||||
</template>
|
||||
<template #body="{ isOpen }">
|
||||
<div v-show="isOpen">
|
||||
<div
|
||||
class="mt-1 rounded-lg bg-surface-white py-1 text-base border-2"
|
||||
<div class="w-full">
|
||||
<Combobox v-model="selectedValue" nullable>
|
||||
<Popover class="w-full" v-model:show="showOptions">
|
||||
<template #target="{ togglePopover }">
|
||||
<ComboboxInput
|
||||
ref="search"
|
||||
class="search-input form-input w-full focus-visible:!ring-0"
|
||||
type="text"
|
||||
:value="query"
|
||||
@change="
|
||||
(e) => {
|
||||
query = e.target.value
|
||||
showOptions = true
|
||||
}
|
||||
"
|
||||
autocomplete="off"
|
||||
@focus="() => togglePopover()"
|
||||
@keydown.delete.capture.stop="removeLastValue"
|
||||
/>
|
||||
</template>
|
||||
<template #body="{ isOpen, close }">
|
||||
<div v-show="isOpen">
|
||||
<div
|
||||
class="mt-1 rounded-lg bg-surface-white py-1 text-base border-2"
|
||||
>
|
||||
<ComboboxOptions
|
||||
class="my-1 min-h-[6rem] max-h-[12rem] overflow-y-auto px-1.5"
|
||||
static
|
||||
>
|
||||
<ComboboxOptions
|
||||
class="my-1 max-h-[12rem] overflow-y-auto px-1.5"
|
||||
static
|
||||
<ComboboxOption
|
||||
v-for="option in options"
|
||||
:key="option.value"
|
||||
:value="option"
|
||||
v-slot="{ active }"
|
||||
>
|
||||
<ComboboxOption
|
||||
v-for="option in options"
|
||||
:key="option.value"
|
||||
:value="option"
|
||||
v-slot="{ active }"
|
||||
<li
|
||||
:class="[
|
||||
'flex cursor-pointer items-center rounded px-2 py-1 text-base',
|
||||
{ 'bg-surface-gray-2': active },
|
||||
]"
|
||||
>
|
||||
<li
|
||||
:class="[
|
||||
'flex cursor-pointer items-center rounded px-2 py-1 text-base',
|
||||
{ 'bg-surface-gray-2': active },
|
||||
]"
|
||||
>
|
||||
<div class="flex flex-col gap-1 p-1">
|
||||
<div class="text-base font-medium text-ink-gray-8">
|
||||
{{ option.description }}
|
||||
</div>
|
||||
<div class="text-sm text-ink-gray-5">
|
||||
{{ option.value }}
|
||||
</div>
|
||||
<div class="flex flex-col gap-1 p-1">
|
||||
<div class="text-base font-medium text-ink-gray-8">
|
||||
{{ option.description }}
|
||||
</div>
|
||||
</li>
|
||||
</ComboboxOption>
|
||||
</ComboboxOptions>
|
||||
</div>
|
||||
<div class="text-sm text-ink-gray-5">
|
||||
{{ option.value }}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ComboboxOption>
|
||||
<div
|
||||
v-if="attrs.onCreate"
|
||||
class="absolute bottom-2 left-1 w-[98%] pt-2 bg-white border-t"
|
||||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
class="w-full !justify-start"
|
||||
:label="__('Create New')"
|
||||
@click="attrs.onCreate(close)"
|
||||
>
|
||||
<template #prefix>
|
||||
<Plus class="h-4 w-4 stroke-1.5" />
|
||||
</template>
|
||||
</Button>
|
||||
</div>
|
||||
</ComboboxOptions>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</Combobox>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</Combobox>
|
||||
</div>
|
||||
<div v-if="values.length" class="grid grid-cols-2 gap-2 mt-1">
|
||||
<div
|
||||
v-for="value in values"
|
||||
class="flex items-center justify-between break-all bg-surface-gray-2 text-ink-gray-7 word-wrap p-2 rounded-md mr-2"
|
||||
>
|
||||
<span class="break-all">
|
||||
{{ value }}
|
||||
</span>
|
||||
<X
|
||||
class="size-4 stroke-1.5 cursor-pointer"
|
||||
@click="removeValue(value)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <ErrorMessage class="mt-2 pl-2" v-if="error" :message="error" /> -->
|
||||
@@ -90,9 +103,9 @@ import {
|
||||
ComboboxOption,
|
||||
} from '@headlessui/vue'
|
||||
import { createResource, Popover, Button } from 'frappe-ui'
|
||||
import { ref, computed, nextTick } from 'vue'
|
||||
import { ref, computed, nextTick, useAttrs } from 'vue'
|
||||
import { watchDebounced } from '@vueuse/core'
|
||||
import { X } from 'lucide-vue-next'
|
||||
import { X, Plus } from 'lucide-vue-next'
|
||||
|
||||
const props = defineProps({
|
||||
label: {
|
||||
@@ -124,7 +137,7 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const values = defineModel()
|
||||
|
||||
const attrs = useAttrs()
|
||||
const emails = ref([])
|
||||
const search = ref(null)
|
||||
const error = ref(null)
|
||||
|
||||
@@ -146,8 +146,8 @@
|
||||
<script setup>
|
||||
import { BookOpen, Users, Star, GraduationCap } from 'lucide-vue-next'
|
||||
import { computed, inject } from 'vue'
|
||||
import { Badge, Button, createResource } from 'frappe-ui'
|
||||
import { showToast, formatAmount } from '@/utils/'
|
||||
import { Badge, Button, createResource, toast } from 'frappe-ui'
|
||||
import { formatAmount } from '@/utils/'
|
||||
import { capture } from '@/telemetry'
|
||||
import { useRouter } from 'vue-router'
|
||||
import CertificationLinks from '@/components/CertificationLinks.vue'
|
||||
@@ -172,11 +172,7 @@ const video_link = computed(() => {
|
||||
|
||||
function enrollStudent() {
|
||||
if (!user.data) {
|
||||
showToast(
|
||||
__('Please Login'),
|
||||
__('You need to login first to enroll for this course'),
|
||||
'alert-circle'
|
||||
)
|
||||
toast.success(__('You need to login first to enroll for this course'))
|
||||
setTimeout(() => {
|
||||
window.location.href = `/login?redirect-to=${window.location.pathname}`
|
||||
}, 1000)
|
||||
@@ -192,11 +188,7 @@ function enrollStudent() {
|
||||
capture('enrolled_in_course', {
|
||||
course: props.course.data.name,
|
||||
})
|
||||
showToast(
|
||||
__('Success'),
|
||||
__('You have been enrolled in this course'),
|
||||
'check'
|
||||
)
|
||||
toast.success(__('You have been enrolled in this course'))
|
||||
setTimeout(() => {
|
||||
router.push({
|
||||
name: 'Lesson',
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Button, createResource, Tooltip } from 'frappe-ui'
|
||||
import { Button, createResource, Tooltip, toast } from 'frappe-ui'
|
||||
import { getCurrentInstance, inject, ref } from 'vue'
|
||||
import Draggable from 'vuedraggable'
|
||||
import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/vue'
|
||||
@@ -162,7 +162,6 @@ import {
|
||||
} from 'lucide-vue-next'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import ChapterModal from '@/components/Modals/ChapterModal.vue'
|
||||
import { showToast } from '@/utils'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -215,7 +214,7 @@ const deleteLesson = createResource({
|
||||
},
|
||||
onSuccess() {
|
||||
outline.reload()
|
||||
showToast('Success', 'Lesson deleted successfully', 'check')
|
||||
toast.success(__('Lesson deleted successfully'))
|
||||
},
|
||||
})
|
||||
|
||||
@@ -230,7 +229,7 @@ const updateLessonIndex = createResource({
|
||||
}
|
||||
},
|
||||
onSuccess() {
|
||||
showToast('Success', 'Lesson moved successfully', 'check')
|
||||
toast.success(__('Lesson moved successfully'))
|
||||
},
|
||||
})
|
||||
|
||||
@@ -288,7 +287,7 @@ const deleteChapter = createResource({
|
||||
},
|
||||
onSuccess() {
|
||||
outline.reload()
|
||||
showToast('Success', 'Chapter deleted successfully', 'check')
|
||||
toast.success(__('Chapter deleted successfully'))
|
||||
},
|
||||
})
|
||||
|
||||
@@ -317,11 +316,7 @@ const redirectToChapter = (chapter) => {
|
||||
event.preventDefault()
|
||||
if (props.allowEdit) return
|
||||
if (!user.data) {
|
||||
showToast(
|
||||
__('You are not enrolled'),
|
||||
__('Please enroll for this course to view this lesson'),
|
||||
'alert-circle'
|
||||
)
|
||||
toast.success(__('Please enroll for this course to view this lesson'))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -93,12 +93,11 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { createResource, TextEditor, Button, Dropdown } from 'frappe-ui'
|
||||
import { createResource, TextEditor, Button, Dropdown, toast } from 'frappe-ui'
|
||||
import { timeAgo } from '../utils'
|
||||
import UserAvatar from '@/components/UserAvatar.vue'
|
||||
import { ChevronLeft, MoreHorizontal } from 'lucide-vue-next'
|
||||
import { ref, inject, onMounted } from 'vue'
|
||||
import { createToast } from '../utils'
|
||||
|
||||
const showTopics = defineModel('showTopics')
|
||||
const newReply = ref('')
|
||||
@@ -192,14 +191,7 @@ const postReply = () => {
|
||||
replies.reload()
|
||||
},
|
||||
onError(err) {
|
||||
createToast({
|
||||
title: 'Error',
|
||||
text: err.messages?.[0] || err,
|
||||
icon: 'x',
|
||||
iconClasses: 'bg-surface-red-5 text-ink-white rounded-md p-px',
|
||||
position: 'top-center',
|
||||
timeout: 10,
|
||||
})
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
24
frontend/src/components/EmptyState.vue
Normal file
24
frontend/src/components/EmptyState.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div class="flex flex-col items-center justify-center mt-60">
|
||||
<GraduationCap class="size-10 mx-auto stroke-1 text-ink-gray-5" />
|
||||
<div class="text-lg font-semibold text-ink-gray-7 mb-2.5">
|
||||
{{ __('No {0}').format(type?.toLowerCase()) }}
|
||||
</div>
|
||||
<div
|
||||
class="leading-5 text-base w-2/5 text-base text-center text-ink-gray-7"
|
||||
>
|
||||
{{
|
||||
__(
|
||||
'There are no {0} currently. Keep an eye out, fresh learning experiences are on the way!'
|
||||
).format(type?.toLowerCase())
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { BookOpen, GraduationCap } from 'lucide-vue-next'
|
||||
|
||||
const props = defineProps({
|
||||
type: String,
|
||||
})
|
||||
</script>
|
||||
@@ -17,10 +17,11 @@
|
||||
:debounce="300"
|
||||
/>
|
||||
<Button @click="() => (showForm = !showForm)">
|
||||
<template #icon>
|
||||
<Plus v-if="!showForm" class="h-3 w-3 stroke-1.5" />
|
||||
<X v-else class="h-3 w-3 stroke-1.5" />
|
||||
<template #prefix>
|
||||
<Plus v-if="!showForm" class="size-4 stroke-1.5" />
|
||||
<X v-else class="size-4 stroke-1.5" />
|
||||
</template>
|
||||
{{ showForm ? __('Close') : __('New') }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
:debounce="300"
|
||||
/>
|
||||
<Button @click="() => (showForm = !showForm)">
|
||||
<template #icon>
|
||||
<Plus v-if="!showForm" class="h-3 w-3 stroke-1.5" />
|
||||
<X v-else class="h-3 w-3 stroke-1.5" />
|
||||
<template #prefix>
|
||||
<Plus v-if="!showForm" class="size-4 stroke-1.5" />
|
||||
<X v-else class="size-4 stroke-1.5" />
|
||||
</template>
|
||||
{{ showForm ? __('Close') : __('New') }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
<div class="mb-4">
|
||||
<div class="mb-1.5 text-sm text-ink-gray-5">
|
||||
{{ __('Announcement') }}
|
||||
<span class="text-ink-red-3">*</span>
|
||||
</div>
|
||||
<TextEditor
|
||||
:fixedMenu="true"
|
||||
@@ -43,9 +44,8 @@
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Dialog, Input, TextEditor, createResource } from 'frappe-ui'
|
||||
import { Dialog, Input, TextEditor, createResource, toast } from 'frappe-ui'
|
||||
import { reactive } from 'vue'
|
||||
import { showToast } from '@/utils/'
|
||||
|
||||
const show = defineModel()
|
||||
|
||||
@@ -87,22 +87,21 @@ const makeAnnouncement = (close) => {
|
||||
{
|
||||
validate() {
|
||||
if (!props.students.length) {
|
||||
return 'No students in this batch'
|
||||
return __('No students in this batch')
|
||||
}
|
||||
if (!announcement.subject) {
|
||||
return 'Subject is required'
|
||||
return __('Subject is required')
|
||||
}
|
||||
if (!announcement.announcement) {
|
||||
return __('Announcement is required')
|
||||
}
|
||||
},
|
||||
onSuccess() {
|
||||
close()
|
||||
showToast(
|
||||
__('Success'),
|
||||
__('Announcement has been sent successfully'),
|
||||
'check'
|
||||
)
|
||||
toast.success(__('Announcement has been sent successfully'))
|
||||
},
|
||||
onError(err) {
|
||||
showToast(__('Error'), __(err.messages?.[0] || err), 'alert-circle')
|
||||
toast.error(__(err.messages?.[0] || err))
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -25,21 +25,39 @@
|
||||
v-model="assessment"
|
||||
:doctype="assessmentType"
|
||||
:label="__('Assessment')"
|
||||
:onCreate="
|
||||
(value, close) => {
|
||||
close()
|
||||
if (assessmentType === 'LMS Quiz') {
|
||||
router.push({
|
||||
name: 'QuizForm',
|
||||
params: {
|
||||
quizID: 'new',
|
||||
},
|
||||
})
|
||||
} else if (assessmentType === 'LMS Assignment') {
|
||||
router.push({
|
||||
name: 'Assignments',
|
||||
})
|
||||
}
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Dialog, FormControl, createResource } from 'frappe-ui'
|
||||
import { Dialog, FormControl, createResource, toast } from 'frappe-ui'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { showToast } from '@/utils'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const show = defineModel()
|
||||
const assessmentType = ref(null)
|
||||
const assessment = ref(null)
|
||||
const assessments = defineModel('assessments')
|
||||
const router = useRouter()
|
||||
|
||||
const props = defineProps({
|
||||
batch: {
|
||||
@@ -70,7 +88,7 @@ const addAssessment = (close) => {
|
||||
{
|
||||
onSuccess(data) {
|
||||
assessments.value.reload()
|
||||
showToast(__('Success'), __('Assessment added successfully'), 'check')
|
||||
toast.success(__('Assessment added successfully'))
|
||||
close()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
@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]"
|
||||
editorClass="prose-sm max-w-none border-b border-x bg-surface-gray-2 rounded-b-md py-1 px-2 min-h-[7rem] max-h-[18rem] overflow-y-auto"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -64,9 +64,8 @@
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { Button, Dialog, FormControl, TextEditor } from 'frappe-ui'
|
||||
import { Button, Dialog, FormControl, TextEditor, toast } from 'frappe-ui'
|
||||
import { computed, reactive, watch } from 'vue'
|
||||
import { showToast } from '@/utils'
|
||||
|
||||
const show = defineModel()
|
||||
const assignments = defineModel<Assignments>('assignments')
|
||||
@@ -123,11 +122,7 @@ const saveAssignment = () => {
|
||||
{
|
||||
onSuccess() {
|
||||
show.value = false
|
||||
showToast(
|
||||
__('Success'),
|
||||
__('Assignment created successfully'),
|
||||
'check'
|
||||
)
|
||||
toast.success(__('Assignment created successfully'))
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -140,11 +135,7 @@ const saveAssignment = () => {
|
||||
{
|
||||
onSuccess() {
|
||||
show.value = false
|
||||
showToast(
|
||||
__('Success'),
|
||||
__('Assignment updated successfully'),
|
||||
'check'
|
||||
)
|
||||
toast.success(__('Assignment updated successfully'))
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -19,32 +19,43 @@
|
||||
v-model="course"
|
||||
:label="__('Course')"
|
||||
:required="true"
|
||||
:onCreate="
|
||||
(value, close) => {
|
||||
close()
|
||||
router.push({
|
||||
name: 'CourseForm',
|
||||
params: {
|
||||
courseName: 'new',
|
||||
},
|
||||
})
|
||||
}
|
||||
"
|
||||
/>
|
||||
<Link
|
||||
doctype="Course Evaluator"
|
||||
v-model="evaluator"
|
||||
:label="__('Evaluator')"
|
||||
:onCreate="(value, close) => openSettings(close)"
|
||||
:onCreate="(value, close) => openSettings('Evaluators', close)"
|
||||
class="mt-4"
|
||||
/>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Dialog, createResource } from 'frappe-ui'
|
||||
import { Dialog, createResource, toast } from 'frappe-ui'
|
||||
import { ref, inject } from 'vue'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import { showToast } from '@/utils'
|
||||
import { useOnboarding } from 'frappe-ui/frappe'
|
||||
import { useSettings } from '@/stores/settings'
|
||||
import { openSettings } from '@/utils'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const show = defineModel()
|
||||
const course = ref(null)
|
||||
const evaluator = ref(null)
|
||||
const user = inject('$user')
|
||||
const courses = defineModel('courses')
|
||||
const router = useRouter()
|
||||
const { updateOnboardingStep } = useOnboarding('learning')
|
||||
const settingsStore = useSettings()
|
||||
|
||||
const props = defineProps({
|
||||
batch: {
|
||||
@@ -83,15 +94,9 @@ const addCourse = (close) => {
|
||||
evaluator.value = null
|
||||
},
|
||||
onError(err) {
|
||||
showToast('Error', err.message[0] || err, 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const openSettings = (close) => {
|
||||
close()
|
||||
settingsStore.activeTab = 'Evaluators'
|
||||
settingsStore.isSettingsOpen = true
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -14,7 +14,13 @@
|
||||
<div class="text-xl font-semibold">
|
||||
{{ student.full_name }}
|
||||
</div>
|
||||
<Badge :theme="student.progress === 100 ? 'green' : 'red'">
|
||||
<Badge
|
||||
v-if="
|
||||
Object.keys(student.assessments).length ||
|
||||
Object.keys(student.courses).length
|
||||
"
|
||||
:theme="student.progress === 100 ? 'green' : 'red'"
|
||||
>
|
||||
{{ student.progress }}% {{ __('Complete') }}
|
||||
</Badge>
|
||||
</div>
|
||||
@@ -26,7 +32,10 @@
|
||||
|
||||
<div class="space-y-8">
|
||||
<!-- Assessments -->
|
||||
<div class="space-y-2 text-sm">
|
||||
<div
|
||||
v-if="Object.keys(student.assessments).length"
|
||||
class="space-y-2 text-sm"
|
||||
>
|
||||
<div class="flex items-center border-b pb-1 font-medium">
|
||||
<span class="flex-1">
|
||||
{{ __('Assessment') }}
|
||||
@@ -73,7 +82,10 @@
|
||||
</div>
|
||||
|
||||
<!-- Courses -->
|
||||
<div class="space-y-2 text-sm">
|
||||
<div
|
||||
v-if="Object.keys(student.courses).length"
|
||||
class="space-y-2 text-sm"
|
||||
>
|
||||
<div class="flex items-center border-b pb-1 font-medium">
|
||||
<span class="flex-1">
|
||||
{{ __('Courses') }}
|
||||
|
||||
@@ -62,9 +62,8 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import { inject, reactive } from 'vue'
|
||||
import { createResource, Dialog, FormControl, Switch } from 'frappe-ui'
|
||||
import { createResource, Dialog, FormControl, Switch, toast } from 'frappe-ui'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import { showToast } from '@/utils'
|
||||
|
||||
const show = defineModel()
|
||||
const dayjs = inject('$dayjs')
|
||||
@@ -112,13 +111,13 @@ const generateCertificates = (close) => {
|
||||
},
|
||||
{
|
||||
onError(err) {
|
||||
showToast(__('Error'), err.messages?.[0] || err, 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
close()
|
||||
showToast(__('Success'), __('Certificates generated successfully'), 'check')
|
||||
toast.success(__('Certificates generated successfully'))
|
||||
}
|
||||
|
||||
const getCourses = () => {
|
||||
|
||||
@@ -76,9 +76,10 @@ import {
|
||||
FileUploader,
|
||||
FormControl,
|
||||
Switch,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { reactive, watch, inject } from 'vue'
|
||||
import { showToast, getFileSize } from '@/utils/'
|
||||
import { getFileSize } from '@/utils/'
|
||||
import { capture } from '@/telemetry'
|
||||
import { FileText, X } from 'lucide-vue-next'
|
||||
import { useOnboarding } from 'frappe-ui/frappe'
|
||||
@@ -150,21 +151,17 @@ const addChapter = async (close) => {
|
||||
onSuccess(data) {
|
||||
cleanChapter()
|
||||
outline.value.reload()
|
||||
showToast(
|
||||
__('Success'),
|
||||
__('Chapter added successfully'),
|
||||
'check'
|
||||
)
|
||||
toast.success(__('Chapter added successfully'))
|
||||
},
|
||||
onError(err) {
|
||||
showToast(__('Error'), err.messages?.[0] || err, 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
close()
|
||||
},
|
||||
onError(err) {
|
||||
showToast(__('Error'), err.messages?.[0] || err, 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -196,11 +193,11 @@ const editChapter = (close) => {
|
||||
},
|
||||
onSuccess() {
|
||||
outline.value.reload()
|
||||
showToast(__('Success'), __('Chapter updated successfully'), 'check')
|
||||
toast.success(__('Chapter updated successfully'))
|
||||
close()
|
||||
},
|
||||
onError(err) {
|
||||
showToast(__('Error'), err.messages?.[0] || err, 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -34,9 +34,15 @@
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Dialog, FormControl, TextEditor, createResource } from 'frappe-ui'
|
||||
import {
|
||||
Dialog,
|
||||
FormControl,
|
||||
TextEditor,
|
||||
createResource,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { reactive } from 'vue'
|
||||
import { showToast, singularize } from '@/utils'
|
||||
import { singularize } from '@/utils'
|
||||
|
||||
const topics = defineModel('reloadTopics')
|
||||
|
||||
@@ -115,7 +121,7 @@ const submitTopic = (close) => {
|
||||
)
|
||||
},
|
||||
onError(err) {
|
||||
showToast('Error', err.message, 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -93,10 +93,11 @@ import {
|
||||
Button,
|
||||
createResource,
|
||||
TextEditor,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { reactive, watch } from 'vue'
|
||||
import { FileText, X } from 'lucide-vue-next'
|
||||
import { getFileSize, showToast, escapeHTML } from '@/utils'
|
||||
import { getFileSize, escapeHTML } from '@/utils'
|
||||
|
||||
const reloadProfile = defineModel('reloadProfile')
|
||||
|
||||
@@ -155,7 +156,7 @@ const saveProfile = (close) => {
|
||||
reloadProfile.value.reload()
|
||||
},
|
||||
onError(err) {
|
||||
showToast('Error', err.messages?.[0] || err, 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
<script setup>
|
||||
import { Dialog, createResource, Select, FormControl } from 'frappe-ui'
|
||||
import { reactive, watch, inject } from 'vue'
|
||||
import { createToast, formatTime } from '@/utils/'
|
||||
import { formatTime } from '@/utils/'
|
||||
|
||||
const user = inject('$user')
|
||||
const dayjs = inject('$dayjs')
|
||||
@@ -148,14 +148,7 @@ function submitEvaluation(close) {
|
||||
unavailabilityMessage = false
|
||||
}
|
||||
|
||||
createToast({
|
||||
title: unavailabilityMessage ? __('Evaluator is Unavailable') : '',
|
||||
text: message,
|
||||
icon: unavailabilityMessage ? 'alert-circle' : 'x',
|
||||
iconClasses: 'bg-yellow-600 text-ink-white rounded-md p-px',
|
||||
position: 'top-center',
|
||||
timeout: 10,
|
||||
})
|
||||
toast.warning(__('Evaluator is unavailable'))
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -144,6 +144,7 @@ import {
|
||||
Tabs,
|
||||
Tooltip,
|
||||
Textarea,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import {
|
||||
User,
|
||||
@@ -157,7 +158,7 @@ import {
|
||||
ClipboardList,
|
||||
} from 'lucide-vue-next'
|
||||
import { inject, reactive, watch, ref, computed } from 'vue'
|
||||
import { formatTime, showToast } from '@/utils'
|
||||
import { formatTime } from '@/utils'
|
||||
import Rating from '@/components/Controls/Rating.vue'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
|
||||
@@ -252,7 +253,7 @@ const saveEvaluation = () => {
|
||||
} else {
|
||||
show.value = false
|
||||
}
|
||||
showToast(__('Success'), __('Evaluation saved successfully'), 'check')
|
||||
toast.success(__('Evaluation saved successfully'))
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -307,7 +308,7 @@ const saveCertificate = () => {
|
||||
{},
|
||||
{
|
||||
onSuccess: () => {
|
||||
showToast(__('Success'), __('Certificate saved successfully'), 'check')
|
||||
toast.success(__('Certificate saved successfully'))
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -64,10 +64,10 @@
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Dialog, FileUploader, Button, createResource } from 'frappe-ui'
|
||||
import { Dialog, FileUploader, Button, createResource, toast } from 'frappe-ui'
|
||||
import { FileText } from 'lucide-vue-next'
|
||||
import { ref, inject } from 'vue'
|
||||
import { createToast, getFileSize } from '@/utils/'
|
||||
import { getFileSize } from '@/utils/'
|
||||
|
||||
const resume = ref(null)
|
||||
const show = defineModel()
|
||||
@@ -112,24 +112,12 @@ const submitResume = (close) => {
|
||||
}
|
||||
},
|
||||
onSuccess() {
|
||||
createToast({
|
||||
title: 'Success',
|
||||
text: 'Your application has been submitted',
|
||||
icon: 'check',
|
||||
iconClasses: 'bg-surface-green-3 text-ink-white rounded-md p-px',
|
||||
})
|
||||
toast.success('Your application has been submitted successfully')
|
||||
application.value.reload()
|
||||
close()
|
||||
},
|
||||
onError(err) {
|
||||
createToast({
|
||||
title: 'Error',
|
||||
text: err.messages?.[0] || err,
|
||||
icon: 'x',
|
||||
iconClasses: 'bg-surface-red-5 text-ink-white rounded-md p-px',
|
||||
position: 'top-center',
|
||||
timeout: 10,
|
||||
})
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -94,9 +94,10 @@ import {
|
||||
Tooltip,
|
||||
FormControl,
|
||||
Autocomplete,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { reactive, inject, onMounted } from 'vue'
|
||||
import { getTimezones, createToast, getUserTimezone } from '@/utils/'
|
||||
import { getTimezones, getUserTimezone } from '@/utils/'
|
||||
|
||||
const liveClasses = defineModel('reloadLiveClasses')
|
||||
const show = defineModel()
|
||||
@@ -202,14 +203,7 @@ const submitLiveClass = (close) => {
|
||||
close()
|
||||
},
|
||||
onError(err) {
|
||||
createToast({
|
||||
title: 'Error',
|
||||
text: err.messages?.[0] || err,
|
||||
icon: 'x',
|
||||
iconClasses: 'bg-surface-red-5 text-ink-white rounded-md p-px',
|
||||
position: 'top-center',
|
||||
timeout: 10,
|
||||
})
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -30,11 +30,10 @@
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Dialog, createResource } from 'frappe-ui'
|
||||
import { Dialog, createResource, toast } from 'frappe-ui'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import { reactive, watch } from 'vue'
|
||||
import IconPicker from '@/components/Controls/IconPicker.vue'
|
||||
import { showToast } from '@/utils'
|
||||
|
||||
const sidebar = defineModel('reloadSidebar')
|
||||
const show = defineModel()
|
||||
@@ -78,10 +77,10 @@ const addWebPage = (close) => {
|
||||
onSuccess() {
|
||||
sidebar.value.reload()
|
||||
close()
|
||||
showToast('Success', 'Web page added to sidebar', 'check')
|
||||
toast.success(__('Web page added to sidebar'))
|
||||
},
|
||||
onError(err) {
|
||||
showToast('Error', err.message[0] || err, 'x')
|
||||
toast.error(err.message[0] || err)
|
||||
close()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -121,10 +121,10 @@ import {
|
||||
createResource,
|
||||
Switch,
|
||||
Button,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { computed, watch, reactive, ref, inject } from 'vue'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import { showToast } from '@/utils'
|
||||
import { useOnboarding } from 'frappe-ui/frappe'
|
||||
|
||||
const show = defineModel()
|
||||
@@ -260,7 +260,7 @@ const addQuestion = () => {
|
||||
})
|
||||
},
|
||||
onError(err) {
|
||||
showToast(__('Error'), __(err.messages?.[0] || err), 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -278,12 +278,12 @@ const addQuestionRow = (question) => {
|
||||
updateOnboardingStep('create_first_quiz')
|
||||
|
||||
show.value = false
|
||||
showToast(__('Success'), __('Question added successfully'), 'check')
|
||||
toast.success(__('Question added successfully'))
|
||||
quiz.value.reload()
|
||||
show.value = false
|
||||
},
|
||||
onError(err) {
|
||||
showToast(__('Error'), __(err.messages?.[0] || err), 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
show.value = false
|
||||
},
|
||||
}
|
||||
@@ -328,18 +328,14 @@ const updateQuestion = () => {
|
||||
{
|
||||
onSuccess() {
|
||||
show.value = false
|
||||
showToast(
|
||||
__('Success'),
|
||||
__('Question updated successfully'),
|
||||
'check'
|
||||
)
|
||||
toast.success(__('Question updated successfully'))
|
||||
quiz.value.reload()
|
||||
},
|
||||
}
|
||||
)
|
||||
},
|
||||
onError(err) {
|
||||
showToast(__('Error'), __(err.messages?.[0] || err), 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -32,10 +32,9 @@
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Dialog, Textarea, createResource } from 'frappe-ui'
|
||||
import { Dialog, Textarea, createResource, toast } from 'frappe-ui'
|
||||
import { reactive } from 'vue'
|
||||
import Rating from '@/components/Controls/Rating.vue'
|
||||
import { createToast } from '@/utils/'
|
||||
|
||||
const show = defineModel()
|
||||
const reviews = defineModel('reloadReviews')
|
||||
@@ -78,11 +77,7 @@ function submitReview(close) {
|
||||
hasReviewed.value.reload()
|
||||
},
|
||||
onError(err) {
|
||||
createToast({
|
||||
text: err.messages?.[0] || err,
|
||||
icon: 'x',
|
||||
iconClasses: 'text-ink-red-4 bg-surface-red-4',
|
||||
})
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
})
|
||||
close()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Dialog v-model="show" :options="{ size: '4xl' }">
|
||||
<Dialog v-model="show" :options="{ size: '5xl' }">
|
||||
<template #body>
|
||||
<div class="flex h-[calc(100vh_-_8rem)]">
|
||||
<div class="flex w-52 shrink-0 flex-col bg-surface-gray-2 p-2">
|
||||
|
||||
@@ -19,19 +19,25 @@
|
||||
doctype="User"
|
||||
v-model="student"
|
||||
:filters="{ ignore_user_type: 1 }"
|
||||
:onCreate="
|
||||
(value, close) => {
|
||||
openSettings('Members', close)
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Dialog, createResource } from 'frappe-ui'
|
||||
import { Dialog, createResource, toast } from 'frappe-ui'
|
||||
import { ref, inject } from 'vue'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import { showToast } from '@/utils'
|
||||
import { useOnboarding } from 'frappe-ui/frappe'
|
||||
import { openSettings } from '@/utils'
|
||||
|
||||
const students = defineModel('reloadStudents')
|
||||
const batchModal = defineModel('batchModal')
|
||||
const student = ref()
|
||||
const user = inject('$user')
|
||||
const { updateOnboardingStep } = useOnboarding('learning')
|
||||
@@ -66,11 +72,12 @@ const addStudent = (close) => {
|
||||
updateOnboardingStep('add_batch_student')
|
||||
|
||||
students.value.reload()
|
||||
batchModal.value.reload()
|
||||
student.value = null
|
||||
close()
|
||||
},
|
||||
onError(err) {
|
||||
showToast(__('Error'), __(err.messages?.[0] || err), 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -291,9 +291,9 @@ import {
|
||||
ListView,
|
||||
TextEditor,
|
||||
FormControl,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { ref, watch, reactive, inject, computed } from 'vue'
|
||||
import { createToast, showToast } from '@/utils/'
|
||||
import { CheckCircle, XCircle, MinusCircle } from 'lucide-vue-next'
|
||||
import { timeAgo } from '@/utils'
|
||||
import { useRouter } from 'vue-router'
|
||||
@@ -494,12 +494,7 @@ const getAnswers = () => {
|
||||
const checkAnswer = () => {
|
||||
let answers = getAnswers()
|
||||
if (!answers.length) {
|
||||
createToast({
|
||||
title: 'Please select an option',
|
||||
icon: 'alert-circle',
|
||||
iconClasses: 'text-yellow-600 bg-yellow-100 rounded-full',
|
||||
position: 'top-center',
|
||||
})
|
||||
toast.warning(__('Please select an option'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -589,7 +584,7 @@ const createSubmission = () => {
|
||||
const errorTitle = err?.message || ''
|
||||
if (errorTitle.includes('MaximumAttemptsExceededError')) {
|
||||
const errorMessage = err.messages?.[0] || err
|
||||
showToast(__('Error'), __(errorMessage), 'x')
|
||||
toast.error(__(errorMessage))
|
||||
setTimeout(() => {
|
||||
window.location.reload()
|
||||
}, 3000)
|
||||
|
||||
@@ -27,9 +27,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Button, Badge } from 'frappe-ui'
|
||||
import { Button, Badge, toast } from 'frappe-ui'
|
||||
import SettingFields from '@/components/SettingFields.vue'
|
||||
import { showToast } from '@/utils'
|
||||
|
||||
const props = defineProps({
|
||||
fields: {
|
||||
@@ -61,7 +60,7 @@ const update = () => {
|
||||
{},
|
||||
{
|
||||
onError(err) {
|
||||
showToast(__('Error'), err.messages?.[0] || err, 'x')
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user