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