feat: generate bulk certificates for batch students
This commit is contained in:
@@ -24,12 +24,13 @@
|
||||
"codemirror-editor-vue3": "^2.8.0",
|
||||
"dayjs": "^1.11.6",
|
||||
"feather-icons": "^4.28.0",
|
||||
"frappe-ui": "^0.1.72",
|
||||
"frappe-ui": "^0.1.89",
|
||||
"lucide-vue-next": "^0.383.0",
|
||||
"markdown-it": "^14.0.0",
|
||||
"pinia": "^2.0.33",
|
||||
"socket.io-client": "^4.7.2",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"typescript": "^5.7.2",
|
||||
"vue": "^3.4.23",
|
||||
"vue-chartjs": "^5.3.0",
|
||||
"vue-draggable-next": "^2.2.1",
|
||||
|
||||
132
frontend/src/components/Modals/BulkCertificates.vue
Normal file
132
frontend/src/components/Modals/BulkCertificates.vue
Normal file
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<Dialog
|
||||
v-model="show"
|
||||
:options="{
|
||||
title: __('Generate Certificates'),
|
||||
size: 'lg',
|
||||
actions: [
|
||||
{
|
||||
label: 'Create',
|
||||
variant: 'solid',
|
||||
onClick: ({ close }) => {
|
||||
generateCertificates(close)
|
||||
},
|
||||
},
|
||||
],
|
||||
}"
|
||||
>
|
||||
<template #body-content>
|
||||
<div class="space-y-4">
|
||||
<FormControl
|
||||
type="select"
|
||||
v-model="details.course"
|
||||
:label="__('Course')"
|
||||
:options="getCourses()"
|
||||
/>
|
||||
<Link
|
||||
v-model="details.evaluator"
|
||||
:label="__('Evaluator')"
|
||||
doctype="Course Evaluator"
|
||||
/>
|
||||
<FormControl
|
||||
type="date"
|
||||
v-model="details.issue_date"
|
||||
:label="__('Issue Date')"
|
||||
/>
|
||||
<FormControl
|
||||
type="date"
|
||||
v-model="details.expiry_date"
|
||||
:label="__('Expiry Date')"
|
||||
/>
|
||||
<Link
|
||||
v-model="details.template"
|
||||
:label="__('Template')"
|
||||
doctype="Print Format"
|
||||
:filters="{
|
||||
doc_type: 'LMS Certificate',
|
||||
}"
|
||||
/>
|
||||
<Switch
|
||||
size="sm"
|
||||
:label="__('Published')"
|
||||
:description="
|
||||
__(
|
||||
'Enabling this will publish the certificate on the certified participants page.'
|
||||
)
|
||||
"
|
||||
v-model="details.published"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { inject, reactive } from 'vue'
|
||||
import { createResource, Dialog, FormControl, Switch } from 'frappe-ui'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import { showToast } from '@/utils'
|
||||
|
||||
const show = defineModel()
|
||||
const dayjs = inject('$dayjs')
|
||||
const details = reactive({
|
||||
issue_date: dayjs().format('YYYY-MM-DD'),
|
||||
expiry_date: null,
|
||||
template: null,
|
||||
evaluator: null,
|
||||
published: true,
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
batch: {
|
||||
type: [Object, null],
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const createCertificate = createResource({
|
||||
url: 'frappe.client.insert',
|
||||
makeParams(values) {
|
||||
return {
|
||||
doc: {
|
||||
doctype: 'LMS Certificate',
|
||||
issue_date: details.issue_date,
|
||||
expiry_date: details.expiry_date,
|
||||
template: details.template,
|
||||
published: details.published,
|
||||
course: values.course,
|
||||
batch: values.batch,
|
||||
member: values.member,
|
||||
evaluator: details.evaluator,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const generateCertificates = (close) => {
|
||||
props.batch?.students.forEach((student) => {
|
||||
createCertificate.submit(
|
||||
{
|
||||
course: details.course,
|
||||
batch: props.batch.name,
|
||||
member: student,
|
||||
},
|
||||
{
|
||||
onError(err) {
|
||||
showToast(__('Error'), err.messages?.[0] || err, 'x')
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
close()
|
||||
showToast(__('Success'), __('Certificates generated successfully'), 'check')
|
||||
}
|
||||
|
||||
const getCourses = () => {
|
||||
return props.batch?.courses.map((course) => {
|
||||
return {
|
||||
label: course.course,
|
||||
value: course.course,
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -59,7 +59,7 @@ const update = () => {
|
||||
{},
|
||||
{
|
||||
onError(err) {
|
||||
showToast('Error', err.messages?.[0] || err, 'x')
|
||||
showToast(__('Error'), err.messages?.[0] || err, 'x')
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
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" />
|
||||
<div class="flex items-center space-x-2">
|
||||
<Button
|
||||
v-if="user.data?.is_moderator"
|
||||
@click="openCertificateDialog = true"
|
||||
>
|
||||
{{ __('Generate Certificates') }}
|
||||
</Button>
|
||||
<Button v-if="user.data?.is_moderator" @click="openAnnouncementModal()">
|
||||
<span>
|
||||
{{ __('Make an Announcement') }}
|
||||
@@ -12,13 +19,14 @@
|
||||
<SendIcon class="h-4 stroke-1.5" />
|
||||
</template>
|
||||
</Button>
|
||||
</div>
|
||||
</header>
|
||||
<div v-if="batch.data" class="grid grid-cols-[70%,30%] h-screen">
|
||||
<div class="border-r-2">
|
||||
<Tabs
|
||||
v-model="tabIndex"
|
||||
:tabs="tabs"
|
||||
tablistClass="overflow-y-hidden sticky top-11 bg-white z-10"
|
||||
tablistClass="overflow-y-hidden bg-white"
|
||||
>
|
||||
<template #tab="{ tab, selected }" class="overflow-x-hidden">
|
||||
<div>
|
||||
@@ -169,6 +177,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BulkCertificates v-model="openCertificateDialog" :batch="batch.data" />
|
||||
</template>
|
||||
<script setup>
|
||||
import { Breadcrumbs, Button, createResource, Tabs, Badge } from 'frappe-ui'
|
||||
@@ -197,9 +206,11 @@ import Announcements from '@/components/Annoucements.vue'
|
||||
import AnnouncementModal from '@/components/Modals/AnnouncementModal.vue'
|
||||
import Discussions from '@/components/Discussions.vue'
|
||||
import DateRange from '@/components/Common/DateRange.vue'
|
||||
import BulkCertificates from '@/components/Modals/BulkCertificates.vue'
|
||||
|
||||
const user = inject('$user')
|
||||
const showAnnouncementModal = ref(false)
|
||||
const openCertificateDialog = ref(false)
|
||||
|
||||
const props = defineProps({
|
||||
batchName: {
|
||||
|
||||
1107
frontend/yarn.lock
1107
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -114,7 +114,7 @@
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2024-09-11 11:37:20.419955",
|
||||
"modified": "2024-09-11 11:37:20.419956",
|
||||
"modified_by": "Administrator",
|
||||
"module": "LMS",
|
||||
"name": "LMS Certificate",
|
||||
|
||||
Reference in New Issue
Block a user