feat: batch billing

This commit is contained in:
Jannat Patel
2024-01-23 15:33:31 +05:30
parent b07940951c
commit 9671c4d63f
154 changed files with 112825 additions and 51286 deletions

View File

@@ -14,11 +14,11 @@
"lucide-vue-next": "^0.309.0",
"markdown-it": "^14.0.0",
"pinia": "^2.0.33",
"tailwindcss": "^3.2.7",
"socket.io-client": "^4.7.2",
"tailwindcss": "^3.2.7",
"vue": "^3.2.25",
"vue-router": "^4.0.12",
"vue-chartjs": "^5.0.0"
"vue-chartjs": "^5.0.0",
"vue-router": "^4.0.12"
},
"devDependencies": {
"@vitejs/plugin-vue": "^2.0.0",

View File

@@ -1,5 +1,5 @@
<template>
<div v-if="communications.data">
<div v-if="communications.data?.length">
<div v-for="comm in communications.data">
<div class="mb-8">
<div class="flex items-center justify-between mb-2">
@@ -20,6 +20,9 @@
</div>
</div>
</div>
<div v-else class="text-sm italic text-gray-600">
{{ __('No announcements') }}
</div>
</template>
<script setup>
import { createListResource, Avatar } from 'frappe-ui'

View File

@@ -50,15 +50,23 @@
</span>
</Button>
</router-link>
<Button
<router-link
:to="{
name: 'Billing',
params: {
type: 'batch',
name: batch.data.name,
},
}"
v-else-if="batch.data.paid_batch"
class="w-full mt-4"
variant="solid"
>
<span>
{{ __('Register Now') }}
</span>
</Button>
<Button class="w-full mt-4" variant="solid">
<span>
{{ __('Register Now') }}
</span>
</Button>
</router-link>
<Button v-if="user?.data?.is_moderator" class="w-full mt-2">
<span>
{{ __('Edit') }}

View File

