@@ -293,8 +293,8 @@ const tabsStructure = computed(() => {
|
||||
type: 'checkbox',
|
||||
},
|
||||
{
|
||||
label: 'Certified Participants',
|
||||
name: 'certified_participants',
|
||||
label: 'Certified Members',
|
||||
name: 'certified_members',
|
||||
type: 'checkbox',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</button>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Tooltip, Button } from 'frappe-ui'
|
||||
import { Tooltip } from 'frappe-ui'
|
||||
import { computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import * as icons from 'lucide-vue-next'
|
||||
|
||||
@@ -12,10 +12,7 @@
|
||||
</Button>
|
||||
</router-link>
|
||||
</header>
|
||||
<div
|
||||
v-if="participants.data?.length"
|
||||
class="mx-auto w-full max-w-4xl pt-6 pb-10"
|
||||
>
|
||||
<div class="mx-auto w-full max-w-4xl pt-6 pb-10">
|
||||
<div class="flex flex-col md:flex-row justify-between mb-4 px-3">
|
||||
<div class="text-xl font-semibold text-ink-gray-7 mb-4 md:mb-0">
|
||||
{{ memberCount }} {{ __('certified members') }}
|
||||
@@ -41,7 +38,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="divide-y">
|
||||
<div v-if="participants.data?.length" class="divide-y">
|
||||
<template v-for="participant in participants.data">
|
||||
<router-link
|
||||
:to="{
|
||||
@@ -92,6 +89,7 @@
|
||||
</router-link>
|
||||
</template>
|
||||
</div>
|
||||
<EmptyState v-else type="Certified Members" />
|
||||
<div
|
||||
v-if="!participants.list.loading && participants.hasNextPage"
|
||||
class="flex justify-center mt-5"
|
||||
@@ -101,7 +99,6 @@
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<EmptyState v-else type="Certified Members" />
|
||||
</template>
|
||||
<script setup>
|
||||
import {
|
||||
@@ -134,9 +131,8 @@ onMounted(() => {
|
||||
const participants = createListResource({
|
||||
doctype: 'LMS Certificate',
|
||||
url: 'lms.lms.api.get_certified_participants',
|
||||
cache: ['certified_participants'],
|
||||
start: 0,
|
||||
pageLength: 30,
|
||||
pageLength: 100,
|
||||
})
|
||||
|
||||
const getMemberCount = () => {
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
</header>
|
||||
<div>
|
||||
<div
|
||||
v-if="jobCount"
|
||||
class="flex flex-col lg:flex-row space-y-4 lg:space-y-0 lg:items-center justify-between w-full md:w-4/5 mx-auto p-5"
|
||||
>
|
||||
<div class="text-xl font-semibold text-ink-gray-7 mb-4 md:mb-0">
|
||||
@@ -34,7 +33,6 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="jobs.data?.length || jobCount > 0"
|
||||
class="grid grid-cols-1 gap-2"
|
||||
:class="user.data ? 'md:grid-cols-3' : 'md:grid-cols-2'"
|
||||
>
|
||||
@@ -119,12 +117,14 @@ onMounted(() => {
|
||||
jobType.value = queries.get('type')
|
||||
}
|
||||
updateJobs()
|
||||
getJobCount()
|
||||
})
|
||||
|
||||
const jobs = createResource({
|
||||
url: 'lms.lms.api.get_job_opportunities',
|
||||
cache: ['jobs'],
|
||||
onSuccess(data) {
|
||||
jobCount.value = data.length
|
||||
},
|
||||
})
|
||||
|
||||
const updateJobs = () => {
|
||||
@@ -165,18 +165,6 @@ const updateFilters = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const getJobCount = () => {
|
||||
call('lms.lms.api.get_count', {
|
||||
doctype: 'Job Opportunity',
|
||||
filters: {
|
||||
status: 'Open',
|
||||
disabled: 0,
|
||||
},
|
||||
}).then((data) => {
|
||||
jobCount.value = data
|
||||
})
|
||||
}
|
||||
|
||||
watch(country, (val) => {
|
||||
updateJobs()
|
||||
})
|
||||
|
||||
@@ -20,7 +20,6 @@ from frappe.utils import (
|
||||
date_diff,
|
||||
)
|
||||
from frappe.query_builder import DocType
|
||||
from pypika.functions import DistinctOptionFunction
|
||||
from lms.lms.utils import get_average_rating, get_lesson_count
|
||||
from xml.dom.minidom import parseString
|
||||
from lms.lms.doctype.course_lesson.course_lesson import save_progress
|
||||
@@ -413,7 +412,7 @@ def get_evaluator_details(evaluator):
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_certified_participants(filters=None, start=0, page_length=30):
|
||||
def get_certified_participants(filters=None, start=0, page_length=100):
|
||||
or_filters = {}
|
||||
if not filters:
|
||||
filters = {}
|
||||
@@ -451,18 +450,14 @@ def get_certified_participants(filters=None, start=0, page_length=30):
|
||||
return participants
|
||||
|
||||
|
||||
class CountDistinct(DistinctOptionFunction):
|
||||
def __init__(self, field):
|
||||
super().__init__("COUNT", field, distinct=True)
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_count_of_certified_members(filters=None):
|
||||
Certificate = DocType("LMS Certificate")
|
||||
|
||||
query = (
|
||||
frappe.qb.from_(Certificate)
|
||||
.select(CountDistinct(Certificate.member).as_("total"))
|
||||
.select(Certificate.member)
|
||||
.distinct()
|
||||
.where(Certificate.published == 1)
|
||||
)
|
||||
|
||||
@@ -473,9 +468,11 @@ def get_count_of_certified_members(filters=None):
|
||||
Certificate.course_title.like(f"%{value}%")
|
||||
| Certificate.batch_title.like(f"%{value}%")
|
||||
)
|
||||
elif field == "member_name":
|
||||
query = query.where(Certificate.member_name.like(value[1]))
|
||||
|
||||
result = query.run(as_dict=True)
|
||||
return result[0]["total"] if result else 0
|
||||
return len(result) or 0
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@@ -552,7 +549,7 @@ def get_sidebar_settings():
|
||||
items = [
|
||||
"courses",
|
||||
"batches",
|
||||
"certified_participants",
|
||||
"certified_members",
|
||||
"jobs",
|
||||
"statistics",
|
||||
"notifications",
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
"courses",
|
||||
"batches",
|
||||
"certified_participants",
|
||||
"certified_members",
|
||||
"column_break_exdz",
|
||||
"jobs",
|
||||
"statistics",
|
||||
@@ -277,6 +278,7 @@
|
||||
"default": "1",
|
||||
"fieldname": "certified_participants",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Certified Participants"
|
||||
},
|
||||
{
|
||||
@@ -397,13 +399,19 @@
|
||||
"fieldtype": "Check",
|
||||
"label": "Persona Captured",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "certified_members",
|
||||
"fieldtype": "Check",
|
||||
"label": "Certified Members"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2025-05-14 12:43:22.749850",
|
||||
"modified": "2025-05-30 19:02:51.381668",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Settings",
|
||||
|
||||
@@ -106,4 +106,5 @@ lms.patches.v2_0.update_job_city_and_country
|
||||
lms.patches.v2_0.update_course_evaluator_data
|
||||
lms.patches.v2_0.move_zoom_settings #20-05-2025
|
||||
lms.patches.v2_0.link_zoom_account_to_live_class
|
||||
lms.patches.v2_0.link_zoom_account_to_batch
|
||||
lms.patches.v2_0.link_zoom_account_to_batch
|
||||
lms.patches.v2_0.sidebar_for_certified_members
|
||||
@@ -7,6 +7,10 @@ def execute():
|
||||
|
||||
def create_settings():
|
||||
current_settings = frappe.get_single("Zoom Settings")
|
||||
|
||||
if not current_settings.enable:
|
||||
return
|
||||
|
||||
member = current_settings.owner
|
||||
member_name = frappe.get_value("User", member, "full_name")
|
||||
|
||||
|
||||
10
lms/patches/v2_0/sidebar_for_certified_members.py
Normal file
10
lms/patches/v2_0/sidebar_for_certified_members.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
show_certified_members = frappe.db.get_single_value(
|
||||
"LMS Settings", "certified_participants"
|
||||
)
|
||||
|
||||
if show_certified_members:
|
||||
frappe.db.set_single_value("LMS Settings", "certified_members", 1)
|
||||
Reference in New Issue
Block a user