feat: upcoming evals
This commit is contained in:
@@ -12,7 +12,6 @@
|
||||
"frappe-ui": "^0.1.16",
|
||||
"lucide-vue-next": "^0.259.0",
|
||||
"pinia": "^2.0.33",
|
||||
"qalendar": "^3.6.1",
|
||||
"tailwindcss": "^3.2.7",
|
||||
"vue": "^3.2.25",
|
||||
"dayjs": "^1.11.6",
|
||||
|
||||
47
frontend/src/components/Assessments.vue
Normal file
47
frontend/src/components/Assessments.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-lg font-semibold mb-4">
|
||||
{{ __('Assessments') }}
|
||||
</div>
|
||||
<div v-if="assessments?.length">
|
||||
<ListView
|
||||
:columns="getAssessmentColumns()"
|
||||
:rows="attempts?.data"
|
||||
row-key="name"
|
||||
:options="{ selectable: false, showTooltip: false }"
|
||||
>
|
||||
</ListView>
|
||||
</div>
|
||||
<div v-else class="text-sm italic text-gray-600">
|
||||
{{ __('No Assessments') }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ListView } from 'frappe-ui'
|
||||
|
||||
const props = defineProps({
|
||||
assessments: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
})
|
||||
|
||||
const getSubmissionColumns = () => {
|
||||
return [
|
||||
{
|
||||
label: 'Assessment',
|
||||
key: 'title',
|
||||
},
|
||||
{
|
||||
label: 'Type',
|
||||
key: 'type',
|
||||
},
|
||||
{
|
||||
label: 'Status/Score',
|
||||
key: 'status',
|
||||
align: 'center',
|
||||
},
|
||||
]
|
||||
}
|
||||
</script>
|
||||
@@ -29,7 +29,7 @@
|
||||
</div>
|
||||
<div class="flex items-center mb-3">
|
||||
<BookOpen class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span> {{ batch.courses }} {{ __('Courses') }} </span>
|
||||
<span> {{ batch.courses.length }} {{ __('Courses') }} </span>
|
||||
</div>
|
||||
<div class="flex items-center mb-3">
|
||||
<Calendar class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
|
||||
17
frontend/src/components/BatchDashboard.vue
Normal file
17
frontend/src/components/BatchDashboard.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<UpcomingEvaluations :upcoming_evals="batch.data.upcoming_evals" />
|
||||
<Assessments :assessments="batch.data.assessments" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import UpcomingEvaluations from './UpcomingEvaluations.vue'
|
||||
import Assessments from './Assessments.vue'
|
||||
|
||||
const props = defineProps({
|
||||
batch: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
@@ -1,38 +1,38 @@
|
||||
<template>
|
||||
<div class="shadow rounded-md p-5" style="width: 300px">
|
||||
<div v-if="batch.data" class="shadow rounded-md p-5" style="width: 300px">
|
||||
<Badge
|
||||
v-if="batch.doc.seat_count && seats_left > 0"
|
||||
v-if="batch.data.seat_count && seats_left > 0"
|
||||
theme="green"
|
||||
class="self-start mb-2 float-right"
|
||||
>
|
||||
{{ seats_left }} {{ __('Seat Left') }}
|
||||
</Badge>
|
||||
<Badge
|
||||
v-else-if="batch.doc.seat_count && seats_left <= 0"
|
||||
v-else-if="batch.data.seat_count && seats_left <= 0"
|
||||
theme="red"
|
||||
class="self-start mb-2 float-right"
|
||||
>
|
||||
{{ __('Sold Out') }}
|
||||
</Badge>
|
||||
<div v-if="batch.doc.amount" class="text-lg font-semibold mb-3">
|
||||
{{ formatNumberIntoCurrency(batch.doc.amount, batch.doc.currency) }}
|
||||
<div v-if="batch.data.amount" class="text-lg font-semibold mb-3">
|
||||
{{ formatNumberIntoCurrency(batch.data.amount, batch.data.currency) }}
|
||||
</div>
|
||||
<div class="flex items-center mb-3">
|
||||
<BookOpen class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span> {{ batch.doc.courses.length }} {{ __('Courses') }} </span>
|
||||
<span> {{ batch.data.courses.length }} {{ __('Courses') }} </span>
|
||||
</div>
|
||||
<div class="flex items-center mb-3">
|
||||
<Calendar class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span>
|
||||
{{ dayjs(batch.doc.start_date).format('DD MMM YYYY') }} -
|
||||
{{ dayjs(batch.doc.end_date).format('DD MMM YYYY') }}
|
||||
{{ dayjs(batch.data.start_date).format('DD MMM YYYY') }} -
|
||||
{{ dayjs(batch.data.end_date).format('DD MMM YYYY') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<Clock class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span>
|
||||
{{ formatTime(batch.doc.start_time) }} -
|
||||
{{ formatTime(batch.doc.end_time) }}
|
||||
{{ formatTime(batch.data.start_time) }} -
|
||||
{{ formatTime(batch.data.end_time) }}
|
||||
</span>
|
||||
</div>
|
||||
<Button v-if="user?.data?.is_moderator" class="w-full mt-4">
|
||||
@@ -41,7 +41,7 @@
|
||||
</span>
|
||||
</Button>
|
||||
<Button
|
||||
v-else-if="batch.doc.paid_batch"
|
||||
v-else-if="batch.data.paid_batch"
|
||||
class="w-full mt-4"
|
||||
variant="solid"
|
||||
>
|
||||
@@ -73,8 +73,8 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const seats_left = computed(() => {
|
||||
if (props.batch.doc.seat_count) {
|
||||
return props.batch.doc.seat_count - props.batch.doc.students.length
|
||||
if (props.batch.data?.seat_count) {
|
||||
return props.batch.data?.seat_count - props.batch.data?.students?.length
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
@@ -114,35 +114,13 @@ import { Badge, createResource } from 'frappe-ui'
|
||||
import { ref, watchEffect } from 'vue'
|
||||
|
||||
const { user } = sessionStore()
|
||||
let course = ref({})
|
||||
|
||||
const props = defineProps({
|
||||
course: {
|
||||
type: [Object, String],
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
})
|
||||
|
||||
const courseDetails = createResource({
|
||||
url: 'lms.lms.utils.get_course_details',
|
||||
cache: ['course', props.courseName],
|
||||
makeParams() {
|
||||
return {
|
||||
course: props.course,
|
||||
}
|
||||
},
|
||||
transform(data) {
|
||||
course.value = data
|
||||
},
|
||||
})
|
||||
|
||||
/* watchEffect(() => {
|
||||
if (props.course && typeof props.course === "object") {
|
||||
course.value = props.course;
|
||||
} else {
|
||||
courseDetails.reload();
|
||||
}
|
||||
}); */
|
||||
</script>
|
||||
<style>
|
||||
.course-image {
|
||||
|
||||
53
frontend/src/components/UpcomingEvaluations.vue
Normal file
53
frontend/src/components/UpcomingEvaluations.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div class="mb-10">
|
||||
<div class="text-lg font-semibold mb-4">
|
||||
{{ __('Upcoming Evaluations') }}
|
||||
</div>
|
||||
<div v-if="upcoming_evals.length">
|
||||
<div class="grid grid-cols-2">
|
||||
<div v-for="evl in upcoming_evals">
|
||||
<div class="border rounded-md p-3">
|
||||
<div class="font-medium mb-3">
|
||||
{{ evl.course_title }}
|
||||
</div>
|
||||
<div class="flex items-center mb-2">
|
||||
<Calendar class="w-4 h-4 stroke-1.5" />
|
||||
<span class="ml-2">
|
||||
{{ dayjs(evl.date).format('DD MMMM YYYY') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center mb-2">
|
||||
<Clock class="w-4 h-4 stroke-1.5" />
|
||||
<span class="ml-2">
|
||||
{{ formatTime(evl.start_time) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<UserCog2 class="w-4 h-4 stroke-1.5" />
|
||||
<span class="ml-2">
|
||||
{{ evl.evaluator_name }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-sm italic text-gray-600">
|
||||
{{ __('No upcoming evaluations.') }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Calendar, Clock, UserCog2 } from 'lucide-vue-next'
|
||||
import { inject } from 'vue'
|
||||
import { formatTime } from '../utils'
|
||||
|
||||
const dayjs = inject('$dayjs')
|
||||
|
||||
const props = defineProps({
|
||||
upcoming_evals: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
})
|
||||
</script>
|
||||
@@ -1,44 +1,135 @@
|
||||
<template>
|
||||
<div class="h-screen text-base">
|
||||
<div v-if="user.data?.is_moderator || is_student" class="h-screen text-base">
|
||||
<header
|
||||
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
|
||||
>
|
||||
<Breadcrumbs class="h-7" :items="breadcrumbs" />
|
||||
</header>
|
||||
<div v-if="batch.doc">
|
||||
<div v-if="batch.data">
|
||||
<div class="grid grid-cols-[70%,30%] h-full">
|
||||
<div class="border-r-2"></div>
|
||||
<div class="border-r-2">
|
||||
<Tabs class="overflow-hidden" v-model="tabIndex" :tabs="tabs">
|
||||
<template #tab="{ tab, selected }">
|
||||
<div>
|
||||
<button
|
||||
class="group -mb-px flex items-center gap-1 border-b border-transparent py-2.5 text-base text-gray-600 duration-300 ease-in-out hover:border-gray-400 hover:text-gray-900"
|
||||
:class="{ 'text-gray-900': selected }"
|
||||
>
|
||||
<component
|
||||
v-if="tab.icon"
|
||||
:is="tab.icon"
|
||||
class="h-4 stroke-1.5"
|
||||
/>
|
||||
{{ __(tab.label) }}
|
||||
<Badge
|
||||
v-if="tab.count"
|
||||
:class="{
|
||||
'text-gray-900 border border-gray-900': selected,
|
||||
}"
|
||||
variant="subtle"
|
||||
theme="gray"
|
||||
size="sm"
|
||||
>
|
||||
{{ tab.count }}
|
||||
</Badge>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<template #default="{ tab }">
|
||||
<div class="p-10">
|
||||
<div v-if="tab.label == 'Courses'">
|
||||
<div class="text-xl font-semibold">
|
||||
{{ __('Courses') }}
|
||||
</div>
|
||||
<div
|
||||
class="grid grid-cols-1 sm:grid-cols-1 md:grid-cols-2 gap-8 mt-5"
|
||||
>
|
||||
<div v-for="course in courses.data">
|
||||
<router-link
|
||||
:to="{
|
||||
name: 'CourseDetail',
|
||||
params: {
|
||||
courseName: course.name,
|
||||
},
|
||||
}"
|
||||
>
|
||||
<CourseCard :key="course.name" :course="course" />
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="tab.label == 'Dashboard'">
|
||||
<BatchDashboard :batch="batch" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Tabs>
|
||||
</div>
|
||||
<div class="p-5">
|
||||
<div class="text-2xl font-semibold mb-3">
|
||||
{{ batch.doc.title }}
|
||||
{{ batch.data.title }}
|
||||
</div>
|
||||
<div class="flex items-center mb-2">
|
||||
<div class="flex items-center mb-3">
|
||||
<Calendar class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span>
|
||||
{{ dayjs(batch.doc.start_date).format('DD MMM YYYY') }} -
|
||||
{{ dayjs(batch.doc.end_date).format('DD MMM YYYY') }}
|
||||
{{ dayjs(batch.data.start_date).format('DD MMM YYYY') }} -
|
||||
{{ dayjs(batch.data.end_date).format('DD MMM YYYY') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center mb-6">
|
||||
<Clock class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span>
|
||||
{{ formatTime(batch.doc.start_time) }} -
|
||||
{{ formatTime(batch.doc.end_time) }}
|
||||
{{ formatTime(batch.data.start_time) }} -
|
||||
{{ formatTime(batch.data.end_time) }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-html="batch.doc.description"></div>
|
||||
<div v-html="batch.data.description"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="h-screen">
|
||||
<div class="text-base border rounded-md w-1/3 mx-auto my-32">
|
||||
<div class="border-b px-5 py-3 font-medium">
|
||||
<span
|
||||
class="inline-flex items-center before:bg-red-600 before:w-2 before:h-2 before:rounded-md before:mr-2"
|
||||
></span>
|
||||
{{ __('Not Permitted') }}
|
||||
</div>
|
||||
<div class="px-5 py-3">
|
||||
<div class="mb-4 leading-6">
|
||||
{{
|
||||
__(
|
||||
'You are not a member of this batch. Please checkout our upcoming batches.'
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
<router-link
|
||||
:to="{
|
||||
name: 'Batches',
|
||||
params: {
|
||||
batchName: batch.data?.name,
|
||||
},
|
||||
}"
|
||||
>
|
||||
<Button variant="solid" class="w-full">
|
||||
{{ __('Upcoming Batches') }}
|
||||
</Button>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Breadcrumbs, createDocumentResource } from 'frappe-ui'
|
||||
import { computed, inject } from 'vue'
|
||||
import { Calendar, Clock } from 'lucide-vue-next'
|
||||
import { Breadcrumbs, Button, createResource, Tabs, Badge } from 'frappe-ui'
|
||||
import { computed, inject, ref } from 'vue'
|
||||
import { Calendar, Clock, LayoutDashboard, BookOpen } from 'lucide-vue-next'
|
||||
import { formatTime } from '@/utils'
|
||||
import CourseCard from '@/components/CourseCard.vue'
|
||||
import BatchDashboard from '@/components/BatchDashboard.vue'
|
||||
|
||||
const dayjs = inject('$dayjs')
|
||||
const user = inject('$user')
|
||||
|
||||
const props = defineProps({
|
||||
batchName: {
|
||||
@@ -47,10 +138,12 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const batch = createDocumentResource({
|
||||
doctype: 'LMS Batch',
|
||||
name: props.batchName,
|
||||
const batch = createResource({
|
||||
url: 'lms.lms.utils.get_batch_details',
|
||||
cache: ['batch', props.batchName],
|
||||
params: {
|
||||
batch: props.batchName,
|
||||
},
|
||||
auto: true,
|
||||
})
|
||||
|
||||
@@ -62,9 +155,42 @@ const breadcrumbs = computed(() => {
|
||||
route: { name: 'BatchDetail', params: { batchName: props.batchName } },
|
||||
},
|
||||
{
|
||||
label: batch?.doc?.title,
|
||||
label: batch?.data?.title,
|
||||
route: { name: 'Batch', params: { batchName: props.batchName } },
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
const is_student = computed(() => {
|
||||
return (
|
||||
user?.data &&
|
||||
batch.data?.students.length &&
|
||||
batch.data?.students.includes(user.data.name)
|
||||
)
|
||||
})
|
||||
|
||||
const tabIndex = ref(0)
|
||||
const tabs = []
|
||||
|
||||
if (is_student) {
|
||||
tabs.push({
|
||||
label: 'Dashboard',
|
||||
icon: LayoutDashboard,
|
||||
})
|
||||
}
|
||||
|
||||
tabs.push({
|
||||
label: 'Courses',
|
||||
count: computed(() => courses?.data?.length),
|
||||
icon: BookOpen,
|
||||
})
|
||||
|
||||
const courses = createResource({
|
||||
url: 'lms.lms.utils.get_batch_courses',
|
||||
params: {
|
||||
batch: props.batchName,
|
||||
},
|
||||
cache: ['batchCourses', props.batchName],
|
||||
auto: true,
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,42 +1,45 @@
|
||||
<template>
|
||||
<div v-if="batch.doc" class="h-screen text-base">
|
||||
<div v-if="batch.data" class="h-screen text-base">
|
||||
<header class="sticky top-0 z-10 border-b bg-white px-3 py-2.5 sm:px-5">
|
||||
<Breadcrumbs :items="breadcrumbs" />
|
||||
</header>
|
||||
<div class="m-5 pb-10">
|
||||
<div>
|
||||
<div class="text-3xl font-semibold">
|
||||
{{ batch.doc.title }}
|
||||
{{ batch.data.title }}
|
||||
</div>
|
||||
<div class="my-3">
|
||||
{{ batch.doc.description }}
|
||||
{{ batch.data.description }}
|
||||
</div>
|
||||
<div class="flex items-center justify-between w-1/2">
|
||||
<div class="flex items-center">
|
||||
<BookOpen class="h-4 w-4 text-gray-700 mr-2" />
|
||||
<span> {{ batch.doc.courses.length }} {{ __('Courses') }} </span>
|
||||
<span> {{ batch.data.courses.length }} {{ __('Courses') }} </span>
|
||||
</div>
|
||||
<span v-if="batch.doc.courses">·</span>
|
||||
<span v-if="batch.data.courses">·</span>
|
||||
<div class="flex items-center">
|
||||
<Calendar class="h-4 w-4 text-gray-700 mr-2" />
|
||||
<span>
|
||||
{{ dayjs(batch.doc.start_date).format('DD MMM YYYY') }} -
|
||||
{{ dayjs(batch.doc.end_date).format('DD MMM YYYY') }}
|
||||
{{ dayjs(batch.data.start_date).format('DD MMM YYYY') }} -
|
||||
{{ dayjs(batch.data.end_date).format('DD MMM YYYY') }}
|
||||
</span>
|
||||
</div>
|
||||
<span v-if="batch.doc.start_date">·</span>
|
||||
<span v-if="batch.data.start_date">·</span>
|
||||
<div class="flex items-center">
|
||||
<Clock class="h-4 w-4 text-gray-700 mr-2" />
|
||||
<span>
|
||||
{{ formatTime(batch.doc.start_time) }} -
|
||||
{{ formatTime(batch.doc.end_time) }}
|
||||
{{ formatTime(batch.data.start_time) }} -
|
||||
{{ formatTime(batch.data.end_time) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-[60%,20%] gap-20 mt-10">
|
||||
<div class="">
|
||||
<div v-html="batch.doc.batch_details" class="batch-description"></div>
|
||||
<div
|
||||
v-html="batch.data.batch_details"
|
||||
class="batch-description"
|
||||
></div>
|
||||
</div>
|
||||
<div>
|
||||
<BatchOverlay :batch="batch" />
|
||||
@@ -46,29 +49,41 @@
|
||||
<div class="text-2xl font-semibold">
|
||||
{{ __('Courses') }}
|
||||
</div>
|
||||
<div
|
||||
v-if="batch.doc.courses"
|
||||
v-for="course in batch.doc.courses"
|
||||
:key="course.course"
|
||||
class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8 mt-5"
|
||||
>
|
||||
<router-link
|
||||
:to="{
|
||||
name: 'CourseDetail',
|
||||
params: {
|
||||
courseName: course.course,
|
||||
},
|
||||
}"
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8 mt-5">
|
||||
<div
|
||||
v-if="batch.data.courses"
|
||||
v-for="course in courses.data"
|
||||
:key="course.course"
|
||||
>
|
||||
<CourseCard :course="course.course" :key="course.course" />
|
||||
</router-link>
|
||||
<router-link
|
||||
:to="{
|
||||
name: 'CourseDetail',
|
||||
params: {
|
||||
courseName: course.name,
|
||||
},
|
||||
}"
|
||||
>
|
||||
<CourseCard :course="course" :key="course.name" />
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="batch.data.batch_details_raw">
|
||||
<div
|
||||
v-html="batch.data.batch_details_raw"
|
||||
class="batch-description"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Breadcrumbs, createDocumentResource } from 'frappe-ui'
|
||||
import {
|
||||
Breadcrumbs,
|
||||
createDocumentResource,
|
||||
createListResource,
|
||||
createResource,
|
||||
} from 'frappe-ui'
|
||||
import { BookOpen, Calendar, Clock } from 'lucide-vue-next'
|
||||
import { formatTime } from '../utils'
|
||||
import { computed, inject } from 'vue'
|
||||
@@ -84,18 +99,29 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const batch = createDocumentResource({
|
||||
doctype: 'LMS Batch',
|
||||
name: props.batchName,
|
||||
const batch = createResource({
|
||||
url: 'lms.lms.utils.get_batch_details',
|
||||
cache: ['batch', props.batchName],
|
||||
params: {
|
||||
batch: props.batchName,
|
||||
},
|
||||
auto: true,
|
||||
})
|
||||
|
||||
const courses = createResource({
|
||||
url: 'lms.lms.utils.get_batch_courses',
|
||||
params: {
|
||||
batch: props.batchName,
|
||||
},
|
||||
cache: ['batchCourses', props.batchName],
|
||||
auto: true,
|
||||
})
|
||||
|
||||
const breadcrumbs = computed(() => {
|
||||
let items = [{ label: 'All Batches', route: { name: 'Batches' } }]
|
||||
items.push({
|
||||
label: batch?.doc?.title,
|
||||
route: { name: 'BatchDetail', params: { batchName: batch?.doc?.name } },
|
||||
label: batch?.data?.title,
|
||||
route: { name: 'BatchDetail', params: { batchName: batch?.data?.name } },
|
||||
})
|
||||
return items
|
||||
})
|
||||
|
||||
@@ -1,119 +1,151 @@
|
||||
<template>
|
||||
<div class="h-screen">
|
||||
<div v-if="courses.data">
|
||||
<header class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5">
|
||||
<Breadcrumbs class="h-7" :items="[{ label: __('All Courses'), route: { name: 'Courses' } }]" />
|
||||
<div class="flex">
|
||||
<Button variant="solid">
|
||||
<template #prefix>
|
||||
<Plus class="h-4 w-4" />
|
||||
</template>
|
||||
{{ __("New Course") }}
|
||||
</Button>
|
||||
</div>
|
||||
</header>
|
||||
<div class="mx-5 py-5">
|
||||
<Tabs class="overflow-hidden" v-model="tabIndex" :tabs="tabs">
|
||||
<template #tab="{ tab, selected }">
|
||||
<div>
|
||||
<button
|
||||
class="group -mb-px flex items-center gap-2 border-b border-transparent py-2.5 text-base text-gray-600 duration-300 ease-in-out hover:border-gray-400 hover:text-gray-900"
|
||||
:class="{ 'text-gray-900': selected }">
|
||||
<component v-if="tab.icon" :is="tab.icon" class="h-5" />
|
||||
{{ __(tab.label) }}
|
||||
<Badge :class="{ 'text-gray-900 border border-gray-900': selected }" variant="subtle" theme="gray"
|
||||
size="sm">
|
||||
{{ tab.count }}
|
||||
</Badge>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<template #default="{ tab }">
|
||||
<div v-if="tab.courses && tab.courses.value.length" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8 mt-5">
|
||||
<router-link v-for="course in tab.courses.value"
|
||||
:to="course.membership && course.current_lesson
|
||||
? {
|
||||
name: 'Lesson', params: {
|
||||
courseName: course.name,
|
||||
chapterNumber: course.current_lesson.split('.')[0],
|
||||
lessonNumber: course.current_lesson.split('.')[1]
|
||||
}
|
||||
}
|
||||
: course.membership ? {
|
||||
name: 'Lesson', params: {
|
||||
courseName: course.name,
|
||||
chapterNumber: 1,
|
||||
lessonNumber: 1
|
||||
}
|
||||
} : { name: 'CourseDetail', params: { courseName: course.name } }">
|
||||
<CourseCard :course="course" />
|
||||
</router-link>
|
||||
</div>
|
||||
<div v-else class="grid flex-1 place-items-center text-xl font-medium text-gray-500">
|
||||
<div class="flex flex-col items-center justify-center mt-4">
|
||||
<div>
|
||||
{{ __("No {0} courses found").format(tab.label.toLowerCase()) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-screen">
|
||||
<div v-if="courses.data">
|
||||
<header
|
||||
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
|
||||
>
|
||||
<Breadcrumbs
|
||||
class="h-7"
|
||||
:items="[{ label: __('All Courses'), route: { name: 'Courses' } }]"
|
||||
/>
|
||||
<div class="flex">
|
||||
<Button variant="solid">
|
||||
<template #prefix>
|
||||
<Plus class="h-4 w-4" />
|
||||
</template>
|
||||
{{ __('New Course') }}
|
||||
</Button>
|
||||
</div>
|
||||
</header>
|
||||
<div class="mx-5 py-5">
|
||||
<Tabs class="overflow-hidden" v-model="tabIndex" :tabs="tabs">
|
||||
<template #tab="{ tab, selected }">
|
||||
<div>
|
||||
<button
|
||||
class="group -mb-px flex items-center gap-2 border-b border-transparent py-2.5 text-base text-gray-600 duration-300 ease-in-out hover:border-gray-400 hover:text-gray-900"
|
||||
:class="{ 'text-gray-900': selected }"
|
||||
>
|
||||
<component v-if="tab.icon" :is="tab.icon" class="h-5" />
|
||||
{{ __(tab.label) }}
|
||||
<Badge
|
||||
:class="{ 'text-gray-900 border border-gray-900': selected }"
|
||||
variant="subtle"
|
||||
theme="gray"
|
||||
size="sm"
|
||||
>
|
||||
{{ tab.count }}
|
||||
</Badge>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<template #default="{ tab }">
|
||||
<div
|
||||
v-if="tab.courses && tab.courses.value.length"
|
||||
class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8 mt-5"
|
||||
>
|
||||
<router-link
|
||||
v-for="course in tab.courses.value"
|
||||
:to="
|
||||
course.membership && course.current_lesson
|
||||
? {
|
||||
name: 'Lesson',
|
||||
params: {
|
||||
courseName: course.name,
|
||||
chapterNumber: course.current_lesson.split('.')[0],
|
||||
lessonNumber: course.current_lesson.split('.')[1],
|
||||
},
|
||||
}
|
||||
: course.membership
|
||||
? {
|
||||
name: 'Lesson',
|
||||
params: {
|
||||
courseName: course.name,
|
||||
chapterNumber: 1,
|
||||
lessonNumber: 1,
|
||||
},
|
||||
}
|
||||
: {
|
||||
name: 'CourseDetail',
|
||||
params: { courseName: course.name },
|
||||
}
|
||||
"
|
||||
>
|
||||
<CourseCard :course="course" />
|
||||
</router-link>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="grid flex-1 place-items-center text-xl font-medium text-gray-500"
|
||||
>
|
||||
<div class="flex flex-col items-center justify-center mt-4">
|
||||
<div>
|
||||
{{
|
||||
__('No {0} courses found').format(tab.label.toLowerCase())
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { sessionStore } from '@/stores/session'
|
||||
import { createListResource, Breadcrumbs, Tabs, Badge, Button } from 'frappe-ui';
|
||||
import CourseCard from '@/components/CourseCard.vue';
|
||||
import { createListResource, Breadcrumbs, Tabs, Badge, Button } from 'frappe-ui'
|
||||
import CourseCard from '@/components/CourseCard.vue'
|
||||
import { Plus } from 'lucide-vue-next'
|
||||
import { ref, computed, inject } from 'vue'
|
||||
|
||||
const user = inject("$user")
|
||||
const user = inject('$user')
|
||||
const courses = createListResource({
|
||||
type: 'list',
|
||||
doctype: 'LMS Course',
|
||||
cache: ["courses", user?.data?.email],
|
||||
url: "lms.lms.utils.get_courses",
|
||||
auto: true,
|
||||
});
|
||||
type: 'list',
|
||||
doctype: 'LMS Course',
|
||||
cache: ['courses', user?.data?.email],
|
||||
url: 'lms.lms.utils.get_courses',
|
||||
auto: true,
|
||||
})
|
||||
|
||||
const tabIndex = ref(0)
|
||||
const tabs = [
|
||||
{
|
||||
label: 'Live',
|
||||
courses: computed(() => courses.data?.live || []),
|
||||
count: computed(() => courses.data?.live?.length),
|
||||
},
|
||||
{
|
||||
label: 'Upcoming',
|
||||
courses: computed(() => courses.data?.upcoming),
|
||||
count: computed(() => courses.data?.upcoming?.length),
|
||||
}
|
||||
];
|
||||
{
|
||||
label: 'Live',
|
||||
courses: computed(() => courses.data?.live || []),
|
||||
count: computed(() => courses.data?.live?.length),
|
||||
},
|
||||
{
|
||||
label: 'Upcoming',
|
||||
courses: computed(() => courses.data?.upcoming),
|
||||
count: computed(() => courses.data?.upcoming?.length),
|
||||
},
|
||||
]
|
||||
|
||||
if (user.data) {
|
||||
tabs.push({
|
||||
label: 'Enrolled',
|
||||
courses: computed(() => courses.data?.enrolled),
|
||||
count: computed(() => courses.data?.enrolled?.length),
|
||||
});
|
||||
tabs.push({
|
||||
label: 'Enrolled',
|
||||
courses: computed(() => courses.data?.enrolled),
|
||||
count: computed(() => courses.data?.enrolled?.length),
|
||||
})
|
||||
|
||||
if (user.data.is_moderator || user.data.is_instructor || courses.data?.created?.length) {
|
||||
tabs.push({
|
||||
label: 'Created',
|
||||
courses: computed(() => courses.data?.created),
|
||||
count: computed(() => courses.data?.created?.length),
|
||||
});
|
||||
};
|
||||
if (
|
||||
user.data.is_moderator ||
|
||||
user.data.is_instructor ||
|
||||
courses.data?.created?.length
|
||||
) {
|
||||
tabs.push({
|
||||
label: 'Created',
|
||||
courses: computed(() => courses.data?.created),
|
||||
count: computed(() => courses.data?.created?.length),
|
||||
})
|
||||
}
|
||||
|
||||
if (user.data.is_moderator) {
|
||||
tabs.push({
|
||||
label: 'Under Review',
|
||||
courses: computed(() => courses.data?.under_review),
|
||||
count: computed(() => courses.data?.under_review?.length),
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
if (user.data.is_moderator) {
|
||||
tabs.push({
|
||||
label: 'Under Review',
|
||||
courses: computed(() => courses.data?.under_review),
|
||||
count: computed(() => courses.data?.under_review?.length),
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -20,6 +20,15 @@ frappe.ui.form.on("LMS Batch", {
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("assessment_type", "assessment", function () {
|
||||
let doctypes = ["LMS Quiz", "LMS Assignment"];
|
||||
return {
|
||||
filters: {
|
||||
name: ["in", doctypes],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("reference_doctype", "timetable_legends", function () {
|
||||
let doctypes = ["Course Lesson", "LMS Quiz", "LMS Assignment"];
|
||||
return {
|
||||
|
||||
@@ -297,7 +297,7 @@
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2023-12-21 12:27:16.849362",
|
||||
"modified": "2024-01-08 09:58:23.212334",
|
||||
"modified_by": "Administrator",
|
||||
"module": "LMS",
|
||||
"name": "LMS Batch",
|
||||
|
||||
150
lms/lms/utils.py
150
lms/lms/utils.py
@@ -1348,12 +1348,27 @@ def get_neighbour_lesson(course, chapter, lesson):
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_batches():
|
||||
batches = frappe.get_all(
|
||||
batches = []
|
||||
batch_list = frappe.get_all("LMS Batch", pluck="name")
|
||||
|
||||
for batch in batch_list:
|
||||
batches.append(get_batch_details(batch))
|
||||
|
||||
batches = categorize_batches(batches)
|
||||
return batches
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_batch_details(batch):
|
||||
batch_details = frappe.db.get_value(
|
||||
"LMS Batch",
|
||||
fields=[
|
||||
batch,
|
||||
[
|
||||
"name",
|
||||
"title",
|
||||
"description",
|
||||
"batch_details",
|
||||
"batch_details_raw",
|
||||
"start_date",
|
||||
"end_date",
|
||||
"start_time",
|
||||
@@ -1362,19 +1377,36 @@ def get_batches():
|
||||
"published",
|
||||
"amount",
|
||||
"currency",
|
||||
"paid_batch",
|
||||
],
|
||||
as_dict=True,
|
||||
)
|
||||
for batch in batches:
|
||||
batch.courses = frappe.db.count("Batch Course", {"parent": batch.name})
|
||||
batch.price = fmt_money(batch.amount, 0, batch.currency)
|
||||
if batch.seat_count:
|
||||
students_enrolled = frappe.db.count(
|
||||
"Batch Student",
|
||||
{"parent": batch.name},
|
||||
|
||||
batch_details.courses = frappe.get_all(
|
||||
"Batch Course", {"parent": batch}, pluck="course"
|
||||
)
|
||||
batch_details.students = frappe.get_all(
|
||||
"Batch Student", {"parent": batch}, pluck="student"
|
||||
)
|
||||
batch_details.price = fmt_money(batch_details.amount, 0, batch_details.currency)
|
||||
|
||||
is_student = frappe.session.user in batch_details.students
|
||||
if frappe.session.user != "Guest":
|
||||
if is_student:
|
||||
batch_details.upcoming_evals = get_upcoming_evals(
|
||||
frappe.session.user, batch_details.courses
|
||||
)
|
||||
batch.seats_left = batch.seat_count - students_enrolled
|
||||
batches = categorize_batches(batches)
|
||||
return batches
|
||||
if is_student or has_course_moderator_role():
|
||||
batch_details.assessments = get_assessments(batch, frappe.session.user)
|
||||
|
||||
if batch_details.seat_count:
|
||||
students_enrolled = frappe.db.count(
|
||||
"Batch Student",
|
||||
{"parent": batch},
|
||||
)
|
||||
batch_details.seats_left = batch_details.seat_count - students_enrolled
|
||||
|
||||
return batch_details
|
||||
|
||||
|
||||
def categorize_batches(batches):
|
||||
@@ -1434,3 +1466,97 @@ def get_question_details(question):
|
||||
|
||||
question_details = frappe.db.get_value("LMS Question", question, fields, as_dict=1)
|
||||
return question_details
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_batch_courses(batch):
|
||||
courses = []
|
||||
course_list = frappe.get_all("Batch Course", {"parent": batch}, pluck="course")
|
||||
|
||||
for course in course_list:
|
||||
courses.append(get_course_details(course))
|
||||
|
||||
return courses
|
||||
|
||||
|
||||
def get_assessments(batch, member=None):
|
||||
if not member:
|
||||
member = frappe.session.user
|
||||
|
||||
assessments = frappe.get_all(
|
||||
"LMS Assessment",
|
||||
{"parent": batch},
|
||||
["name", "assessment_type", "assessment_name"],
|
||||
)
|
||||
|
||||
for assessment in assessments:
|
||||
if assessment.assessment_type == "LMS Assignment":
|
||||
assessment = get_assignment_details(assessment, member)
|
||||
|
||||
elif assessment.assessment_type == "LMS Quiz":
|
||||
assessment = get_quiz_details(assessment, member)
|
||||
|
||||
return assessments
|
||||
|
||||
|
||||
def get_assignment_details(assessment, member):
|
||||
assessment.title = frappe.db.get_value(
|
||||
"LMS Assignment", assessment.assessment_name, "title"
|
||||
)
|
||||
|
||||
existing_submission = frappe.db.exists(
|
||||
{
|
||||
"doctype": "LMS Assignment Submission",
|
||||
"member": member,
|
||||
"assignment": assessment.assessment_name,
|
||||
}
|
||||
)
|
||||
assessment.completed = False
|
||||
if existing_submission:
|
||||
assessment.submission = frappe.db.get_value(
|
||||
"LMS Assignment Submission",
|
||||
existing_submission,
|
||||
["name", "status", "comments"],
|
||||
as_dict=True,
|
||||
)
|
||||
assessment.completed = True
|
||||
|
||||
assessment.edit_url = f"/assignments/{assessment.assessment_name}"
|
||||
submission_name = existing_submission if existing_submission else "new-submission"
|
||||
assessment.url = (
|
||||
f"/assignment-submission/{assessment.assessment_name}/{submission_name}"
|
||||
)
|
||||
|
||||
return assessment
|
||||
|
||||
|
||||
def get_quiz_details(assessment, member):
|
||||
assessment_details = frappe.db.get_value(
|
||||
"LMS Quiz", assessment.assessment_name, ["title", "passing_percentage"], as_dict=1
|
||||
)
|
||||
assessment.title = assessment_details.title
|
||||
|
||||
existing_submission = frappe.get_all(
|
||||
"LMS Quiz Submission",
|
||||
{
|
||||
"member": member,
|
||||
"quiz": assessment.assessment_name,
|
||||
},
|
||||
["name", "score", "percentage"],
|
||||
order_by="percentage desc",
|
||||
)
|
||||
|
||||
if len(existing_submission):
|
||||
assessment.submission = existing_submission[0]
|
||||
|
||||
assessment.completed = False
|
||||
if assessment.submission:
|
||||
assessment.completed = True
|
||||
|
||||
assessment.edit_url = f"/quizzes/{assessment.assessment_name}"
|
||||
submission_name = (
|
||||
existing_submission[0].name if len(existing_submission) else "new-submission"
|
||||
)
|
||||
assessment.url = f"/quiz-submission/{assessment.assessment_name}/{submission_name}"
|
||||
|
||||
return assessment
|
||||
|
||||
730
lms/public/frontend/assets/Batch.6cc6d79c.js
Normal file
730
lms/public/frontend/assets/Batch.6cc6d79c.js
Normal file
@@ -0,0 +1,730 @@
|
||||
import {
|
||||
a as k,
|
||||
s as o,
|
||||
u as n,
|
||||
A as e,
|
||||
E as a,
|
||||
K as j,
|
||||
L as A,
|
||||
C as r,
|
||||
D as s,
|
||||
af as T,
|
||||
k as M,
|
||||
j as g,
|
||||
r as E,
|
||||
P as I,
|
||||
z as h,
|
||||
B as Y,
|
||||
y as x,
|
||||
J as P,
|
||||
F as y,
|
||||
X as f,
|
||||
Z as F,
|
||||
a0 as H,
|
||||
a1 as O,
|
||||
$ as S,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
import { f as $ } from "./index.05189aed.js";
|
||||
import { _ as q } from "./CourseCard.6a41330a.js";
|
||||
import { C as L, a as V } from "./clock.4d13ba48.js";
|
||||
import { c as U, B as J } from "./index.43e529db.js";
|
||||
import "./UserAvatar.b64a03ac.js";
|
||||
import "./star.d3e8ecca.js";
|
||||
const K = U("LayoutDashboardIcon", [
|
||||
[
|
||||
"rect",
|
||||
{ width: "7", height: "9", x: "3", y: "3", rx: "1", key: "10lvy0" },
|
||||
],
|
||||
[
|
||||
"rect",
|
||||
{
|
||||
width: "7",
|
||||
height: "5",
|
||||
x: "14",
|
||||
y: "3",
|
||||
rx: "1",
|
||||
key: "16une8",
|
||||
},
|
||||
],
|
||||
[
|
||||
"rect",
|
||||
{
|
||||
width: "7",
|
||||
height: "9",
|
||||
x: "14",
|
||||
y: "12",
|
||||
rx: "1",
|
||||
key: "1hutg5",
|
||||
},
|
||||
],
|
||||
[
|
||||
"rect",
|
||||
{
|
||||
width: "7",
|
||||
height: "5",
|
||||
x: "3",
|
||||
y: "16",
|
||||
rx: "1",
|
||||
key: "ldoo1y",
|
||||
},
|
||||
],
|
||||
]),
|
||||
R = U("UserCog2Icon", [
|
||||
["path", { d: "M14 19a6 6 0 0 0-12 0", key: "vej9p1" }],
|
||||
["circle", { cx: "8", cy: "9", r: "4", key: "143rtg" }],
|
||||
["circle", { cx: "19", cy: "11", r: "2", key: "1rxg02" }],
|
||||
["path", { d: "M19 8v1", key: "1iffrw" }],
|
||||
["path", { d: "M19 13v1", key: "z4xc62" }],
|
||||
["path", { d: "m21.6 9.5-.87.5", key: "6lxupl" }],
|
||||
["path", { d: "m17.27 12-.87.5", key: "1rwhxx" }],
|
||||
["path", { d: "m21.6 12.5-.87-.5", key: "agvc9a" }],
|
||||
["path", { d: "m17.27 10-.87-.5", key: "12d57s" }],
|
||||
]),
|
||||
X = { class: "mb-10" },
|
||||
Z = { class: "text-lg font-semibold mb-4" },
|
||||
G = { key: 0 },
|
||||
Q = { class: "grid grid-cols-2" },
|
||||
W = { class: "border rounded-md p-3" },
|
||||
ee = { class: "font-medium mb-3" },
|
||||
se = { class: "flex items-center mb-2" },
|
||||
te = { class: "ml-2" },
|
||||
ae = { class: "flex items-center mb-2" },
|
||||
oe = { class: "ml-2" },
|
||||
ne = { class: "flex items-center" },
|
||||
ce = { class: "ml-2" },
|
||||
re = { key: 1, class: "text-sm italic text-gray-600" },
|
||||
le = {
|
||||
__name: "UpcomingEvaluations",
|
||||
props: { upcoming_evals: { type: Array, default: [] } },
|
||||
setup(_) {
|
||||
const l = k("$dayjs");
|
||||
return (i, d) => (
|
||||
o(),
|
||||
n("div", X, [
|
||||
e("div", Z, a(i.__("Upcoming Evaluations")), 1),
|
||||
_.upcoming_evals.length
|
||||
? (o(),
|
||||
n("div", G, [
|
||||
e("div", Q, [
|
||||
(o(!0),
|
||||
n(
|
||||
j,
|
||||
null,
|
||||
A(
|
||||
_.upcoming_evals,
|
||||
(t) => (
|
||||
o(),
|
||||
n("div", null, [
|
||||
e("div", W, [
|
||||
e(
|
||||
"div",
|
||||
ee,
|
||||
a(t.course_title),
|
||||
1
|
||||
),
|
||||
e("div", se, [
|
||||
r(s(L), {
|
||||
class: "w-4 h-4 stroke-1.5",
|
||||
}),
|
||||
e(
|
||||
"span",
|
||||
te,
|
||||
a(
|
||||
s(l)(
|
||||
t.date
|
||||
).format(
|
||||
"DD MMMM YYYY"
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
e("div", ae, [
|
||||
r(s(V), {
|
||||
class: "w-4 h-4 stroke-1.5",
|
||||
}),
|
||||
e(
|
||||
"span",
|
||||
oe,
|
||||
a(
|
||||
s($)(
|
||||
t.start_time
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
e("div", ne, [
|
||||
r(s(R), {
|
||||
class: "w-4 h-4 stroke-1.5",
|
||||
}),
|
||||
e(
|
||||
"span",
|
||||
ce,
|
||||
a(
|
||||
t.evaluator_name
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
]),
|
||||
])
|
||||
)
|
||||
),
|
||||
256
|
||||
)),
|
||||
]),
|
||||
]))
|
||||
: (o(),
|
||||
n("div", re, a(i.__("No upcoming evaluations.")), 1)),
|
||||
])
|
||||
);
|
||||
},
|
||||
},
|
||||
ie = { class: "text-lg font-semibold mb-4" },
|
||||
de = { key: 0 },
|
||||
me = { key: 1, class: "text-sm italic text-gray-600" },
|
||||
_e = {
|
||||
__name: "Assessments",
|
||||
props: { assessments: { type: Array, default: [] } },
|
||||
setup(_) {
|
||||
return (l, i) => {
|
||||
var d, t;
|
||||
return (
|
||||
o(),
|
||||
n("div", null, [
|
||||
e("div", ie, a(l.__("Assessments")), 1),
|
||||
(d = _.assessments) != null && d.length
|
||||
? (o(),
|
||||
n("div", de, [
|
||||
r(
|
||||
s(T),
|
||||
{
|
||||
columns: l.getAssessmentColumns(),
|
||||
rows:
|
||||
(t = l.attempts) == null
|
||||
? void 0
|
||||
: t.data,
|
||||
"row-key": "name",
|
||||
options: {
|
||||
selectable: !1,
|
||||
showTooltip: !1,
|
||||
},
|
||||
},
|
||||
null,
|
||||
8,
|
||||
["columns", "rows"]
|
||||
),
|
||||
]))
|
||||
: (o(), n("div", me, a(l.__("No Assessments")), 1)),
|
||||
])
|
||||
);
|
||||
};
|
||||
},
|
||||
},
|
||||
ue = {
|
||||
__name: "BatchDashboard",
|
||||
props: { batch: { type: Object, default: null } },
|
||||
setup(_) {
|
||||
return (l, i) => (
|
||||
o(),
|
||||
n("div", null, [
|
||||
r(
|
||||
le,
|
||||
{ upcoming_evals: _.batch.data.upcoming_evals },
|
||||
null,
|
||||
8,
|
||||
["upcoming_evals"]
|
||||
),
|
||||
r(_e, { assessments: _.batch.data.assessments }, null, 8, [
|
||||
"assessments",
|
||||
]),
|
||||
])
|
||||
);
|
||||
},
|
||||
},
|
||||
he = { key: 0, class: "h-screen text-base" },
|
||||
pe = {
|
||||
class: "sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5",
|
||||
},
|
||||
be = { key: 0 },
|
||||
ye = { class: "grid grid-cols-[70%,30%] h-full" },
|
||||
fe = { class: "border-r-2" },
|
||||
ve = { class: "p-10" },
|
||||
ge = { key: 0 },
|
||||
xe = { class: "text-xl font-semibold" },
|
||||
ke = { class: "grid grid-cols-1 sm:grid-cols-1 md:grid-cols-2 gap-8 mt-5" },
|
||||
$e = { key: 1 },
|
||||
we = { class: "p-5" },
|
||||
Ne = { class: "text-2xl font-semibold mb-3" },
|
||||
Ce = { class: "flex items-center mb-3" },
|
||||
De = { class: "flex items-center mb-6" },
|
||||
Be = ["innerHTML"],
|
||||
Me = { key: 1, class: "h-screen" },
|
||||
Ye = { class: "text-base border rounded-md w-1/3 mx-auto my-32" },
|
||||
je = { class: "border-b px-5 py-3 font-medium" },
|
||||
Ae = e(
|
||||
"span",
|
||||
{
|
||||
class: "inline-flex items-center before:bg-red-600 before:w-2 before:h-2 before:rounded-md before:mr-2",
|
||||
},
|
||||
null,
|
||||
-1
|
||||
),
|
||||
Le = { class: "px-5 py-3" },
|
||||
Ve = { class: "mb-4 leading-6" },
|
||||
He = {
|
||||
__name: "Batch",
|
||||
props: { batchName: { type: String, required: !0 } },
|
||||
setup(_) {
|
||||
const l = k("$dayjs"),
|
||||
i = k("$user"),
|
||||
d = _,
|
||||
t = M({
|
||||
url: "lms.lms.utils.get_batch_details",
|
||||
cache: ["batch", d.batchName],
|
||||
params: { batch: d.batchName },
|
||||
auto: !0,
|
||||
}),
|
||||
z = g(() => {
|
||||
var c;
|
||||
return [
|
||||
{ label: "All Batches", route: { name: "Batches" } },
|
||||
{
|
||||
label: "Batch Details",
|
||||
route: {
|
||||
name: "BatchDetail",
|
||||
params: { batchName: d.batchName },
|
||||
},
|
||||
},
|
||||
{
|
||||
label:
|
||||
(c = t == null ? void 0 : t.data) == null
|
||||
? void 0
|
||||
: c.title,
|
||||
route: {
|
||||
name: "Batch",
|
||||
params: { batchName: d.batchName },
|
||||
},
|
||||
},
|
||||
];
|
||||
}),
|
||||
w = g(() => {
|
||||
var c, p;
|
||||
return (
|
||||
(i == null ? void 0 : i.data) &&
|
||||
((c = t.data) == null ? void 0 : c.students.length) &&
|
||||
((p = t.data) == null
|
||||
? void 0
|
||||
: p.students.includes(i.data.name))
|
||||
);
|
||||
}),
|
||||
N = E(0),
|
||||
v = [];
|
||||
w && v.push({ label: "Dashboard", icon: K }),
|
||||
v.push({
|
||||
label: "Courses",
|
||||
count: g(() => {
|
||||
var c;
|
||||
return (c = b == null ? void 0 : b.data) == null
|
||||
? void 0
|
||||
: c.length;
|
||||
}),
|
||||
icon: J,
|
||||
});
|
||||
const b = M({
|
||||
url: "lms.lms.utils.get_batch_courses",
|
||||
params: { batch: d.batchName },
|
||||
cache: ["batchCourses", d.batchName],
|
||||
auto: !0,
|
||||
});
|
||||
return (c, p) => {
|
||||
var D, B;
|
||||
const C = I("router-link");
|
||||
return ((D = s(i).data) == null ? void 0 : D.is_moderator) ||
|
||||
w.value
|
||||
? (o(),
|
||||
n("div", he, [
|
||||
e("header", pe, [
|
||||
r(
|
||||
s(F),
|
||||
{ class: "h-7", items: z.value },
|
||||
null,
|
||||
8,
|
||||
["items"]
|
||||
),
|
||||
]),
|
||||
s(t).data
|
||||
? (o(),
|
||||
n("div", be, [
|
||||
e("div", ye, [
|
||||
e("div", fe, [
|
||||
r(
|
||||
s(O),
|
||||
{
|
||||
class: "overflow-hidden",
|
||||
modelValue: N.value,
|
||||
"onUpdate:modelValue":
|
||||
p[0] ||
|
||||
(p[0] = (m) =>
|
||||
(N.value = m)),
|
||||
tabs: v,
|
||||
},
|
||||
{
|
||||
tab: h(
|
||||
({
|
||||
tab: m,
|
||||
selected: u,
|
||||
}) => [
|
||||
e("div", null, [
|
||||
e(
|
||||
"button",
|
||||
{
|
||||
class: Y(
|
||||
[
|
||||
"group -mb-px flex items-center gap-1 border-b border-transparent py-2.5 text-base text-gray-600 duration-300 ease-in-out hover:border-gray-400 hover:text-gray-900",
|
||||
{
|
||||
"text-gray-900":
|
||||
u,
|
||||
},
|
||||
]
|
||||
),
|
||||
},
|
||||
[
|
||||
m.icon
|
||||
? (o(),
|
||||
x(
|
||||
P(
|
||||
m.icon
|
||||
),
|
||||
{
|
||||
key: 0,
|
||||
class: "h-4 stroke-1.5",
|
||||
}
|
||||
))
|
||||
: y(
|
||||
"",
|
||||
!0
|
||||
),
|
||||
f(
|
||||
" " +
|
||||
a(
|
||||
c.__(
|
||||
m.label
|
||||
)
|
||||
) +
|
||||
" ",
|
||||
1
|
||||
),
|
||||
m.count
|
||||
? (o(),
|
||||
x(
|
||||
s(
|
||||
H
|
||||
),
|
||||
{
|
||||
key: 1,
|
||||
class: Y(
|
||||
{
|
||||
"text-gray-900 border border-gray-900":
|
||||
u,
|
||||
}
|
||||
),
|
||||
variant:
|
||||
"subtle",
|
||||
theme: "gray",
|
||||
size: "sm",
|
||||
},
|
||||
{
|
||||
default:
|
||||
h(
|
||||
() => [
|
||||
f(
|
||||
a(
|
||||
m.count
|
||||
),
|
||||
1
|
||||
),
|
||||
]
|
||||
),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
[
|
||||
"class",
|
||||
]
|
||||
))
|
||||
: y(
|
||||
"",
|
||||
!0
|
||||
),
|
||||
],
|
||||
2
|
||||
),
|
||||
]),
|
||||
]
|
||||
),
|
||||
default: h(
|
||||
({ tab: m }) => [
|
||||
e("div", ve, [
|
||||
m.label ==
|
||||
"Courses"
|
||||
? (o(),
|
||||
n(
|
||||
"div",
|
||||
ge,
|
||||
[
|
||||
e(
|
||||
"div",
|
||||
xe,
|
||||
a(
|
||||
c.__(
|
||||
"Courses"
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
e(
|
||||
"div",
|
||||
ke,
|
||||
[
|
||||
(o(
|
||||
!0
|
||||
),
|
||||
n(
|
||||
j,
|
||||
null,
|
||||
A(
|
||||
s(
|
||||
b
|
||||
)
|
||||
.data,
|
||||
(
|
||||
u
|
||||
) => (
|
||||
o(),
|
||||
n(
|
||||
"div",
|
||||
null,
|
||||
[
|
||||
r(
|
||||
C,
|
||||
{
|
||||
to: {
|
||||
name: "CourseDetail",
|
||||
params: {
|
||||
courseName:
|
||||
u.name,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
default:
|
||||
h(
|
||||
() => [
|
||||
(o(),
|
||||
x(
|
||||
q,
|
||||
{
|
||||
key: u.name,
|
||||
course: u,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
"course",
|
||||
]
|
||||
)),
|
||||
]
|
||||
),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
[
|
||||
"to",
|
||||
]
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
256
|
||||
)),
|
||||
]
|
||||
),
|
||||
]
|
||||
))
|
||||
: m.label ==
|
||||
"Dashboard"
|
||||
? (o(),
|
||||
n(
|
||||
"div",
|
||||
$e,
|
||||
[
|
||||
r(
|
||||
ue,
|
||||
{
|
||||
batch: s(
|
||||
t
|
||||
),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
"batch",
|
||||
]
|
||||
),
|
||||
]
|
||||
))
|
||||
: y(
|
||||
"",
|
||||
!0
|
||||
),
|
||||
]),
|
||||
]
|
||||
),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
["modelValue"]
|
||||
),
|
||||
]),
|
||||
e("div", we, [
|
||||
e(
|
||||
"div",
|
||||
Ne,
|
||||
a(s(t).data.title),
|
||||
1
|
||||
),
|
||||
e("div", Ce, [
|
||||
r(s(L), {
|
||||
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
|
||||
}),
|
||||
e(
|
||||
"span",
|
||||
null,
|
||||
a(
|
||||
s(l)(
|
||||
s(t).data
|
||||
.start_date
|
||||
).format(
|
||||
"DD MMM YYYY"
|
||||
)
|
||||
) +
|
||||
" - " +
|
||||
a(
|
||||
s(l)(
|
||||
s(t).data
|
||||
.end_date
|
||||
).format(
|
||||
"DD MMM YYYY"
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
e("div", De, [
|
||||
r(s(V), {
|
||||
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
|
||||
}),
|
||||
e(
|
||||
"span",
|
||||
null,
|
||||
a(
|
||||
s($)(
|
||||
s(t).data
|
||||
.start_time
|
||||
)
|
||||
) +
|
||||
" - " +
|
||||
a(
|
||||
s($)(
|
||||
s(t).data
|
||||
.end_time
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
e(
|
||||
"div",
|
||||
{
|
||||
innerHTML:
|
||||
s(t).data
|
||||
.description,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
Be
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]))
|
||||
: y("", !0),
|
||||
]))
|
||||
: (o(),
|
||||
n("div", Me, [
|
||||
e("div", Ye, [
|
||||
e("div", je, [
|
||||
Ae,
|
||||
f(" " + a(c.__("Not Permitted")), 1),
|
||||
]),
|
||||
e("div", Le, [
|
||||
e(
|
||||
"div",
|
||||
Ve,
|
||||
a(
|
||||
c.__(
|
||||
"You are not a member of this batch. Please checkout our upcoming batches."
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
r(
|
||||
C,
|
||||
{
|
||||
to: {
|
||||
name: "Batches",
|
||||
params: {
|
||||
batchName:
|
||||
(B = s(t).data) == null
|
||||
? void 0
|
||||
: B.name,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
default: h(() => [
|
||||
r(
|
||||
s(S),
|
||||
{
|
||||
variant: "solid",
|
||||
class: "w-full",
|
||||
},
|
||||
{
|
||||
default: h(() => [
|
||||
f(
|
||||
a(
|
||||
c.__(
|
||||
"Upcoming Batches"
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
}
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
["to"]
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]));
|
||||
};
|
||||
},
|
||||
};
|
||||
export { He as default };
|
||||
454
lms/public/frontend/assets/BatchDetail.c5dd0840.js
Normal file
454
lms/public/frontend/assets/BatchDetail.c5dd0840.js
Normal file
@@ -0,0 +1,454 @@
|
||||
import {
|
||||
a as k,
|
||||
j as D,
|
||||
s as l,
|
||||
u as m,
|
||||
y as b,
|
||||
z as f,
|
||||
X as w,
|
||||
E as s,
|
||||
D as t,
|
||||
a0 as M,
|
||||
F as o,
|
||||
A as a,
|
||||
C as u,
|
||||
$ as g,
|
||||
k as Y,
|
||||
P as N,
|
||||
K as j,
|
||||
L,
|
||||
Z as T,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
import { a as H, f as p } from "./index.05189aed.js";
|
||||
import { B as $ } from "./index.43e529db.js";
|
||||
import { C as B, a as C } from "./clock.4d13ba48.js";
|
||||
import { _ as O } from "./CourseCard.6a41330a.js";
|
||||
import "./UserAvatar.b64a03ac.js";
|
||||
import "./star.d3e8ecca.js";
|
||||
const S = { key: 0, class: "shadow rounded-md p-5", style: { width: "300px" } },
|
||||
V = { key: 2, class: "text-lg font-semibold mb-3" },
|
||||
E = { class: "flex items-center mb-3" },
|
||||
z = { class: "flex items-center mb-3" },
|
||||
A = { class: "flex items-center" },
|
||||
F = {
|
||||
__name: "BatchOverlay",
|
||||
props: { batch: { type: Object, default: null } },
|
||||
setup(c) {
|
||||
const y = k("$dayjs"),
|
||||
_ = k("$user"),
|
||||
e = c,
|
||||
v = D(() => {
|
||||
var r, d, i, n;
|
||||
return (r = e.batch.data) != null && r.seat_count
|
||||
? ((d = e.batch.data) == null ? void 0 : d.seat_count) -
|
||||
((n =
|
||||
(i = e.batch.data) == null
|
||||
? void 0
|
||||
: i.students) == null
|
||||
? void 0
|
||||
: n.length)
|
||||
: null;
|
||||
});
|
||||
return (r, d) => {
|
||||
var i, n, h, x;
|
||||
return c.batch.data
|
||||
? (l(),
|
||||
m("div", S, [
|
||||
c.batch.data.seat_count && v.value > 0
|
||||
? (l(),
|
||||
b(
|
||||
t(M),
|
||||
{
|
||||
key: 0,
|
||||
theme: "green",
|
||||
class: "self-start mb-2 float-right",
|
||||
},
|
||||
{
|
||||
default: f(() => [
|
||||
w(
|
||||
s(v.value) +
|
||||
" " +
|
||||
s(r.__("Seat Left")),
|
||||
1
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
}
|
||||
))
|
||||
: c.batch.data.seat_count && v.value <= 0
|
||||
? (l(),
|
||||
b(
|
||||
t(M),
|
||||
{
|
||||
key: 1,
|
||||
theme: "red",
|
||||
class: "self-start mb-2 float-right",
|
||||
},
|
||||
{
|
||||
default: f(() => [
|
||||
w(s(r.__("Sold Out")), 1),
|
||||
]),
|
||||
_: 1,
|
||||
}
|
||||
))
|
||||
: o("", !0),
|
||||
c.batch.data.amount
|
||||
? (l(),
|
||||
m(
|
||||
"div",
|
||||
V,
|
||||
s(
|
||||
t(H)(
|
||||
c.batch.data.amount,
|
||||
c.batch.data.currency
|
||||
)
|
||||
),
|
||||
1
|
||||
))
|
||||
: o("", !0),
|
||||
a("div", E, [
|
||||
u(t($), {
|
||||
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
|
||||
}),
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
s(c.batch.data.courses.length) +
|
||||
" " +
|
||||
s(r.__("Courses")),
|
||||
1
|
||||
),
|
||||
]),
|
||||
a("div", z, [
|
||||
u(t(B), {
|
||||
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
|
||||
}),
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
s(
|
||||
t(y)(c.batch.data.start_date).format(
|
||||
"DD MMM YYYY"
|
||||
)
|
||||
) +
|
||||
" - " +
|
||||
s(
|
||||
t(y)(c.batch.data.end_date).format(
|
||||
"DD MMM YYYY"
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
a("div", A, [
|
||||
u(t(C), {
|
||||
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
|
||||
}),
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
s(t(p)(c.batch.data.start_time)) +
|
||||
" - " +
|
||||
s(t(p)(c.batch.data.end_time)),
|
||||
1
|
||||
),
|
||||
]),
|
||||
(n = (i = t(_)) == null ? void 0 : i.data) !=
|
||||
null && n.is_moderator
|
||||
? (l(),
|
||||
b(
|
||||
t(g),
|
||||
{ key: 3, class: "w-full mt-4" },
|
||||
{
|
||||
default: f(() => [
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
s(r.__("Manage Batch")),
|
||||
1
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
}
|
||||
))
|
||||
: c.batch.data.paid_batch
|
||||
? (l(),
|
||||
b(
|
||||
t(g),
|
||||
{
|
||||
key: 4,
|
||||
class: "w-full mt-4",
|
||||
variant: "solid",
|
||||
},
|
||||
{
|
||||
default: f(() => [
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
s(r.__("Register Now")),
|
||||
1
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
}
|
||||
))
|
||||
: o("", !0),
|
||||
(x = (h = t(_)) == null ? void 0 : h.data) !=
|
||||
null && x.is_moderator
|
||||
? (l(),
|
||||
b(
|
||||
t(g),
|
||||
{ key: 5, class: "w-full mt-2" },
|
||||
{
|
||||
default: f(() => [
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
s(r.__("Edit")),
|
||||
1
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
}
|
||||
))
|
||||
: o("", !0),
|
||||
]))
|
||||
: o("", !0);
|
||||
};
|
||||
},
|
||||
};
|
||||
const R = { key: 0, class: "h-screen text-base" },
|
||||
q = { class: "sticky top-0 z-10 border-b bg-white px-3 py-2.5 sm:px-5" },
|
||||
I = { class: "m-5 pb-10" },
|
||||
K = { class: "text-3xl font-semibold" },
|
||||
P = { class: "my-3" },
|
||||
X = { class: "flex items-center justify-between w-1/2" },
|
||||
Z = { class: "flex items-center" },
|
||||
G = { key: 0 },
|
||||
J = { class: "flex items-center" },
|
||||
Q = { key: 1 },
|
||||
U = { class: "flex items-center" },
|
||||
W = { class: "grid grid-cols-[60%,20%] gap-20 mt-10" },
|
||||
tt = { class: "" },
|
||||
at = ["innerHTML"],
|
||||
et = { class: "text-2xl font-semibold" },
|
||||
st = { class: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8 mt-5" },
|
||||
ct = { key: 0 },
|
||||
lt = ["innerHTML"],
|
||||
_t = {
|
||||
__name: "BatchDetail",
|
||||
props: { batchName: { type: String, required: !0 } },
|
||||
setup(c) {
|
||||
const y = k("$dayjs"),
|
||||
_ = c,
|
||||
e = Y({
|
||||
url: "lms.lms.utils.get_batch_details",
|
||||
cache: ["batch", _.batchName],
|
||||
params: { batch: _.batchName },
|
||||
auto: !0,
|
||||
}),
|
||||
v = Y({
|
||||
url: "lms.lms.utils.get_batch_courses",
|
||||
params: { batch: _.batchName },
|
||||
cache: ["batchCourses", _.batchName],
|
||||
auto: !0,
|
||||
}),
|
||||
r = D(() => {
|
||||
var i, n;
|
||||
let d = [
|
||||
{ label: "All Batches", route: { name: "Batches" } },
|
||||
];
|
||||
return (
|
||||
d.push({
|
||||
label:
|
||||
(i = e == null ? void 0 : e.data) == null
|
||||
? void 0
|
||||
: i.title,
|
||||
route: {
|
||||
name: "BatchDetail",
|
||||
params: {
|
||||
batchName:
|
||||
(n = e == null ? void 0 : e.data) ==
|
||||
null
|
||||
? void 0
|
||||
: n.name,
|
||||
},
|
||||
},
|
||||
}),
|
||||
d
|
||||
);
|
||||
});
|
||||
return (d, i) => {
|
||||
const n = N("router-link");
|
||||
return t(e).data
|
||||
? (l(),
|
||||
m("div", R, [
|
||||
a("header", q, [
|
||||
u(t(T), { items: r.value }, null, 8, ["items"]),
|
||||
]),
|
||||
a("div", I, [
|
||||
a("div", null, [
|
||||
a("div", K, s(t(e).data.title), 1),
|
||||
a("div", P, s(t(e).data.description), 1),
|
||||
a("div", X, [
|
||||
a("div", Z, [
|
||||
u(t($), {
|
||||
class: "h-4 w-4 text-gray-700 mr-2",
|
||||
}),
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
s(t(e).data.courses.length) +
|
||||
" " +
|
||||
s(d.__("Courses")),
|
||||
1
|
||||
),
|
||||
]),
|
||||
t(e).data.courses
|
||||
? (l(), m("span", G, "\xB7"))
|
||||
: o("", !0),
|
||||
a("div", J, [
|
||||
u(t(B), {
|
||||
class: "h-4 w-4 text-gray-700 mr-2",
|
||||
}),
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
s(
|
||||
t(y)(
|
||||
t(e).data.start_date
|
||||
).format("DD MMM YYYY")
|
||||
) +
|
||||
" - " +
|
||||
s(
|
||||
t(y)(
|
||||
t(e).data.end_date
|
||||
).format("DD MMM YYYY")
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
t(e).data.start_date
|
||||
? (l(), m("span", Q, "\xB7"))
|
||||
: o("", !0),
|
||||
a("div", U, [
|
||||
u(t(C), {
|
||||
class: "h-4 w-4 text-gray-700 mr-2",
|
||||
}),
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
s(t(p)(t(e).data.start_time)) +
|
||||
" - " +
|
||||
s(t(p)(t(e).data.end_time)),
|
||||
1
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
a("div", W, [
|
||||
a("div", tt, [
|
||||
a(
|
||||
"div",
|
||||
{
|
||||
innerHTML:
|
||||
t(e).data.batch_details,
|
||||
class: "batch-description",
|
||||
},
|
||||
null,
|
||||
8,
|
||||
at
|
||||
),
|
||||
]),
|
||||
a("div", null, [
|
||||
u(F, { batch: t(e) }, null, 8, [
|
||||
"batch",
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
a("div", null, [
|
||||
a("div", et, s(d.__("Courses")), 1),
|
||||
a("div", st, [
|
||||
t(e).data.courses
|
||||
? (l(!0),
|
||||
m(
|
||||
j,
|
||||
{ key: 0 },
|
||||
L(
|
||||
t(v).data,
|
||||
(h) => (
|
||||
l(),
|
||||
m(
|
||||
"div",
|
||||
{
|
||||
key: h.course,
|
||||
},
|
||||
[
|
||||
u(
|
||||
n,
|
||||
{
|
||||
to: {
|
||||
name: "CourseDetail",
|
||||
params: {
|
||||
courseName:
|
||||
h.name,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
default:
|
||||
f(
|
||||
() => [
|
||||
(l(),
|
||||
b(
|
||||
O,
|
||||
{
|
||||
course: h,
|
||||
key: h.name,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
"course",
|
||||
]
|
||||
)),
|
||||
]
|
||||
),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
["to"]
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
128
|
||||
))
|
||||
: o("", !0),
|
||||
]),
|
||||
t(e).data.batch_details_raw
|
||||
? (l(),
|
||||
m("div", ct, [
|
||||
a(
|
||||
"div",
|
||||
{
|
||||
innerHTML:
|
||||
t(e).data
|
||||
.batch_details_raw,
|
||||
class: "batch-description",
|
||||
},
|
||||
null,
|
||||
8,
|
||||
lt
|
||||
),
|
||||
]))
|
||||
: o("", !0),
|
||||
]),
|
||||
]),
|
||||
]))
|
||||
: o("", !0);
|
||||
};
|
||||
},
|
||||
};
|
||||
export { _t as default };
|
||||
1
lms/public/frontend/assets/BatchDetail.f109aa14.css
Normal file
1
lms/public/frontend/assets/BatchDetail.f109aa14.css
Normal file
@@ -0,0 +1 @@
|
||||
.batch-description p{margin-bottom:1rem;line-height:1.7}.batch-description li{line-height:1.7}.batch-description ol{list-style:auto;margin:revert;padding:revert}.batch-description strong{font-weight:600;color:#171717!important}
|
||||
1
lms/public/frontend/assets/Batches.70c9cf07.css
Normal file
1
lms/public/frontend/assets/Batches.70c9cf07.css
Normal file
@@ -0,0 +1 @@
|
||||
.short-introduction{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;text-overflow:ellipsis;width:100%;overflow:hidden;margin:.25rem 0 1.25rem;line-height:1.5}
|
||||
443
lms/public/frontend/assets/Batches.f9864378.js
Normal file
443
lms/public/frontend/assets/Batches.f9864378.js
Normal file
@@ -0,0 +1,443 @@
|
||||
import {
|
||||
a as C,
|
||||
s as n,
|
||||
u,
|
||||
y as g,
|
||||
z as h,
|
||||
X as _,
|
||||
E as t,
|
||||
D as c,
|
||||
a0 as y,
|
||||
F as x,
|
||||
A as a,
|
||||
C as i,
|
||||
k as D,
|
||||
r as Y,
|
||||
j as m,
|
||||
P as j,
|
||||
B as $,
|
||||
J as N,
|
||||
K as V,
|
||||
L as M,
|
||||
Z as z,
|
||||
$ as L,
|
||||
a1 as P,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
import { f as B } from "./index.05189aed.js";
|
||||
import { B as A } from "./index.43e529db.js";
|
||||
import { C as E, a as O } from "./clock.4d13ba48.js";
|
||||
import { P as S } from "./plus.8f4bce9f.js";
|
||||
const F = {
|
||||
class: "flex flex-col border border-gray-200 rounded-md p-4 h-full",
|
||||
style: { "min-height": "150px" },
|
||||
},
|
||||
T = { class: "text-xl font-semibold mb-1" },
|
||||
U = { class: "short-introduction" },
|
||||
I = { class: "mt-auto" },
|
||||
J = { key: 0, class: "font-semibold text-lg mb-4" },
|
||||
K = { class: "flex items-center mb-3" },
|
||||
R = { class: "flex items-center mb-3" },
|
||||
X = { class: "flex items-center" },
|
||||
Z = {
|
||||
__name: "BatchCard",
|
||||
props: { batch: { type: Object, default: null } },
|
||||
setup(s) {
|
||||
const d = C("$dayjs");
|
||||
return (o, v) => (
|
||||
n(),
|
||||
u("div", F, [
|
||||
s.batch.seat_count && s.batch.seats_left > 0
|
||||
? (n(),
|
||||
g(
|
||||
c(y),
|
||||
{
|
||||
key: 0,
|
||||
theme: "green",
|
||||
class: "self-start mb-2",
|
||||
},
|
||||
{
|
||||
default: h(() => [
|
||||
_(
|
||||
t(s.batch.seats_left) +
|
||||
" " +
|
||||
t(o.__("Seat Left")),
|
||||
1
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
}
|
||||
))
|
||||
: s.batch.seat_count && s.batch.seats_left <= 0
|
||||
? (n(),
|
||||
g(
|
||||
c(y),
|
||||
{
|
||||
key: 1,
|
||||
theme: "red",
|
||||
class: "self-start mb-2",
|
||||
},
|
||||
{
|
||||
default: h(() => [
|
||||
_(t(o.__("Sold Out")), 1),
|
||||
]),
|
||||
_: 1,
|
||||
}
|
||||
))
|
||||
: x("", !0),
|
||||
a("div", T, t(s.batch.title), 1),
|
||||
a("div", U, t(s.batch.description), 1),
|
||||
a("div", I, [
|
||||
s.batch.amount
|
||||
? (n(), u("div", J, t(s.batch.price), 1))
|
||||
: x("", !0),
|
||||
a("div", K, [
|
||||
i(c(A), {
|
||||
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
|
||||
}),
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
t(s.batch.courses.length) +
|
||||
" " +
|
||||
t(o.__("Courses")),
|
||||
1
|
||||
),
|
||||
]),
|
||||
a("div", R, [
|
||||
i(c(E), {
|
||||
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
|
||||
}),
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
t(
|
||||
c(d)(s.batch.start_date).format(
|
||||
"DD MMM YYYY"
|
||||
)
|
||||
) +
|
||||
" - " +
|
||||
t(
|
||||
c(d)(s.batch.end_date).format(
|
||||
"DD MMM YYYY"
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
a("div", X, [
|
||||
i(c(O), {
|
||||
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
|
||||
}),
|
||||
a(
|
||||
"span",
|
||||
null,
|
||||
t(c(B)(s.batch.start_time)) +
|
||||
" - " +
|
||||
t(c(B)(s.batch.end_time)),
|
||||
1
|
||||
),
|
||||
]),
|
||||
]),
|
||||
])
|
||||
);
|
||||
},
|
||||
},
|
||||
q = { class: "h-screen text-base" },
|
||||
G = {
|
||||
class: "sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5",
|
||||
},
|
||||
H = { class: "flex" },
|
||||
Q = { class: "mx-5 py-5" },
|
||||
W = {
|
||||
key: 0,
|
||||
class: "grid grid-cols-1 sm:grid-cols-3 md:grid-cols-4 gap-8 mt-5",
|
||||
},
|
||||
ee = {
|
||||
key: 1,
|
||||
class: "grid flex-1 place-items-center text-xl font-medium text-gray-500",
|
||||
},
|
||||
te = { class: "flex flex-col items-center justify-center mt-4" },
|
||||
re = {
|
||||
__name: "Batches",
|
||||
setup(s) {
|
||||
var p, k;
|
||||
const d = C("$user"),
|
||||
o = D({
|
||||
url: "lms.lms.utils.get_batches",
|
||||
cache: [
|
||||
"batches",
|
||||
(p = d == null ? void 0 : d.data) == null
|
||||
? void 0
|
||||
: p.email,
|
||||
],
|
||||
auto: !0,
|
||||
}),
|
||||
v = Y(0),
|
||||
f = [
|
||||
{
|
||||
label: "Upcoming",
|
||||
batches: m(() => {
|
||||
var e;
|
||||
return (
|
||||
((e = o.data) == null ? void 0 : e.upcoming) ||
|
||||
[]
|
||||
);
|
||||
}),
|
||||
count: m(() => {
|
||||
var e, l;
|
||||
return (l =
|
||||
(e = o.data) == null ? void 0 : e.upcoming) ==
|
||||
null
|
||||
? void 0
|
||||
: l.length;
|
||||
}),
|
||||
},
|
||||
];
|
||||
return (
|
||||
(k = d.data) != null &&
|
||||
k.is_moderator &&
|
||||
(f.push({
|
||||
label: "Archived",
|
||||
batches: m(() => {
|
||||
var e;
|
||||
return (e = o.data) == null ? void 0 : e.archived;
|
||||
}),
|
||||
count: m(() => {
|
||||
var e, l;
|
||||
return (l =
|
||||
(e = o.data) == null ? void 0 : e.archived) ==
|
||||
null
|
||||
? void 0
|
||||
: l.length;
|
||||
}),
|
||||
}),
|
||||
f.push({
|
||||
label: "Private",
|
||||
batches: m(() => {
|
||||
var e;
|
||||
return (e = o.data) == null ? void 0 : e.private;
|
||||
}),
|
||||
count: m(() => {
|
||||
var e, l;
|
||||
return (l =
|
||||
(e = o.data) == null ? void 0 : e.private) ==
|
||||
null
|
||||
? void 0
|
||||
: l.length;
|
||||
}),
|
||||
})),
|
||||
d.data &&
|
||||
f.push({
|
||||
label: "Enrolled",
|
||||
batches: m(() => {
|
||||
var e;
|
||||
return (e = o.data) == null ? void 0 : e.enrolled;
|
||||
}),
|
||||
count: m(() => {
|
||||
var e, l;
|
||||
return (l =
|
||||
(e = o.data) == null ? void 0 : e.enrolled) ==
|
||||
null
|
||||
? void 0
|
||||
: l.length;
|
||||
}),
|
||||
}),
|
||||
(e, l) => {
|
||||
const w = j("router-link");
|
||||
return (
|
||||
n(),
|
||||
u("div", q, [
|
||||
a("header", G, [
|
||||
i(
|
||||
c(z),
|
||||
{
|
||||
class: "h-7",
|
||||
items: [
|
||||
{
|
||||
label: e.__("All Batches"),
|
||||
route: { name: "Batches" },
|
||||
},
|
||||
],
|
||||
},
|
||||
null,
|
||||
8,
|
||||
["items"]
|
||||
),
|
||||
a("div", H, [
|
||||
i(
|
||||
c(L),
|
||||
{ variant: "solid" },
|
||||
{
|
||||
prefix: h(() => [
|
||||
i(c(S), { class: "h-4 w-4" }),
|
||||
]),
|
||||
default: h(() => [
|
||||
_(
|
||||
" " + t(e.__("New Batch")),
|
||||
1
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
}
|
||||
),
|
||||
]),
|
||||
]),
|
||||
a("div", Q, [
|
||||
i(
|
||||
c(P),
|
||||
{
|
||||
class: "overflow-hidden",
|
||||
modelValue: v.value,
|
||||
"onUpdate:modelValue":
|
||||
l[0] ||
|
||||
(l[0] = (r) => (v.value = r)),
|
||||
tabs: f,
|
||||
},
|
||||
{
|
||||
tab: h(({ tab: r, selected: b }) => [
|
||||
a("div", null, [
|
||||
a(
|
||||
"button",
|
||||
{
|
||||
class: $([
|
||||
"group -mb-px flex items-center gap-2 border-b border-transparent py-2.5 text-base text-gray-600 duration-300 ease-in-out hover:border-gray-400 hover:text-gray-900",
|
||||
{
|
||||
"text-gray-900":
|
||||
b,
|
||||
},
|
||||
]),
|
||||
},
|
||||
[
|
||||
r.icon
|
||||
? (n(),
|
||||
g(N(r.icon), {
|
||||
key: 0,
|
||||
class: "h-5",
|
||||
}))
|
||||
: x("", !0),
|
||||
_(
|
||||
" " +
|
||||
t(
|
||||
e.__(
|
||||
r.label
|
||||
)
|
||||
) +
|
||||
" ",
|
||||
1
|
||||
),
|
||||
i(
|
||||
c(y),
|
||||
{
|
||||
class: $({
|
||||
"text-gray-900 border border-gray-900":
|
||||
b,
|
||||
}),
|
||||
variant:
|
||||
"subtle",
|
||||
theme: "gray",
|
||||
size: "sm",
|
||||
},
|
||||
{
|
||||
default: h(
|
||||
() => [
|
||||
_(
|
||||
t(
|
||||
r.count
|
||||
),
|
||||
1
|
||||
),
|
||||
]
|
||||
),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
["class"]
|
||||
),
|
||||
],
|
||||
2
|
||||
),
|
||||
]),
|
||||
]),
|
||||
default: h(({ tab: r }) => [
|
||||
r.batches && r.batches.value.length
|
||||
? (n(),
|
||||
u("div", W, [
|
||||
(n(!0),
|
||||
u(
|
||||
V,
|
||||
null,
|
||||
M(
|
||||
r.batches.value,
|
||||
(b) => (
|
||||
n(),
|
||||
g(
|
||||
w,
|
||||
{
|
||||
to: {
|
||||
name: "BatchDetail",
|
||||
params: {
|
||||
batchName:
|
||||
b.name,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
default:
|
||||
h(
|
||||
() => [
|
||||
i(
|
||||
Z,
|
||||
{
|
||||
batch: b,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
"batch",
|
||||
]
|
||||
),
|
||||
]
|
||||
),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
["to"]
|
||||
)
|
||||
)
|
||||
),
|
||||
256
|
||||
)),
|
||||
]))
|
||||
: (n(),
|
||||
u("div", ee, [
|
||||
a("div", te, [
|
||||
a(
|
||||
"div",
|
||||
null,
|
||||
t(
|
||||
e
|
||||
.__(
|
||||
"No {0} batches found"
|
||||
)
|
||||
.format(
|
||||
r.label.toLowerCase()
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
])),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
["modelValue"]
|
||||
),
|
||||
]),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
};
|
||||
export { re as default };
|
||||
@@ -1 +1 @@
|
||||
.course-image{height:168px;width:100%;background-size:cover;background-position:center;background-repeat:no-repeat}.course-card-pills{background:#ffffff;margin-left:0;margin-right:.5rem;padding:3.5px 8px;font-size:11px;text-align:center;letter-spacing:.011em;text-transform:uppercase;font-weight:600;width:-moz-fit-content;width:fit-content}.default-image{display:flex;flex-direction:column;align-items:center;background-color:#ededed;color:#525252}
|
||||
.course-image{height:168px;width:100%;background-size:cover;background-position:center;background-repeat:no-repeat}.course-card-pills{background:#ffffff;margin-left:0;margin-right:.5rem;padding:3.5px 8px;font-size:11px;text-align:center;letter-spacing:.011em;text-transform:uppercase;font-weight:600;width:-moz-fit-content;width:fit-content}.default-image{display:flex;flex-direction:column;align-items:center;background-color:#ededed;color:#525252}.avatar-group{display:inline-flex;align-items:center}.avatar-group .avatar{transition:margin .1s ease-in-out}.image-placeholder{display:flex;align-items:center;flex:1;font-size:5rem;color:#525252;font-weight:600}.avatar-group.overlap .avatar+.avatar{margin-left:-8px}.short-introduction{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;text-overflow:ellipsis;width:100%;overflow:hidden;margin:.25rem 0 1.25rem;line-height:1.5}
|
||||
298
lms/public/frontend/assets/CourseCard.6a41330a.js
Normal file
298
lms/public/frontend/assets/CourseCard.6a41330a.js
Normal file
@@ -0,0 +1,298 @@
|
||||
import { _ as f } from "./UserAvatar.b64a03ac.js";
|
||||
import { s as g, B as v, U as y } from "./index.43e529db.js";
|
||||
import {
|
||||
s,
|
||||
u as r,
|
||||
A as o,
|
||||
K as i,
|
||||
L as d,
|
||||
E as t,
|
||||
F as c,
|
||||
B as m,
|
||||
a2 as h,
|
||||
C as n,
|
||||
D as a,
|
||||
z as x,
|
||||
X as b,
|
||||
a0 as k,
|
||||
y as w,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
import { S as _ } from "./star.d3e8ecca.js";
|
||||
const C = {
|
||||
key: 0,
|
||||
class: "flex flex-col border border-gray-200 h-full rounded-md shadow-sm text-base overflow-auto",
|
||||
style: { "min-height": "320px" },
|
||||
},
|
||||
B = { class: "flex relative top-4 left-4 w-fit" },
|
||||
S = { class: "course-card-pills rounded-md border border-gray-200" },
|
||||
z = { key: 0, class: "image-placeholder" },
|
||||
N = { class: "flex flex-col flex-auto p-4" },
|
||||
U = { class: "flex items-center justify-between mb-2" },
|
||||
V = { key: 0, class: "flex items-center space-x-1 py-1" },
|
||||
j = { key: 1, class: "flex items-center space-x-1 py-1" },
|
||||
A = { key: 2, class: "flex items-center space-x-1 py-1" },
|
||||
D = { key: 3 },
|
||||
E = { class: "text-xl font-semibold" },
|
||||
F = { class: "short-introduction" },
|
||||
I = { key: 0, class: "w-full bg-gray-200 rounded-full h-1 mb-2" },
|
||||
L = { key: 1, class: "text-sm mb-4" },
|
||||
M = { class: "flex items-center justify-between mt-auto" },
|
||||
O = { class: "flex avatar-group overlap" },
|
||||
R = { key: 0 },
|
||||
$ = { key: 1 },
|
||||
K = { key: 2 },
|
||||
T = { class: "font-semibold" },
|
||||
Q = {
|
||||
__name: "CourseCard",
|
||||
props: { course: { type: Object, default: null } },
|
||||
setup(e) {
|
||||
const { user: u } = g();
|
||||
return (X, q) =>
|
||||
e.course.title
|
||||
? (s(),
|
||||
r("div", C, [
|
||||
o(
|
||||
"div",
|
||||
{
|
||||
class: m([
|
||||
"course-image",
|
||||
{ "default-image": !e.course.image },
|
||||
]),
|
||||
style: h({
|
||||
backgroundImage:
|
||||
"url(" +
|
||||
encodeURI(e.course.image) +
|
||||
")",
|
||||
}),
|
||||
},
|
||||
[
|
||||
o("div", B, [
|
||||
(s(!0),
|
||||
r(
|
||||
i,
|
||||
null,
|
||||
d(
|
||||
e.course.tags,
|
||||
(l) => (
|
||||
s(), r("div", S, t(l), 1)
|
||||
)
|
||||
),
|
||||
256
|
||||
)),
|
||||
]),
|
||||
e.course.image
|
||||
? c("", !0)
|
||||
: (s(),
|
||||
r("div", z, t(e.course.title[0]), 1)),
|
||||
],
|
||||
6
|
||||
),
|
||||
o("div", N, [
|
||||
o("div", U, [
|
||||
e.course.lesson_count
|
||||
? (s(),
|
||||
r("div", V, [
|
||||
n(a(v), {
|
||||
class: "h-4 w-4 stroke-1.5 text-gray-700",
|
||||
}),
|
||||
o(
|
||||
"span",
|
||||
null,
|
||||
t(e.course.lesson_count),
|
||||
1
|
||||
),
|
||||
]))
|
||||
: c("", !0),
|
||||
e.course.enrollment_count
|
||||
? (s(),
|
||||
r("div", j, [
|
||||
n(a(y), {
|
||||
class: "h-4 w-4 stroke-1.5 text-gray-700",
|
||||
}),
|
||||
o(
|
||||
"span",
|
||||
null,
|
||||
t(
|
||||
e.course
|
||||
.enrollment_count
|
||||
),
|
||||
1
|
||||
),
|
||||
]))
|
||||
: c("", !0),
|
||||
e.course.avg_rating
|
||||
? (s(),
|
||||
r("div", A, [
|
||||
n(a(_), {
|
||||
class: "h-4 w-4 stroke-1.5 text-gray-700",
|
||||
}),
|
||||
o(
|
||||
"span",
|
||||
null,
|
||||
t(e.course.avg_rating),
|
||||
1
|
||||
),
|
||||
]))
|
||||
: c("", !0),
|
||||
e.course.status != "Approved"
|
||||
? (s(),
|
||||
r("div", D, [
|
||||
n(
|
||||
a(k),
|
||||
{
|
||||
variant: "solid",
|
||||
theme:
|
||||
e.course.status ===
|
||||
"Under Review"
|
||||
? "orange"
|
||||
: "blue",
|
||||
size: "sm",
|
||||
},
|
||||
{
|
||||
default: x(() => [
|
||||
b(
|
||||
t(
|
||||
e.course
|
||||
.status
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
["theme"]
|
||||
),
|
||||
]))
|
||||
: c("", !0),
|
||||
]),
|
||||
o("div", E, t(e.course.title), 1),
|
||||
o("div", F, t(e.course.short_introduction), 1),
|
||||
a(u) && e.course.membership
|
||||
? (s(),
|
||||
r("div", I, [
|
||||
o(
|
||||
"div",
|
||||
{
|
||||
class: "bg-gray-900 h-1 rounded-full",
|
||||
style: h({
|
||||
width:
|
||||
Math.ceil(
|
||||
e.course
|
||||
.membership
|
||||
.progress
|
||||
) + "%",
|
||||
}),
|
||||
},
|
||||
null,
|
||||
4
|
||||
),
|
||||
]))
|
||||
: c("", !0),
|
||||
a(u) && e.course.membership
|
||||
? (s(),
|
||||
r(
|
||||
"div",
|
||||
L,
|
||||
t(
|
||||
Math.ceil(
|
||||
e.course.membership.progress
|
||||
)
|
||||
) + "% completed ",
|
||||
1
|
||||
))
|
||||
: c("", !0),
|
||||
o("div", M, [
|
||||
o("div", O, [
|
||||
o(
|
||||
"div",
|
||||
{
|
||||
class: m([
|
||||
"mr-1",
|
||||
{
|
||||
"avatar-group overlap":
|
||||
e.course.instructors
|
||||
.length > 1,
|
||||
},
|
||||
]),
|
||||
},
|
||||
[
|
||||
(s(!0),
|
||||
r(
|
||||
i,
|
||||
null,
|
||||
d(
|
||||
e.course.instructors,
|
||||
(l) => (
|
||||
s(),
|
||||
w(
|
||||
f,
|
||||
{ user: l },
|
||||
null,
|
||||
8,
|
||||
["user"]
|
||||
)
|
||||
)
|
||||
),
|
||||
256
|
||||
)),
|
||||
],
|
||||
2
|
||||
),
|
||||
e.course.instructors.length == 1
|
||||
? (s(),
|
||||
r(
|
||||
"span",
|
||||
R,
|
||||
t(
|
||||
e.course.instructors[0]
|
||||
.full_name
|
||||
),
|
||||
1
|
||||
))
|
||||
: c("", !0),
|
||||
e.course.instructors.length == 2
|
||||
? (s(),
|
||||
r(
|
||||
"span",
|
||||
$,
|
||||
t(
|
||||
e.course.instructors[0]
|
||||
.first_name
|
||||
) +
|
||||
" and " +
|
||||
t(
|
||||
e.course
|
||||
.instructors[1]
|
||||
.first_name
|
||||
),
|
||||
1
|
||||
))
|
||||
: c("", !0),
|
||||
e.course.instructors.length > 2
|
||||
? (s(),
|
||||
r(
|
||||
"span",
|
||||
K,
|
||||
t(
|
||||
e.course.instructors[0]
|
||||
.first_name
|
||||
) +
|
||||
" and " +
|
||||
t(
|
||||
e.course.instructors
|
||||
.length - 1
|
||||
) +
|
||||
" others ",
|
||||
1
|
||||
))
|
||||
: c("", !0),
|
||||
]),
|
||||
o("div", T, t(e.course.price), 1),
|
||||
]),
|
||||
]),
|
||||
]))
|
||||
: c("", !0);
|
||||
},
|
||||
};
|
||||
export { Q as _ };
|
||||
1
lms/public/frontend/assets/CourseDetail.6888eccf.css
Normal file
1
lms/public/frontend/assets/CourseDetail.6888eccf.css
Normal file
@@ -0,0 +1 @@
|
||||
.course-description p{margin-bottom:1rem;line-height:1.7}.course-description li{line-height:1.7}.course-description ol{list-style:auto;margin:revert;padding:revert}.avatar-group{display:inline-flex;align-items:center}.avatar-group .avatar{transition:margin .1s ease-in-out}
|
||||
1046
lms/public/frontend/assets/CourseDetail.f6fd1d68.js
Normal file
1046
lms/public/frontend/assets/CourseDetail.f6fd1d68.js
Normal file
File diff suppressed because it is too large
Load Diff
1
lms/public/frontend/assets/CourseOutline.6dd858fb.css
Normal file
1
lms/public/frontend/assets/CourseOutline.6dd858fb.css
Normal file
@@ -0,0 +1 @@
|
||||
.outline-lesson:has(.router-link-active){background-color:#f3f3f3;padding:.5rem 0 .5rem 2rem}
|
||||
277
lms/public/frontend/assets/CourseOutline.df6c648a.js
Normal file
277
lms/public/frontend/assets/CourseOutline.df6c648a.js
Normal file
@@ -0,0 +1,277 @@
|
||||
import {
|
||||
a8 as C,
|
||||
k as b,
|
||||
P as N,
|
||||
s as e,
|
||||
u as o,
|
||||
A as r,
|
||||
K as d,
|
||||
L as h,
|
||||
y as n,
|
||||
z as c,
|
||||
C as l,
|
||||
D as t,
|
||||
a9 as w,
|
||||
B as M,
|
||||
E as _,
|
||||
aa as V,
|
||||
F as z,
|
||||
X as B,
|
||||
ab as I,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
import { c as i } from "./index.43e529db.js";
|
||||
const L = i("ChevronRightIcon", [
|
||||
["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }],
|
||||
]),
|
||||
F = i("FileTextIcon", [
|
||||
[
|
||||
"path",
|
||||
{
|
||||
d: "M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z",
|
||||
key: "1nnpy2",
|
||||
},
|
||||
],
|
||||
["polyline", { points: "14 2 14 8 20 8", key: "1ew0cm" }],
|
||||
["line", { x1: "16", x2: "8", y1: "13", y2: "13", key: "14keom" }],
|
||||
["line", { x1: "16", x2: "8", y1: "17", y2: "17", key: "17nazh" }],
|
||||
["line", { x1: "10", x2: "8", y1: "9", y2: "9", key: "1a5vjj" }],
|
||||
]),
|
||||
O = i("HelpCircleIcon", [
|
||||
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
||||
["path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3", key: "1u773s" }],
|
||||
["path", { d: "M12 17h.01", key: "p32p05" }],
|
||||
]),
|
||||
R = i("MonitorPlayIcon", [
|
||||
["path", { d: "m10 7 5 3-5 3Z", key: "29ljg6" }],
|
||||
[
|
||||
"rect",
|
||||
{
|
||||
width: "20",
|
||||
height: "14",
|
||||
x: "2",
|
||||
y: "3",
|
||||
rx: "2",
|
||||
key: "48i651",
|
||||
},
|
||||
],
|
||||
["path", { d: "M12 17v4", key: "1riwvh" }],
|
||||
["path", { d: "M8 21h8", key: "1ev6f3" }],
|
||||
]);
|
||||
const j = { class: "course-outline text-base" },
|
||||
q = { class: "mt-4" },
|
||||
H = { class: "text-base" },
|
||||
P = { class: "outline-lesson mb-2 pl-9" },
|
||||
T = { class: "flex items-center text-sm" },
|
||||
X = {
|
||||
__name: "CourseOutline",
|
||||
props: { courseName: { type: String, required: !0 } },
|
||||
setup(m) {
|
||||
const k = C(),
|
||||
y = m,
|
||||
x = b({
|
||||
url: "lms.lms.utils.get_course_outline",
|
||||
cache: ["course_outline", y.courseName],
|
||||
params: { course: y.courseName },
|
||||
auto: !0,
|
||||
}),
|
||||
v = (u) => u == k.params.chapterNumber || u == 1;
|
||||
return (u, D) => {
|
||||
const f = N("router-link");
|
||||
return (
|
||||
e(),
|
||||
o("div", j, [
|
||||
r("div", q, [
|
||||
(e(!0),
|
||||
o(
|
||||
d,
|
||||
null,
|
||||
h(
|
||||
t(x).data,
|
||||
(a, g) => (
|
||||
e(),
|
||||
n(
|
||||
t(I),
|
||||
{
|
||||
key: a.name,
|
||||
defaultOpen: v(a.idx),
|
||||
},
|
||||
{
|
||||
default: c(({ open: p }) => [
|
||||
l(
|
||||
t(w),
|
||||
{
|
||||
class: "flex w-full px-2 pt-2 pb-3",
|
||||
},
|
||||
{
|
||||
default: c(() => [
|
||||
l(
|
||||
t(L),
|
||||
{
|
||||
class: M(
|
||||
[
|
||||
{
|
||||
"rotate-90 transform duration-200":
|
||||
p,
|
||||
"duration-200":
|
||||
!p,
|
||||
open:
|
||||
g ==
|
||||
1,
|
||||
},
|
||||
"h-5 w-5 text-gray-900 stroke-1 mr-2",
|
||||
]
|
||||
),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
["class"]
|
||||
),
|
||||
r(
|
||||
"div",
|
||||
H,
|
||||
_(a.title),
|
||||
1
|
||||
),
|
||||
]),
|
||||
_: 2,
|
||||
},
|
||||
1024
|
||||
),
|
||||
l(
|
||||
t(V),
|
||||
{ class: "pb-2" },
|
||||
{
|
||||
default: c(() => [
|
||||
(e(!0),
|
||||
o(
|
||||
d,
|
||||
null,
|
||||
h(
|
||||
a.lessons,
|
||||
(s) => (
|
||||
e(),
|
||||
o(
|
||||
"div",
|
||||
{
|
||||
key: s.name,
|
||||
},
|
||||
[
|
||||
r(
|
||||
"div",
|
||||
P,
|
||||
[
|
||||
l(
|
||||
f,
|
||||
{
|
||||
to: {
|
||||
name: "Lesson",
|
||||
params: {
|
||||
courseName:
|
||||
m.courseName,
|
||||
chapterNumber:
|
||||
s.number.split(
|
||||
"."
|
||||
)[0],
|
||||
lessonNumber:
|
||||
s.number.split(
|
||||
"."
|
||||
)[1],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
default:
|
||||
c(
|
||||
() => [
|
||||
r(
|
||||
"div",
|
||||
T,
|
||||
[
|
||||
s.icon ===
|
||||
"icon-youtube"
|
||||
? (e(),
|
||||
n(
|
||||
t(
|
||||
R
|
||||
),
|
||||
{
|
||||
key: 0,
|
||||
class: "h-4 w-4 text-gray-900 stroke-1 mr-2",
|
||||
}
|
||||
))
|
||||
: s.icon ===
|
||||
"icon-quiz"
|
||||
? (e(),
|
||||
n(
|
||||
t(
|
||||
O
|
||||
),
|
||||
{
|
||||
key: 1,
|
||||
class: "h-4 w-4 text-gray-900 stroke-1 mr-2",
|
||||
}
|
||||
))
|
||||
: s.icon ===
|
||||
"icon-list"
|
||||
? (e(),
|
||||
n(
|
||||
t(
|
||||
F
|
||||
),
|
||||
{
|
||||
key: 2,
|
||||
class: "h-4 w-4 text-gray-900 stroke-1 mr-2",
|
||||
}
|
||||
))
|
||||
: z(
|
||||
"",
|
||||
!0
|
||||
),
|
||||
B(
|
||||
" " +
|
||||
_(
|
||||
s.title
|
||||
),
|
||||
1
|
||||
),
|
||||
]
|
||||
),
|
||||
]
|
||||
),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
[
|
||||
"to",
|
||||
]
|
||||
),
|
||||
]
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
128
|
||||
)),
|
||||
]),
|
||||
_: 2,
|
||||
},
|
||||
1024
|
||||
),
|
||||
]),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
["defaultOpen"]
|
||||
)
|
||||
)
|
||||
),
|
||||
128
|
||||
)),
|
||||
]),
|
||||
])
|
||||
);
|
||||
};
|
||||
},
|
||||
};
|
||||
export { L as C, X as _ };
|
||||
@@ -1,286 +0,0 @@
|
||||
var N = Object.defineProperty,
|
||||
S = Object.defineProperties;
|
||||
var j = Object.getOwnPropertyDescriptors;
|
||||
var h = Object.getOwnPropertySymbols;
|
||||
var b = Object.prototype.hasOwnProperty,
|
||||
w = Object.prototype.propertyIsEnumerable;
|
||||
var p = (e, s, t) =>
|
||||
s in e
|
||||
? N(e, s, {
|
||||
enumerable: !0,
|
||||
configurable: !0,
|
||||
writable: !0,
|
||||
value: t,
|
||||
})
|
||||
: (e[s] = t),
|
||||
m = (e, s) => {
|
||||
for (var t in s || (s = {})) b.call(s, t) && p(e, t, s[t]);
|
||||
if (h) for (var t of h(s)) w.call(s, t) && p(e, t, s[t]);
|
||||
return e;
|
||||
},
|
||||
g = (e, s) => S(e, j(s));
|
||||
var C = (e, s) => {
|
||||
var t = {};
|
||||
for (var a in e) b.call(e, a) && s.indexOf(a) < 0 && (t[a] = e[a]);
|
||||
if (e != null && h)
|
||||
for (var a of h(e)) s.indexOf(a) < 0 && w.call(e, a) && (t[a] = e[a]);
|
||||
return t;
|
||||
};
|
||||
import {
|
||||
l as $,
|
||||
o,
|
||||
d as c,
|
||||
k as r,
|
||||
F as v,
|
||||
m as y,
|
||||
t as l,
|
||||
n as B,
|
||||
p as z,
|
||||
q as A,
|
||||
e as n,
|
||||
u,
|
||||
v as O,
|
||||
x as q,
|
||||
y as U,
|
||||
z as V,
|
||||
} from "./frappe-ui.8966d601.js";
|
||||
var _ = {
|
||||
xmlns: "http://www.w3.org/2000/svg",
|
||||
width: 24,
|
||||
height: 24,
|
||||
viewBox: "0 0 24 24",
|
||||
fill: "none",
|
||||
stroke: "currentColor",
|
||||
"stroke-width": 2,
|
||||
"stroke-linecap": "round",
|
||||
"stroke-linejoin": "round",
|
||||
};
|
||||
const F = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(),
|
||||
f =
|
||||
(e, s) =>
|
||||
(oe, { attrs: d, slots: x }) => {
|
||||
var k = oe,
|
||||
{
|
||||
size: t,
|
||||
strokeWidth: a = 2,
|
||||
absoluteStrokeWidth: i,
|
||||
color: M,
|
||||
} = k,
|
||||
I = C(k, [
|
||||
"size",
|
||||
"strokeWidth",
|
||||
"absoluteStrokeWidth",
|
||||
"color",
|
||||
]);
|
||||
return $(
|
||||
"svg",
|
||||
m(
|
||||
g(
|
||||
m(
|
||||
g(m({}, _), {
|
||||
width: t || _.width,
|
||||
height: t || _.height,
|
||||
stroke: M || _.stroke,
|
||||
"stroke-width": i
|
||||
? (Number(a) * 24) / Number(t)
|
||||
: a,
|
||||
}),
|
||||
d
|
||||
),
|
||||
{
|
||||
class: [
|
||||
"lucide",
|
||||
`lucide-${F(e)}`,
|
||||
(d == null ? void 0 : d.class) || "",
|
||||
],
|
||||
}
|
||||
),
|
||||
I
|
||||
),
|
||||
[...s.map((L) => $(...L)), ...(x.default ? [x.default()] : [])]
|
||||
);
|
||||
},
|
||||
H = f("BookOpenIcon", [
|
||||
[
|
||||
"path",
|
||||
{ d: "M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z", key: "vv98re" },
|
||||
],
|
||||
[
|
||||
"path",
|
||||
{ d: "M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z", key: "1cyq3y" },
|
||||
],
|
||||
]),
|
||||
D = f("StarIcon", [
|
||||
[
|
||||
"polygon",
|
||||
{
|
||||
points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2",
|
||||
key: "8f66p6",
|
||||
},
|
||||
],
|
||||
]),
|
||||
E = f("UsersIcon", [
|
||||
[
|
||||
"path",
|
||||
{ d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2", key: "1yyitq" },
|
||||
],
|
||||
["circle", { cx: "9", cy: "7", r: "4", key: "nufk8" }],
|
||||
["path", { d: "M22 21v-2a4 4 0 0 0-3-3.87", key: "kshegd" }],
|
||||
["path", { d: "M16 3.13a4 4 0 0 1 0 7.75", key: "1da9ce" }],
|
||||
]);
|
||||
const K = {
|
||||
class: "flex flex-col h-full border border-gray-200 rounded-md shadow-sm mt-5",
|
||||
},
|
||||
P = { class: "flex relative top-4 left-4" },
|
||||
R = { class: "course-card-pills rounded-md border border-gray-200" },
|
||||
Z = { key: 0, class: "flex flex-1 text-4xl font-bold" },
|
||||
G = { class: "p-4" },
|
||||
J = { class: "flex text-base items-center justify-between" },
|
||||
Q = { class: "flex items-center space-x-1 py-1" },
|
||||
T = { class: "flex items-center space-x-1 py-1" },
|
||||
X = { class: "flex items-center space-x-1 py-1" },
|
||||
Y = { class: "text-2xl font-semibold" },
|
||||
W = { class: "text-ellipsis truncate text-base" },
|
||||
ee = {
|
||||
__name: "CourseCard",
|
||||
props: { course: { type: Object, default: null } },
|
||||
setup(e) {
|
||||
return (s, t) => (
|
||||
o(),
|
||||
c("div", K, [
|
||||
r(
|
||||
"div",
|
||||
{
|
||||
class: z([
|
||||
"course-image",
|
||||
{ "default-image": !e.course.image },
|
||||
]),
|
||||
style: A({
|
||||
backgroundImage: "url(" + e.course.image + ")",
|
||||
}),
|
||||
},
|
||||
[
|
||||
r("div", P, [
|
||||
(o(!0),
|
||||
c(
|
||||
v,
|
||||
null,
|
||||
y(
|
||||
e.course.tags,
|
||||
(a) => (o(), c("div", R, l(a), 1))
|
||||
),
|
||||
256
|
||||
)),
|
||||
]),
|
||||
e.course.image
|
||||
? B("", !0)
|
||||
: (o(), c("div", Z, l(e.course.title[0]), 1)),
|
||||
],
|
||||
6
|
||||
),
|
||||
r("div", G, [
|
||||
r("div", J, [
|
||||
r("div", Q, [
|
||||
n(u(H), { class: "h-4 w-4 text-gray-700" }),
|
||||
r("span", null, l(e.course.lesson_count), 1),
|
||||
]),
|
||||
r("div", T, [
|
||||
n(u(E), { class: "h-4 w-4 text-gray-700" }),
|
||||
r(
|
||||
"span",
|
||||
null,
|
||||
l(e.course.enrollment_count),
|
||||
1
|
||||
),
|
||||
]),
|
||||
r("div", X, [
|
||||
n(u(D), { class: "h-4 w-4 text-gray-700" }),
|
||||
r("span", null, l(e.course.avg_rating), 1),
|
||||
]),
|
||||
]),
|
||||
r("div", Y, l(e.course.title), 1),
|
||||
r("div", W, l(e.course.short_introduction), 1),
|
||||
(o(!0),
|
||||
c(
|
||||
v,
|
||||
null,
|
||||
y(e.course.instructors, (a) => (o(), c("div"))),
|
||||
256
|
||||
)),
|
||||
]),
|
||||
])
|
||||
);
|
||||
},
|
||||
},
|
||||
se = {
|
||||
__name: "UserAvatar",
|
||||
props: { user: { type: Object, default: null } },
|
||||
setup(e) {
|
||||
return (s, t) =>
|
||||
e.user
|
||||
? (o(),
|
||||
O(
|
||||
u(U),
|
||||
q(
|
||||
{
|
||||
key: 0,
|
||||
class: "",
|
||||
label: e.user.full_name,
|
||||
image: e.user.user_image,
|
||||
},
|
||||
s.$attrs
|
||||
),
|
||||
null,
|
||||
16,
|
||||
["label", "image"]
|
||||
))
|
||||
: B("", !0);
|
||||
},
|
||||
},
|
||||
te = { class: "container" },
|
||||
ae = r("div", { class: "text-2xl font-semibold" }, " All Courses ", -1),
|
||||
re = { class: "grid grid-cols-3 gap-8" },
|
||||
ne = {
|
||||
__name: "Courses",
|
||||
setup(e) {
|
||||
const s = V({
|
||||
type: "list",
|
||||
doctype: "LMS Course",
|
||||
url: "lms.lms.utils.get_courses",
|
||||
auto: !0,
|
||||
});
|
||||
return (t, a) => (
|
||||
o(),
|
||||
c("div", te, [
|
||||
ae,
|
||||
r("div", re, [
|
||||
(o(!0),
|
||||
c(
|
||||
v,
|
||||
null,
|
||||
y(
|
||||
u(s).data,
|
||||
(i) => (
|
||||
o(),
|
||||
c("div", null, [
|
||||
n(ee, { course: i }, null, 8, [
|
||||
"course",
|
||||
]),
|
||||
n(
|
||||
se,
|
||||
{ user: i.instructors[0] },
|
||||
null,
|
||||
8,
|
||||
["user"]
|
||||
),
|
||||
])
|
||||
)
|
||||
),
|
||||
256
|
||||
)),
|
||||
]),
|
||||
])
|
||||
);
|
||||
},
|
||||
};
|
||||
export { ne as default };
|
||||
433
lms/public/frontend/assets/Courses.3f5a0719.js
Normal file
433
lms/public/frontend/assets/Courses.3f5a0719.js
Normal file
@@ -0,0 +1,433 @@
|
||||
import {
|
||||
a as k,
|
||||
Y as w,
|
||||
r as L,
|
||||
j as o,
|
||||
P as V,
|
||||
s as n,
|
||||
u as m,
|
||||
D as c,
|
||||
A as i,
|
||||
C as d,
|
||||
z as u,
|
||||
X as h,
|
||||
E as p,
|
||||
B as y,
|
||||
y as x,
|
||||
J as $,
|
||||
F as C,
|
||||
K as B,
|
||||
L as j,
|
||||
Z as z,
|
||||
$ as D,
|
||||
a0 as E,
|
||||
a1 as P,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
import { _ as U } from "./CourseCard.6a41330a.js";
|
||||
import { P as A } from "./plus.8f4bce9f.js";
|
||||
import "./UserAvatar.b64a03ac.js";
|
||||
import "./index.43e529db.js";
|
||||
import "./star.d3e8ecca.js";
|
||||
const F = { class: "h-screen" },
|
||||
R = { key: 0 },
|
||||
S = {
|
||||
class: "sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5",
|
||||
},
|
||||
I = { class: "flex" },
|
||||
J = { class: "mx-5 py-5" },
|
||||
K = {
|
||||
key: 0,
|
||||
class: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8 mt-5",
|
||||
},
|
||||
M = {
|
||||
key: 1,
|
||||
class: "grid flex-1 place-items-center text-xl font-medium text-gray-500",
|
||||
},
|
||||
T = { class: "flex flex-col items-center justify-center mt-4" },
|
||||
Q = {
|
||||
__name: "Courses",
|
||||
setup(X) {
|
||||
var g, b, v;
|
||||
const l = k("$user"),
|
||||
a = w({
|
||||
type: "list",
|
||||
doctype: "LMS Course",
|
||||
cache: [
|
||||
"courses",
|
||||
(g = l == null ? void 0 : l.data) == null
|
||||
? void 0
|
||||
: g.email,
|
||||
],
|
||||
url: "lms.lms.utils.get_courses",
|
||||
auto: !0,
|
||||
}),
|
||||
f = L(0),
|
||||
_ = [
|
||||
{
|
||||
label: "Live",
|
||||
courses: o(() => {
|
||||
var e;
|
||||
return (
|
||||
((e = a.data) == null ? void 0 : e.live) || []
|
||||
);
|
||||
}),
|
||||
count: o(() => {
|
||||
var e, s;
|
||||
return (s =
|
||||
(e = a.data) == null ? void 0 : e.live) == null
|
||||
? void 0
|
||||
: s.length;
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: "Upcoming",
|
||||
courses: o(() => {
|
||||
var e;
|
||||
return (e = a.data) == null ? void 0 : e.upcoming;
|
||||
}),
|
||||
count: o(() => {
|
||||
var e, s;
|
||||
return (s =
|
||||
(e = a.data) == null ? void 0 : e.upcoming) ==
|
||||
null
|
||||
? void 0
|
||||
: s.length;
|
||||
}),
|
||||
},
|
||||
];
|
||||
return (
|
||||
l.data &&
|
||||
(_.push({
|
||||
label: "Enrolled",
|
||||
courses: o(() => {
|
||||
var e;
|
||||
return (e = a.data) == null ? void 0 : e.enrolled;
|
||||
}),
|
||||
count: o(() => {
|
||||
var e, s;
|
||||
return (s =
|
||||
(e = a.data) == null ? void 0 : e.enrolled) ==
|
||||
null
|
||||
? void 0
|
||||
: s.length;
|
||||
}),
|
||||
}),
|
||||
(l.data.is_moderator ||
|
||||
l.data.is_instructor ||
|
||||
((v = (b = a.data) == null ? void 0 : b.created) == null
|
||||
? void 0
|
||||
: v.length)) &&
|
||||
_.push({
|
||||
label: "Created",
|
||||
courses: o(() => {
|
||||
var e;
|
||||
return (e = a.data) == null
|
||||
? void 0
|
||||
: e.created;
|
||||
}),
|
||||
count: o(() => {
|
||||
var e, s;
|
||||
return (s =
|
||||
(e = a.data) == null
|
||||
? void 0
|
||||
: e.created) == null
|
||||
? void 0
|
||||
: s.length;
|
||||
}),
|
||||
}),
|
||||
l.data.is_moderator &&
|
||||
_.push({
|
||||
label: "Under Review",
|
||||
courses: o(() => {
|
||||
var e;
|
||||
return (e = a.data) == null
|
||||
? void 0
|
||||
: e.under_review;
|
||||
}),
|
||||
count: o(() => {
|
||||
var e, s;
|
||||
return (s =
|
||||
(e = a.data) == null
|
||||
? void 0
|
||||
: e.under_review) == null
|
||||
? void 0
|
||||
: s.length;
|
||||
}),
|
||||
})),
|
||||
(e, s) => {
|
||||
const N = V("router-link");
|
||||
return (
|
||||
n(),
|
||||
m("div", F, [
|
||||
c(a).data
|
||||
? (n(),
|
||||
m("div", R, [
|
||||
i("header", S, [
|
||||
d(
|
||||
c(z),
|
||||
{
|
||||
class: "h-7",
|
||||
items: [
|
||||
{
|
||||
label: e.__(
|
||||
"All Courses"
|
||||
),
|
||||
route: {
|
||||
name: "Courses",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
null,
|
||||
8,
|
||||
["items"]
|
||||
),
|
||||
i("div", I, [
|
||||
d(
|
||||
c(D),
|
||||
{ variant: "solid" },
|
||||
{
|
||||
prefix: u(() => [
|
||||
d(c(A), {
|
||||
class: "h-4 w-4",
|
||||
}),
|
||||
]),
|
||||
default: u(() => [
|
||||
h(
|
||||
" " +
|
||||
p(
|
||||
e.__(
|
||||
"New Course"
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
}
|
||||
),
|
||||
]),
|
||||
]),
|
||||
i("div", J, [
|
||||
d(
|
||||
c(P),
|
||||
{
|
||||
class: "overflow-hidden",
|
||||
modelValue: f.value,
|
||||
"onUpdate:modelValue":
|
||||
s[0] ||
|
||||
(s[0] = (r) =>
|
||||
(f.value = r)),
|
||||
tabs: _,
|
||||
},
|
||||
{
|
||||
tab: u(
|
||||
({
|
||||
tab: r,
|
||||
selected: t,
|
||||
}) => [
|
||||
i("div", null, [
|
||||
i(
|
||||
"button",
|
||||
{
|
||||
class: y(
|
||||
[
|
||||
"group -mb-px flex items-center gap-2 border-b border-transparent py-2.5 text-base text-gray-600 duration-300 ease-in-out hover:border-gray-400 hover:text-gray-900",
|
||||
{
|
||||
"text-gray-900":
|
||||
t,
|
||||
},
|
||||
]
|
||||
),
|
||||
},
|
||||
[
|
||||
r.icon
|
||||
? (n(),
|
||||
x(
|
||||
$(
|
||||
r.icon
|
||||
),
|
||||
{
|
||||
key: 0,
|
||||
class: "h-5",
|
||||
}
|
||||
))
|
||||
: C(
|
||||
"",
|
||||
!0
|
||||
),
|
||||
h(
|
||||
" " +
|
||||
p(
|
||||
e.__(
|
||||
r.label
|
||||
)
|
||||
) +
|
||||
" ",
|
||||
1
|
||||
),
|
||||
d(
|
||||
c(
|
||||
E
|
||||
),
|
||||
{
|
||||
class: y(
|
||||
{
|
||||
"text-gray-900 border border-gray-900":
|
||||
t,
|
||||
}
|
||||
),
|
||||
variant:
|
||||
"subtle",
|
||||
theme: "gray",
|
||||
size: "sm",
|
||||
},
|
||||
{
|
||||
default:
|
||||
u(
|
||||
() => [
|
||||
h(
|
||||
p(
|
||||
r.count
|
||||
),
|
||||
1
|
||||
),
|
||||
]
|
||||
),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
[
|
||||
"class",
|
||||
]
|
||||
),
|
||||
],
|
||||
2
|
||||
),
|
||||
]),
|
||||
]
|
||||
),
|
||||
default: u(({ tab: r }) => [
|
||||
r.courses &&
|
||||
r.courses.value.length
|
||||
? (n(),
|
||||
m("div", K, [
|
||||
(n(!0),
|
||||
m(
|
||||
B,
|
||||
null,
|
||||
j(
|
||||
r
|
||||
.courses
|
||||
.value,
|
||||
(
|
||||
t
|
||||
) => (
|
||||
n(),
|
||||
x(
|
||||
N,
|
||||
{
|
||||
to:
|
||||
t.membership &&
|
||||
t.current_lesson
|
||||
? {
|
||||
name: "Lesson",
|
||||
params: {
|
||||
courseName:
|
||||
t.name,
|
||||
chapterNumber:
|
||||
t.current_lesson.split(
|
||||
"."
|
||||
)[0],
|
||||
lessonNumber:
|
||||
t.current_lesson.split(
|
||||
"."
|
||||
)[1],
|
||||
},
|
||||
}
|
||||
: t.membership
|
||||
? {
|
||||
name: "Lesson",
|
||||
params: {
|
||||
courseName:
|
||||
t.name,
|
||||
chapterNumber: 1,
|
||||
lessonNumber: 1,
|
||||
},
|
||||
}
|
||||
: {
|
||||
name: "CourseDetail",
|
||||
params: {
|
||||
courseName:
|
||||
t.name,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
default:
|
||||
u(
|
||||
() => [
|
||||
d(
|
||||
U,
|
||||
{
|
||||
course: t,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
"course",
|
||||
]
|
||||
),
|
||||
]
|
||||
),
|
||||
_: 2,
|
||||
},
|
||||
1032,
|
||||
[
|
||||
"to",
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
256
|
||||
)),
|
||||
]))
|
||||
: (n(),
|
||||
m("div", M, [
|
||||
i(
|
||||
"div",
|
||||
T,
|
||||
[
|
||||
i(
|
||||
"div",
|
||||
null,
|
||||
p(
|
||||
e
|
||||
.__(
|
||||
"No {0} courses found"
|
||||
)
|
||||
.format(
|
||||
r.label.toLowerCase()
|
||||
)
|
||||
),
|
||||
1
|
||||
),
|
||||
]
|
||||
),
|
||||
])),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
["modelValue"]
|
||||
),
|
||||
]),
|
||||
]))
|
||||
: C("", !0),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
};
|
||||
export { Q as default };
|
||||
@@ -1,21 +1,21 @@
|
||||
import {
|
||||
b as f,
|
||||
P as g,
|
||||
q as f,
|
||||
ai as g,
|
||||
T as _,
|
||||
r as d,
|
||||
o,
|
||||
v as l,
|
||||
w as r,
|
||||
A as p,
|
||||
B as C,
|
||||
C as k,
|
||||
k as a,
|
||||
d as c,
|
||||
F as u,
|
||||
m,
|
||||
q as h,
|
||||
p as b,
|
||||
} from "./frappe-ui.8966d601.js";
|
||||
P as c,
|
||||
s as o,
|
||||
y as l,
|
||||
z as r,
|
||||
I as p,
|
||||
aj as C,
|
||||
ak as k,
|
||||
A as a,
|
||||
u as d,
|
||||
K as u,
|
||||
L as m,
|
||||
a2 as h,
|
||||
B as b,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
const v = {
|
||||
name: "FontColor",
|
||||
props: ["editor"],
|
||||
@@ -67,17 +67,17 @@ const v = {
|
||||
B = a("div", { class: "text-sm text-gray-700" }, "Text Color", -1),
|
||||
P = { class: "mt-1 grid grid-cols-8 gap-1" },
|
||||
F = ["aria-label", "onClick"],
|
||||
w = a(
|
||||
D = a(
|
||||
"div",
|
||||
{ class: "mt-2 text-sm text-gray-700" },
|
||||
"Background Color",
|
||||
-1
|
||||
),
|
||||
D = { class: "mt-1 grid grid-cols-8 gap-1" },
|
||||
w = { class: "mt-1 grid grid-cols-8 gap-1" },
|
||||
T = ["aria-label", "onClick"];
|
||||
function A(t, z, E, R, $, n) {
|
||||
const i = d("Tooltip"),
|
||||
x = d("Popover");
|
||||
function z(t, A, j, E, R, n) {
|
||||
const i = c("Tooltip"),
|
||||
x = c("Popover");
|
||||
return (
|
||||
o(),
|
||||
l(
|
||||
@@ -96,7 +96,7 @@ function A(t, z, E, R, $, n) {
|
||||
B,
|
||||
a("div", P, [
|
||||
(o(!0),
|
||||
c(
|
||||
d(
|
||||
u,
|
||||
null,
|
||||
m(
|
||||
@@ -141,10 +141,10 @@ function A(t, z, E, R, $, n) {
|
||||
128
|
||||
)),
|
||||
]),
|
||||
w,
|
||||
a("div", D, [
|
||||
D,
|
||||
a("div", w, [
|
||||
(o(!0),
|
||||
c(
|
||||
d(
|
||||
u,
|
||||
null,
|
||||
m(
|
||||
@@ -202,5 +202,5 @@ function A(t, z, E, R, $, n) {
|
||||
)
|
||||
);
|
||||
}
|
||||
const G = f(v, [["render", A]]);
|
||||
const G = f(v, [["render", z]]);
|
||||
export { G as default };
|
||||
@@ -1,15 +1,15 @@
|
||||
import {
|
||||
b as d,
|
||||
D as g,
|
||||
r,
|
||||
o as m,
|
||||
d as f,
|
||||
e as t,
|
||||
w as s,
|
||||
j as l,
|
||||
k as p,
|
||||
t as u,
|
||||
} from "./frappe-ui.8966d601.js";
|
||||
q as d,
|
||||
O as g,
|
||||
P as r,
|
||||
s as m,
|
||||
u as f,
|
||||
C as s,
|
||||
z as t,
|
||||
X as l,
|
||||
A as u,
|
||||
E as p,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
const D = {
|
||||
name: "Home",
|
||||
data() {
|
||||
@@ -19,13 +19,13 @@ const D = {
|
||||
components: { Dialog: g },
|
||||
},
|
||||
_ = { class: "max-w-3xl py-12 mx-auto" };
|
||||
function k(e, o, w, C, n, V) {
|
||||
function C(e, o, k, w, n, V) {
|
||||
const a = r("Button"),
|
||||
c = r("Dialog");
|
||||
return (
|
||||
m(),
|
||||
f("div", _, [
|
||||
t(
|
||||
s(
|
||||
a,
|
||||
{
|
||||
"icon-left": "code",
|
||||
@@ -33,20 +33,20 @@ function k(e, o, w, C, n, V) {
|
||||
loading: e.$resources.ping.loading,
|
||||
},
|
||||
{
|
||||
default: s(() => [l(" Click to send 'ping' request ")]),
|
||||
default: t(() => [l(" Click to send 'ping' request ")]),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
["onClick", "loading"]
|
||||
),
|
||||
p("div", null, u(e.$resources.ping.data), 1),
|
||||
p("pre", null, u(e.$resources.ping), 1),
|
||||
t(
|
||||
u("div", null, p(e.$resources.ping.data), 1),
|
||||
u("pre", null, p(e.$resources.ping), 1),
|
||||
s(
|
||||
a,
|
||||
{ onClick: o[0] || (o[0] = (i) => (n.showDialog = !0)) },
|
||||
{ default: s(() => [l("Open Dialog")]), _: 1 }
|
||||
{ default: t(() => [l("Open Dialog")]), _: 1 }
|
||||
),
|
||||
t(
|
||||
s(
|
||||
c,
|
||||
{
|
||||
title: "Title",
|
||||
@@ -54,12 +54,12 @@ function k(e, o, w, C, n, V) {
|
||||
"onUpdate:modelValue":
|
||||
o[1] || (o[1] = (i) => (n.showDialog = i)),
|
||||
},
|
||||
{ default: s(() => [l(" Dialog content ")]), _: 1 },
|
||||
{ default: t(() => [l(" Dialog content ")]), _: 1 },
|
||||
8,
|
||||
["modelValue"]
|
||||
),
|
||||
])
|
||||
);
|
||||
}
|
||||
const B = d(D, [["render", k]]);
|
||||
const B = d(D, [["render", C]]);
|
||||
export { B as default };
|
||||
@@ -1,30 +1,30 @@
|
||||
import {
|
||||
b as f,
|
||||
h as I,
|
||||
D,
|
||||
G as h,
|
||||
r as d,
|
||||
o as m,
|
||||
d as c,
|
||||
A as _,
|
||||
B as y,
|
||||
C,
|
||||
e as n,
|
||||
w as s,
|
||||
k as r,
|
||||
t as w,
|
||||
n as b,
|
||||
j as u,
|
||||
F as k,
|
||||
} from "./frappe-ui.8966d601.js";
|
||||
const v = {
|
||||
q as I,
|
||||
$ as f,
|
||||
O as D,
|
||||
an as h,
|
||||
P as d,
|
||||
s as m,
|
||||
u as c,
|
||||
I as _,
|
||||
aj as y,
|
||||
ak as C,
|
||||
C as n,
|
||||
z as s,
|
||||
A as i,
|
||||
E as k,
|
||||
F as v,
|
||||
X as u,
|
||||
K as w,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
const b = {
|
||||
name: "InsertImage",
|
||||
props: ["editor"],
|
||||
expose: ["openDialog"],
|
||||
data() {
|
||||
return { addImageDialog: { url: "", file: null, show: !1 } };
|
||||
},
|
||||
components: { Button: I, Dialog: D },
|
||||
components: { Button: f, Dialog: D },
|
||||
methods: {
|
||||
openDialog() {
|
||||
this.addImageDialog.show = !0;
|
||||
@@ -33,8 +33,8 @@ const v = {
|
||||
let e = t.target.files[0];
|
||||
!e ||
|
||||
((this.addImageDialog.file = e),
|
||||
h(e).then((i) => {
|
||||
this.addImageDialog.url = i;
|
||||
h(e).then((r) => {
|
||||
this.addImageDialog.url = r;
|
||||
}));
|
||||
},
|
||||
addImage(t) {
|
||||
@@ -46,18 +46,18 @@ const v = {
|
||||
},
|
||||
},
|
||||
},
|
||||
B = {
|
||||
x = {
|
||||
class: "relative cursor-pointer rounded-lg bg-gray-100 py-1 focus-within:bg-gray-200 hover:bg-gray-200",
|
||||
},
|
||||
x = { class: "absolute inset-0 select-none px-2 py-1 text-base" },
|
||||
B = { class: "absolute inset-0 select-none px-2 py-1 text-base" },
|
||||
S = ["src"];
|
||||
function V(t, e, i, A, a, o) {
|
||||
function V(t, e, r, A, a, o) {
|
||||
const g = d("Button"),
|
||||
p = d("Dialog");
|
||||
return (
|
||||
m(),
|
||||
c(
|
||||
k,
|
||||
w,
|
||||
null,
|
||||
[
|
||||
_(t.$slots, "default", y(C({ onClick: o.openDialog }))),
|
||||
@@ -72,8 +72,8 @@ function V(t, e, i, A, a, o) {
|
||||
},
|
||||
{
|
||||
"body-content": s(() => [
|
||||
r("label", B, [
|
||||
r(
|
||||
i("label", x, [
|
||||
i(
|
||||
"input",
|
||||
{
|
||||
type: "file",
|
||||
@@ -88,10 +88,10 @@ function V(t, e, i, A, a, o) {
|
||||
null,
|
||||
32
|
||||
),
|
||||
r(
|
||||
i(
|
||||
"span",
|
||||
x,
|
||||
w(
|
||||
B,
|
||||
k(
|
||||
a.addImageDialog.file
|
||||
? "Select another image"
|
||||
: "Select an image"
|
||||
@@ -112,7 +112,7 @@ function V(t, e, i, A, a, o) {
|
||||
8,
|
||||
S
|
||||
))
|
||||
: b("", !0),
|
||||
: v("", !0),
|
||||
]),
|
||||
actions: s(() => [
|
||||
n(
|
||||
@@ -147,5 +147,5 @@ function V(t, e, i, A, a, o) {
|
||||
)
|
||||
);
|
||||
}
|
||||
const F = f(v, [["render", V]]);
|
||||
export { F as default };
|
||||
const P = I(b, [["render", V]]);
|
||||
export { P as default };
|
||||
@@ -1,20 +1,20 @@
|
||||
import {
|
||||
b as d,
|
||||
h as g,
|
||||
I as L,
|
||||
D as m,
|
||||
r as i,
|
||||
o as p,
|
||||
d as f,
|
||||
A as D,
|
||||
B as h,
|
||||
C as c,
|
||||
e as l,
|
||||
w as a,
|
||||
E as w,
|
||||
j as _,
|
||||
F as v,
|
||||
} from "./frappe-ui.8966d601.js";
|
||||
q as d,
|
||||
$ as g,
|
||||
al as L,
|
||||
O as m,
|
||||
P as i,
|
||||
s as p,
|
||||
u as f,
|
||||
I as D,
|
||||
aj as c,
|
||||
ak as h,
|
||||
C as l,
|
||||
z as a,
|
||||
am as _,
|
||||
X as v,
|
||||
K as w,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
const x = {
|
||||
name: "InsertLink",
|
||||
props: ["editor"],
|
||||
@@ -56,10 +56,10 @@ function V(t, e, C, B, n, s) {
|
||||
return (
|
||||
p(),
|
||||
f(
|
||||
v,
|
||||
w,
|
||||
null,
|
||||
[
|
||||
D(t.$slots, "default", h(c({ onClick: s.openDialog }))),
|
||||
D(t.$slots, "default", c(h({ onClick: s.openDialog }))),
|
||||
l(
|
||||
k,
|
||||
{
|
||||
@@ -83,7 +83,7 @@ function V(t, e, C, B, n, s) {
|
||||
(n.setLinkDialog.url = o)),
|
||||
onKeydown:
|
||||
e[1] ||
|
||||
(e[1] = w(
|
||||
(e[1] = _(
|
||||
(o) => s.setLink(o.target.value),
|
||||
["enter"]
|
||||
)),
|
||||
@@ -103,7 +103,7 @@ function V(t, e, C, B, n, s) {
|
||||
(e[2] = (o) =>
|
||||
s.setLink(n.setLinkDialog.url)),
|
||||
},
|
||||
{ default: a(() => [_(" Save ")]), _: 1 }
|
||||
{ default: a(() => [v(" Save ")]), _: 1 }
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
@@ -116,5 +116,5 @@ function V(t, e, C, B, n, s) {
|
||||
)
|
||||
);
|
||||
}
|
||||
const b = d(x, [["render", V]]);
|
||||
export { b as default };
|
||||
const y = d(x, [["render", V]]);
|
||||
export { y as default };
|
||||
@@ -1,24 +1,24 @@
|
||||
import {
|
||||
b as _,
|
||||
h as C,
|
||||
D as k,
|
||||
H as v,
|
||||
r,
|
||||
o as u,
|
||||
d as c,
|
||||
A as h,
|
||||
B,
|
||||
C as w,
|
||||
e as t,
|
||||
w as l,
|
||||
k as x,
|
||||
j as n,
|
||||
t as y,
|
||||
v as U,
|
||||
n as p,
|
||||
F,
|
||||
} from "./frappe-ui.8966d601.js";
|
||||
const A = {
|
||||
q as _,
|
||||
$ as C,
|
||||
O as k,
|
||||
ao as v,
|
||||
P as r,
|
||||
s as u,
|
||||
u as c,
|
||||
I as h,
|
||||
aj as x,
|
||||
ak as y,
|
||||
C as a,
|
||||
z as l,
|
||||
A as B,
|
||||
X as n,
|
||||
E as w,
|
||||
y as U,
|
||||
F as p,
|
||||
K as F,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
const I = {
|
||||
name: "InsertImage",
|
||||
props: ["editor"],
|
||||
expose: ["openDialog"],
|
||||
@@ -47,9 +47,9 @@ const A = {
|
||||
},
|
||||
},
|
||||
},
|
||||
I = { class: "flex items-center space-x-2" },
|
||||
A = { class: "flex items-center space-x-2" },
|
||||
N = ["src"];
|
||||
function S(i, o, b, L, e, a) {
|
||||
function S(i, o, P, z, e, t) {
|
||||
const s = r("Button"),
|
||||
V = r("FileUploader"),
|
||||
g = r("Dialog");
|
||||
@@ -59,19 +59,19 @@ function S(i, o, b, L, e, a) {
|
||||
F,
|
||||
null,
|
||||
[
|
||||
h(i.$slots, "default", B(w({ onClick: a.openDialog }))),
|
||||
t(
|
||||
h(i.$slots, "default", x(y({ onClick: t.openDialog }))),
|
||||
a(
|
||||
g,
|
||||
{
|
||||
options: { title: "Add Video" },
|
||||
modelValue: e.addVideoDialog.show,
|
||||
"onUpdate:modelValue":
|
||||
o[2] || (o[2] = (d) => (e.addVideoDialog.show = d)),
|
||||
onAfterLeave: a.reset,
|
||||
onAfterLeave: t.reset,
|
||||
},
|
||||
{
|
||||
"body-content": l(() => [
|
||||
t(
|
||||
a(
|
||||
V,
|
||||
{
|
||||
"file-types": "video/*",
|
||||
@@ -89,14 +89,14 @@ function S(i, o, b, L, e, a) {
|
||||
uploading: m,
|
||||
openFileSelector: D,
|
||||
}) => [
|
||||
x("div", I, [
|
||||
t(
|
||||
B("div", A, [
|
||||
a(
|
||||
s,
|
||||
{ onClick: D },
|
||||
{
|
||||
default: l(() => [
|
||||
n(
|
||||
y(
|
||||
w(
|
||||
m
|
||||
? `Uploading ${f}%`
|
||||
: e
|
||||
@@ -164,23 +164,23 @@ function S(i, o, b, L, e, a) {
|
||||
: p("", !0),
|
||||
]),
|
||||
actions: l(() => [
|
||||
t(
|
||||
a(
|
||||
s,
|
||||
{
|
||||
variant: "solid",
|
||||
onClick:
|
||||
o[1] ||
|
||||
(o[1] = (d) =>
|
||||
a.addVideo(e.addVideoDialog.url)),
|
||||
t.addVideo(e.addVideoDialog.url)),
|
||||
},
|
||||
{
|
||||
default: l(() => [n(" Insert Video ")]),
|
||||
_: 1,
|
||||
}
|
||||
),
|
||||
t(
|
||||
a(
|
||||
s,
|
||||
{ onClick: a.reset },
|
||||
{ onClick: t.reset },
|
||||
{ default: l(() => [n("Cancel")]), _: 1 },
|
||||
8,
|
||||
["onClick"]
|
||||
@@ -196,5 +196,5 @@ function S(i, o, b, L, e, a) {
|
||||
)
|
||||
);
|
||||
}
|
||||
const R = _(A, [["render", S]]);
|
||||
export { R as default };
|
||||
const L = _(I, [["render", S]]);
|
||||
export { L as default };
|
||||
1
lms/public/frontend/assets/Lesson.3532a62c.css
Normal file
1
lms/public/frontend/assets/Lesson.3532a62c.css
Normal file
@@ -0,0 +1 @@
|
||||
.avatar-group{display:inline-flex;align-items:center}.avatar-group .avatar{transition:margin .1s ease-in-out}iframe{border:1px solid #ddd;border-radius:.5rem;margin-bottom:1rem}.lesson-content p{margin-bottom:1rem;line-height:1.7}.lesson-content li{line-height:1.7}.lesson-content ol{list-style:auto;margin:revert;padding:1rem}.lesson-content ul{list-style:auto;padding:1rem;margin:revert}.lesson-content img{border:1px solid #EDEDED;border-radius:.5rem}.lesson-content code{display:block;overflow-x:auto;padding:1rem 1.25rem;background:#011627;color:#d6deeb;border-radius:.5rem;margin-bottom:1rem}.lesson-content a{color:#171717;text-decoration:underline;font-weight:500}
|
||||
5877
lms/public/frontend/assets/Lesson.c80fc3b7.js
Normal file
5877
lms/public/frontend/assets/Lesson.c80fc3b7.js
Normal file
File diff suppressed because one or more lines are too long
35
lms/public/frontend/assets/UserAvatar.b64a03ac.js
Normal file
35
lms/public/frontend/assets/UserAvatar.b64a03ac.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import {
|
||||
s as r,
|
||||
y as s,
|
||||
a3 as t,
|
||||
D as l,
|
||||
a4 as u,
|
||||
F as n,
|
||||
} from "./frappe-ui.f2211ca2.js";
|
||||
const i = {
|
||||
__name: "UserAvatar",
|
||||
props: { user: { type: Object, default: null }, size: { type: String } },
|
||||
setup(e) {
|
||||
return (a, m) =>
|
||||
e.user
|
||||
? (r(),
|
||||
s(
|
||||
l(u),
|
||||
t(
|
||||
{
|
||||
key: 0,
|
||||
class: "avatar border border-gray-300",
|
||||
label: e.user.full_name,
|
||||
image: e.user.user_image,
|
||||
size: e.size,
|
||||
},
|
||||
a.$attrs
|
||||
),
|
||||
null,
|
||||
16,
|
||||
["label", "image", "size"]
|
||||
))
|
||||
: n("", !0);
|
||||
},
|
||||
};
|
||||
export { i as _ };
|
||||
23
lms/public/frontend/assets/clock.4d13ba48.js
Normal file
23
lms/public/frontend/assets/clock.4d13ba48.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { c as e } from "./index.43e529db.js";
|
||||
const c = e("CalendarIcon", [
|
||||
[
|
||||
"rect",
|
||||
{
|
||||
width: "18",
|
||||
height: "18",
|
||||
x: "3",
|
||||
y: "4",
|
||||
rx: "2",
|
||||
ry: "2",
|
||||
key: "eu3xkr",
|
||||
},
|
||||
],
|
||||
["line", { x1: "16", x2: "16", y1: "2", y2: "6", key: "m3sa8f" }],
|
||||
["line", { x1: "8", x2: "8", y1: "2", y2: "6", key: "18kwsl" }],
|
||||
["line", { x1: "3", x2: "21", y1: "10", y2: "10", key: "xt86sb" }],
|
||||
]),
|
||||
l = e("ClockIcon", [
|
||||
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
||||
["polyline", { points: "12 6 12 12 16 14", key: "68esgv" }],
|
||||
]);
|
||||
export { c as C, l as a };
|
||||
@@ -1 +1 @@
|
||||
.form-select{background-image:url("data:image/svg+xml;utf8,<svg fill='none' width='8' xmlns='http://www.w3.org/2000/svg' viewBox='-4 -2 16 16'><path d='M4.5 3.636 6.136 2l1.637 1.636M4.5 8.364 6.136 10l1.637-1.636' stroke='%23333C44' stroke-linecap='round' stroke-linejoin='round'/></svg>")}.spinner[data-v-10b50c78]{animation:rotate-10b50c78 2s linear infinite}.spinner-path[data-v-10b50c78]{stroke-linecap:round;animation:dash-10b50c78 1.5s ease-in-out infinite}@keyframes rotate-10b50c78{to{transform:rotate(360deg)}}@keyframes dash-10b50c78{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}to{stroke-dasharray:120,150;stroke-dashoffset:-124}}.item{display:block;margin:0;width:100%;text-align:left;background:transparent;border-radius:.4rem;border:1px solid transparent;padding:.2rem .4rem}.item.is-selected{border-color:#000}.ProseMirror{outline:none;caret-color:#171717;word-break:break-word}.ProseMirror-focused:focus-visible{outline:none}.ProseMirror:not(.ProseMirror-focused) p.is-editor-empty:first-child:before{content:attr(data-placeholder);float:left;color:#999;pointer-events:none;height:0}.ProseMirror-selectednode video,img.ProseMirror-selectednode{outline:2px solid #E2E2E2}.mention{font-weight:600;-webkit-box-decoration-break:clone;box-decoration-break:clone}.prose table p{margin:0}.ProseMirror table .selectedCell:after{z-index:2;position:absolute;content:"";inset:0;pointer-events:none;background:#E3F1FD;opacity:.3}.ProseMirror table .column-resize-handle{position:absolute;right:-1px;top:0;bottom:-2px;width:4px;background-color:#e3f1fd;pointer-events:none}.resize-cursor{cursor:ew-resize;cursor:col-resize}.ProseMirror mark{border-radius:3px;padding:0 2px}
|
||||
.form-select{background-image:url("data:image/svg+xml;utf8,<svg fill='none' width='8' xmlns='http://www.w3.org/2000/svg' viewBox='-4 -2 16 16'><path d='M4.5 3.636 6.136 2l1.637 1.636M4.5 8.364 6.136 10l1.637-1.636' stroke='%23333C44' stroke-linecap='round' stroke-linejoin='round'/></svg>")}.spinner[data-v-d1174afc]{animation:rotate-d1174afc 2s linear infinite}.spinner-path[data-v-d1174afc]{stroke-linecap:round;animation:dash-d1174afc 1.5s ease-in-out infinite}@keyframes rotate-d1174afc{to{transform:rotate(360deg)}}@keyframes dash-d1174afc{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}to{stroke-dasharray:120,150;stroke-dashoffset:-124}}.item{display:block;margin:0;width:100%;text-align:left;background:transparent;border-radius:.4rem;border:1px solid transparent;padding:.2rem .4rem}.item.is-selected{border-color:#000}.ProseMirror{outline:none;caret-color:#171717;word-break:break-word}.ProseMirror-focused:focus-visible{outline:none}.ProseMirror:not(.ProseMirror-focused) p.is-editor-empty:first-child:before{content:attr(data-placeholder);float:left;color:#999;pointer-events:none;height:0}.ProseMirror-selectednode video,img.ProseMirror-selectednode{outline:2px solid #E2E2E2}.mention{font-weight:600;-webkit-box-decoration-break:clone;box-decoration-break:clone}.prose table p{margin:0}.ProseMirror table .selectedCell:after{z-index:2;position:absolute;content:"";inset:0;pointer-events:none;background:#E3F1FD;opacity:.3}.ProseMirror table .column-resize-handle{position:absolute;right:-1px;top:0;bottom:-2px;width:4px;background-color:#e3f1fd;pointer-events:none}.resize-cursor{cursor:ew-resize;cursor:col-resize}.ProseMirror mark{border-radius:3px;padding:0 2px}
|
||||
File diff suppressed because it is too large
Load Diff
45
lms/public/frontend/assets/index.05189aed.js
Normal file
45
lms/public/frontend/assets/index.05189aed.js
Normal file
@@ -0,0 +1,45 @@
|
||||
var u = Object.defineProperty;
|
||||
var o = Object.getOwnPropertySymbols;
|
||||
var i = Object.prototype.hasOwnProperty,
|
||||
c = Object.prototype.propertyIsEnumerable;
|
||||
var n = (t, e, r) =>
|
||||
e in t
|
||||
? u(t, e, {
|
||||
enumerable: !0,
|
||||
configurable: !0,
|
||||
writable: !0,
|
||||
value: r,
|
||||
})
|
||||
: (t[e] = r),
|
||||
a = (t, e) => {
|
||||
for (var r in e || (e = {})) i.call(e, r) && n(t, r, e[r]);
|
||||
if (o) for (var r of o(e)) c.call(e, r) && n(t, r, e[r]);
|
||||
return t;
|
||||
};
|
||||
import { ac as s, ad as f } from "./frappe-ui.f2211ca2.js";
|
||||
function y(t) {
|
||||
s(a({ position: "bottom-right" }, t));
|
||||
}
|
||||
function d(t) {
|
||||
return f(t).value;
|
||||
}
|
||||
function g(t) {
|
||||
if (!t) return "";
|
||||
const [e, r] = t.split(":").map(Number),
|
||||
m = new Date(0, 0, 0, e, r);
|
||||
return new Intl.DateTimeFormat("en-US", {
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
hour12: !0,
|
||||
}).format(m);
|
||||
}
|
||||
function h(t, e) {
|
||||
return t
|
||||
? t.toLocaleString("en-IN", {
|
||||
maximumFractionDigits: 0,
|
||||
style: "currency",
|
||||
currency: e,
|
||||
})
|
||||
: "";
|
||||
}
|
||||
export { h as a, y as c, g as f, d as t };
|
||||
1790
lms/public/frontend/assets/index.43e529db.js
Normal file
1790
lms/public/frontend/assets/index.43e529db.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,88 +0,0 @@
|
||||
import {
|
||||
c as u,
|
||||
a as l,
|
||||
_ as i,
|
||||
b as f,
|
||||
r as p,
|
||||
o as d,
|
||||
d as m,
|
||||
e as _,
|
||||
f as h,
|
||||
g as y,
|
||||
h as g,
|
||||
s as v,
|
||||
i as L,
|
||||
} from "./frappe-ui.8966d601.js";
|
||||
(function () {
|
||||
const o = document.createElement("link").relList;
|
||||
if (o && o.supports && o.supports("modulepreload")) return;
|
||||
for (const e of document.querySelectorAll('link[rel="modulepreload"]'))
|
||||
c(e);
|
||||
new MutationObserver((e) => {
|
||||
for (const t of e)
|
||||
if (t.type === "childList")
|
||||
for (const s of t.addedNodes)
|
||||
s.tagName === "LINK" && s.rel === "modulepreload" && c(s);
|
||||
}).observe(document, { childList: !0, subtree: !0 });
|
||||
function n(e) {
|
||||
const t = {};
|
||||
return (
|
||||
e.integrity && (t.integrity = e.integrity),
|
||||
e.referrerpolicy && (t.referrerPolicy = e.referrerpolicy),
|
||||
e.crossorigin === "use-credentials"
|
||||
? (t.credentials = "include")
|
||||
: e.crossorigin === "anonymous"
|
||||
? (t.credentials = "omit")
|
||||
: (t.credentials = "same-origin"),
|
||||
t
|
||||
);
|
||||
}
|
||||
function c(e) {
|
||||
if (e.ep) return;
|
||||
e.ep = !0;
|
||||
const t = n(e);
|
||||
fetch(e.href, t);
|
||||
}
|
||||
})();
|
||||
const E = [
|
||||
{
|
||||
path: "/",
|
||||
name: "Home",
|
||||
component: () =>
|
||||
i(
|
||||
() => import("./Home.24891fef.js"),
|
||||
[
|
||||
"assets/Home.24891fef.js",
|
||||
"assets/frappe-ui.8966d601.js",
|
||||
"assets/frappe-ui.e894a05e.css",
|
||||
]
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/courses",
|
||||
name: "Courses",
|
||||
component: () =>
|
||||
i(
|
||||
() => import("./Courses.10129947.js"),
|
||||
[
|
||||
"assets/Courses.10129947.js",
|
||||
"assets/frappe-ui.8966d601.js",
|
||||
"assets/frappe-ui.e894a05e.css",
|
||||
"assets/Courses.4fd15046.css",
|
||||
]
|
||||
),
|
||||
},
|
||||
];
|
||||
let O = u({ history: l("/"), routes: E });
|
||||
const P = {};
|
||||
function b(a, o) {
|
||||
const n = p("router-view");
|
||||
return d(), m("div", null, [_(n)]);
|
||||
}
|
||||
const A = f(P, [["render", b]]);
|
||||
let r = h(A);
|
||||
v("resourceFetcher", L);
|
||||
r.use(O);
|
||||
r.use(y);
|
||||
r.component("Button", g);
|
||||
r.mount("#app");
|
||||
1
lms/public/frontend/assets/index.64bc1bc1.css
Normal file
1
lms/public/frontend/assets/index.64bc1bc1.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
lms/public/frontend/assets/plus.8f4bce9f.js
Normal file
6
lms/public/frontend/assets/plus.8f4bce9f.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import { c as e } from "./index.43e529db.js";
|
||||
const n = e("PlusIcon", [
|
||||
["line", { x1: "12", x2: "12", y1: "5", y2: "19", key: "pwfkuu" }],
|
||||
["line", { x1: "5", x2: "19", y1: "12", y2: "12", key: "13b5wn" }],
|
||||
]);
|
||||
export { n as P };
|
||||
11
lms/public/frontend/assets/star.d3e8ecca.js
Normal file
11
lms/public/frontend/assets/star.d3e8ecca.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { c as o } from "./index.43e529db.js";
|
||||
const c = o("StarIcon", [
|
||||
[
|
||||
"polygon",
|
||||
{
|
||||
points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2",
|
||||
key: "8f66p6",
|
||||
},
|
||||
],
|
||||
]);
|
||||
export { c as S };
|
||||
@@ -5,10 +5,10 @@
|
||||
<link rel="icon" href="/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Frappe UI App</title>
|
||||
<script type="module" crossorigin src="/assets/index.52b6e5cb.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/frappe-ui.8966d601.js">
|
||||
<link rel="stylesheet" href="/assets/frappe-ui.e894a05e.css">
|
||||
<link rel="stylesheet" href="/assets/index.943a3ec2.css">
|
||||
<script type="module" crossorigin src="/assets/index.43e529db.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/frappe-ui.f2211ca2.js">
|
||||
<link rel="stylesheet" href="/assets/frappe-ui.7692ed2d.css">
|
||||
<link rel="stylesheet" href="/assets/index.64bc1bc1.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from frappe import _
|
||||
import frappe
|
||||
from frappe.utils import getdate
|
||||
from lms.www.utils import get_assessments, is_student
|
||||
from lms.www.utils import is_student
|
||||
from lms.lms.utils import (
|
||||
has_course_moderator_role,
|
||||
has_course_evaluator_role,
|
||||
@@ -12,6 +12,7 @@ from lms.lms.utils import (
|
||||
get_lesson_url,
|
||||
get_lesson_icon,
|
||||
get_membership,
|
||||
get_assessments,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -61,89 +61,6 @@ def get_current_lesson_details(lesson_number, context, is_edit=False):
|
||||
return lesson_info
|
||||
|
||||
|
||||
def get_assessments(batch, member=None):
|
||||
if not member:
|
||||
member = frappe.session.user
|
||||
|
||||
assessments = frappe.get_all(
|
||||
"LMS Assessment",
|
||||
{"parent": batch},
|
||||
["name", "assessment_type", "assessment_name"],
|
||||
)
|
||||
|
||||
for assessment in assessments:
|
||||
if assessment.assessment_type == "LMS Assignment":
|
||||
assessment = get_assignment_details(assessment, member)
|
||||
|
||||
elif assessment.assessment_type == "LMS Quiz":
|
||||
assessment = get_quiz_details(assessment, member)
|
||||
|
||||
return assessments
|
||||
|
||||
|
||||
def get_assignment_details(assessment, member):
|
||||
assessment.title = frappe.db.get_value(
|
||||
"LMS Assignment", assessment.assessment_name, "title"
|
||||
)
|
||||
|
||||
existing_submission = frappe.db.exists(
|
||||
{
|
||||
"doctype": "LMS Assignment Submission",
|
||||
"member": member,
|
||||
"assignment": assessment.assessment_name,
|
||||
}
|
||||
)
|
||||
assessment.completed = False
|
||||
if existing_submission:
|
||||
assessment.submission = frappe.db.get_value(
|
||||
"LMS Assignment Submission",
|
||||
existing_submission,
|
||||
["name", "status", "comments"],
|
||||
as_dict=True,
|
||||
)
|
||||
assessment.completed = True
|
||||
|
||||
assessment.edit_url = f"/assignments/{assessment.assessment_name}"
|
||||
submission_name = existing_submission if existing_submission else "new-submission"
|
||||
assessment.url = (
|
||||
f"/assignment-submission/{assessment.assessment_name}/{submission_name}"
|
||||
)
|
||||
|
||||
return assessment
|
||||
|
||||
|
||||
def get_quiz_details(assessment, member):
|
||||
assessment_details = frappe.db.get_value(
|
||||
"LMS Quiz", assessment.assessment_name, ["title", "passing_percentage"], as_dict=1
|
||||
)
|
||||
assessment.title = assessment_details.title
|
||||
|
||||
existing_submission = frappe.get_all(
|
||||
"LMS Quiz Submission",
|
||||
{
|
||||
"member": member,
|
||||
"quiz": assessment.assessment_name,
|
||||
},
|
||||
["name", "score", "percentage"],
|
||||
order_by="percentage desc",
|
||||
)
|
||||
|
||||
if len(existing_submission):
|
||||
assessment.submission = existing_submission[0]
|
||||
|
||||
assessment.completed = False
|
||||
if assessment.submission:
|
||||
assessment.completed = True
|
||||
|
||||
assessment.edit_url = f"/quizzes/{assessment.assessment_name}"
|
||||
submission_name = (
|
||||
existing_submission[0].name if len(existing_submission) else "new-submission"
|
||||
)
|
||||
assessment.url = f"/quiz-submission/{assessment.assessment_name}/{submission_name}"
|
||||
|
||||
return assessment
|
||||
|
||||
|
||||
def is_student(batch, member=None):
|
||||
if not member:
|
||||
member = frappe.session.user
|
||||
|
||||
Reference in New Issue
Block a user