From c36977b84a9ce1efab70b786372fa93480079567 Mon Sep 17 00:00:00 2001 From: "Calum H. (IMB11)" Date: Mon, 12 Jan 2026 11:36:47 +0000 Subject: [PATCH 01/24] feat: filtering + sorting alignment --- .../src/pages/moderation/technical-review.vue | 117 +++++++++++------- .../api-client/src/modules/labrinth/types.ts | 3 + 2 files changed, 77 insertions(+), 43 deletions(-) diff --git a/apps/frontend/src/pages/moderation/technical-review.vue b/apps/frontend/src/pages/moderation/technical-review.vue index 8805653b9f..1f564faf74 100644 --- a/apps/frontend/src/pages/moderation/technical-review.vue +++ b/apps/frontend/src/pages/moderation/technical-review.vue @@ -213,12 +213,25 @@ const filterTypes = computed[]>(() => { return [...base, ...sortedTypes.map((type) => ({ value: type, label: type }))] }) -const currentSortType = ref('Severe first') +const currentSortType = ref('Severity highest') const sortTypes: ComboboxOption[] = [ + { value: 'Severity highest', label: 'Severity highest' }, + { value: 'Severity lowest', label: 'Severity lowest' }, { value: 'Oldest', label: 'Oldest' }, { value: 'Newest', label: 'Newest' }, - { value: 'Severe first', label: 'Severe first' }, - { value: 'Severe last', label: 'Severe last' }, +] + +const currentResponseFilter = ref('All') +const responseFilterTypes: ComboboxOption[] = [ + { value: 'All', label: 'All' }, + { value: 'Unread', label: 'Unread' }, + { value: 'Read', label: 'Read' }, +] + +const currentQueueFilter = ref('All') +const queueFilterTypes: ComboboxOption[] = [ + { value: 'All', label: 'All' }, + { value: 'In other queue', label: 'In other queue' }, ] const fuse = computed(() => { @@ -246,36 +259,11 @@ const baseFiltered = computed(() => { return query.value && searchResults.value ? searchResults.value : [...reviewItems.value] }) -const typeFiltered = computed(() => { - if (currentFilterType.value === 'All issues') return baseFiltered.value - const type = currentFilterType.value - - return baseFiltered.value.filter((review) => { - return review.reports.some((report: Labrinth.TechReview.Internal.FileReport) => - report.issues.some( - (issue: Labrinth.TechReview.Internal.FileIssue) => issue.issue_type === type, - ), - ) - }) -}) - -const filteredItems = computed(() => typeFiltered.value) +const filteredItems = computed(() => baseFiltered.value) const filteredIssuesCount = computed(() => { return filteredItems.value.reduce((total, review) => { - if (currentFilterType.value === 'All issues') { - return total + review.reports.reduce((sum, report) => sum + report.issues.length, 0) - } else { - return ( - total + - review.reports.reduce((sum, report) => { - return ( - sum + - report.issues.filter((issue) => issue.issue_type === currentFilterType.value).length - ) - }, 0) - ) - } + return total + review.reports.reduce((sum, report) => sum + report.issues.length, 0) }, 0) }) @@ -304,9 +292,9 @@ function toApiSort(label: string): Labrinth.TechReview.Internal.SearchProjectsSo return 'created_asc' case 'Newest': return 'created_desc' - case 'Severe first': + case 'Severity highest': return 'severity_desc' - case 'Severe last': + case 'Severity lowest': return 'severity_asc' default: return 'severity_desc' @@ -321,12 +309,35 @@ const { hasNextPage, refetch, } = useInfiniteQuery({ - queryKey: ['tech-reviews', currentSortType], + queryKey: [ + 'tech-reviews', + currentSortType, + currentResponseFilter, + currentQueueFilter, + currentFilterType, + ], queryFn: async ({ pageParam = 0 }) => { + const filter: Labrinth.TechReview.Internal.SearchProjectsFilter = {} + + if (currentResponseFilter.value === 'Unread') { + filter.replied_to = 'unreplied' + } else if (currentResponseFilter.value === 'Read') { + filter.replied_to = 'replied' + } + + if (currentQueueFilter.value === 'In other queue') { + filter.project_status = ['pending'] + } + + if (currentFilterType.value !== 'All issues') { + filter.issue_types = [currentFilterType.value] + } + return await client.labrinth.tech_review_internal.searchProjects({ limit: API_PAGE_SIZE, page: pageParam, sort_by: toApiSort(currentSortType.value), + filter, }) }, getNextPageParam: (lastPage, allPages) => { @@ -413,7 +424,7 @@ const reviewItems = computed(() => { function handleMarkComplete(projectId: string) { queryClient.setQueryData( - ['tech-reviews', currentSortType], + ['tech-reviews', currentSortType, currentResponseFilter, currentQueueFilter, currentFilterType], ( oldData: | { @@ -449,7 +460,7 @@ function handleShowMaliciousSummary(unsafeFiles: UnsafeFile[]) { maliciousSummaryModalRef.value?.show() } -watch(currentSortType, () => { +watch([currentSortType, currentResponseFilter, currentQueueFilter, currentFilterType], () => { goToPage(1) }) @@ -492,13 +503,38 @@ watch(currentSortType, () => {
+ + + + + + + +