@@ -77,6 +77,7 @@ const valuePropPassed = computed(() => 'value' in attrs)
const value = computed({
get: () => (valuePropPassed.value ? attrs.value : props.modelValue),
set: (val) => {
console.log(val?.value, valuePropPassed.value)
return (
val?.value &&
emit(valuePropPassed.value ? 'change' : 'update:modelValue', val?.value)

View File

@@ -27,6 +27,22 @@
</span>
</Button>
</router-link>
<router-link
v-else-if="course.data.paid_course"
:to="{
name: 'Billing',
params: {
type: 'course',
name: course.data.name,
},
}"
>
<Button variant="solid" class="w-full mb-3">
<span>
{{ __('Buy this course') }}
</span>
</Button>
</router-link>
<Button
v-else
@click="enrollStudent()"

View File

@@ -0,0 +1,44 @@
<template>
<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>
{{ __(title) }}
</div>
<div class="px-5 py-3">
<div class="mb-4 leading-6">
{{ __(text) }}
</div>
<Button variant="solid" class="w-full" @click="redirect()">
{{ __(buttonLabel) }}
</Button>
</div>
</div>
</template>
<script setup>
import { Button } from 'frappe-ui'
const props = defineProps({
title: {
type: String,
default: 'Not Permitted',
},
text: {
type: String,
default: 'You are not permitted to access this page.',
},
buttonLabel: {
type: String,
default: 'Login',
},
buttonLink: {
type: String,
default: '/login',
},
})
const redirect = () => {
window.location.href = props.buttonLink
}
</script>

View File

@@ -6,7 +6,7 @@
<div class="text-lg font-semibold mb-4">
{{ __('Upcoming Evaluations') }}
</div>
<div v-if="upcoming_evals.data">
<div v-if="upcoming_evals.data?.length">
<div class="grid grid-cols-2 gap-4">
<div v-for="evl in upcoming_evals.data">
<div class="border rounded-md p-3">

View File

@@ -120,7 +120,7 @@
/>
</div>
</div>
<div v-else class="h-screen">
<div v-else-if="!user.data?.name" 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
@@ -238,44 +238,41 @@ const isStudent = computed(() => {
})
const tabIndex = ref(0)
const tabs = []
if (isStudent.value) {
tabs.push({
label: 'Dashboard',
icon: LayoutDashboard,
const tabs = computed(() => {
let batchTabs = []
if (isStudent.value) {
batchTabs.push({
label: 'Dashboard',
icon: LayoutDashboard,
})
}
if (user.data?.is_moderator) {
batchTabs.push({
label: 'Students',
icon: Contact2,
})
batchTabs.push({
label: 'Assessments',
icon: BookOpenCheck,
})
}
batchTabs.push({
label: 'Live Class',
icon: Laptop,
})
}
if (user.data?.is_moderator) {
tabs.push({
label: 'Students',
icon: Contact2,
batchTabs.push({
label: 'Courses',
icon: BookOpen,
})
tabs.push({
label: 'Assessments',
icon: BookOpenCheck,
batchTabs.push({
label: 'Announcements',
icon: Mail,
})
}
tabs.push({
label: 'Live Class',
icon: Laptop,
})
tabs.push({
label: 'Courses',
icon: BookOpen,
})
tabs.push({
label: 'Announcements',
icon: Mail,
})
tabs.push({
label: 'Discussions',
icon: MessageCircle,
batchTabs.push({
label: 'Discussions',
icon: MessageCircle,
})
return batchTabs
})
const courses = createResource({

View File

@@ -78,12 +78,7 @@
</div>
</template>
<script setup>
import {
Breadcrumbs,
createDocumentResource,
createListResource,
createResource,
} from 'frappe-ui'
import { Breadcrumbs, createResource } from 'frappe-ui'
import { BookOpen, Calendar, Clock } from 'lucide-vue-next'
import { formatTime } from '../utils'
import { computed, inject } from 'vue'
@@ -110,7 +105,7 @@ const batch = createResource({
},
auto: true,
onSuccess(data) {
if (data.students?.includes(user.data.name)) {
if (data.students?.includes(user.data?.name)) {
router.push({
name: 'Batch',
params: {

View File

@@ -1,14 +1,64 @@
<template>
<div class="text-base h-screen">
<div v-if="access.data?.access" class="mt-20 w-1/2 mx-auto">
<div
v-if="access.data?.access && orderSummary.data"
class="mt-10 w-1/2 mx-auto"
>
<div class="text-3xl font-bold">
{{ __('Billing Details') }}
</div>
<div class="text-gray-600 mt-1">
{{ __('Enter the billing information to complete the payment.') }}
</div>
<div class="border rounded-md p-8 mt-10">
<div class="border rounded-md p-5 mt-5">
<div class="text-xl font-semibold">
{{ __('Summary') }}
</div>
<div class="text-gray-600 mt-1">
{{ __('Review the details of your purchase.') }}
</div>
<div class="mt-5">
<div class="flex items-center justify-between">
<div>
{{ orderSummary.data.title }}
</div>
<div
:class="{
'font-semibold text-xl': !orderSummary.data.gst_applied,
}"
>
{{
orderSummary.data.gst_applied
? orderSummary.data.original_amount_formatted
: orderSummary.data.total_amount_formatted
}}
</div>
</div>
<div
v-if="orderSummary.data.gst_applied"
class="flex items-center justify-between mt-2"
>
<div>
{{ __('GST Amount') }}
</div>
<div>
{{ orderSummary.data.gst_amount_formatted }}
</div>
</div>
<div
v-if="orderSummary.data.gst_applied"
class="flex items-center justify-between mt-2"
>
<div>
{{ __('Total Amount') }}
</div>
<div class="font-semibold text-2xl">
{{ orderSummary.data.total_amount_formatted }}
</div>
</div>
</div>
<div class="text-xl font-semibold mt-10">
{{ __('Address') }}
</div>
<div class="text-gray-600 mt-1">
@@ -26,13 +76,13 @@
<div class="mb-1.5 text-sm text-gray-700">
{{ __('Address Line 1') }}
</div>
<Input type="text" v-model="billingDetails.address_line_1" />
<Input type="text" v-model="billingDetails.address_line1" />
</div>
<div class="mt-4">
<div class="mb-1.5 text-sm text-gray-700">
{{ __('Address Line 2') }}
</div>
<Input type="text" v-model="billingDetails.address_line_2" />
<Input type="text" v-model="billingDetails.address_line2" />
</div>
<div class="mt-4">
<div class="mb-1.5 text-sm text-gray-700">
@@ -52,7 +102,11 @@
<div class="mb-1.5 text-sm text-gray-700">
{{ __('Country') }}
</div>
<Input type="text" v-model="billingDetails.country" />
<Link
doctype="Country"
:value="billingDetails.country"
@change="(option) => changeCurrency(option)"
/>
</div>
<div class="mt-4">
<div class="mb-1.5 text-sm text-gray-700">
@@ -70,7 +124,11 @@
<div class="mb-1.5 text-sm text-gray-700">
{{ __('Source') }}
</div>
<Input type="text" v-model="billingDetails.source" />
<Link
doctype="LMS Source"
:value="billingDetails.source"
@change="(option) => (billingDetails.source = option)"
/>
</div>
<div v-if="billingDetails.country == 'India'" class="mt-4">
<div class="mb-1.5 text-sm text-gray-700">
@@ -86,62 +144,46 @@
</div>
</div>
</div>
<Button variant="solid" class="mt-8">
<Button variant="solid" class="mt-8" @click="generatePaymentLink()">
{{ __('Proceed to Payment') }}
</Button>
</div>
</div>
<div v-else>
<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">
{{ access.data?.message }}
</div>
<Button
v-if="!user.data.name"
variant="solid"
class="w-full"
@click="redirectToLogin()"
>
{{ __('Login') }}
</Button>
<router-link
v-else-if="type == 'course'"
:to="{
name: 'Courses',
}"
>
<Button variant="solid">
{{ __('Checkout Courses') }}
</Button>
</router-link>
<router-link
v-else-if="type == 'batch'"
:to="{
name: 'Batches',
}"
>
<Button varian="solid">
{{ __('Checkout Batches') }}
</Button>
</router-link>
</div>
</div>
<div v-else-if="access.data?.message">
<NotPermitted
:text="access.data.message"
:buttonLabel="
type == 'course' ? 'Checkout Courses' : 'Checkout Batches'
"
:buttonLink="type == 'course' ? '/courses' : '/batches'"
/>
</div>
<div v-else-if="!user.data?.name">
<NotPermitted
text="Please login to access this page."
:buttonLink="`/login?redirect-to=/billing/${type}/${name}`"
/>
</div>
</div>
</template>
<script setup>
import { Input, Button, createResource } from 'frappe-ui'
import { reactive, inject, onMounted, ref } from 'vue'
import Link from '@/components/Controls/Link.vue'
import NotPermitted from '@/components/NotPermitted.vue'
import { createToast } from '@/utils/'
const user = inject('$user')
onMounted(() => {
const script = document.createElement('script')
script.src = `https://checkout.razorpay.com/v1/checkout.js`
document.body.appendChild(script)
if (user.data?.name) {
access.submit()
}
})
const props = defineProps({
type: {
type: String,
@@ -159,24 +201,189 @@ const access = createResource({
type: props.type,
name: props.name,
},
auto: true,
onSuccess(data) {
orderSummary.submit()
setBillingDetails(data.address)
},
})
const billingDetails = reactive({
billing_name: '',
address_line_1: '',
address_line_2: '',
city: '',
state: '',
pincode: '',
country: '',
phone: '',
source: '',
gstin: '',
pan: '',
const orderSummary = createResource({
url: 'lms.lms.utils.get_order_summary',
makeParams(values) {
return {
doctype: props.type == 'course' ? 'LMS Course' : 'LMS Batch',
docname: props.name,
country: billingDetails.country,
}
},
onError(err) {
showError(err)
},
})
const redirectToLogin = () => {
window.location.href = `/login?redirect-to=/billing/${props.type}/${props.name}`
const billingDetails = reactive({})
const setBillingDetails = (data) => {
billingDetails.billing_name = data.billing_name || ''
billingDetails.address_line1 = data.address_line1 || ''
billingDetails.address_line2 = data.address_line2 || ''
billingDetails.city = data.city || ''
billingDetails.state = data.state || ''
billingDetails.country = data.country || ''
billingDetails.pincode = data.pincode || ''
billingDetails.phone = data.phone || ''
billingDetails.source = data.source || ''
billingDetails.gstin = data.gstin || ''
billingDetails.pan = data.pan || ''
}
const paymentOptions = createResource({
url: 'lms.lms.utils.get_payment_options',
makeParams(values) {
return {
doctype: props.type == 'course' ? 'LMS Course' : 'LMS Batch',
docname: props.name,
phone: billingDetails.phone,
country: billingDetails.country,
}
},
})
const generatePaymentLink = () => {
paymentOptions.submit(
{},
{
validate(params) {
return validateAddress()
},
onSuccess(data) {
data.handler = (response) => {
let doctype = props.type == 'course' ? 'LMS Course' : 'LMS Batch'
let docname = props.name
handleSuccess(response, doctype, docname, data.order_id)
}
let rzp1 = new Razorpay(data)
rzp1.open()
},
onError(err) {
showError(err)
},
}
)
}
const paymentResource = createResource({
url: 'lms.lms.utils.verify_payment',
makeParams(values) {
return {
response: values.response,
doctype: props.type == 'course' ? 'LMS Course' : 'LMS Batch',
docname: props.name,
address: billingDetails,
order_id: values.orderId,
}
},
})
const handleSuccess = (response, doctype, docname, orderId) => {
paymentResource.submit(
{
response: response,
orderId: orderId,
},
{
onSuccess(data) {
createToast({
title: 'Success',
text: 'Payment Successful',
icon: 'check',
iconClasses: 'bg-green-600 text-white rounded-md p-px',
})
setTimeout(() => {
window.location.href = data
}, 3000)
},
}
)
}
const validateAddress = () => {
let mandatoryFields = [
'billing_name',
'address_line1',
'city',
'pincode',
'country',
'phone',
'source',
]
for (let field of mandatoryFields) {
if (!billingDetails[field])
return (
'Please enter a valid ' +
field
.replaceAll('_', ' ')
.toLowerCase()
.replace(/\b\w/g, (s) => s.toUpperCase())
)
}
if (billingDetails.gstin && !billingDetails.pan)
return 'Please enter a valid pan number.'
if (billingDetails.country == 'India' && !billingDetails.state)
return 'Please enter a valid state with correct spelling and the first letter capitalized.'
const states = [
'Andhra Pradesh',
'Arunachal Pradesh',
'Assam',
'Bihar',
'Chhattisgarh',
'Goa',
'Gujarat',
'Haryana',
'Himachal Pradesh',
'Jharkhand',
'Karnataka',
'Kerala',
'Madhya Pradesh',
'Maharashtra',
'Manipur',
'Meghalaya',
'Mizoram',
'Nagaland',
'Odisha',
'Punjab',
'Rajasthan',
'Sikkim',
'Tamil Nadu',
'Telangana',
'Tripura',
'Uttar Pradesh',
'Uttarakhand',
'West Bengal',
]
if (
billingDetails.country == 'India' &&
!states.includes(billingDetails.state)
)
return 'Please enter a valid state with correct spelling and the first letter capitalized.'
}
const showError = (err) => {
createToast({
title: 'Error',
text: err.messages?.[0] || err,
icon: 'x',
iconClasses: 'bg-red-600 text-white rounded-md p-px',
position: 'top-center',
timeout: 10,
})
}
const changeCurrency = (country) => {
billingDetails.country = country
orderSummary.reload()
}
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -170,6 +170,7 @@ def get_translations():
def validate_billing_access(type, name):
access = True
message = ""
doctype = "LMS Course" if type == "course" else "LMS Batch"
if frappe.session.user == "Guest":
access = False
@@ -179,7 +180,7 @@ def validate_billing_access(type, name):
access = False
message = _("Module is incorrect.")
if not frappe.db.exists(type, name):
if not frappe.db.exists(doctype, name):
access = False
message = _("Module Name is incorrect or does not exist.")
@@ -199,4 +200,21 @@ def validate_billing_access(type, name):
access = False
message = _("You are already enrolled for this batch.")
return {"access": access, "message": message}
address = frappe.db.get_value(
"Address",
{"email_id": frappe.session.user},
[
"name",
"address_title as billing_name",
"address_line1",
"address_line2",
"city",
"state",
"country",
"pincode",
"phone",
],
as_dict=1,
)
return {"access": access, "message": message, "address": address}

View File

@@ -972,15 +972,15 @@ def check_multicurrency(amount, currency, country=None, amount_usd=None):
def apply_gst(amount, country=None):
gst_applied = False
gst_applied = 0
apply_gst = frappe.db.get_single_value("LMS Settings", "apply_gst")
if not country:
country = frappe.db.get_value("User", frappe.session.user, "country")
if apply_gst and country == "India":
gst_applied = True
amount = amount * 1.18
gst_applied = amount * 0.18
amount += gst_applied
return amount, gst_applied
@@ -1062,7 +1062,6 @@ def create_order(client, amount, currency):
@frappe.whitelist()
def verify_payment(response, doctype, docname, address, order_id):
response = json.loads(response)
client = get_client()
client.utility.verify_payment_signature(
{
@@ -1080,7 +1079,7 @@ def verify_payment(response, doctype, docname, address, order_id):
def record_payment(address, response, client, doctype, docname):
address = frappe._dict(json.loads(address))
address = frappe._dict(address)
address_name = save_address(address)
payment_details = get_payment_details(doctype, docname, address)
@@ -1131,7 +1130,7 @@ def create_membership(course, payment):
{"member": frappe.session.user, "course": course, "payment": payment.name}
)
membership.save(ignore_permissions=True)
return f"/courses/{course}/learn/1.1"
return f"/courses/{course}/learn/1-1"
def add_student_to_batch(batchname, payment):
@@ -1680,3 +1679,40 @@ def get_discussion_replies(topic):
)
return replies
@frappe.whitelist()
def get_order_summary(doctype, docname, country=None):
if doctype == "LMS Course":
details = frappe.db.get_value(
"LMS Course",
docname,
["title", "name", "paid_course", "course_price as amount", "currency", "amount_usd"],
as_dict=True,
)
if not details.paid_course:
raise frappe.throw(_("This course is free."))
else:
details = frappe.db.get_value(
"LMS Batch",
docname,
["title", "name", "paid_batch", "amount", "currency", "amount_usd"],
as_dict=True,
)
if not details.paid_batch:
raise frappe.throw(_("To join this batch, please contact the Administrator."))
details.amount, details.currency = check_multicurrency(
details.amount, details.currency, country, details.amount_usd
)
details.original_amount_formatted = fmt_money(details.amount, 0, details.currency)
if details.currency == "INR":
details.amount, details.gst_applied = apply_gst(details.amount)
details.gst_amount_formatted = fmt_money(details.gst_applied, 0, details.currency)
details.total_amount_formatted = fmt_money(details.amount, 0, details.currency)
return details

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.prose-sm p{margin:0 0 .5rem}

View File

@@ -1,730 +0,0 @@
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.a747cf9c.js";
import { f as $ } from "./index.6f049c1a.js";
import { _ as q } from "./CourseCard.bf057db6.js";
import { C as L, a as V } from "./clock.b36d19aa.js";
import { c as U, B as J } from "./index.51e5b051.js";
import "./UserAvatar.3cd4adb4.js";
import "./star.d358f014.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 };

View File

@@ -0,0 +1,494 @@
import {
a as k,
j as B,
W as $,
x as n,
y as u,
A as f,
B as _,
H as s,
U as M,
G as t,
a8 as N,
I as o,
J as e,
F as l,
a7 as w,
k as Y,
Q as L,
R as T,
L as H,
a6 as S,
} from "./frappe-ui-iPT8hMkb.js";
import { b as O, B as C, f as x } from "./index-qZ7Yta4u.js";
import { C as D, a as j } from "./clock-z0R6Od6V.js";
import { _ as R } from "./CourseCard-1i2yp1tI.js";
import "./UserAvatar-nJqmkBPv.js";
import "./star-xishKgdq.js";
const V = { key: 0, class: "shadow rounded-md p-5", style: { width: "300px" } },
A = { key: 2, class: "text-lg font-semibold mb-3" },
E = { class: "flex items-center mb-3" },
F = { class: "flex items-center mb-3" },
I = { class: "flex items-center" },
q = {
__name: "BatchOverlay",
props: { batch: { type: Object, default: null } },
setup(c) {
const y = k("$dayjs"),
g = k("$user"),
p = c,
d = B(() => {
var a, v, b, r;
return (a = p.batch.data) != null && a.seat_count
? ((v = p.batch.data) == null ? void 0 : v.seat_count) -
((r =
(b = p.batch.data) == null
? void 0
: b.students) == null
? void 0
: r.length)
: null;
});
return (a, v) => {
var r, i, m, h;
const b = $("router-link");
return c.batch.data
? (n(),
u("div", V, [
c.batch.data.seat_count && d.value > 0
? (n(),
f(
t(N),
{
key: 0,
theme: "green",
class: "self-start mb-2 float-right",
},
{
default: _(() => [
M(
s(d.value) +
" " +
s(a.__("Seat Left")),
1
),
]),
_: 1,
}
))
: c.batch.data.seat_count && d.value <= 0
? (n(),
f(
t(N),
{
key: 1,
theme: "red",
class: "self-start mb-2 float-right",
},
{
default: _(() => [
M(s(a.__("Sold Out")), 1),
]),
_: 1,
}
))
: o("", !0),
c.batch.data.amount
? (n(),
u(
"div",
A,
s(
t(O)(
c.batch.data.amount,
c.batch.data.currency
)
),
1
))
: o("", !0),
e("div", E, [
l(t(C), {
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
}),
e(
"span",
null,
s(c.batch.data.courses.length) +
" " +
s(a.__("Courses")),
1
),
]),
e("div", F, [
l(t(D), {
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
}),
e(
"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
),
]),
e("div", I, [
l(t(j), {
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
}),
e(
"span",
null,
s(t(x)(c.batch.data.start_time)) +
" - " +
s(t(x)(c.batch.data.end_time)),
1
),
]),
(i = (r = t(g)) == null ? void 0 : r.data) !=
null && i.is_moderator
? (n(),
f(
b,
{
key: 3,
to: {
name: "Batch",
params: {
batchName:
c.batch.data.name,
},
},
},
{
default: _(() => [
l(
t(w),
{
variant: "solid",
class: "w-full mt-4",
},
{
default: _(() => [
e(
"span",
null,
s(
a.__(
"Manage Batch"
)
),
1
),
]),
_: 1,
}
),
]),
_: 1,
},
8,
["to"]
))
: c.batch.data.paid_batch
? (n(),
f(
t(w),
{
key: 4,
class: "w-full mt-4",
variant: "solid",
},
{
default: _(() => [
e(
"span",
null,
s(a.__("Register Now")),
1
),
]),
_: 1,
}
))
: o("", !0),
(h = (m = t(g)) == null ? void 0 : m.data) !=
null && h.is_moderator
? (n(),
f(
t(w),
{ key: 5, class: "w-full mt-2" },
{
default: _(() => [
e(
"span",
null,
s(a.__("Edit")),
1
),
]),
_: 1,
}
))
: o("", !0),
]))
: o("", !0);
};
},
},
z = { key: 0, class: "h-screen text-base" },
G = { class: "sticky top-0 z-10 border-b bg-white px-3 py-2.5 sm:px-5" },
J = { class: "m-5 pb-10" },
Q = { class: "text-3xl font-semibold" },
U = { class: "my-3" },
W = { class: "flex items-center justify-between w-1/2" },
K = { class: "flex items-center" },
P = { key: 0 },
X = { class: "flex items-center" },
Z = { key: 1 },
tt = { class: "flex items-center" },
at = { class: "grid grid-cols-[60%,20%] gap-20 mt-10" },
et = { class: "" },
st = ["innerHTML"],
ct = { class: "text-2xl font-semibold" },
nt = { class: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8 mt-5" },
rt = { key: 0 },
lt = ["innerHTML"],
_t = {
__name: "BatchDetail",
props: { batchName: { type: String, required: !0 } },
setup(c) {
const y = k("$dayjs"),
g = k("$user"),
p = H(),
d = c,
a = Y({
url: "lms.lms.utils.get_batch_details",
cache: ["batch", d.batchName],
params: { batch: d.batchName },
auto: !0,
onSuccess(r) {
var i;
(i = r.students) != null &&
i.includes(g.data.name) &&
p.push({
name: "Batch",
params: { batchName: d.batchName },
});
},
}),
v = Y({
url: "lms.lms.utils.get_batch_courses",
params: { batch: d.batchName },
cache: ["batchCourses", d.batchName],
auto: !0,
}),
b = B(() => {
var i, m;
let r = [
{ label: "All Batches", route: { name: "Batches" } },
];
return (
r.push({
label:
(i = a == null ? void 0 : a.data) == null
? void 0
: i.title,
route: {
name: "BatchDetail",
params: {
batchName:
(m = a == null ? void 0 : a.data) ==
null
? void 0
: m.name,
},
},
}),
r
);
});
return (r, i) => {
const m = $("router-link");
return t(a).data
? (n(),
u("div", z, [
e("header", G, [
l(t(S), { items: b.value }, null, 8, ["items"]),
]),
e("div", J, [
e("div", null, [
e("div", Q, s(t(a).data.title), 1),
e("div", U, s(t(a).data.description), 1),
e("div", W, [
e("div", K, [
l(t(C), {
class: "h-4 w-4 text-gray-700 mr-2",
}),
e(
"span",
null,
s(t(a).data.courses.length) +
" " +
s(r.__("Courses")),
1
),
]),
t(a).data.courses
? (n(), u("span", P, "·"))
: o("", !0),
e("div", X, [
l(t(D), {
class: "h-4 w-4 text-gray-700 mr-2",
}),
e(
"span",
null,
s(
t(y)(
t(a).data.start_date
).format("DD MMM YYYY")
) +
" - " +
s(
t(y)(
t(a).data.end_date
).format("DD MMM YYYY")
),
1
),
]),
t(a).data.start_date
? (n(), u("span", Z, "·"))
: o("", !0),
e("div", tt, [
l(t(j), {
class: "h-4 w-4 text-gray-700 mr-2",
}),
e(
"span",
null,
s(t(x)(t(a).data.start_time)) +
" - " +
s(t(x)(t(a).data.end_time)),
1
),
]),
]),
]),
e("div", at, [
e("div", et, [
e(
"div",
{
innerHTML:
t(a).data.batch_details,
class: "batch-description",
},
null,
8,
st
),
]),
e("div", null, [
l(q, { batch: t(a) }, null, 8, [
"batch",
]),
]),
]),
e("div", null, [
e("div", ct, s(r.__("Courses")), 1),
e("div", nt, [
t(a).data.courses
? (n(!0),
u(
L,
{ key: 0 },
T(
t(v).data,
(h) => (
n(),
u(
"div",
{
key: h.course,
},
[
l(
m,
{
to: {
name: "CourseDetail",
params: {
courseName:
h.name,
},
},
},
{
default:
_(
() => [
(n(),
f(
R,
{
course: h,
key: h.name,
},
null,
8,
[
"course",
]
)),
]
),
_: 2,
},
1032,
["to"]
),
]
)
)
),
128
))
: o("", !0),
]),
t(a).data.batch_details_raw
? (n(),
u("div", rt, [
e(
"div",
{
innerHTML:
t(a).data
.batch_details_raw,
class: "batch-description",
},
null,
8,
lt
),
]))
: o("", !0),
]),
]),
]))
: o("", !0);
};
},
};
export { _t as default };
//# sourceMappingURL=BatchDetail-MDvOC8VN.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,454 +0,0 @@
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.a747cf9c.js";
import { a as H, f as p } from "./index.6f049c1a.js";
import { B as $ } from "./index.51e5b051.js";
import { C as B, a as C } from "./clock.b36d19aa.js";
import { _ as O } from "./CourseCard.bf057db6.js";
import "./UserAvatar.3cd4adb4.js";
import "./star.d358f014.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 };

View File

@@ -1,55 +1,54 @@
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,
x as n,
y as u,
A as g,
B as h,
H as t,
U as f,
G as c,
a8 as x,
I as y,
J as a,
F as i,
k as Y,
r as j,
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.a747cf9c.js";
import { f as B } from "./index.6f049c1a.js";
import { B as A } from "./index.51e5b051.js";
import { C as E, a as O } from "./clock.b36d19aa.js";
import { P as S } from "./plus.d245902e.js";
const F = {
C as $,
M as D,
Q as M,
R as N,
W as V,
a6 as z,
a7 as A,
a9 as L,
} from "./frappe-ui-iPT8hMkb.js";
import { B as O, f as B } from "./index-qZ7Yta4u.js";
import { C as P, a as S } from "./clock-z0R6Od6V.js";
import { P as U } from "./plus-_m-8cMp1.js";
const E = {
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 = {
F = { class: "text-xl font-semibold mb-1" },
I = { class: "short-introduction" },
R = { class: "mt-auto" },
T = { key: 0, class: "font-semibold text-lg mb-4" },
G = { class: "flex items-center mb-3" },
H = { class: "flex items-center mb-3" },
J = { class: "flex items-center" },
Q = {
__name: "BatchCard",
props: { batch: { type: Object, default: null } },
setup(s) {
const d = C("$dayjs");
return (o, v) => (
n(),
u("div", F, [
u("div", E, [
s.batch.seat_count && s.batch.seats_left > 0
? (n(),
g(
c(y),
c(x),
{
key: 0,
theme: "green",
@@ -57,7 +56,7 @@ const F = {
},
{
default: h(() => [
_(
f(
t(s.batch.seats_left) +
" " +
t(o.__("Seat Left")),
@@ -70,7 +69,7 @@ const F = {
: s.batch.seat_count && s.batch.seats_left <= 0
? (n(),
g(
c(y),
c(x),
{
key: 1,
theme: "red",
@@ -78,20 +77,20 @@ const F = {
},
{
default: h(() => [
_(t(o.__("Sold Out")), 1),
f(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, [
: y("", !0),
a("div", F, t(s.batch.title), 1),
a("div", I, t(s.batch.description), 1),
a("div", R, [
s.batch.amount
? (n(), u("div", J, t(s.batch.price), 1))
: x("", !0),
a("div", K, [
i(c(A), {
? (n(), u("div", T, t(s.batch.price), 1))
: y("", !0),
a("div", G, [
i(c(O), {
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
}),
a(
@@ -103,8 +102,8 @@ const F = {
1
),
]),
a("div", R, [
i(c(E), {
a("div", H, [
i(c(P), {
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
}),
a(
@@ -124,8 +123,8 @@ const F = {
1
),
]),
a("div", X, [
i(c(O), {
a("div", J, [
i(c(S), {
class: "h-4 w-4 stroke-1.5 mr-2 text-gray-700",
}),
a(
@@ -142,13 +141,13 @@ const F = {
);
},
},
q = { class: "h-screen text-base" },
G = {
W = { class: "h-screen text-base" },
q = {
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 = {
K = { class: "flex" },
X = { class: "mx-5 py-5" },
Z = {
key: 0,
class: "grid grid-cols-1 sm:grid-cols-3 md:grid-cols-4 gap-8 mt-5",
},
@@ -157,12 +156,12 @@ const F = {
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 = {
oe = {
__name: "Batches",
setup(s) {
var p, k;
const d = C("$user"),
o = D({
o = Y({
url: "lms.lms.utils.get_batches",
cache: [
"batches",
@@ -172,8 +171,8 @@ const F = {
],
auto: !0,
}),
v = Y(0),
f = [
v = j(0),
_ = [
{
label: "Upcoming",
batches: m(() => {
@@ -196,7 +195,7 @@ const F = {
return (
(k = d.data) != null &&
k.is_moderator &&
(f.push({
(_.push({
label: "Archived",
batches: m(() => {
var e;
@@ -211,7 +210,7 @@ const F = {
: l.length;
}),
}),
f.push({
_.push({
label: "Private",
batches: m(() => {
var e;
@@ -227,7 +226,7 @@ const F = {
}),
})),
d.data &&
f.push({
_.push({
label: "Enrolled",
batches: m(() => {
var e;
@@ -243,11 +242,11 @@ const F = {
}),
}),
(e, l) => {
const w = j("router-link");
const w = V("router-link");
return (
n(),
u("div", q, [
a("header", G, [
u("div", W, [
a("header", q, [
i(
c(z),
{
@@ -263,16 +262,16 @@ const F = {
8,
["items"]
),
a("div", H, [
a("div", K, [
i(
c(L),
c(A),
{ variant: "solid" },
{
prefix: h(() => [
i(c(S), { class: "h-4 w-4" }),
i(c(U), { class: "h-4 w-4" }),
]),
default: h(() => [
_(
f(
" " + t(e.__("New Batch")),
1
),
@@ -282,16 +281,16 @@ const F = {
),
]),
]),
a("div", Q, [
a("div", X, [
i(
c(P),
c(L),
{
class: "overflow-hidden",
modelValue: v.value,
"onUpdate:modelValue":
l[0] ||
(l[0] = (r) => (v.value = r)),
tabs: f,
tabs: _,
},
{
tab: h(({ tab: r, selected: b }) => [
@@ -310,12 +309,12 @@ const F = {
[
r.icon
? (n(),
g(N(r.icon), {
g(D(r.icon), {
key: 0,
class: "h-5",
}))
: x("", !0),
_(
: y("", !0),
f(
" " +
t(
e.__(
@@ -326,7 +325,7 @@ const F = {
1
),
i(
c(y),
c(x),
{
class: $({
"text-gray-900 border border-gray-900":
@@ -340,7 +339,7 @@ const F = {
{
default: h(
() => [
_(
f(
t(
r.count
),
@@ -361,12 +360,12 @@ const F = {
default: h(({ tab: r }) => [
r.batches && r.batches.value.length
? (n(),
u("div", W, [
u("div", Z, [
(n(!0),
u(
V,
M,
null,
M(
N(
r.batches.value,
(b) => (
n(),
@@ -386,7 +385,7 @@ const F = {
h(
() => [
i(
Z,
Q,
{
batch: b,
},
@@ -440,4 +439,5 @@ const F = {
);
},
};
export { re as default };
export { oe as default };
//# sourceMappingURL=Batches-gDWZzuli.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,53 +1,53 @@
import { _ as f } from "./UserAvatar.3cd4adb4.js";
import { s as g, B as v, U as y } from "./index.51e5b051.js";
import { _ as f } from "./UserAvatar-nJqmkBPv.js";
import { s as g, B as v, U as y } from "./index-qZ7Yta4u.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.a747cf9c.js";
import { S as _ } from "./star.d358f014.js";
x as s,
y as r,
J as o,
Q as u,
R as d,
H as t,
I as c,
C as m,
V as h,
F as n,
G as a,
B as x,
U as b,
a8 as k,
A as w,
} from "./frappe-ui-iPT8hMkb.js";
import { S as B } from "./star-xishKgdq.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" },
S = { class: "flex relative top-4 left-4 w-fit" },
U = { class: "course-card-pills rounded-md border border-gray-200" },
V = { 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 = {
j = { class: "flex items-center justify-between mb-2" },
z = { key: 0, class: "flex items-center space-x-1 py-1" },
I = { key: 1, class: "flex items-center space-x-1 py-1" },
R = { key: 2, class: "flex items-center space-x-1 py-1" },
A = { key: 3 },
F = { class: "text-xl font-semibold" },
M = { class: "short-introduction" },
O = { key: 0, class: "w-full bg-gray-200 rounded-full h-1 mb-2" },
_ = { key: 1, class: "text-sm mb-4" },
$ = { class: "flex items-center justify-between mt-auto" },
D = { class: "flex avatar-group overlap" },
E = { key: 0 },
G = { key: 1 },
H = { key: 2 },
J = { class: "font-semibold" },
W = {
__name: "CourseCard",
props: { course: { type: Object, default: null } },
setup(e) {
const { user: u } = g();
return (X, q) =>
const { user: i } = g();
return (L, Q) =>
e.course.title
? (s(),
r("div", C, [
@@ -66,15 +66,15 @@ const C = {
}),
},
[
o("div", B, [
o("div", S, [
(s(!0),
r(
i,
u,
null,
d(
e.course.tags,
(l) => (
s(), r("div", S, t(l), 1)
s(), r("div", U, t(l), 1)
)
),
256
@@ -83,15 +83,15 @@ const C = {
e.course.image
? c("", !0)
: (s(),
r("div", z, t(e.course.title[0]), 1)),
r("div", V, t(e.course.title[0]), 1)),
],
6
),
o("div", N, [
o("div", U, [
o("div", j, [
e.course.lesson_count
? (s(),
r("div", V, [
r("div", z, [
n(a(v), {
class: "h-4 w-4 stroke-1.5 text-gray-700",
}),
@@ -105,7 +105,7 @@ const C = {
: c("", !0),
e.course.enrollment_count
? (s(),
r("div", j, [
r("div", I, [
n(a(y), {
class: "h-4 w-4 stroke-1.5 text-gray-700",
}),
@@ -122,8 +122,8 @@ const C = {
: c("", !0),
e.course.avg_rating
? (s(),
r("div", A, [
n(a(_), {
r("div", R, [
n(a(B), {
class: "h-4 w-4 stroke-1.5 text-gray-700",
}),
o(
@@ -136,7 +136,7 @@ const C = {
: c("", !0),
e.course.status != "Approved"
? (s(),
r("div", D, [
r("div", A, [
n(
a(k),
{
@@ -166,11 +166,11 @@ const C = {
]))
: c("", !0),
]),
o("div", E, t(e.course.title), 1),
o("div", F, t(e.course.short_introduction), 1),
a(u) && e.course.membership
o("div", F, t(e.course.title), 1),
o("div", M, t(e.course.short_introduction), 1),
a(i) && e.course.membership
? (s(),
r("div", I, [
r("div", O, [
o(
"div",
{
@@ -189,11 +189,11 @@ const C = {
),
]))
: c("", !0),
a(u) && e.course.membership
a(i) && e.course.membership
? (s(),
r(
"div",
L,
_,
t(
Math.ceil(
e.course.membership.progress
@@ -202,8 +202,8 @@ const C = {
1
))
: c("", !0),
o("div", M, [
o("div", O, [
o("div", $, [
o("div", D, [
o(
"div",
{
@@ -219,7 +219,7 @@ const C = {
[
(s(!0),
r(
i,
u,
null,
d(
e.course.instructors,
@@ -243,7 +243,7 @@ const C = {
? (s(),
r(
"span",
R,
E,
t(
e.course.instructors[0]
.full_name
@@ -255,7 +255,7 @@ const C = {
? (s(),
r(
"span",
$,
G,
t(
e.course.instructors[0]
.first_name
@@ -273,7 +273,7 @@ const C = {
? (s(),
r(
"span",
K,
H,
t(
e.course.instructors[0]
.first_name
@@ -288,11 +288,12 @@ const C = {
))
: c("", !0),
]),
o("div", T, t(e.course.price), 1),
o("div", J, t(e.course.price), 1),
]),
]),
]))
: c("", !0);
},
};
export { Q as _ };
export { W as _ };
//# sourceMappingURL=CourseCard-1i2yp1tI.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.course-image{height:168px;width:100%;background-size:cover;background-position:center;background-repeat:no-repeat}.course-card-pills{background:#fff;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}

View File

@@ -1 +0,0 @@
.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}

File diff suppressed because one or more lines are too long

View File

@@ -1,47 +1,67 @@
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.a747cf9c.js";
import { c as i } from "./index.51e5b051.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", [
ag as N,
k as C,
W as b,
x as e,
y as o,
J as r,
Q as d,
R as h,
A as n,
B as c,
ah as w,
G as t,
C as M,
F as l,
H as k,
ai as I,
I as V,
U as B,
aj as R,
} from "./frappe-ui-iPT8hMkb.js";
import { a as i } from "./index-qZ7Yta4u.js";
/**
* @license lucide-vue-next v0.309.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/ const j = i("ChevronRightIcon", [
["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }],
]);
/**
* @license lucide-vue-next v0.309.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/ const z = 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" }],
]);
/**
* @license lucide-vue-next v0.309.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/ const F = 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" }],
]);
/**
* @license lucide-vue-next v0.309.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/ const H = i("MonitorPlayIcon", [
["path", { d: "m10 7 5 3-5 3Z", key: "29ljg6" }],
[
"rect",
@@ -56,44 +76,44 @@ const L = i("ChevronRightIcon", [
],
["path", { d: "M12 17v4", key: "1riwvh" }],
["path", { d: "M8 21h8", key: "1ev6f3" }],
]);
const j = { class: "course-outline text-base" },
]),
L = { 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 = {
O = { class: "text-base" },
T = { class: "outline-lesson mb-2 pl-9" },
P = { class: "flex items-center text-sm" },
D = {
__name: "CourseOutline",
props: { courseName: { type: String, required: !0 } },
setup(m) {
const k = C(),
const x = N(),
y = m,
x = b({
_ = C({
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");
f = (u) => u == x.params.chapterNumber || u == 1;
return (u, Q) => {
const g = b("router-link");
return (
e(),
o("div", j, [
o("div", L, [
r("div", q, [
(e(!0),
o(
d,
null,
h(
t(x).data,
(a, g) => (
t(_).data,
(s, v) => (
e(),
n(
t(I),
t(R),
{
key: a.name,
defaultOpen: v(a.idx),
key: s.name,
defaultOpen: f(s.idx),
},
{
default: c(({ open: p }) => [
@@ -105,7 +125,7 @@ const j = { class: "course-outline text-base" },
{
default: c(() => [
l(
t(L),
t(j),
{
class: M(
[
@@ -115,7 +135,7 @@ const j = { class: "course-outline text-base" },
"duration-200":
!p,
open:
g ==
v ==
1,
},
"h-5 w-5 text-gray-900 stroke-1 mr-2",
@@ -128,8 +148,8 @@ const j = { class: "course-outline text-base" },
),
r(
"div",
H,
_(a.title),
O,
k(s.title),
1
),
]),
@@ -138,7 +158,7 @@ const j = { class: "course-outline text-base" },
1024
),
l(
t(V),
t(I),
{ class: "pb-2" },
{
default: c(() => [
@@ -147,21 +167,21 @@ const j = { class: "course-outline text-base" },
d,
null,
h(
a.lessons,
(s) => (
s.lessons,
(a) => (
e(),
o(
"div",
{
key: s.name,
key: a.name,
},
[
r(
"div",
P,
T,
[
l(
f,
g,
{
to: {
name: "Lesson",
@@ -169,11 +189,11 @@ const j = { class: "course-outline text-base" },
courseName:
m.courseName,
chapterNumber:
s.number.split(
a.number.split(
"."
)[0],
lessonNumber:
s.number.split(
a.number.split(
"."
)[1],
},
@@ -185,52 +205,52 @@ const j = { class: "course-outline text-base" },
() => [
r(
"div",
T,
P,
[
s.icon ===
a.icon ===
"icon-youtube"
? (e(),
n(
t(
R
H
),
{
key: 0,
class: "h-4 w-4 text-gray-900 stroke-1 mr-2",
}
))
: s.icon ===
: a.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: 1,
class: "h-4 w-4 text-gray-900 stroke-1 mr-2",
}
))
: a.icon ===
"icon-list"
? (e(),
n(
t(
z
),
{
key: 2,
class: "h-4 w-4 text-gray-900 stroke-1 mr-2",
}
))
: z(
: V(
"",
!0
),
B(
" " +
_(
s.title
k(
a.title
),
1
),
@@ -274,4 +294,5 @@ const j = { class: "course-outline text-base" },
};
},
};
export { L as C, X as _ };
export { j as C, D as _ };
//# sourceMappingURL=CourseOutline-7cUm8E8p.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,54 +1,54 @@
import {
a as k,
Y as w,
r as L,
a5 as w,
r as k,
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.a747cf9c.js";
import { _ as U } from "./CourseCard.bf057db6.js";
import { P as A } from "./plus.d245902e.js";
import "./UserAvatar.3cd4adb4.js";
import "./index.51e5b051.js";
import "./star.d358f014.js";
x as n,
y as m,
G as c,
J as i,
F as d,
B as u,
U as h,
H as p,
C as y,
A as x,
M as L,
I as C,
Q as V,
R as $,
a as B,
W as j,
a6 as U,
a7 as z,
a8 as D,
a9 as R,
} from "./frappe-ui-iPT8hMkb.js";
import { _ as A } from "./CourseCard-1i2yp1tI.js";
import { P as E } from "./plus-_m-8cMp1.js";
import "./UserAvatar-nJqmkBPv.js";
import "./index-qZ7Yta4u.js";
import "./star-xishKgdq.js";
const F = { class: "h-screen" },
R = { key: 0 },
S = {
I = { key: 0 },
M = {
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 = {
P = { class: "flex" },
S = { class: "mx-5 py-5" },
G = {
key: 0,
class: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8 mt-5",
},
M = {
H = {
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 = {
J = { class: "flex flex-col items-center justify-center mt-4" },
Y = {
__name: "Courses",
setup(X) {
var g, b, v;
const l = k("$user"),
setup(Q) {
var g, v, b;
const l = B("$user"),
a = w({
type: "list",
doctype: "LMS Course",
@@ -61,7 +61,7 @@ const F = { class: "h-screen" },
url: "lms.lms.utils.get_courses",
auto: !0,
}),
f = L(0),
f = k(0),
_ = [
{
label: "Live",
@@ -114,9 +114,9 @@ const F = { class: "h-screen" },
}),
(l.data.is_moderator ||
l.data.is_instructor ||
((v = (b = a.data) == null ? void 0 : b.created) == null
? void 0
: v.length)) &&
((b = (v = a.data) == null ? void 0 : v.created) !=
null &&
b.length)) &&
_.push({
label: "Created",
courses: o(() => {
@@ -155,16 +155,16 @@ const F = { class: "h-screen" },
}),
})),
(e, s) => {
const N = V("router-link");
const N = j("router-link");
return (
n(),
m("div", F, [
c(a).data
? (n(),
m("div", R, [
i("header", S, [
m("div", I, [
i("header", M, [
d(
c(z),
c(U),
{
class: "h-7",
items: [
@@ -182,13 +182,13 @@ const F = { class: "h-screen" },
8,
["items"]
),
i("div", I, [
i("div", P, [
d(
c(D),
c(z),
{ variant: "solid" },
{
prefix: u(() => [
d(c(A), {
d(c(E), {
class: "h-4 w-4",
}),
]),
@@ -208,9 +208,9 @@ const F = { class: "h-screen" },
),
]),
]),
i("div", J, [
i("div", S, [
d(
c(P),
c(R),
{
class: "overflow-hidden",
modelValue: f.value,
@@ -232,7 +232,7 @@ const F = { class: "h-screen" },
{
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",
"group -mb-px flex items-center gap-2 overflow-hidden 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,
@@ -244,7 +244,7 @@ const F = { class: "h-screen" },
r.icon
? (n(),
x(
$(
L(
r.icon
),
{
@@ -268,7 +268,7 @@ const F = { class: "h-screen" },
),
d(
c(
E
D
),
{
class: y(
@@ -311,12 +311,12 @@ const F = { class: "h-screen" },
r.courses &&
r.courses.value.length
? (n(),
m("div", K, [
m("div", G, [
(n(!0),
m(
B,
V,
null,
j(
$(
r
.courses
.value,
@@ -368,7 +368,7 @@ const F = { class: "h-screen" },
u(
() => [
d(
U,
A,
{
course: t,
},
@@ -393,10 +393,10 @@ const F = { class: "h-screen" },
)),
]))
: (n(),
m("div", M, [
m("div", H, [
i(
"div",
T,
J,
[
i(
"div",
@@ -430,4 +430,5 @@ const F = { class: "h-screen" },
);
},
};
export { Q as default };
export { Y as default };
//# sourceMappingURL=Courses-hTDCCPUa.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,838 @@
import {
aa as B,
ab as N,
r as $,
a as S,
s as j,
k,
x as i,
y,
F as n,
B as x,
G as t,
a7 as T,
J as s,
H as d,
I as R,
Q as M,
R as E,
A as V,
K as A,
U as D,
au as P,
C as I,
b as F,
am as G,
D as J,
c as K,
} from "./frappe-ui-iPT8hMkb.js";
import { _ as U } from "./UserAvatar-nJqmkBPv.js";
import { a as q, t as H, c as O } from "./index-qZ7Yta4u.js";
/**
* @license lucide-vue-next v0.309.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/ const Q = q("ChevronLeftIcon", [
["path", { d: "m15 18-6-6 6-6", key: "1wnfg3" }],
]);
/**
* @license lucide-vue-next v0.309.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/ const W = q("MessageSquareIcon", [
[
"path",
{
d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z",
key: "1lielz",
},
],
]);
/**
* @license lucide-vue-next v0.309.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/ const X = q("MoreHorizontalIcon", [
["circle", { cx: "12", cy: "12", r: "1", key: "41hilf" }],
["circle", { cx: "19", cy: "12", r: "1", key: "1wjl8i" }],
["circle", { cx: "5", cy: "12", r: "1", key: "1pcz8c" }],
]),
Y = { class: "mt-6" },
Z = { key: 0, class: "flex items-center mb-5" },
ee = { class: "text-lg font-semibold ml-2" },
te = { class: "flex items-center justify-between mb-2" },
se = { class: "flex items-center" },
oe = { class: "text-sm ml-2" },
ae = { key: 1 },
le = { class: "flex justify-between mt-2" },
re = s("span", null, null, -1),
z = {
__name: "DiscussionReplies",
props: B(
{
topic: { type: Object, required: !0 },
singleThread: { type: Boolean, default: !1 },
},
{ showTopics: {}, showTopicsModifiers: {} }
),
emits: ["update:showTopics"],
setup(l) {
const g = N(l, "showTopics"),
m = $(""),
c = S("$socket"),
_ = S("$user"),
p = l;
j(() => {
c.on("publish_message", (e) => {
o.reload();
}),
c.on("update_message", (e) => {
o.reload();
}),
c.on("delete_message", (e) => {
o.reload();
});
});
const o = k({
url: "lms.lms.utils.get_discussion_replies",
cache: ["replies", p.topic],
makeParams(e) {
return { topic: p.topic.name };
},
auto: !0,
}),
f = k({
url: "frappe.client.insert",
makeParams(e) {
return {
doc: {
doctype: "Discussion Reply",
reply: m.value,
topic: p.topic.name,
},
};
},
}),
h = () => {
f.submit(
{},
{
validate() {
if (!m.value) return "Reply cannot be empty";
},
onSuccess() {
(m.value = ""), o.reload();
},
onError(e) {
var v;
O({
title: "Error",
text:
((v = e.messages) == null
? void 0
: v[0]) || e,
icon: "x",
iconClasses:
"bg-red-600 text-white rounded-md p-px",
position: "top-center",
timeout: 10,
});
},
}
);
},
r = k({
url: "frappe.client.set_value",
makeParams(e) {
return {
doctype: "Discussion Reply",
name: e.name,
fieldname: "reply",
value: e.reply,
};
},
}),
b = (e) => {
r.submit(
{ name: e.name, reply: e.reply },
{
validate() {
if (!e.reply) return "Reply cannot be empty";
},
onSuccess() {
(e.editable = !1), o.reload();
},
}
);
},
w = k({
url: "frappe.client.delete",
makeParams(e) {
return { doctype: "Discussion Reply", name: e.name };
},
}),
u = (e) => {
w.submit(
{ name: e.name },
{
onSuccess() {
o.reload();
},
}
);
};
return (e, v) => (
i(),
y("div", Y, [
l.singleThread
? R("", !0)
: (i(),
y("div", Z, [
n(
t(T),
{
variant: "outline",
onClick:
v[0] ||
(v[0] = (a) => (g.value = !0)),
},
{
icon: x(() => [
n(t(Q), {
class: "w-5 h-5 stroke-1.5 text-gray-700",
}),
]),
_: 1,
}
),
s("span", ee, d(l.topic.title), 1),
])),
(i(!0),
y(
M,
null,
E(
t(o).data,
(a, L) => (
i(),
y("div", null, [
s(
"div",
{
class: I([
"py-3",
{
"border-b":
L + 1 !=
t(o).data.length,
},
]),
},
[
s("div", te, [
s("div", se, [
n(
U,
{
user: a.user,
class: "mr-2",
},
null,
8,
["user"]
),
s(
"span",
null,
d(a.user.full_name),
1
),
s(
"span",
oe,
d(t(H)(a.creation)),
1
),
]),
t(_).data.name == a.owner &&
!a.editable
? (i(),
V(
t(A),
{
key: 0,
options: [
{
label: "Edit",
onClick() {
a.editable =
!0;
},
},
{
label: "Delete",
onClick() {
u(
a
);
},
},
],
},
{
default: x(
({
open: C,
}) => [
n(
t(
X
),
{
class: "w-4 h-4 stroke-1.5 cursor-pointer",
}
),
]
),
_: 2,
},
1032,
["options"]
))
: R("", !0),
a.editable
? (i(),
y("div", ae, [
n(
t(T),
{
variant:
"ghost",
onClick: (
C
) => b(a),
},
{
default: x(
() => [
D(
d(
e.__(
"Post"
)
),
1
),
]
),
_: 2,
},
1032,
["onClick"]
),
n(
t(T),
{
variant:
"ghost",
onClick: (
C
) =>
(a.editable =
!1),
},
{
default: x(
() => [
D(
d(
e.__(
"Discard"
)
),
1
),
]
),
_: 2,
},
1032,
["onClick"]
),
]))
: R("", !0),
]),
n(
t(P),
{
content: a.reply,
onChange: (C) =>
(a.reply = C),
editable: a.editable || !1,
fixedMenu: a.editable || !1,
editorClass: a.editable
? "ProseMirror prose prose-table:table-fixed prose-td:p-2 prose-th:p-2 prose-td:border prose-th:border prose-td:border-gray-300 prose-th:border-gray-300 prose-td:relative prose-th:relative prose-th:bg-gray-100 prose-sm max-w-none"
: "prose-sm",
},
null,
8,
[
"content",
"onChange",
"editable",
"fixedMenu",
"editorClass",
]
),
],
2
),
])
)
),
256
)),
n(
t(P),
{
class: "mt-5",
content: m.value,
onChange: v[1] || (v[1] = (a) => (m.value = a)),
placeholder: "Type your reply here...",
fixedMenu: !0,
editorClass:
"ProseMirror prose prose-table:table-fixed prose-td:p-2 prose-th:p-2 prose-td:border prose-th:border prose-td:border-gray-300 prose-th:border-gray-300 prose-td:relative prose-th:relative prose-th:bg-gray-100 prose-sm max-w-none border border-gray-300 rounded-b-md min-h-[7rem] py-1 px-2",
},
null,
8,
["content"]
),
s("div", le, [
re,
n(
t(T),
{ onClick: v[2] || (v[2] = (a) => h()) },
{
default: x(() => [
s("span", null, d(e.__("Post")), 1),
]),
_: 1,
}
),
]),
])
);
},
},
ne = { class: "flex flex-col gap-4" },
ie = { class: "mb-1.5 text-sm text-gray-600" },
de = { class: "mb-1.5 text-sm text-gray-600" },
ce = {
__name: "DiscussionModal",
props: B(
{
title: { type: String, required: !0 },
doctype: { type: String, required: !0 },
docname: { type: String, required: !0 },
},
{ reloadTopics: {}, reloadTopicsModifiers: {} }
),
emits: ["update:reloadTopics"],
setup(l) {
const g = N(l, "reloadTopics"),
m = l,
c = F({ title: "", reply: "" }),
_ = k({
url: "frappe.client.insert",
makeParams(f) {
return {
doc: {
doctype: "Discussion Topic",
reference_doctype: m.doctype,
reference_docname: m.docname,
title: c.title,
},
};
},
}),
p = k({
url: "frappe.client.insert",
makeParams(f) {
return {
doc: {
doctype: "Discussion Reply",
topic: f.topic,
reply: c.reply,
},
};
},
}),
o = (f) => {
_.submit(
{},
{
onSuccess(h) {
p.submit(
{ topic: h.name },
{
onSuccess() {
(c.title = ""),
(c.reply = ""),
g.value.reload(),
f();
},
}
);
},
}
);
};
return (f, h) => (
i(),
V(
t(J),
{
options: {
title: m.title,
size: "2xl",
actions: [
{
label: "Submit",
variant: "solid",
onClick: (r) => o(r),
},
],
},
},
{
"body-content": x(() => [
s("div", ne, [
s("div", null, [
s("div", ie, d(f.__("Title")), 1),
n(
t(G),
{
type: "text",
modelValue: c.title,
"onUpdate:modelValue":
h[0] ||
(h[0] = (r) => (c.title = r)),
},
null,
8,
["modelValue"]
),
]),
s("div", null, [
s("div", de, d(f.__("Details")), 1),
n(
t(P),
{
content: c.reply,
onChange:
h[1] ||
(h[1] = (r) => (c.reply = r)),
editable: !0,
fixedMenu: !0,
editorClass:
"prose-sm max-w-none border-b border-x bg-gray-100 rounded-b-md py-1 px-2 min-h-[7rem]",
},
null,
8,
["content"]
),
]),
]),
]),
_: 1,
},
8,
["options"]
)
);
},
},
ue = { class: "text-xl font-semibold" },
pe = { key: 0 },
me = ["onClick"],
ye = { class: "text-lg font-semibold mb-1" },
fe = { class: "flex items-center" },
he = { class: "text-sm ml-2" },
be = { key: 1 },
ve = { key: 1 },
ge = { key: 2, class: "flex justify-center border mt-5 p-5 rounded-md" },
_e = { class: "text-xl font-semibold mb-2" },
we = {
__name: "Discussions",
props: {
title: { type: String, required: !0 },
doctype: { type: String, required: !0 },
docname: { type: String, required: !0 },
emptyStateTitle: { type: String, default: "No topics yet" },
emptyStateText: {
type: String,
default: "Be the first to start a discussion",
},
singleThread: { type: Boolean, default: !1 },
},
setup(l) {
const g = $(!0),
m = $(null),
c = S("$socket"),
_ = $(!1),
p = l;
j(() => {
c.on("new_discussion_topic", (r) => {
o.refresh();
});
});
const o = k({
url: "lms.lms.utils.get_discussion_topics",
cache: ["topics", p.doctype, p.docname],
makeParams() {
return {
doctype: p.doctype,
docname: p.docname,
single_thread: p.singleThread,
};
},
auto: !0,
}),
f = (r) => {
(g.value = !1), (m.value = r);
},
h = () => {
_.value = !0;
};
return (r, b) => {
var w;
return (
i(),
y(
M,
null,
[
s("div", null, [
l.singleThread
? R("", !0)
: (i(),
V(
t(T),
{
key: 0,
class: "float-right",
onClick:
b[0] || (b[0] = (u) => h()),
},
{
default: x(() => [
D(
d(
r
.__("New {0}")
.format(l.title)
),
1
),
]),
_: 1,
}
)),
s("div", ue, d(r.__(l.title)), 1),
]),
(w = t(o).data) != null &&
w.length &&
!l.singleThread
? (i(),
y("div", pe, [
g.value
? (i(!0),
y(
M,
{ key: 0 },
E(
t(o).data,
(u, e) => (
i(),
y("div", null, [
s(
"div",
{
onClick:
(
v
) =>
f(
u
),
class: I(
[
"flex items-center cursor-pointer py-5",
{
"border-b":
e +
1 !=
t(
o
)
.data
.length,
},
]
),
},
[
n(
U,
{
user: u.user,
size: "2xl",
class: "mr-4",
},
null,
8,
[
"user",
]
),
s(
"div",
null,
[
s(
"div",
ye,
d(
u.title
),
1
),
s(
"div",
fe,
[
s(
"span",
null,
d(
u
.user
.full_name
),
1
),
s(
"span",
he,
d(
t(
H
)(
u.creation
)
),
1
),
]
),
]
),
],
10,
me
),
])
)
),
256
))
: (i(),
y("div", be, [
n(
z,
{
topic: m.value,
showTopics: g.value,
"onUpdate:showTopics":
b[1] ||
(b[1] = (u) =>
(g.value =
u)),
},
null,
8,
["topic", "showTopics"]
),
])),
]))
: l.singleThread && t(o).data
? (i(),
y("div", ve, [
n(
z,
{
topic: t(o).data,
singleThread: l.singleThread,
},
null,
8,
["topic", "singleThread"]
),
]))
: (i(),
y("div", ge, [
n(t(W), {
class: "w-10 h-10 stroke-1.5 text-gray-800 mr-2",
}),
s("div", null, [
s(
"div",
_e,
d(r.__(l.emptyStateTitle)),
1
),
s(
"div",
null,
d(r.__(l.emptyStateText)),
1
),
]),
])),
n(
ce,
{
modelValue: _.value,
"onUpdate:modelValue":
b[2] || (b[2] = (u) => (_.value = u)),
title: r.__("New {0}").format(l.title),
doctype: p.doctype,
docname: p.docname,
reloadTopics: t(o),
"onUpdate:reloadTopics":
b[3] ||
(b[3] = (u) =>
K(o) ? (o.value = u) : null),
},
null,
8,
[
"modelValue",
"title",
"doctype",
"docname",
"reloadTopics",
]
),
],
64
)
);
};
},
};
export { Q as C, we as _ };
//# sourceMappingURL=Discussions-0iopHFAD.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,21 +1,21 @@
import {
q as f,
ai as g,
v as f,
aB as g,
T as _,
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.a747cf9c.js";
W as c,
x as o,
A as l,
B as r,
aC as C,
aD as p,
N as k,
Q as d,
V as u,
J as a,
R as m,
y as h,
C as b,
} from "./frappe-ui-iPT8hMkb.js";
const v = {
name: "FontColor",
props: ["editor"],
@@ -66,8 +66,8 @@ const v = {
y = { class: "p-2" },
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"],
D = a(
D = ["aria-label", "onClick"],
F = a(
"div",
{ class: "mt-2 text-sm text-gray-700" },
"Background Color",
@@ -75,7 +75,7 @@ const v = {
),
w = { class: "mt-1 grid grid-cols-8 gap-1" },
T = ["aria-label", "onClick"];
function z(t, A, j, E, R, n) {
function A(t, R, z, E, $, n) {
const i = c("Tooltip"),
x = c("Popover");
return (
@@ -85,10 +85,10 @@ function z(t, A, j, E, R, n) {
{ transition: "default" },
{
target: r(({ togglePopover: e, isOpen: s }) => [
p(
k(
t.$slots,
"default",
C(k({ onClick: () => e(), isActive: s }))
p(C({ onClick: () => e(), isActive: s }))
),
]),
"body-main": r(() => [
@@ -96,8 +96,8 @@ function z(t, A, j, E, R, n) {
B,
a("div", P, [
(o(!0),
d(
u,
h(
d,
null,
m(
n.foregroundColors,
@@ -118,7 +118,7 @@ function z(t, A, j, E, R, n) {
"aria-label":
e.name,
class: "flex h-5 w-5 items-center justify-center rounded border text-base",
style: h({
style: u({
color: e.hex,
}),
onClick: (s) =>
@@ -128,7 +128,7 @@ function z(t, A, j, E, R, n) {
},
" A ",
12,
F
D
),
]),
_: 2,
@@ -141,11 +141,11 @@ function z(t, A, j, E, R, n) {
128
)),
]),
D,
F,
a("div", w, [
(o(!0),
d(
u,
h(
d,
null,
m(
n.backgroundColors,
@@ -171,7 +171,7 @@ function z(t, A, j, E, R, n) {
? "border-transparent"
: "border-gray-200",
]),
style: h({
style: u({
backgroundColor:
e.hex,
}),
@@ -202,5 +202,6 @@ function z(t, A, j, E, R, n) {
)
);
}
const G = f(v, [["render", z]]);
const G = f(v, [["render", A]]);
export { G as default };
//# sourceMappingURL=FontColor-67MjDpop.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,15 +1,15 @@
import {
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.a747cf9c.js";
v as d,
D as g,
x as m,
y as f,
F as s,
B as t,
U as l,
J as r,
H as p,
W as u,
} from "./frappe-ui-iPT8hMkb.js";
const D = {
name: "Home",
data() {
@@ -19,9 +19,9 @@ const D = {
components: { Dialog: g },
},
_ = { class: "max-w-3xl py-12 mx-auto" };
function C(e, o, k, w, n, V) {
const a = r("Button"),
c = r("Dialog");
function k(e, o, w, B, n, C) {
const a = u("Button"),
c = u("Dialog");
return (
m(),
f("div", _, [
@@ -39,8 +39,8 @@ function C(e, o, k, w, n, V) {
8,
["onClick", "loading"]
),
u("div", null, p(e.$resources.ping.data), 1),
u("pre", null, p(e.$resources.ping), 1),
r("div", null, p(e.$resources.ping.data), 1),
r("pre", null, p(e.$resources.ping), 1),
s(
a,
{ onClick: o[0] || (o[0] = (i) => (n.showDialog = !0)) },
@@ -61,5 +61,6 @@ function C(e, o, k, w, n, V) {
])
);
}
const B = d(D, [["render", C]]);
export { B as default };
const $ = d(D, [["render", k]]);
export { $ as default };
//# sourceMappingURL=Home-x768lxic.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Home-x768lxic.js","sources":["../../../../frontend/src/pages/Home.vue"],"sourcesContent":["<template>\n <div class=\"max-w-3xl py-12 mx-auto\">\n <Button\n icon-left=\"code\"\n @click=\"$resources.ping.fetch\"\n :loading=\"$resources.ping.loading\"\n >\n Click to send 'ping' request\n </Button>\n <div>\n {{ $resources.ping.data }}\n </div>\n <pre>{{ $resources.ping }}</pre>\n\n <Button @click=\"showDialog = true\">Open Dialog</Button>\n <Dialog title=\"Title\" v-model=\"showDialog\"> Dialog content </Dialog>\n </div>\n</template>\n\n<script>\nimport { Dialog } from 'frappe-ui'\n\nexport default {\n name: 'Home',\n data() {\n return {\n showDialog: false,\n }\n },\n resources: {\n ping: {\n url: 'ping',\n },\n },\n components: {\n Dialog,\n },\n}\n</script>\n"],"names":["_sfc_main","Dialog","_hoisted_1","_openBlock","_createElementBlock","_createVNode","_component_Button","_ctx","_createElementVNode","_toDisplayString","$data","_component_Dialog","$event"],"mappings":"2GAsBA,MAAKA,EAAU,CACb,KAAM,OACN,MAAO,CACL,MAAO,CACL,WAAY,EACd,CACD,EACD,UAAW,CACT,KAAM,CACJ,IAAK,MACN,CACF,EACD,WAAY,CACV,OAAAC,CACD,CACH,EApCOC,EAAA,CAAA,MAAM,yBAAyB,4DAApC,OAAAC,EAAA,EAAAC,EAeM,MAfNF,EAeM,CAdJG,EAMSC,EAAA,CALP,YAAU,OACT,QAAOC,EAAA,WAAW,KAAK,MACvB,QAASA,EAAA,WAAW,KAAK,oBAC3B,IAED,GAFC,gCAED,kCACAC,EAEM,MADD,KAAAC,EAAAF,EAAA,WAAW,KAAK,IAAI,EAAA,CAAA,EAEzBC,EAAgC,MAAA,KAAAC,EAAxBF,EAAU,WAAC,IAAI,EAAA,CAAA,EAEvBF,EAAuDC,EAAA,CAA9C,uBAAOI,EAAU,WAAA,gBAAS,IAAW,GAAX,aAAW,UAC9CL,EAAoEM,EAAA,CAA5D,MAAM,mBAAiBD,EAAU,gDAAVA,EAAU,WAAAE,eAAE,IAAgB,GAAhB,kBAAgB"}

View File

@@ -1,23 +1,23 @@
import {
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.a747cf9c.js";
const b = {
v as I,
a7 as f,
D,
aN as h,
W as d,
x as m,
y as c,
N as _,
aD as y,
aC as C,
F as n,
B as s,
J as i,
H as v,
I as w,
U as u,
Q as x,
} from "./frappe-ui-iPT8hMkb.js";
const B = {
name: "InsertImage",
props: ["editor"],
expose: ["openDialog"],
@@ -31,7 +31,7 @@ const b = {
},
onImageSelect(t) {
let e = t.target.files[0];
!e ||
e &&
((this.addImageDialog.file = e),
h(e).then((r) => {
this.addImageDialog.url = r;
@@ -46,18 +46,18 @@ const b = {
},
},
},
x = {
b = {
class: "relative cursor-pointer rounded-lg bg-gray-100 py-1 focus-within:bg-gray-200 hover:bg-gray-200",
},
B = { class: "absolute inset-0 select-none px-2 py-1 text-base" },
k = { class: "absolute inset-0 select-none px-2 py-1 text-base" },
S = ["src"];
function V(t, e, r, A, a, o) {
function V(t, e, r, N, a, o) {
const g = d("Button"),
p = d("Dialog");
return (
m(),
c(
w,
x,
null,
[
_(t.$slots, "default", y(C({ onClick: o.openDialog }))),
@@ -72,7 +72,7 @@ function V(t, e, r, A, a, o) {
},
{
"body-content": s(() => [
i("label", x, [
i("label", b, [
i(
"input",
{
@@ -90,8 +90,8 @@ function V(t, e, r, A, a, o) {
),
i(
"span",
B,
k(
k,
v(
a.addImageDialog.file
? "Select another image"
: "Select an image"
@@ -112,7 +112,7 @@ function V(t, e, r, A, a, o) {
8,
S
))
: v("", !0),
: w("", !0),
]),
actions: s(() => [
n(
@@ -147,5 +147,6 @@ function V(t, e, r, A, a, o) {
)
);
}
const P = I(b, [["render", V]]);
export { P as default };
const F = I(B, [["render", V]]);
export { F as default };
//# sourceMappingURL=InsertImage-pFxauZ_l.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"InsertImage-pFxauZ_l.js","sources":["../../../../frontend/node_modules/frappe-ui/src/components/TextEditor/InsertImage.vue"],"sourcesContent":["<template>\n <slot v-bind=\"{ onClick: openDialog }\"></slot>\n <Dialog\n :options=\"{ title: 'Add Image' }\"\n v-model=\"addImageDialog.show\"\n @after-leave=\"reset\"\n >\n <template #body-content>\n <label\n class=\"relative cursor-pointer rounded-lg bg-gray-100 py-1 focus-within:bg-gray-200 hover:bg-gray-200\"\n >\n <input\n type=\"file\"\n class=\"w-full opacity-0\"\n @change=\"onImageSelect\"\n accept=\"image/*\"\n />\n <span class=\"absolute inset-0 select-none px-2 py-1 text-base\">\n {{ addImageDialog.file ? 'Select another image' : 'Select an image' }}\n </span>\n </label>\n <img\n v-if=\"addImageDialog.url\"\n :src=\"addImageDialog.url\"\n class=\"mt-2 w-full rounded-lg\"\n />\n </template>\n <template #actions>\n <Button variant=\"solid\" @click=\"addImage(addImageDialog.url)\">\n Insert Image\n </Button>\n <Button @click=\"reset\"> Cancel </Button>\n </template>\n </Dialog>\n</template>\n<script>\nimport fileToBase64 from '../../utils/file-to-base64'\nimport Dialog from '../Dialog.vue'\nimport Button from '../Button.vue'\n\nexport default {\n name: 'InsertImage',\n props: ['editor'],\n expose: ['openDialog'],\n data() {\n return {\n addImageDialog: { url: '', file: null, show: false },\n }\n },\n components: { Button, Dialog },\n methods: {\n openDialog() {\n this.addImageDialog.show = true\n },\n onImageSelect(e) {\n let file = e.target.files[0]\n if (!file) {\n return\n }\n this.addImageDialog.file = file\n fileToBase64(file).then((base64) => {\n this.addImageDialog.url = base64\n })\n },\n addImage(src) {\n this.editor.chain().focus().setImage({ src }).run()\n this.reset()\n },\n reset() {\n this.addImageDialog = this.$options.data().addImageDialog\n },\n },\n}\n</script>\n"],"names":["_sfc_main","Button","Dialog","e","file","fileToBase64","base64","src","_hoisted_1","_hoisted_2","_renderSlot","_ctx","$options","_createVNode","_component_Dialog","$data","_cache","$event","_createElementVNode","args","_toDisplayString","_createElementBlock","_component_Button"],"mappings":"2JAwCA,MAAKA,EAAU,CACb,KAAM,cACN,MAAO,CAAC,QAAQ,EAChB,OAAQ,CAAC,YAAY,EACrB,MAAO,CACL,MAAO,CACL,eAAgB,CAAE,IAAK,GAAI,KAAM,KAAM,KAAM,EAAO,CACtD,CACD,EACD,WAAY,CAAA,OAAEC,EAAQ,OAAAC,CAAQ,EAC9B,QAAS,CACP,YAAa,CACX,KAAK,eAAe,KAAO,EAC5B,EACD,cAAcC,EAAG,CACf,IAAIC,EAAOD,EAAE,OAAO,MAAM,CAAC,EACtBC,IAGL,KAAK,eAAe,KAAOA,EAC3BC,EAAaD,CAAI,EAAE,KAAME,GAAW,CAClC,KAAK,eAAe,IAAMA,EAC3B,EACF,EACD,SAASC,EAAK,CACZ,KAAK,OAAO,MAAK,EAAG,MAAK,EAAG,SAAS,CAAE,IAAAA,EAAK,EAAE,IAAI,EAClD,KAAK,MAAM,CACZ,EACD,OAAQ,CACN,KAAK,eAAiB,KAAK,SAAS,KAAM,EAAC,cAC5C,CACF,CACH,EA/DQC,EAAA,CAAA,MAAM,gGAAgG,EAQhGC,EAAA,CAAA,MAAM,kDAAkD,2FAhBpEC,EAA8CC,gCAArBC,EAAU,UAAA,CAAA,CAAA,CAAA,EACnCC,EA+BSC,EAAA,CA9BN,QAAS,CAAsB,MAAA,WAAA,EACvB,WAAAC,EAAA,eAAe,KAAf,sBAAAC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAAF,EAAA,eAAe,KAAIE,GAC3B,aAAaL,EAAK,QAER,iBACT,IAYQ,CAZRM,EAYQ,QAZRV,EAYQ,CATNU,EAKE,QAAA,CAJA,KAAK,OACL,MAAM,mBACL,6BAAQN,EAAa,eAAAA,EAAA,cAAA,GAAAO,CAAA,GACtB,OAAO,oBAETD,EAEO,OAFPT,EACKW,EAAAL,EAAA,eAAe,KAAI,uBAAA,iBAAA,EAAA,CAAA,IAIlBA,EAAA,eAAe,SADvBM,EAIE,MAAA,OAFC,IAAKN,EAAc,eAAC,IACrB,MAAM,gDAGC,UACT,IAES,CAFTF,EAESS,EAAA,CAFD,QAAQ,QAAS,QAAON,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAAL,EAAA,SAASG,EAAA,eAAe,GAAG,eAAG,IAE9D,GAF8D,gBAE9D,UACAF,EAAwCS,EAAA,CAA/B,QAAOV,EAAK,KAAA,EAAA,WAAE,IAAQ,GAAR,UAAQ","x_google_ignoreList":[0]}

View File

@@ -1,21 +1,21 @@
import {
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.a747cf9c.js";
const x = {
v as d,
a7 as g,
am as L,
D as m,
W as i,
x as p,
y as f,
N as D,
aD as c,
aC as h,
F as a,
B as l,
aM as v,
U as x,
Q as _,
} from "./frappe-ui-iPT8hMkb.js";
const w = {
name: "InsertLink",
props: ["editor"],
components: { Button: g, Input: L, Dialog: m },
@@ -56,11 +56,11 @@ function V(t, e, C, B, n, s) {
return (
p(),
f(
w,
_,
null,
[
D(t.$slots, "default", c(h({ onClick: s.openDialog }))),
l(
a(
k,
{
options: { title: "Set Link" },
@@ -70,8 +70,8 @@ function V(t, e, C, B, n, s) {
onAfterLeave: s.reset,
},
{
"body-content": a(() => [
l(
"body-content": l(() => [
a(
r,
{
type: "text",
@@ -83,7 +83,7 @@ function V(t, e, C, B, n, s) {
(n.setLinkDialog.url = o)),
onKeydown:
e[1] ||
(e[1] = _(
(e[1] = v(
(o) => s.setLink(o.target.value),
["enter"]
)),
@@ -93,8 +93,8 @@ function V(t, e, C, B, n, s) {
["modelValue"]
),
]),
actions: a(() => [
l(
actions: l(() => [
a(
u,
{
variant: "solid",
@@ -103,7 +103,7 @@ function V(t, e, C, B, n, s) {
(e[2] = (o) =>
s.setLink(n.setLinkDialog.url)),
},
{ default: a(() => [v(" Save ")]), _: 1 }
{ default: l(() => [x(" Save ")]), _: 1 }
),
]),
_: 1,
@@ -116,5 +116,6 @@ function V(t, e, C, B, n, s) {
)
);
}
const y = d(x, [["render", V]]);
export { y as default };
const R = d(w, [["render", V]]);
export { R as default };
//# sourceMappingURL=InsertLink-PJVOdU-g.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"InsertLink-PJVOdU-g.js","sources":["../../../../frontend/node_modules/frappe-ui/src/components/TextEditor/InsertLink.vue"],"sourcesContent":["<template>\n <slot v-bind=\"{ onClick: openDialog }\"></slot>\n <Dialog\n :options=\"{ title: 'Set Link' }\"\n v-model=\"setLinkDialog.show\"\n @after-leave=\"reset\"\n >\n <template #body-content>\n <FormControl\n type=\"text\"\n label=\"URL\"\n v-model=\"setLinkDialog.url\"\n @keydown.enter=\"(e) => setLink(e.target.value)\"\n />\n </template>\n <template #actions>\n <Button variant=\"solid\" @click=\"setLink(setLinkDialog.url)\">\n Save\n </Button>\n </template>\n </Dialog>\n</template>\n<script>\nimport Dialog from '../Dialog.vue'\nimport Button from '../Button.vue'\nimport Input from '../Input.vue'\n\nexport default {\n name: 'InsertLink',\n props: ['editor'],\n components: { Button, Input, Dialog },\n data() {\n return {\n setLinkDialog: { url: '', show: false },\n }\n },\n methods: {\n openDialog() {\n let existingURL = this.editor.getAttributes('link').href\n if (existingURL) {\n this.setLinkDialog.url = existingURL\n }\n this.setLinkDialog.show = true\n },\n setLink(url) {\n // empty\n if (url === '') {\n this.editor.chain().focus().extendMarkRange('link').unsetLink().run()\n } else {\n // update link\n this.editor\n .chain()\n .focus()\n .extendMarkRange('link')\n .setLink({ href: url })\n .run()\n }\n\n this.setLinkDialog.show = false\n this.setLinkDialog.url = ''\n },\n reset() {\n this.setLinkDialog = this.$options.data().setLinkDialog\n },\n },\n}\n</script>\n"],"names":["_sfc_main","Button","Input","Dialog","existingURL","url","_renderSlot","_ctx","$options","_createVNode","_component_Dialog","$data","_cache","$event","_component_FormControl","_withKeys","e","_component_Button"],"mappings":"mJA2BA,MAAKA,EAAU,CACb,KAAM,aACN,MAAO,CAAC,QAAQ,EAChB,WAAY,CAAEC,OAAAA,EAAQ,MAAAC,EAAO,OAAAC,CAAQ,EACrC,MAAO,CACL,MAAO,CACL,cAAe,CAAE,IAAK,GAAI,KAAM,EAAO,CACzC,CACD,EACD,QAAS,CACP,YAAa,CACX,IAAIC,EAAc,KAAK,OAAO,cAAc,MAAM,EAAE,KAChDA,IACF,KAAK,cAAc,IAAMA,GAE3B,KAAK,cAAc,KAAO,EAC3B,EACD,QAAQC,EAAK,CAEPA,IAAQ,GACV,KAAK,OAAO,MAAK,EAAG,MAAK,EAAG,gBAAgB,MAAM,EAAE,UAAW,EAAC,IAAI,EAGpE,KAAK,OACF,MAAM,EACN,MAAM,EACN,gBAAgB,MAAM,EACtB,QAAQ,CAAE,KAAMA,EAAK,EACrB,IAAI,EAGT,KAAK,cAAc,KAAO,GAC1B,KAAK,cAAc,IAAM,EAC1B,EACD,OAAQ,CACN,KAAK,cAAgB,KAAK,SAAS,KAAM,EAAC,aAC3C,CACF,CACH,oGAhEEC,EAA8CC,gCAArBC,EAAU,UAAA,CAAA,CAAA,CAAA,EACnCC,EAkBSC,EAAA,CAjBN,QAAS,CAAqB,MAAA,UAAA,EACtB,WAAAC,EAAA,cAAc,KAAd,sBAAAC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAAF,EAAA,cAAc,KAAIE,GAC1B,aAAaL,EAAK,QAER,iBACT,IAKE,CALFC,EAKEK,EAAA,CAJA,KAAK,OACL,MAAM,MACG,WAAAH,EAAA,cAAc,IAAd,sBAAAC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAAF,EAAA,cAAc,IAAGE,GACzB,UAAOD,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAG,EAASC,GAAMR,EAAA,QAAQQ,EAAE,OAAO,KAAK,EAAA,CAAA,OAAA,CAAA,6BAGtC,UACT,IAES,CAFTP,EAESQ,EAAA,CAFD,QAAQ,QAAS,QAAOL,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAAL,EAAA,QAAQG,EAAA,cAAc,GAAG,eAAG,IAE5D,GAF4D,QAE5D","x_google_ignoreList":[0]}

View File

@@ -1,23 +1,23 @@
import {
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.a747cf9c.js";
v as _,
a7 as C,
D as v,
aO as k,
W as r,
x as u,
y as c,
N as h,
aD as x,
aC as B,
F as a,
B as l,
H as y,
U as n,
A as U,
I as p,
J as w,
Q as F,
} from "./frappe-ui-iPT8hMkb.js";
const I = {
name: "InsertImage",
props: ["editor"],
@@ -25,14 +25,14 @@ const I = {
data() {
return { addVideoDialog: { url: "", file: null, show: !1 } };
},
components: { Button: C, Dialog: k, FileUploader: v },
components: { Button: C, Dialog: v, FileUploader: k },
methods: {
openDialog() {
this.addVideoDialog.show = !0;
},
onVideoSelect(i) {
let o = i.target.files[0];
!o || (this.addVideoDialog.file = o);
o && (this.addVideoDialog.file = o);
},
addVideo(i) {
this.editor
@@ -47,9 +47,9 @@ const I = {
},
},
},
A = { class: "flex items-center space-x-2" },
N = ["src"];
function S(i, o, P, z, e, t) {
N = { class: "flex items-center space-x-2" },
A = ["src"];
function S(i, o, L, P, e, t) {
const s = r("Button"),
V = r("FileUploader"),
g = r("Dialog");
@@ -59,7 +59,7 @@ function S(i, o, P, z, e, t) {
F,
null,
[
h(i.$slots, "default", x(y({ onClick: t.openDialog }))),
h(i.$slots, "default", x(B({ onClick: t.openDialog }))),
a(
g,
{
@@ -89,14 +89,14 @@ function S(i, o, P, z, e, t) {
uploading: m,
openFileSelector: D,
}) => [
B("div", A, [
w("div", N, [
a(
s,
{ onClick: D },
{
default: l(() => [
n(
w(
y(
m
? `Uploading ${f}%`
: e
@@ -159,7 +159,7 @@ function S(i, o, P, z, e, t) {
},
null,
8,
N
A
))
: p("", !0),
]),
@@ -196,5 +196,6 @@ function S(i, o, P, z, e, t) {
)
);
}
const L = _(I, [["render", S]]);
export { L as default };
const b = _(I, [["render", S]]);
export { b as default };
//# sourceMappingURL=InsertVideo-5zm7I1WB.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"InsertVideo-5zm7I1WB.js","sources":["../../../../frontend/node_modules/frappe-ui/src/components/TextEditor/InsertVideo.vue"],"sourcesContent":["<template>\n <slot v-bind=\"{ onClick: openDialog }\"></slot>\n <Dialog\n :options=\"{ title: 'Add Video' }\"\n v-model=\"addVideoDialog.show\"\n @after-leave=\"reset\"\n >\n <template #body-content>\n <FileUploader\n file-types=\"video/*\"\n @success=\"(file) => (addVideoDialog.url = file.file_url)\"\n >\n <template v-slot=\"{ file, progress, uploading, openFileSelector }\">\n <div class=\"flex items-center space-x-2\">\n <Button @click=\"openFileSelector\">\n {{\n uploading\n ? `Uploading ${progress}%`\n : addVideoDialog.url\n ? 'Change Video'\n : 'Upload Video'\n }}\n </Button>\n <Button\n v-if=\"addVideoDialog.url\"\n @click=\"\n () => {\n addVideoDialog.url = null\n addVideoDialog.file = null\n }\n \"\n >\n Remove\n </Button>\n </div>\n </template>\n </FileUploader>\n <video\n v-if=\"addVideoDialog.url\"\n :src=\"addVideoDialog.url\"\n class=\"mt-2 w-full rounded-lg\"\n type=\"video/mp4\"\n controls\n />\n </template>\n <template #actions>\n <Button variant=\"solid\" @click=\"addVideo(addVideoDialog.url)\">\n Insert Video\n </Button>\n <Button @click=\"reset\">Cancel</Button>\n </template>\n </Dialog>\n</template>\n<script>\nimport Button from '../Button.vue'\nimport Dialog from '../Dialog.vue'\nimport FileUploader from '../FileUploader.vue'\n\nexport default {\n name: 'InsertImage',\n props: ['editor'],\n expose: ['openDialog'],\n data() {\n return {\n addVideoDialog: { url: '', file: null, show: false },\n }\n },\n components: { Button, Dialog, FileUploader },\n methods: {\n openDialog() {\n this.addVideoDialog.show = true\n },\n onVideoSelect(e) {\n let file = e.target.files[0]\n if (!file) {\n return\n }\n this.addVideoDialog.file = file\n },\n\n addVideo(src) {\n this.editor\n .chain()\n .focus()\n .insertContent(`<video src=\"${src}\"></video>`)\n .run()\n this.reset()\n },\n reset() {\n this.addVideoDialog = this.$options.data().addVideoDialog\n },\n },\n}\n</script>\n"],"names":["_sfc_main","Button","Dialog","FileUploader","e","file","src","_hoisted_1","_renderSlot","_ctx","$options","_createVNode","_component_Dialog","$data","_cache","$event","_component_FileUploader","_withCtx","progress","uploading","openFileSelector","_createElementVNode","_component_Button","_createBlock","_createElementBlock"],"mappings":"uKA0DA,MAAKA,EAAU,CACb,KAAM,cACN,MAAO,CAAC,QAAQ,EAChB,OAAQ,CAAC,YAAY,EACrB,MAAO,CACL,MAAO,CACL,eAAgB,CAAE,IAAK,GAAI,KAAM,KAAM,KAAM,EAAO,CACtD,CACD,EACD,WAAY,CAAEC,OAAAA,EAAQ,OAAAC,EAAQ,aAAAC,CAAc,EAC5C,QAAS,CACP,YAAa,CACX,KAAK,eAAe,KAAO,EAC5B,EACD,cAAcC,EAAG,CACf,IAAIC,EAAOD,EAAE,OAAO,MAAM,CAAC,EACtBC,IAGL,KAAK,eAAe,KAAOA,EAC5B,EAED,SAASC,EAAK,CACZ,KAAK,OACF,MAAM,EACN,MAAM,EACN,cAAc,eAAeA,CAAG,YAAY,EAC5C,IAAI,EACP,KAAK,MAAM,CACZ,EACD,OAAQ,CACN,KAAK,eAAiB,KAAK,SAAS,KAAM,EAAC,cAC5C,CACF,CACH,EA/EeC,EAAA,CAAA,MAAM,6BAA6B,+GAZhDC,EAA8CC,gCAArBC,EAAU,UAAA,CAAA,CAAA,CAAA,EACnCC,EAiDSC,EAAA,CAhDN,QAAS,CAAsB,MAAA,WAAA,EACvB,WAAAC,EAAA,eAAe,KAAf,sBAAAC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAAF,EAAA,eAAe,KAAIE,GAC3B,aAAaL,EAAK,QAER,iBACT,IA4Be,CA5BfC,EA4BeK,EAAA,CA3Bb,aAAW,UACV,UAAOF,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAGT,GAAUQ,EAAA,eAAe,IAAMR,EAAK,YAG7C,QAAAY,EAAA,CAqBM,CAtBY,KAAAZ,EAAM,SAAAa,EAAU,UAAAC,EAAW,iBAAAC,KAAgB,CAC7DC,EAqBM,MArBNd,EAqBM,CApBJI,EAQSW,EAAA,CARA,QAAOF,CAAgB,EAAA,WAC9B,IAME,KALAD,eAA2CD,CAAQ,IAAwBL,EAAA,eAAe,+DAQtFA,EAAA,eAAe,SADvBU,EAUSD,EAAA,OARN,aAAkDT,EAAA,eAAe,IAAG,KAA0BA,EAAA,eAAe,KAAI,kBAMnH,IAED,GAFC,UAED,+CAKEA,EAAA,eAAe,SADvBW,EAME,QAAA,OAJC,IAAKX,EAAc,eAAC,IACrB,MAAM,yBACN,KAAK,YACL,SAAA,0BAGO,UACT,IAES,CAFTF,EAESW,EAAA,CAFD,QAAQ,QAAS,QAAOR,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAAL,EAAA,SAASG,EAAA,eAAe,GAAG,eAAG,IAE9D,GAF8D,gBAE9D,UACAF,EAAsCW,EAAA,CAA7B,QAAOZ,EAAK,KAAA,EAAA,WAAE,IAAM,GAAN,QAAM","x_google_ignoreList":[0]}

Some files were not shown because too many files have changed in this diff Show More