fix: notification on quiz update and mention
This commit is contained in:
@@ -202,60 +202,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="space-y-5">
|
||||
<div>
|
||||
<div class="text-xs text-ink-gray-5">
|
||||
{{ __('Meta Image') }}
|
||||
</div>
|
||||
<FileUploader
|
||||
v-if="!batch.image"
|
||||
:fileTypes="['image/*']"
|
||||
:validateFile="validateFile"
|
||||
@success="(file) => saveImage(file)"
|
||||
>
|
||||
<template
|
||||
v-slot="{ file, progress, uploading, openFileSelector }"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<div
|
||||
class="border rounded-md w-fit py-5 px-5 md:px-20 cursor-pointer"
|
||||
@click="openFileSelector"
|
||||
>
|
||||
<Image class="size-5 stroke-1 text-ink-gray-7" />
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<Button @click="openFileSelector">
|
||||
{{ __('Upload') }}
|
||||
</Button>
|
||||
<div class="mt-1 text-ink-gray-5 text-sm leading-5">
|
||||
{{
|
||||
__('Appears when the batch URL is shared on socials')
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</FileUploader>
|
||||
<div v-else class="mb-4">
|
||||
<div class="flex items-center">
|
||||
<img
|
||||
:src="batch.image.file_url"
|
||||
class="border rounded-md w-40"
|
||||
/>
|
||||
<div class="ml-4">
|
||||
<Button @click="removeImage()">
|
||||
{{ __('Remove') }}
|
||||
</Button>
|
||||
<div class="mt-2 text-ink-gray-5 text-sm">
|
||||
{{
|
||||
__(
|
||||
'Appears when the batch URL is shared on any online platform'
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Uploader
|
||||
v-model="batch.video_link"
|
||||
:label="__('Preview Video')"
|
||||
type="video"
|
||||
:required="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -292,6 +244,12 @@
|
||||
{{ __('Meta Tags') }}
|
||||
</div>
|
||||
<div class="space-y-5">
|
||||
<Uploader
|
||||
v-model="batch.meta_image"
|
||||
:label="__('Meta Image')"
|
||||
type="image"
|
||||
:required="false"
|
||||
/>
|
||||
<FormControl
|
||||
v-model="meta.description"
|
||||
:label="__('Meta Description')"
|
||||
@@ -345,8 +303,8 @@ import {
|
||||
openSettings,
|
||||
sanitizeHTML,
|
||||
updateMetaInfo,
|
||||
validateFile,
|
||||
} from '@/utils'
|
||||
import Uploader from '@/components/Controls/Uploader.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const user = inject('$user')
|
||||
@@ -380,11 +338,12 @@ const batch = reactive({
|
||||
category: '',
|
||||
allow_self_enrollment: false,
|
||||
certification: false,
|
||||
image: null,
|
||||
meta_image: null,
|
||||
paid_batch: false,
|
||||
currency: '',
|
||||
amount: 0,
|
||||
zoom_account: '',
|
||||
video_link: '',
|
||||
})
|
||||
|
||||
const meta = reactive({
|
||||
@@ -428,7 +387,8 @@ const newBatch = createResource({
|
||||
return {
|
||||
doc: {
|
||||
doctype: 'LMS Batch',
|
||||
meta_image: batch.image?.file_url,
|
||||
meta_image: batch.image,
|
||||
video_link: batch.video_link,
|
||||
instructors: instructors.value.map((instructor) => ({
|
||||
instructor: instructor,
|
||||
})),
|
||||
@@ -447,39 +407,48 @@ const batchDetail = createResource({
|
||||
}
|
||||
},
|
||||
onSuccess(data) {
|
||||
Object.keys(data).forEach((key) => {
|
||||
if (key == 'instructors') {
|
||||
data.instructors.forEach((instructor) => {
|
||||
instructors.value.push(instructor.instructor)
|
||||
})
|
||||
} else if (['start_time', 'end_time'].includes(key)) {
|
||||
let [hours, minutes, seconds] = data[key].split(':')
|
||||
hours = hours.length == 1 ? '0' + hours : hours
|
||||
batch[key] = `${hours}:${minutes}`
|
||||
} else if (Object.hasOwn(batch, key)) batch[key] = data[key]
|
||||
})
|
||||
let checkboxes = [
|
||||
'published',
|
||||
'paid_batch',
|
||||
'allow_self_enrollment',
|
||||
'certification',
|
||||
]
|
||||
for (let idx in checkboxes) {
|
||||
let key = checkboxes[idx]
|
||||
batch[key] = batch[key] ? true : false
|
||||
}
|
||||
if (data.meta_image) imageResource.reload({ image: data.meta_image })
|
||||
updateBatchData(data)
|
||||
},
|
||||
})
|
||||
|
||||
const updateBatchData = (data) => {
|
||||
Object.keys(data).forEach((key) => {
|
||||
if (key == 'instructors') {
|
||||
data.instructors.forEach((instructor) => {
|
||||
instructors.value.push(instructor.instructor)
|
||||
})
|
||||
} else if (['start_time', 'end_time'].includes(key)) {
|
||||
batch[key] = formatTime(data[key])
|
||||
} else if (Object.hasOwn(batch, key)) batch[key] = data[key]
|
||||
})
|
||||
let checkboxes = [
|
||||
'published',
|
||||
'paid_batch',
|
||||
'allow_self_enrollment',
|
||||
'certification',
|
||||
]
|
||||
for (let idx in checkboxes) {
|
||||
let key = checkboxes[idx]
|
||||
batch[key] = batch[key] ? true : false
|
||||
}
|
||||
}
|
||||
|
||||
const formatTime = (timeStr) => {
|
||||
let [hours, minutes, seconds] = timeStr.split(':')
|
||||
hours = hours.length == 1 ? '0' + hours : hours
|
||||
return `${hours}:${minutes}`
|
||||
}
|
||||
|
||||
const editBatch = createResource({
|
||||
url: 'frappe.client.set_value',
|
||||
makeParams(values) {
|
||||
console.log(batch.meta_image, batch.video_link)
|
||||
return {
|
||||
doctype: 'LMS Batch',
|
||||
name: props.batchName,
|
||||
fieldname: {
|
||||
meta_image: batch.image?.file_url,
|
||||
meta_image: batch.meta_image,
|
||||
video_link: batch.video_link,
|
||||
instructors: instructors.value.map((instructor) => ({
|
||||
instructor: instructor,
|
||||
})),
|
||||
@@ -489,19 +458,6 @@ const editBatch = createResource({
|
||||
},
|
||||
})
|
||||
|
||||
const imageResource = createResource({
|
||||
url: 'lms.lms.api.get_file_info',
|
||||
makeParams(values) {
|
||||
return {
|
||||
file_url: values.image,
|
||||
}
|
||||
},
|
||||
auto: false,
|
||||
onSuccess(data) {
|
||||
batch.image = data
|
||||
},
|
||||
})
|
||||
|
||||
const validateFields = () => {
|
||||
batch.description = sanitizeHTML(batch.description)
|
||||
batch.batch_details = sanitizeHTML(batch.batch_details)
|
||||
@@ -603,14 +559,6 @@ const trashBatch = (close) => {
|
||||
})
|
||||
}
|
||||
|
||||
const saveImage = (file) => {
|
||||
batch.image = file
|
||||
}
|
||||
|
||||
const removeImage = () => {
|
||||
batch.image = null
|
||||
}
|
||||
|
||||
const breadcrumbs = computed(() => {
|
||||
let crumbs = [
|
||||
{
|
||||
|
||||
@@ -23,14 +23,19 @@
|
||||
v-if="notifications?.length"
|
||||
v-for="log in notifications"
|
||||
:key="log.name"
|
||||
class="flex space-x-2 p-2 rounded-md"
|
||||
class="flex space-x-2 px-2 py-4"
|
||||
:class="{
|
||||
'cursor-pointer': log.link,
|
||||
'items-center': !showDetails(log) && !isMention(log),
|
||||
}"
|
||||
@click="navigateToPage(log)"
|
||||
>
|
||||
<Avatar :image="log.user_image" size="2xl" :label="log.full_name" />
|
||||
<div class="space-y-2">
|
||||
<Avatar
|
||||
:image="log.from_user_details.user_image"
|
||||
size="xl"
|
||||
:label="log.from_user_details.full_name"
|
||||
/>
|
||||
<div class="space-y-2 w-full">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<div class="text-ink-gray-9" v-html="log.subject"></div>
|
||||
@@ -42,7 +47,7 @@
|
||||
<Button
|
||||
variant="ghost"
|
||||
v-if="!log.read"
|
||||
@click.stop="(e) => handleMarkAsRead(e, log.name)"
|
||||
@click.stop="(e) => handleMarkAsRead(log.name)"
|
||||
>
|
||||
<template #icon>
|
||||
<X class="h-4 w-4 text-ink-gray-7 stroke-1.5" />
|
||||
@@ -51,19 +56,39 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="log.document_type == 'LMS Course' && log.document_details"
|
||||
class="flex space-x-5 border border-outline-gray-2 p-2 rounded-md"
|
||||
v-if="isMention(log)"
|
||||
v-html="log.email_content"
|
||||
class="bg-surface-gray-2 rounded-md px-3 py-2"
|
||||
></div>
|
||||
<div
|
||||
v-else-if="showDetails(log)"
|
||||
class="flex items-stretch border border-outline-gray-2 space-x-2 rounded-md"
|
||||
>
|
||||
<iframe
|
||||
v-if="log.document_details.video_link"
|
||||
v-if="
|
||||
log.document_type == 'LMS Course' &&
|
||||
log.document_details.video_link
|
||||
"
|
||||
:src="`https://www.youtube.com/embed/${log.document_details.video_link}`"
|
||||
class="rounded-md w-64"
|
||||
class="rounded-l-md w-72"
|
||||
/>
|
||||
<div class="">
|
||||
<video
|
||||
v-else-if="
|
||||
log.document_type == 'LMS Batch' &&
|
||||
log.document_details.video_link
|
||||
"
|
||||
:src="log.document_details.video_link"
|
||||
class="rounded-l-md w-72"
|
||||
/>
|
||||
<div class="p-3">
|
||||
<div
|
||||
class="bg-surface-violet-1 w-fit py-1 px-1.5 rounded-full text-ink-violet-1 text-sm mb-2"
|
||||
>
|
||||
{{ __('New Course') }}
|
||||
{{
|
||||
log.document_type === 'LMS Course'
|
||||
? __('New Course')
|
||||
: __('New Batch')
|
||||
}}
|
||||
</div>
|
||||
<div class="font-semibold mb-1">
|
||||
{{ __(log.document_details.title) }}
|
||||
@@ -71,7 +96,31 @@
|
||||
<div class="leading-5">
|
||||
{{ __(log.document_details.short_introduction) }}
|
||||
</div>
|
||||
<div class="mt-5 space-y-2">
|
||||
<div
|
||||
v-if="log.document_details.start_date"
|
||||
class="flex items-center space-x-2 text-sm mt-5"
|
||||
>
|
||||
<Calendar class="size-3 stroke-1.5" />
|
||||
<span>
|
||||
{{
|
||||
dayjs(log.document_details.start_date).format('DD MMM YYYY')
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="log.document_details.start_time"
|
||||
class="flex items-center space-x-2 text-sm mt-2"
|
||||
>
|
||||
<Clock class="size-3 stroke-1.5" />
|
||||
<span>
|
||||
{{ formatTime(log.document_details.start_time) }}
|
||||
{{ log.document_details.timezone }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="log.document_details.instructors.length > 1"
|
||||
class="space-y-2 mt-5"
|
||||
>
|
||||
<div
|
||||
v-for="instructor in log.document_details.instructors"
|
||||
class="flex items-center space-x-2"
|
||||
@@ -81,7 +130,7 @@
|
||||
:image="instructor.user_image"
|
||||
:label="instructor.full_name"
|
||||
/>
|
||||
<span class="text-ink-gray-7 text-sm">
|
||||
<span class="font-medium text-sm">
|
||||
{{ instructor.full_name }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -109,7 +158,8 @@ import {
|
||||
import { sessionStore } from '../stores/session'
|
||||
import { computed, inject, ref, onMounted, onUnmounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { X } from 'lucide-vue-next'
|
||||
import { Calendar, Clock, X } from 'lucide-vue-next'
|
||||
import { formatTime } from '@/utils/'
|
||||
|
||||
const { brand } = sessionStore()
|
||||
const user = inject('$user')
|
||||
@@ -189,13 +239,37 @@ const navigateToPage = (log) => {
|
||||
params: { courseName: link[3] },
|
||||
})
|
||||
} else if (link[2] == 'batches') {
|
||||
router.push({
|
||||
name: 'Batch',
|
||||
params: { batchName: link[3] },
|
||||
})
|
||||
if (link[3] == 'details') {
|
||||
router.push({
|
||||
name: 'BatchDetail',
|
||||
params: { batchName: link[4] },
|
||||
})
|
||||
} else {
|
||||
router.push({
|
||||
name: 'Batch',
|
||||
params: { batchName: link[3] },
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const isMention = (log) => {
|
||||
if (log.type == 'Mention') {
|
||||
return true
|
||||
}
|
||||
if (log.subject.includes('mentioned you')) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const showDetails = (log) => {
|
||||
return (
|
||||
['LMS Course', 'LMS Batch'].includes(log.document_type) &&
|
||||
log.document_details
|
||||
)
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
socket.off('publish_lms_notifications')
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user