perf: misc performance improvements
This commit is contained in:
@@ -71,6 +71,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TextEditor
|
<TextEditor
|
||||||
|
v-if="renderEditor"
|
||||||
class="mt-5"
|
class="mt-5"
|
||||||
:content="newReply"
|
:content="newReply"
|
||||||
:mentions="mentionUsers"
|
:mentions="mentionUsers"
|
||||||
@@ -94,7 +95,7 @@ import { createResource, TextEditor, Button, Dropdown } from 'frappe-ui'
|
|||||||
import { timeAgo } from '../utils'
|
import { timeAgo } from '../utils'
|
||||||
import UserAvatar from '@/components/UserAvatar.vue'
|
import UserAvatar from '@/components/UserAvatar.vue'
|
||||||
import { ChevronLeft, MoreHorizontal } from 'lucide-vue-next'
|
import { ChevronLeft, MoreHorizontal } from 'lucide-vue-next'
|
||||||
import { ref, inject, onMounted, computed } from 'vue'
|
import { ref, inject, onMounted } from 'vue'
|
||||||
import { createToast } from '../utils'
|
import { createToast } from '../utils'
|
||||||
|
|
||||||
const showTopics = defineModel('showTopics')
|
const showTopics = defineModel('showTopics')
|
||||||
@@ -102,6 +103,8 @@ const newReply = ref('')
|
|||||||
const socket = inject('$socket')
|
const socket = inject('$socket')
|
||||||
const user = inject('$user')
|
const user = inject('$user')
|
||||||
const allUsers = inject('$allUsers')
|
const allUsers = inject('$allUsers')
|
||||||
|
const mentionUsers = ref([])
|
||||||
|
const renderEditor = ref(false)
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
topic: {
|
topic: {
|
||||||
@@ -124,6 +127,7 @@ onMounted(() => {
|
|||||||
socket.on('delete_message', (data) => {
|
socket.on('delete_message', (data) => {
|
||||||
replies.reload()
|
replies.reload()
|
||||||
})
|
})
|
||||||
|
fetchMentionUsers()
|
||||||
})
|
})
|
||||||
|
|
||||||
const replies = createResource({
|
const replies = createResource({
|
||||||
@@ -150,15 +154,26 @@ const newReplyResource = createResource({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const mentionUsers = computed(() => {
|
const fetchMentionUsers = () => {
|
||||||
let users = Object.values(allUsers.data).map((user) => {
|
if (user.data?.is_student) {
|
||||||
return {
|
renderEditor.value = true
|
||||||
value: user.name,
|
} else {
|
||||||
label: user.full_name,
|
allUsers.reload(
|
||||||
}
|
{},
|
||||||
})
|
{
|
||||||
return users
|
onSuccess(data) {
|
||||||
})
|
mentionUsers.value = Object.values(data).map((user) => {
|
||||||
|
return {
|
||||||
|
value: user.name,
|
||||||
|
label: user.full_name,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
renderEditor.value = true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const postReply = () => {
|
const postReply = () => {
|
||||||
newReplyResource.submit(
|
newReplyResource.submit(
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import './index.css'
|
import './index.css'
|
||||||
|
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
@@ -8,15 +7,8 @@ import dayjs from '@/utils/dayjs'
|
|||||||
import { createDialog } from '@/utils/dialogs'
|
import { createDialog } from '@/utils/dialogs'
|
||||||
import translationPlugin from './translation'
|
import translationPlugin from './translation'
|
||||||
import { usersStore } from './stores/user'
|
import { usersStore } from './stores/user'
|
||||||
import { sessionStore } from './stores/session'
|
|
||||||
import { initSocket } from './socket'
|
import { initSocket } from './socket'
|
||||||
import {
|
import { FrappeUI, setConfig, frappeRequest, pageMetaPlugin } from 'frappe-ui'
|
||||||
FrappeUI,
|
|
||||||
setConfig,
|
|
||||||
frappeRequest,
|
|
||||||
resourcesPlugin,
|
|
||||||
pageMetaPlugin,
|
|
||||||
} from 'frappe-ui'
|
|
||||||
|
|
||||||
let pinia = createPinia()
|
let pinia = createPinia()
|
||||||
let app = createApp(App)
|
let app = createApp(App)
|
||||||
@@ -32,8 +24,6 @@ app.provide('$socket', initSocket())
|
|||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
||||||
const { userResource, allUsers } = usersStore()
|
const { userResource, allUsers } = usersStore()
|
||||||
let { isLoggedIn } = sessionStore()
|
|
||||||
|
|
||||||
app.provide('$user', userResource)
|
app.provide('$user', userResource)
|
||||||
app.provide('$allUsers', allUsers)
|
app.provide('$allUsers', allUsers)
|
||||||
app.config.globalProperties.$user = userResource
|
app.config.globalProperties.$user = userResource
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
class="flex items-center py-2 justify-between"
|
class="flex items-center py-2 justify-between"
|
||||||
>
|
>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<UserAvatar :user="allUsers.data[log.from_user]" class="mr-2" />
|
<Avatar :image="log.user_image" :label="log.full_name" class="mr-2" />
|
||||||
<div class="notification" v-html="log.subject"></div>
|
<div class="notification" v-html="log.subject"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
@@ -57,6 +57,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
|
Avatar,
|
||||||
createListResource,
|
createListResource,
|
||||||
createResource,
|
createResource,
|
||||||
Breadcrumbs,
|
Breadcrumbs,
|
||||||
@@ -66,14 +67,12 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { computed, inject, ref, onMounted } from 'vue'
|
import { computed, inject, ref, onMounted } from 'vue'
|
||||||
import UserAvatar from '@/components/UserAvatar.vue'
|
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { X } from 'lucide-vue-next'
|
import { X } from 'lucide-vue-next'
|
||||||
import { updateDocumentTitle } from '@/utils'
|
import { updateDocumentTitle } from '@/utils'
|
||||||
|
|
||||||
const user = inject('$user')
|
const user = inject('$user')
|
||||||
const socket = inject('$socket')
|
const socket = inject('$socket')
|
||||||
const allUsers = inject('$allUsers')
|
|
||||||
const activeTab = ref('Unread')
|
const activeTab = ref('Unread')
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@@ -93,24 +92,22 @@ const notifications = computed(() => {
|
|||||||
|
|
||||||
const unReadNotifications = createListResource({
|
const unReadNotifications = createListResource({
|
||||||
doctype: 'Notification Log',
|
doctype: 'Notification Log',
|
||||||
fields: ['subject', 'from_user', 'link', 'read', 'name'],
|
url: 'lms.lms.api.get_notifications',
|
||||||
filters: {
|
filters: {
|
||||||
for_user: user.data?.name,
|
for_user: user.data?.name,
|
||||||
read: 0,
|
read: 0,
|
||||||
},
|
},
|
||||||
orderBy: 'creation desc',
|
|
||||||
auto: true,
|
auto: true,
|
||||||
cache: 'Unread Notifications',
|
cache: 'Unread Notifications',
|
||||||
})
|
})
|
||||||
|
|
||||||
const readNotifications = createListResource({
|
const readNotifications = createListResource({
|
||||||
doctype: 'Notification Log',
|
doctype: 'Notification Log',
|
||||||
fields: ['subject', 'from_user', 'link', 'read', 'name'],
|
url: 'lms.lms.api.get_notifications',
|
||||||
filters: {
|
filters: {
|
||||||
for_user: user.data?.name,
|
for_user: user.data?.name,
|
||||||
read: 1,
|
read: 1,
|
||||||
},
|
},
|
||||||
orderBy: 'creation desc',
|
|
||||||
auto: true,
|
auto: true,
|
||||||
cache: 'Read Notifications',
|
cache: 'Read Notifications',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -217,21 +217,13 @@ let router = createRouter({
|
|||||||
})
|
})
|
||||||
|
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
const { userResource, allUsers } = usersStore()
|
const { userResource } = usersStore()
|
||||||
let { isLoggedIn } = sessionStore()
|
let { isLoggedIn } = sessionStore()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
await userResource.promise
|
await userResource.promise
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
isLoggedIn &&
|
|
||||||
(to.name == 'Lesson' ||
|
|
||||||
to.name == 'Batch' ||
|
|
||||||
to.name == 'Notifications')
|
|
||||||
) {
|
|
||||||
await allUsers.promise
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
isLoggedIn = false
|
isLoggedIn = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import router from '@/router'
|
|||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
|
|
||||||
export const sessionStore = defineStore('lms-session', () => {
|
export const sessionStore = defineStore('lms-session', () => {
|
||||||
let { userResource, allUsers } = usersStore()
|
let { userResource } = usersStore()
|
||||||
|
|
||||||
function sessionUser() {
|
function sessionUser() {
|
||||||
let cookies = new URLSearchParams(document.cookie.split('; ').join('&'))
|
let cookies = new URLSearchParams(document.cookie.split('; ').join('&'))
|
||||||
@@ -17,9 +17,6 @@ export const sessionStore = defineStore('lms-session', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let user = ref(sessionUser())
|
let user = ref(sessionUser())
|
||||||
if (user.value) {
|
|
||||||
allUsers.reload()
|
|
||||||
}
|
|
||||||
const isLoggedIn = computed(() => !!user.value)
|
const isLoggedIn = computed(() => !!user.value)
|
||||||
|
|
||||||
const login = createResource({
|
const login = createResource({
|
||||||
|
|||||||
@@ -434,6 +434,7 @@ def get_assigned_badges(member):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_all_users():
|
def get_all_users():
|
||||||
|
frappe.only_for(["Moderator", "Course Creator", "Batch Evaluator"])
|
||||||
users = frappe.get_all(
|
users = frappe.get_all(
|
||||||
"User",
|
"User",
|
||||||
{
|
{
|
||||||
@@ -1189,3 +1190,21 @@ def prepare_heatmap_data(start_date, number_of_days, date_count):
|
|||||||
def get_week_difference(start_date, current_date):
|
def get_week_difference(start_date, current_date):
|
||||||
diff_in_days = date_diff(current_date, start_date)
|
diff_in_days = date_diff(current_date, start_date)
|
||||||
return diff_in_days // 7
|
return diff_in_days // 7
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_notifications(filters):
|
||||||
|
notifications = frappe.get_all(
|
||||||
|
"Notification Log",
|
||||||
|
filters,
|
||||||
|
["subject", "from_user", "link", "read", "name"],
|
||||||
|
order_by="creation desc",
|
||||||
|
)
|
||||||
|
|
||||||
|
for notification in notifications:
|
||||||
|
from_user_details = frappe.db.get_value(
|
||||||
|
"User", notification.from_user, ["full_name", "user_image"], as_dict=1
|
||||||
|
)
|
||||||
|
notification.update(from_user_details)
|
||||||
|
|
||||||
|
return notifications
|
||||||
|
|||||||
@@ -72,16 +72,6 @@ class CourseLesson(Document):
|
|||||||
exercises = [value for name, value in macros if name == "Exercise"]
|
exercises = [value for name, value in macros if name == "Exercise"]
|
||||||
return [frappe.get_doc("LMS Exercise", name) for name in exercises]
|
return [frappe.get_doc("LMS Exercise", name) for name in exercises]
|
||||||
|
|
||||||
def get_progress(self):
|
|
||||||
return frappe.db.get_value(
|
|
||||||
"LMS Course Progress", {"lesson": self.name, "owner": frappe.session.user}, "status"
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_slugified_class(self):
|
|
||||||
if self.get_progress():
|
|
||||||
return ("").join([s for s in self.get_progress().lower().split()])
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def save_progress(lesson, course):
|
def save_progress(lesson, course):
|
||||||
|
|||||||
@@ -22,7 +22,8 @@
|
|||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Course",
|
"label": "Course",
|
||||||
"options": "LMS Course",
|
"options": "LMS Course",
|
||||||
"read_only": 1
|
"read_only": 1,
|
||||||
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fetch_from": "lesson.chapter",
|
"fetch_from": "lesson.chapter",
|
||||||
@@ -30,14 +31,16 @@
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Chapter",
|
"label": "Chapter",
|
||||||
"options": "Course Chapter",
|
"options": "Course Chapter",
|
||||||
"read_only": 1
|
"read_only": 1,
|
||||||
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "lesson",
|
"fieldname": "lesson",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Lesson",
|
"label": "Lesson",
|
||||||
"options": "Course Lesson"
|
"options": "Course Lesson",
|
||||||
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "status",
|
"fieldname": "status",
|
||||||
@@ -45,7 +48,8 @@
|
|||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Status",
|
"label": "Status",
|
||||||
"options": "Complete\nPartially Complete\nIncomplete"
|
"options": "Complete\nPartially Complete\nIncomplete",
|
||||||
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
@@ -55,7 +59,8 @@
|
|||||||
"fieldname": "member",
|
"fieldname": "member",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Member",
|
"label": "Member",
|
||||||
"options": "User"
|
"options": "User",
|
||||||
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fetch_from": "member.full_name",
|
"fetch_from": "member.full_name",
|
||||||
@@ -67,7 +72,7 @@
|
|||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-02-27 11:43:08.326886",
|
"modified": "2025-01-17 15:54:34.040621",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Course Progress",
|
"name": "LMS Course Progress",
|
||||||
|
|||||||
@@ -450,24 +450,6 @@ def get_signup_optin_checks():
|
|||||||
return (", ").join(links)
|
return (", ").join(links)
|
||||||
|
|
||||||
|
|
||||||
def get_popular_courses():
|
|
||||||
courses = frappe.get_all("LMS Course", {"published": 1, "upcoming": 0})
|
|
||||||
course_membership = []
|
|
||||||
|
|
||||||
for course in courses:
|
|
||||||
course_membership.append(
|
|
||||||
{
|
|
||||||
"course": course.name,
|
|
||||||
"members": cint(frappe.db.count("LMS Enrollment", {"course": course.name})),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
course_membership = sorted(
|
|
||||||
course_membership, key=lambda x: x.get("members"), reverse=True
|
|
||||||
)
|
|
||||||
return course_membership[:3]
|
|
||||||
|
|
||||||
|
|
||||||
def format_amount(amount, currency):
|
def format_amount(amount, currency):
|
||||||
amount_reduced = amount / 1000
|
amount_reduced = amount / 1000
|
||||||
if amount_reduced < 1:
|
if amount_reduced < 1:
|
||||||
|
|||||||
@@ -1,31 +1,9 @@
|
|||||||
{% set enrolled = get_enrolled_courses().in_progress + get_enrolled_courses().completed %}
|
{% set enrolled = get_enrolled_courses().in_progress + get_enrolled_courses().completed %}
|
||||||
|
|
||||||
|
|
||||||
{% if enrolled | length %}
|
{% if enrolled | length %}
|
||||||
<div class="cards-parent">
|
<div class="cards-parent">
|
||||||
{% for course in enrolled %}
|
{% for course in enrolled %}
|
||||||
{{ widgets.CourseCard(course=course) }}
|
{{ widgets.CourseCard(course=course) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
{% set site_name = frappe.db.get_single_value("System Settings", "app_name") %}
|
|
||||||
<div class="empty-state p-5">
|
|
||||||
<div style="text-align: left; flex: 1;">
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="empty-state-heading">{{ _("You haven't enrolled for any courses") }}</div>
|
|
||||||
<div class="course-meta mb-6">{{ _("Here are a few courses we recommend for you to get started with {0}").format(site_name) }}</div>
|
|
||||||
</div>
|
|
||||||
{% set recommended_courses = get_popular_courses() %}
|
|
||||||
<div class="cards-parent">
|
|
||||||
{% for course in recommended_courses %}
|
|
||||||
{% if course %}
|
|
||||||
{% set course_details = frappe.get_doc("LMS Course", course.course) %}
|
|
||||||
{{ widgets.CourseCard(course=course_details) }}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
Reference in New Issue
Block a user