fix: misc issues
This commit is contained in:
@@ -25,7 +25,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { createListResource, Avatar } from 'frappe-ui'
|
import { createResource, Avatar } from 'frappe-ui'
|
||||||
import { timeAgo } from '@/utils'
|
import { timeAgo } from '@/utils'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -35,24 +35,15 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const communications = createListResource({
|
const communications = createResource({
|
||||||
doctype: 'Communication',
|
url: 'lms.lms.api.get_announcements',
|
||||||
fields: [
|
makeParams(value) {
|
||||||
'subject',
|
return {
|
||||||
'content',
|
batch: props.batch,
|
||||||
'recipients',
|
}
|
||||||
'cc',
|
|
||||||
'communication_date',
|
|
||||||
'sender',
|
|
||||||
'sender_full_name',
|
|
||||||
],
|
|
||||||
filters: {
|
|
||||||
reference_doctype: 'LMS Batch',
|
|
||||||
reference_name: props.batch,
|
|
||||||
},
|
},
|
||||||
orderBy: 'communication_date desc',
|
|
||||||
auto: true,
|
auto: true,
|
||||||
cache: ['batch', props.batch],
|
cache: ['announcement', props.batch],
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
<a
|
<a
|
||||||
:href="cls.join_url"
|
:href="cls.join_url"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="w-1/2 cursor-pointer inline-flex items-center justify-center gap-2 transition-colors focus:outline-none text-gray-800 bg-gray-100 hover:bg-gray-200 active:bg-gray-300 focus-visible:ring focus-visible:ring-gray-400 h-7 text-base px-2 rounded"
|
class="w-full cursor-pointer inline-flex items-center justify-center gap-2 transition-colors focus:outline-none text-gray-800 bg-gray-100 hover:bg-gray-200 active:bg-gray-300 focus-visible:ring focus-visible:ring-gray-400 h-7 text-base px-2 rounded"
|
||||||
>
|
>
|
||||||
<Video class="h-4 w-4 stroke-1.5" />
|
<Video class="h-4 w-4 stroke-1.5" />
|
||||||
{{ __('Join') }}
|
{{ __('Join') }}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { Dialog, Input, TextEditor, createResource } from 'frappe-ui'
|
import { Dialog, Input, TextEditor, createResource } from 'frappe-ui'
|
||||||
import { reactive } from 'vue'
|
import { reactive } from 'vue'
|
||||||
import { createToast } from '@/utils/'
|
import { showToast } from '@/utils/'
|
||||||
|
|
||||||
const show = defineModel()
|
const show = defineModel()
|
||||||
|
|
||||||
@@ -94,22 +94,14 @@ const makeAnnouncement = (close) => {
|
|||||||
},
|
},
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
close()
|
close()
|
||||||
createToast({
|
showToast(
|
||||||
title: 'Success',
|
__('Success'),
|
||||||
text: 'Announcement has been sent successfully',
|
__('Announcement has been sent successfully'),
|
||||||
icon: 'Check',
|
'check'
|
||||||
iconClasses: 'bg-green-600 text-white rounded-md p-px',
|
)
|
||||||
})
|
|
||||||
},
|
},
|
||||||
onError(err) {
|
onError(err) {
|
||||||
createToast({
|
showToast(__('Error'), __(err.messages?.[0] || err), 'check')
|
||||||
title: 'Error',
|
|
||||||
text: err.messages?.[0] || err,
|
|
||||||
icon: 'x',
|
|
||||||
iconClasses: 'bg-red-600 text-white rounded-md p-px',
|
|
||||||
position: 'top-center',
|
|
||||||
timeout: 10,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ const breadcrumbs = computed(() => {
|
|||||||
const isStudent = computed(() => {
|
const isStudent = computed(() => {
|
||||||
return (
|
return (
|
||||||
user?.data &&
|
user?.data &&
|
||||||
batch.data?.students.length &&
|
batch.data?.students?.length &&
|
||||||
batch.data?.students.includes(user.data.name)
|
batch.data?.students.includes(user.data.name)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -248,12 +248,7 @@ import {
|
|||||||
reactive,
|
reactive,
|
||||||
watch,
|
watch,
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import {
|
import { convertToTitleCase, showToast, updateDocumentTitle } from '@/utils'
|
||||||
convertToTitleCase,
|
|
||||||
showToast,
|
|
||||||
getFileSize,
|
|
||||||
updateDocumentTitle,
|
|
||||||
} from '@/utils'
|
|
||||||
import Link from '@/components/Controls/Link.vue'
|
import Link from '@/components/Controls/Link.vue'
|
||||||
import { FileText, Image, X } from 'lucide-vue-next'
|
import { FileText, Image, X } from 'lucide-vue-next'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|||||||
@@ -17,14 +17,9 @@
|
|||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</p>
|
</p>
|
||||||
<router-link
|
<Button v-if="user.data" @click="enrollStudent()" variant="solid">
|
||||||
v-if="user.data"
|
{{ __('Start Learning') }}
|
||||||
:to="{ name: 'CourseDetail', params: { courseName: courseName } }"
|
</Button>
|
||||||
>
|
|
||||||
<Button variant="solid">
|
|
||||||
{{ __('Start Learning') }}
|
|
||||||
</Button>
|
|
||||||
</router-link>
|
|
||||||
<Button v-else @click="redirectToLogin()">
|
<Button v-else @click="redirectToLogin()">
|
||||||
{{ __('Login') }}
|
{{ __('Login') }}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -194,7 +189,7 @@ import { createResource, Breadcrumbs, Button } from 'frappe-ui'
|
|||||||
import { computed, watch, inject, ref, onMounted, onBeforeUnmount } from 'vue'
|
import { computed, watch, inject, ref, onMounted, onBeforeUnmount } from 'vue'
|
||||||
import CourseOutline from '@/components/CourseOutline.vue'
|
import CourseOutline from '@/components/CourseOutline.vue'
|
||||||
import UserAvatar from '@/components/UserAvatar.vue'
|
import UserAvatar from '@/components/UserAvatar.vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
|
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
|
||||||
import Discussions from '@/components/Discussions.vue'
|
import Discussions from '@/components/Discussions.vue'
|
||||||
import { getEditorTools, updateDocumentTitle } from '../utils'
|
import { getEditorTools, updateDocumentTitle } from '../utils'
|
||||||
@@ -204,6 +199,7 @@ import CourseInstructors from '@/components/CourseInstructors.vue'
|
|||||||
import ProgressBar from '@/components/ProgressBar.vue'
|
import ProgressBar from '@/components/ProgressBar.vue'
|
||||||
|
|
||||||
const user = inject('$user')
|
const user = inject('$user')
|
||||||
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const allowDiscussions = ref(false)
|
const allowDiscussions = ref(false)
|
||||||
const editor = ref(null)
|
const editor = ref(null)
|
||||||
@@ -379,6 +375,30 @@ const allowInstructorContent = () => {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const enrollment = createResource({
|
||||||
|
url: 'frappe.client.insert',
|
||||||
|
makeParams() {
|
||||||
|
return {
|
||||||
|
doc: {
|
||||||
|
doctype: 'LMS Enrollment',
|
||||||
|
course: props.courseName,
|
||||||
|
member: user.data?.name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const enrollStudent = () => {
|
||||||
|
enrollment.submit(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
onSuccess() {
|
||||||
|
window.location.reload()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const redirectToLogin = () => {
|
const redirectToLogin = () => {
|
||||||
window.location.href = `/login?redirect-to=/lms/courses/${props.courseName}`
|
window.location.href = `/login?redirect-to=/lms/courses/${props.courseName}`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -781,3 +781,24 @@ def update_course_statistics():
|
|||||||
course.name,
|
course.name,
|
||||||
{"lessons": lessons, "enrollments": enrollments, "rating": avg_rating},
|
{"lessons": lessons, "enrollments": enrollments, "rating": avg_rating},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_announcements(batch):
|
||||||
|
return frappe.get_all(
|
||||||
|
"Communication",
|
||||||
|
filters={
|
||||||
|
"reference_doctype": "LMS Batch",
|
||||||
|
"reference_name": batch,
|
||||||
|
},
|
||||||
|
fields=[
|
||||||
|
"subject",
|
||||||
|
"content",
|
||||||
|
"recipients",
|
||||||
|
"cc",
|
||||||
|
"communication_date",
|
||||||
|
"sender",
|
||||||
|
"sender_full_name",
|
||||||
|
],
|
||||||
|
order_by="communication_date desc",
|
||||||
|
)
|
||||||
|
|||||||
@@ -7,17 +7,3 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
class BatchStudent(Document):
|
class BatchStudent(Document):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def enroll_batch(batch_name):
|
|
||||||
if frappe.db.exists(
|
|
||||||
"Batch Student", {"student": frappe.session.user, "parent": batch_name}
|
|
||||||
):
|
|
||||||
frappe.throw("You are already enrolled in this batch")
|
|
||||||
enrollment = frappe.new_doc("Batch Student")
|
|
||||||
enrollment.student = frappe.session.user
|
|
||||||
enrollment.parent = batch_name
|
|
||||||
enrollment.parentfield = "students"
|
|
||||||
enrollment.parenttype = "LMS Batch"
|
|
||||||
enrollment.save(ignore_permissions=True)
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class LMSBatch(Document):
|
|||||||
self.validate_timetable()
|
self.validate_timetable()
|
||||||
self.send_confirmation_mail()
|
self.send_confirmation_mail()
|
||||||
self.validate_evaluation_end_date()
|
self.validate_evaluation_end_date()
|
||||||
|
self.add_students_to_live_class()
|
||||||
|
|
||||||
def validate_batch_end_date(self):
|
def validate_batch_end_date(self):
|
||||||
if self.end_date < self.start_date:
|
if self.end_date < self.start_date:
|
||||||
@@ -139,6 +140,27 @@ class LMSBatch(Document):
|
|||||||
if cint(self.seat_count) < len(self.students):
|
if cint(self.seat_count) < len(self.students):
|
||||||
frappe.throw(_("There are no seats available in this batch."))
|
frappe.throw(_("There are no seats available in this batch."))
|
||||||
|
|
||||||
|
def add_students_to_live_class(self):
|
||||||
|
for student in self.students:
|
||||||
|
if student.is_new():
|
||||||
|
live_classes = frappe.get_all(
|
||||||
|
"LMS Live Class", {"batch_name": self.name}, ["name", "event"]
|
||||||
|
)
|
||||||
|
|
||||||
|
for live_class in live_classes:
|
||||||
|
if live_class.event:
|
||||||
|
frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Event Participants",
|
||||||
|
"reference_doctype": "User",
|
||||||
|
"reference_docname": student.student,
|
||||||
|
"email": student.student,
|
||||||
|
"parent": live_class.event,
|
||||||
|
"parenttype": "Event",
|
||||||
|
"parentfield": "event_participants",
|
||||||
|
}
|
||||||
|
).save()
|
||||||
|
|
||||||
def validate_timetable(self):
|
def validate_timetable(self):
|
||||||
for schedule in self.timetable:
|
for schedule in self.timetable:
|
||||||
if schedule.start_time and schedule.end_time:
|
if schedule.start_time and schedule.end_time:
|
||||||
|
|||||||
@@ -10,19 +10,20 @@
|
|||||||
"title",
|
"title",
|
||||||
"host",
|
"host",
|
||||||
"batch_name",
|
"batch_name",
|
||||||
|
"event",
|
||||||
"column_break_astv",
|
"column_break_astv",
|
||||||
"date",
|
|
||||||
"time",
|
|
||||||
"duration",
|
|
||||||
"section_break_glxh",
|
|
||||||
"description",
|
"description",
|
||||||
|
"section_break_glxh",
|
||||||
|
"date",
|
||||||
|
"duration",
|
||||||
"column_break_spvt",
|
"column_break_spvt",
|
||||||
|
"time",
|
||||||
"timezone",
|
"timezone",
|
||||||
"password",
|
|
||||||
"auto_recording",
|
|
||||||
"section_break_yrpq",
|
"section_break_yrpq",
|
||||||
|
"password",
|
||||||
"start_url",
|
"start_url",
|
||||||
"column_break_yokr",
|
"column_break_yokr",
|
||||||
|
"auto_recording",
|
||||||
"join_url"
|
"join_url"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
@@ -122,11 +123,18 @@
|
|||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Auto Recording",
|
"label": "Auto Recording",
|
||||||
"options": "No Recording\nLocal\nCloud"
|
"options": "No Recording\nLocal\nCloud"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "event",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Event",
|
||||||
|
"options": "Event",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-01-09 11:22:33.272341",
|
"modified": "2024-10-31 15:41:35.540856",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Live Class",
|
"name": "LMS Live Class",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class LMSLiveClass(Document):
|
|||||||
if calendar:
|
if calendar:
|
||||||
event = self.create_event()
|
event = self.create_event()
|
||||||
self.add_event_participants(event, calendar)
|
self.add_event_participants(event, calendar)
|
||||||
|
self.event = event.name
|
||||||
|
|
||||||
def create_event(self):
|
def create_event(self):
|
||||||
start = f"{self.date} {self.time}"
|
start = f"{self.date} {self.time}"
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
"default": "0",
|
"default": "0",
|
||||||
"fieldname": "payment_received",
|
"fieldname": "payment_received",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
|
"in_standard_filter": 1,
|
||||||
"label": "Payment Received"
|
"label": "Payment Received"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -140,7 +141,7 @@
|
|||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-10-26 16:54:12.408274",
|
"modified": "2024-10-31 15:33:39.420366",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Payment",
|
"name": "LMS Payment",
|
||||||
|
|||||||
Reference in New Issue
Block a user