From af08e6842ad5ee1a568b3747d68346692ede09b0 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Fri, 10 Apr 2026 19:54:59 +0530 Subject: [PATCH] fix: list pagination --- frontend/src/pages/Assignments.vue | 12 +- frontend/src/pages/CertifiedParticipants.vue | 4 +- frontend/src/pages/Jobs.vue | 105 ++++++++++++------ .../ProgrammingExercises.vue | 12 +- frontend/src/pages/Quizzes.vue | 14 ++- lms/lms/api.py | 9 +- 6 files changed, 102 insertions(+), 54 deletions(-) diff --git a/frontend/src/pages/Assignments.vue b/frontend/src/pages/Assignments.vue index f2e6f6be..31f21c67 100644 --- a/frontend/src/pages/Assignments.vue +++ b/frontend/src/pages/Assignments.vue @@ -20,8 +20,8 @@ -
-
+
+
{{ __('{0} Assignments').format(assignments.data?.length) }}
@@ -52,7 +52,7 @@ showAssignmentForm = true }, }" - class="h-[79vh] border-b" + class="h-[79vh] px-5" > - -
+
+ +
+
diff --git a/frontend/src/pages/CertifiedParticipants.vue b/frontend/src/pages/CertifiedParticipants.vue index f82f94d8..56b899cb 100644 --- a/frontend/src/pages/CertifiedParticipants.vue +++ b/frontend/src/pages/CertifiedParticipants.vue @@ -107,7 +107,9 @@
- +
+ +
+
+
+ {{ jobs.data?.length }} {{ __('of') }} + {{ jobCount.data }} +
+
@@ -119,6 +134,7 @@ import { Button, Breadcrumbs, call, + createListResource, createResource, FormControl, TabButtons, @@ -141,7 +157,6 @@ const searchQuery = ref('') const country = ref(null) const filters = ref({}) const orFilters = ref({}) -const jobCount = ref(0) const closedJobs = ref(0) const activeTab = ref('Open') const readOnlyMode = window.read_only_mode @@ -157,9 +172,7 @@ const isModerator = computed(() => { }) const getClosedJobCount = () => { - if (!user.data?.name) { - return - } + if (!user.data?.name) return const filters = { status: 'Closed', @@ -177,6 +190,14 @@ const getClosedJobCount = () => { }) } +const jobCount = createResource({ + url: 'frappe.client.get_count', + params: { + doctype: 'Job Opportunity', + filters: filters.value, + }, +}) + const setFiltersFromURL = () => { let queries = new URLSearchParams(location.search) if (queries.has('type')) { @@ -187,53 +208,53 @@ const setFiltersFromURL = () => { } } -const tabs = computed(() => { - const tabsArray = [ - { - label: __('Open'), - }, - ] - - if (closedJobs.value) { - tabsArray.push({ - label: __('Closed'), - }) - } - - return tabsArray -}) - -const jobs = createResource({ +const jobs = createListResource({ url: 'lms.lms.api.get_job_opportunities', + doctype: 'Job Opportunity', + start: 0, cache: ['jobs'], }) const updateJobs = () => { updateFilters() jobs.update({ - params: { - filters: filters.value, - orFilters: orFilters.value, - }, + filters: filters.value, + orFilters: orFilters.value, }) jobs.reload() + jobCount.update({ + filters: filters.value, + orFilters: orFilters.value, + }) + jobCount.reload() } const updateFilters = () => { filters.value.status = 'Open' + updateJobTypeFilter() + updateWorkModeFilter() + updateSearchQueryFilter() + updateCountryFilter() + updateTabFilter() +} +const updateJobTypeFilter = () => { if (jobType.value && jobType.value !== ' ') { filters.value.type = jobType.value } else { delete filters.value.type } +} +const updateWorkModeFilter = () => { if (workMode.value && workMode.value !== ' ') { filters.value.work_mode = workMode.value } else { delete filters.value.work_mode } +} +const updateSearchQueryFilter = () => { if (searchQuery.value) { orFilters.value = { job_title: ['like', `%${searchQuery.value}%`], @@ -243,13 +264,17 @@ const updateFilters = () => { } else { orFilters.value = {} } +} +const updateCountryFilter = () => { if (country.value) { filters.value.country = country.value } else { delete filters.value.country } +} +const updateTabFilter = () => { if (activeTab.value === 'Closed') { filters.value.status = 'Closed' if (!isModerator.value) { @@ -269,8 +294,20 @@ watch(country, (val) => { updateJobs() }) -watch(jobs, () => { - jobCount.value = jobs.data?.length || 0 +const tabs = computed(() => { + const tabsArray = [ + { + label: __('Open'), + }, + ] + + if (closedJobs.value) { + tabsArray.push({ + label: __('Closed'), + }) + } + + return tabsArray }) const jobTypes = computed(() => { @@ -286,9 +323,9 @@ const jobTypes = computed(() => { const workModes = computed(() => { return [ { label: ' ', value: ' ' }, - { label: 'On site', value: 'On-site' }, - { label: 'Hybrid', value: 'Hybrid' }, - { label: 'Remote', value: 'Remote' }, + { label: __('On-site'), value: 'On-site' }, + { label: __('Hybrid'), value: 'Hybrid' }, + { label: __('Remote'), value: 'Remote' }, ] }) diff --git a/frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue b/frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue index f9c43bf6..ecde7da9 100644 --- a/frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue +++ b/frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue @@ -34,8 +34,8 @@
-
-
+
+
{{ __('{0} Exercises').format(exercises.data?.length) }}
@@ -69,7 +69,7 @@ showForm = true }, }" - class="h-[79vh] border-b" + class="h-[79vh] px-5" >
- -
+
+ +
+
diff --git a/frontend/src/pages/Quizzes.vue b/frontend/src/pages/Quizzes.vue index 2935120b..8df31dd7 100644 --- a/frontend/src/pages/Quizzes.vue +++ b/frontend/src/pages/Quizzes.vue @@ -10,8 +10,8 @@ {{ __('Create') }} -
-
+
+
{{ __('{0} Quizzes').format(quizzes.data?.length) }}
@@ -27,7 +27,7 @@ :rows="quizzes.data" row-key="name" :options="{ showTooltip: false, selectable: true }" - class="h-[79vh] border-b" + class="h-[79vh] px-5" > - -
+
+ +
+
@@ -296,7 +298,7 @@ const quizColumns = computed(() => { { label: __('Show Answers'), key: 'show_answers', - width: 1, + width: 0.5, align: 'center', icon: 'eye', }, diff --git a/lms/lms/api.py b/lms/lms/api.py index bfbde0cf..c91ff9ad 100644 --- a/lms/lms/api.py +++ b/lms/lms/api.py @@ -232,14 +232,16 @@ def get_job_details(job: str): @frappe.whitelist(allow_guest=True) -def get_job_opportunities(filters: dict = None, orFilters: dict = None): +def get_job_opportunities( + filters: dict = None, or_filters: dict = None, start: int = 0, page_length: int = 40 +): if not filters: filters = {} jobs = frappe.get_all( "Job Opportunity", filters=filters, - or_filters=orFilters, + or_filters=or_filters, fields=[ "job_title", "location", @@ -252,6 +254,8 @@ def get_job_opportunities(filters: dict = None, orFilters: dict = None): "creation", "description", ], + start=start, + page_length=page_length, order_by="creation desc", ) @@ -348,7 +352,6 @@ def get_certified_participants(filters: dict = None, start: int = 0, page_length query = get_certification_query(filters) query = query.orderby("issue_date", order=frappe.qb.desc).offset(start).limit(page_length) participants = query.run(as_dict=True) - print(participants) for participant in participants: details = get_certified_participant_details(participant.member) participant.update(details)