Merge pull request #2246 from frappe/misc/fixes

fix: misc issues in batch
This commit is contained in:
Hussain Nagaria
2026-03-25 10:33:34 +05:30
committed by GitHub
3 changed files with 115 additions and 95 deletions
+14 -3
View File
@@ -9,6 +9,7 @@
:fileTypes="[fileType]"
:validateFile="(file: File) => validateFile(file, true, type)"
@success="(file: File) => saveFile(file)"
@failure="onUploadFailure"
>
<template v-slot="{ file, progress, uploading, openFileSelector }">
<div class="flex items-center">
@@ -19,8 +20,8 @@
/>
</div>
<div class="ml-4">
<Button @click="openFileSelector">
{{ __('Upload') }}
<Button @click="openFileSelector" :loading="uploading">
{{ uploading ? `${__('Uploading')} ${progress}%` : __('Upload') }}
</Button>
<div class="mt-1 text-ink-gray-5 text-sm leading-5">
{{ __(description) }}
@@ -62,7 +63,7 @@
</template>
<script setup lang="ts">
import { validateFile } from '@/utils'
import { Button, FileUploader } from 'frappe-ui'
import { Button, FileUploader, toast } from 'frappe-ui'
import { Image, Video } from 'lucide-vue-next'
import { computed } from 'vue'
@@ -100,4 +101,14 @@ const saveFile = (file: any) => {
const removeImage = () => {
emit('update:modelValue', '')
}
const onUploadFailure = (error: any) => {
let message = __('Error Uploading File')
if (error?._server_messages) {
message = JSON.parse(JSON.parse(error._server_messages)[0]).message
} else if (error?.exc) {
message = JSON.parse(error.exc)[0].split('\n').slice(-2, -1)[0]
}
toast.error(message)
}
</script>
@@ -1,100 +1,108 @@
<template>
<div v-if="batch.data" class="border-2 rounded-md p-5 lg:w-72">
<Badge
v-if="batch.data.seat_count && batch.data.seats_left > 0"
variant="subtle"
theme="green"
size="md"
:class="
batch.data.amount || batch.data.courses.length
? 'float-right'
: 'w-fit mb-4'
"
:label="
batch.data.seats_left +
' ' +
(batch.data.seats_left > 1 ? __('Seats Left') : __('Seat Left'))
"
<div v-if="batch.data" class="border-2 rounded-md lg:w-72">
<video
v-if="batch.data.video_link"
:src="batch.data.video_link"
controls
class="rounded-t-md w-full"
/>
<Badge
v-else-if="batch.data.seat_count && batch.data.seats_left <= 0"
variant="subtle"
theme="red"
size="md"
class="float-right"
:label="__('Sold Out')"
/>
<div
v-if="batch.data.amount"
class="text-lg font-semibold mb-5 text-ink-gray-9"
>
{{ formatNumberIntoCurrency(batch.data.amount, batch.data.currency) }}
</div>
<div
v-if="batch.data.courses.length"
class="flex items-center mb-3 text-ink-gray-7"
>
<BookOpen class="h-4 w-4 stroke-1.5 mr-2" />
<span> {{ batch.data.courses.length }} {{ __('Courses') }} </span>
</div>
<DateRange
:startDate="batch.data.start_date"
:endDate="batch.data.end_date"
class="mb-3"
/>
<div class="flex items-center mb-3 text-ink-gray-7">
<Clock class="h-4 w-4 stroke-1.5 mr-2" />
<span>
{{ formatTime(batch.data.start_time) }} -
{{ formatTime(batch.data.end_time) }}
</span>
</div>
<div v-if="batch.data.timezone" class="flex items-center text-ink-gray-7">
<Globe class="h-4 w-4 stroke-1.5 mr-2" />
<span>
{{ batch.data.timezone }}
</span>
</div>
<div class="p-5">
<Badge
v-if="batch.data.seat_count && batch.data.seats_left > 0"
variant="subtle"
theme="green"
size="md"
:class="
batch.data.amount || batch.data.courses.length
? 'float-right'
: 'w-fit mb-4'
"
:label="
batch.data.seats_left +
' ' +
(batch.data.seats_left > 1 ? __('Seats Left') : __('Seat Left'))
"
/>
<Badge
v-else-if="batch.data.seat_count && batch.data.seats_left <= 0"
variant="subtle"
theme="red"
size="md"
class="float-right"
:label="__('Sold Out')"
/>
<div
v-if="batch.data.amount"
class="text-lg font-semibold mb-5 text-ink-gray-9"
>
{{ formatNumberIntoCurrency(batch.data.amount, batch.data.currency) }}
</div>
<div
v-if="batch.data.courses.length"
class="flex items-center mb-3 text-ink-gray-7"
>
<BookOpen class="h-4 w-4 stroke-1.5 mr-2" />
<span> {{ batch.data.courses.length }} {{ __('Courses') }} </span>
</div>
<DateRange
:startDate="batch.data.start_date"
:endDate="batch.data.end_date"
class="mb-3"
/>
<div class="flex items-center mb-3 text-ink-gray-7">
<Clock class="h-4 w-4 stroke-1.5 mr-2" />
<span>
{{ formatTime(batch.data.start_time) }} -
{{ formatTime(batch.data.end_time) }}
</span>
</div>
<div v-if="batch.data.timezone" class="flex items-center text-ink-gray-7">
<Globe class="h-4 w-4 stroke-1.5 mr-2" />
<span>
{{ batch.data.timezone }}
</span>
</div>
<div v-if="!readOnlyMode && !canAccessBatch">
<router-link
:to="{
name: 'Billing',
params: {
type: 'batch',
name: batch.data.name,
},
}"
v-if="
batch.data.paid_batch &&
batch.data.seats_left > 0 &&
batch.data.accept_enrollments
"
>
<Button class="w-full mt-4" variant="solid">
<div v-if="!readOnlyMode && !canAccessBatch">
<router-link
:to="{
name: 'Billing',
params: {
type: 'batch',
name: batch.data.name,
},
}"
v-if="
batch.data.paid_batch &&
batch.data.seats_left > 0 &&
batch.data.accept_enrollments
"
>
<Button class="w-full mt-4" variant="solid">
<template #prefix>
<CreditCard class="size-4 stroke-1.5" />
</template>
<span>
{{ __('Register Now') }}
</span>
</Button>
</router-link>
<Button
variant="solid"
class="w-full mt-2"
v-else-if="
batch.data.allow_self_enrollment &&
batch.data.seats_left &&
batch.data.accept_enrollments
"
@click="enrollInBatch()"
>
<template #prefix>
<CreditCard class="size-4 stroke-1.5" />
<GraduationCap class="size-4 stroke-1.5" />
</template>
<span>
{{ __('Register Now') }}
</span>
{{ __('Enroll Now') }}
</Button>
</router-link>
<Button
variant="solid"
class="w-full mt-2"
v-else-if="
batch.data.allow_self_enrollment &&
batch.data.seats_left &&
batch.data.accept_enrollments
"
@click="enrollInBatch()"
>
<template #prefix>
<GraduationCap class="size-4 stroke-1.5" />
</template>
{{ __('Enroll Now') }}
</Button>
</div>
</div>
</div>
</template>
+2 -1
View File
@@ -1087,7 +1087,7 @@ def get_neighbour_lesson(course: str, chapter: int, lesson: int) -> dict:
}
@frappe.whitelist(allow_guest=True)
@frappe.whitelist(allow_guest=True) # nosemgrep: frappe-semgrep-rules.rules.security.guest-whitelisted-method
@rate_limit(limit=500, seconds=60 * 60)
def get_batch_details(batch: str):
if not guest_access_allowed():
@@ -1129,6 +1129,7 @@ def get_batch_details(batch: str):
"zoom_account",
"conferencing_provider",
"google_meet_account",
"video_link",
],
as_dict=True,
)