Merge pull request #883 from pateljannat/batch-timezone
feat: timezone in batches
This commit is contained in:
@@ -36,19 +36,25 @@
|
||||
:endDate="batch.end_date"
|
||||
class="mb-3"
|
||||
/>
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center mb-3">
|
||||
<Clock class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span>
|
||||
{{ formatTime(batch.start_time) }} - {{ formatTime(batch.end_time) }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="batch.timezone" class="flex items-center">
|
||||
<Globe class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span>
|
||||
{{ batch.timezone }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Badge } from 'frappe-ui'
|
||||
import { formatTime } from '../utils'
|
||||
import { Clock, BookOpen } from 'lucide-vue-next'
|
||||
import { Clock, BookOpen, Globe } from 'lucide-vue-next'
|
||||
import DateRange from '@/components/Common/DateRange.vue'
|
||||
|
||||
const props = defineProps({
|
||||
|
||||
@@ -26,13 +26,19 @@
|
||||
:endDate="batch.data.end_date"
|
||||
class="mb-3"
|
||||
/>
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center mb-3">
|
||||
<Clock class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span>
|
||||
{{ formatTime(batch.data.start_time) }} -
|
||||
{{ formatTime(batch.data.end_time) }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="batch.data.timezone" class="flex items-center">
|
||||
<Globe class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span>
|
||||
{{ batch.data.timezone }}
|
||||
</span>
|
||||
</div>
|
||||
<router-link
|
||||
v-if="user?.data?.is_moderator"
|
||||
:to="{
|
||||
@@ -91,7 +97,7 @@
|
||||
<script setup>
|
||||
import { inject, computed } from 'vue'
|
||||
import { Badge, Button } from 'frappe-ui'
|
||||
import { BookOpen, Clock } from 'lucide-vue-next'
|
||||
import { BookOpen, Clock, Globe } from 'lucide-vue-next'
|
||||
import { formatNumberIntoCurrency, formatTime } from '@/utils'
|
||||
import DateRange from '@/components/Common/DateRange.vue'
|
||||
|
||||
|
||||
@@ -87,13 +87,19 @@
|
||||
:endDate="batch.data.end_date"
|
||||
class="mb-3"
|
||||
/>
|
||||
<div class="flex items-center mb-6">
|
||||
<div class="flex items-center mb-4">
|
||||
<Clock class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span>
|
||||
{{ formatTime(batch.data.start_time) }} -
|
||||
{{ formatTime(batch.data.end_time) }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="batch.data.timezone" class="flex items-center mb-4">
|
||||
<Globe class="h-4 w-4 stroke-1.5 mr-2 text-gray-700" />
|
||||
<span>
|
||||
{{ batch.data.timezone }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<AnnouncementModal
|
||||
v-model="showAnnouncementModal"
|
||||
@@ -159,6 +165,7 @@ import {
|
||||
Mail,
|
||||
SendIcon,
|
||||
MessageCircle,
|
||||
Globe,
|
||||
} from 'lucide-vue-next'
|
||||
import { formatTime } from '@/utils'
|
||||
import BatchDashboard from '@/components/BatchDashboard.vue'
|
||||
|
||||
@@ -9,30 +9,24 @@
|
||||
</Button>
|
||||
</header>
|
||||
<div class="py-5">
|
||||
<div class="container">
|
||||
<div class="container border-b">
|
||||
<div class="text-lg font-semibold mb-4">
|
||||
{{ __('Details') }}
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-10">
|
||||
<div class="grid grid-cols-2 gap-10 mb-4">
|
||||
<div>
|
||||
<FormControl
|
||||
v-model="batch.title"
|
||||
:label="__('Title')"
|
||||
class="mb-4"
|
||||
/>
|
||||
<FormControl
|
||||
v-model="batch.description"
|
||||
:label="__('Description')"
|
||||
type="textarea"
|
||||
class="mb-4"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<FormControl
|
||||
v-model="batch.published"
|
||||
type="checkbox"
|
||||
:label="__('Published')"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<FileUploader
|
||||
v-if="!batch.image"
|
||||
class="mt-4"
|
||||
@@ -52,7 +46,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</FileUploader>
|
||||
<div v-else class="mt-4">
|
||||
<div v-else class="my-4">
|
||||
<div class="text-xs text-gray-600 mb-1">
|
||||
{{ __('Meta Image') }}
|
||||
</div>
|
||||
@@ -74,10 +68,21 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<FormControl
|
||||
v-model="batch.allow_self_enrollment"
|
||||
type="checkbox"
|
||||
:label="__('Allow self enrollment')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container border-b mb-5">
|
||||
<div class="container border-b mb-4">
|
||||
<FormControl
|
||||
v-model="batch.description"
|
||||
:label="__('Description')"
|
||||
type="textarea"
|
||||
class="my-4"
|
||||
/>
|
||||
<div>
|
||||
<label class="block text-sm text-gray-600 mb-1">
|
||||
{{ __('Batch Details') }}
|
||||
@@ -91,9 +96,9 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container border-b mb-5">
|
||||
<div class="container border-b mb-4">
|
||||
<div class="text-lg font-semibold mb-4">
|
||||
{{ __('Settings') }}
|
||||
{{ __('Date and Time') }}
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-10">
|
||||
<div>
|
||||
@@ -109,6 +114,8 @@
|
||||
type="date"
|
||||
class="mb-4"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<FormControl
|
||||
v-model="batch.start_time"
|
||||
:label="__('Start Time')"
|
||||
@@ -121,7 +128,20 @@
|
||||
type="time"
|
||||
class="mb-4"
|
||||
/>
|
||||
<FormControl
|
||||
v-model="batch.timezone"
|
||||
:label="__('Timezone')"
|
||||
type="text"
|
||||
class="mb-4"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container border-b mb-4">
|
||||
<div class="text-lg font-semibold mb-4">
|
||||
{{ __('Settings') }}
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-10">
|
||||
<div>
|
||||
<FormControl
|
||||
v-model="batch.seat_count"
|
||||
@@ -135,6 +155,8 @@
|
||||
type="date"
|
||||
class="mb-4"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<FormControl
|
||||
v-model="batch.medium"
|
||||
type="select"
|
||||
@@ -188,7 +210,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed, onMounted, inject, reactive } from 'vue'
|
||||
import { computed, onMounted, inject, reactive, onBeforeUnmount } from 'vue'
|
||||
import {
|
||||
Breadcrumbs,
|
||||
FormControl,
|
||||
@@ -221,10 +243,12 @@ const batch = reactive({
|
||||
end_date: '',
|
||||
start_time: '',
|
||||
end_time: '',
|
||||
timezone: '',
|
||||
evaluation_end_date: '',
|
||||
seat_count: '',
|
||||
medium: '',
|
||||
category: '',
|
||||
allow_self_enrollment: false,
|
||||
image: null,
|
||||
paid_batch: false,
|
||||
currency: '',
|
||||
@@ -236,6 +260,22 @@ onMounted(() => {
|
||||
if (props.batchName != 'new') {
|
||||
batchDetail.reload()
|
||||
}
|
||||
window.addEventListener('keydown', keyboardShortcut)
|
||||
})
|
||||
|
||||
const keyboardShortcut = (e) => {
|
||||
if (
|
||||
e.key === 's' &&
|
||||
(e.ctrlKey || e.metaKey) &&
|
||||
!e.target.classList.contains('ProseMirror')
|
||||
) {
|
||||
saveBatch()
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('keydown', keyboardShortcut)
|
||||
})
|
||||
|
||||
const newBatch = createResource({
|
||||
|
||||
@@ -9,14 +9,15 @@
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"published",
|
||||
"title",
|
||||
"start_date",
|
||||
"end_date",
|
||||
"column_break_4",
|
||||
"allow_self_enrollment",
|
||||
"start_time",
|
||||
"end_time",
|
||||
"published",
|
||||
"allow_self_enrollment",
|
||||
"timezone",
|
||||
"section_break_rgfj",
|
||||
"medium",
|
||||
"category",
|
||||
@@ -301,11 +302,17 @@
|
||||
"fieldname": "allow_self_enrollment",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow Self Enrollment"
|
||||
},
|
||||
{
|
||||
"fieldname": "timezone",
|
||||
"fieldtype": "Data",
|
||||
"label": "Timezone",
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2024-05-14 14:47:48.839162",
|
||||
"modified": "2024-06-21 11:49:32.582832",
|
||||
"modified_by": "Administrator",
|
||||
"module": "LMS",
|
||||
"name": "LMS Batch",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{% set title = frappe.db.get_value("LMS Course", doc.course, "title") %}
|
||||
{% set timezone = frappe.db.get_value("LMS Batch", doc.batch, "timezone") %}
|
||||
{% set timezone = timezone if timezone else '' %}
|
||||
|
||||
<p> {{ _("Hey {0}").format(doc.member_name) }} </p>
|
||||
<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2}.').format(title, frappe.utils.format_date(doc.date, "medium"), frappe.utils.format_time(doc.start_time, "short")) }}</p>
|
||||
<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, "medium"), frappe.utils.format_time(doc.start_time, "short"), timezone) }}</p>
|
||||
<p> {{ _("Please prepare well and be on time for the evaluations.") }} </p>
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
"event": "New",
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"message": "{% set title = frappe.db.get_value(\"LMS Course\", doc.course, \"title\") %}\n\n<p> {{ _(\"Hey {0}\").format(doc.member_name) }} </p>\n<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2}.').format(title, frappe.utils.format_date(doc.date, \"medium\"), frappe.utils.format_time(doc.start_time, \"short\")) }}</p>\n<p> {{ _(\"Please prepare well and be on time for the evaluations.\") }} </p>\n",
|
||||
"message": "{% set title = frappe.db.get_value(\"LMS Course\", doc.course, \"title\") %}\n{% set timezone = frappe.db.get_value(\"LMS Batch\", doc.batch, \"timezone\") %}\n{% set timezone = timezone if timezone else '' %}\n\n<p> {{ _(\"Hey {0}\").format(doc.member_name) }} </p>\n<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, \"medium\"), frappe.utils.format_time(doc.start_time, \"short\"), timezone) }}</p>\n<p> {{ _(\"Please prepare well and be on time for the evaluations.\") }} </p>\n",
|
||||
"message_type": "HTML",
|
||||
"modified": "2023-11-29 17:34:54.514031",
|
||||
"modified": "2024-06-21 13:15:38.588768",
|
||||
"modified_by": "Administrator",
|
||||
"module": "LMS",
|
||||
"name": "Certificate Request Creation",
|
||||
@@ -23,6 +23,9 @@
|
||||
},
|
||||
{
|
||||
"receiver_by_document_field": "evaluator"
|
||||
},
|
||||
{
|
||||
"receiver_by_role": "Frappe School Admin"
|
||||
}
|
||||
],
|
||||
"send_system_notification": 0,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{% set title = frappe.db.get_value("LMS Course", doc.course, "title") %}
|
||||
{% set timezone = frappe.db.get_value("LMS Batch", doc.batch, "timezone") %}
|
||||
{% set timezone = timezone if timezone else '' %}
|
||||
|
||||
<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2}.').format(title, frappe.utils.format_date(doc.date, "medium"), frappe.utils.format_time(doc.start_time, "short")) }}</p>
|
||||
<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, "medium"), frappe.utils.format_time(doc.start_time, "short"), timezone) }}</p>
|
||||
|
||||
<p> {{ _("Please prepare well and be on time for the evaluations.") }} </p>
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
"event": "Days Before",
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"message": "{% set title = frappe.db.get_value(\"LMS Course\", doc.course, \"title\") %}\n\n<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2}.').format(title, frappe.utils.format_date(doc.date, \"medium\"), frappe.utils.format_time(doc.start_time, \"short\")) }}</p>\n\n<p> {{ _(\"Please prepare well and be on time for the evaluations.\") }} </p>\n",
|
||||
"message": "{% set title = frappe.db.get_value(\"LMS Course\", doc.course, \"title\") %}\n{% set timezone = frappe.db.get_value(\"LMS Batch\", doc.batch, \"timezone\") %}\n{% set timezone = timezone if timezone else '' %}\n\n<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, \"medium\"), frappe.utils.format_time(doc.start_time, \"short\"), timezone) }}</p>\n\n<p> {{ _(\"Please prepare well and be on time for the evaluations.\") }} </p>\n",
|
||||
"message_type": "HTML",
|
||||
"modified": "2023-11-29 17:26:53.355501",
|
||||
"modified": "2024-06-21 13:17:26.360030",
|
||||
"modified_by": "Administrator",
|
||||
"module": "LMS",
|
||||
"name": "Certificate Request Reminder",
|
||||
@@ -29,4 +29,4 @@
|
||||
"send_system_notification": 0,
|
||||
"send_to_all_assignees": 0,
|
||||
"subject": "Reminder for Certificate Evaluation"
|
||||
}
|
||||
}
|
||||
@@ -1512,6 +1512,7 @@ def get_batch_details(batch):
|
||||
"paid_batch",
|
||||
"evaluation_end_date",
|
||||
"allow_self_enrollment",
|
||||
"timezone",
|
||||
],
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 440 B |
@@ -1,52 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/assets/lms/frontend/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Frappe Learning</title>
|
||||
<meta name="title" content="{{ meta.title }}" />
|
||||
<meta name="image" content="{{ meta.image }}" />
|
||||
<meta name="description" content="{{ meta.description }}" />
|
||||
<meta name="keywords" content="{{ meta.keywords }}" />
|
||||
<meta property="og:title" content="{{ meta.title }}" />
|
||||
<meta property="og:image" content="{{ meta.image }}" />
|
||||
<meta property="og:description" content="{{ meta.description }}" />
|
||||
<meta name="twitter:title" content="{{ meta.title }}" />
|
||||
<meta name="twitter:image" content="{{ meta.image }}" />
|
||||
<meta name="twitter:description" content="{{ meta.description }}" />
|
||||
<script type="module" crossorigin src="/assets/lms/frontend/assets/index-Cjguiv45.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/lms/frontend/assets/frappe-ui-0rNYcqgR.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/lms/frontend/assets/frappe-ui-DzKBfka9.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/lms/frontend/assets/index-DOZMTxMe.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<div id="seo-content">
|
||||
<h1>{{ meta.title }}</h1>
|
||||
<p>
|
||||
{{ meta.description }}
|
||||
</p>
|
||||
<p>
|
||||
The content here is just for seo purposes. The actual content will be loaded in a few seconds.
|
||||
</p>
|
||||
<p>
|
||||
Seo checks if a page has more than 300 words. So, here are some more words to make it more than 300 words.
|
||||
Page descriptions are the HTML meta tags that provide a brief summary of a web page.
|
||||
Search engines use meta descriptions to help identify the page's topic - they don't use them to rank the page, but they do use them to determine whether or not to display the page in search results.
|
||||
Meta descriptions are important because they're often the first thing people see when they're deciding which search result to click on.
|
||||
They're also important because they can help improve your click-through rate (CTR) from search results.
|
||||
A good meta description can entice people to click on your page instead of someone else's.
|
||||
</p>
|
||||
<a href="{{ meta.link }}">Know More</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modals"></div>
|
||||
<div id="popovers"></div>
|
||||
|
||||
<script>
|
||||
window.csrf_token = '{{ csrf_token }}'
|
||||
document.getElementById('seo-content').style.display = 'none';
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -82,6 +82,14 @@ def get_meta(app_path):
|
||||
|
||||
if re.match(r"^batches/.*$", app_path):
|
||||
batch_name = app_path.split("/")[1]
|
||||
if "new/edit" in app_path:
|
||||
return {
|
||||
"title": _("New Batch"),
|
||||
"image": frappe.db.get_single_value("Website Settings", "banner_image"),
|
||||
"description": "Create a new batch",
|
||||
"keywords": "New Batch, Create Batch",
|
||||
"link": "/lms/batches/new/edit",
|
||||
}
|
||||
batch = frappe.db.get_value(
|
||||
"LMS Batch",
|
||||
batch_name,
|
||||
|
||||
Reference in New Issue
Block a user