fix: fix inconsistencies on the torrent search

This commit is contained in:
FrenchGithubUser
2025-11-06 19:57:47 +01:00
parent b823370883
commit cb9cf4e657
4 changed files with 59 additions and 14 deletions

View File

@@ -909,6 +909,11 @@ SELECT
t.video_resolution,
t.video_resolution_other_x,
t.video_resolution_other_y,
(EXISTS (
SELECT 1
FROM torrent_reports tr
WHERE tr.reported_torrent_id = t.id
)) AS reported,
CASE
WHEN EXISTS (SELECT 1 FROM torrent_reports WHERE reported_torrent_id = t.id) THEN json_agg(row_to_json(tr))
ELSE '[]'::json
@@ -1091,3 +1096,8 @@ create trigger refresh_materialized_view_title_group_hierarchy_lite
after insert or update or delete or truncate
on title_groups for each statement
execute procedure refresh_materialized_view_title_group_hierarchy_lite();
create trigger refresh_materialized_view_title_group_hierarchy_lite
after insert or update or delete or truncate
on torrent_reports for each statement
execute procedure refresh_materialized_view_title_group_hierarchy_lite();

View File

@@ -587,10 +587,24 @@ impl ConnectionPool {
COALESCE(extras, '{}') AS "extras!: _"
FROM torrents_and_reports tar
WHERE edition_group_id = ANY($1)
AND ($2::INT IS NULL OR tar.created_by_id = $2)
AND ($3::BOOLEAN IS NULL OR tar.staff_checked = $3)
AND ($4::BOOLEAN IS NULL OR tar.reported = $4)
AND (
$2::INT IS NULL OR
-- don't return torrents created as anonymous
-- unless the requesting user is the uploader
(tar.created_by_id = $2 AND (
tar.created_by_id = $5 OR
NOT tar.uploaded_as_anonymous)
)
)
"#,
&edition_group_ids,
form.torrent_created_by_id
form.torrent_created_by_id,
form.torrent_staff_checked,
form.torrent_reported,
requesting_user_id,
)
.fetch_all(self.borrow())
.await?;

View File

@@ -87,6 +87,7 @@ import { Dropdown, InputNumber } from 'primevue'
import type { TorrentSearch } from '@/services/api/torrentService'
import { onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { watch } from 'vue'
const { t } = useI18n()
const router = useRouter()
@@ -96,15 +97,11 @@ const props = defineProps<{
initialForm: TorrentSearch
}>()
const emit = defineEmits<{
search: [form: TorrentSearch]
}>()
const sortByOptions = ref([
{ label: t('torrent.created_at'), value: 'torrent_created_at' },
{ label: t('torrent.size'), value: 'torrent_size' },
{ label: t('title_group.original_release_date'), value: 'title_group_original_release_date' },
{ label: t('torrent.snatched_at'), value: 'torrent_snatched_at' },
// { label: t('torrent.snatched_at'), value: 'torrent_snatched_at' },
])
const orderOptions = [
{ label: t('general.ascending'), value: 'asc' },
@@ -134,7 +131,7 @@ const changePage = (page: number) => {
}
const search = () => {
router.push({ query: searchForm.value })
emit('search', searchForm.value)
// a search will be triggered by the query changes through a watcher
}
defineExpose({
searchForm,
@@ -144,6 +141,17 @@ defineExpose({
onMounted(async () => {
searchForm.value = props.initialForm
})
watch(
() => searchForm.value,
(newVal, oldVal) => {
// ignore if only `page` changed
if (newVal.page === oldVal.page) {
searchForm.value.page = 1
}
},
{ deep: true },
)
</script>
<style>

View File

@@ -1,6 +1,6 @@
<template>
<div v-if="search_results">
<TorrentSearchInputs v-if="initialForm" ref="searchInputsRef" class="torrent-search-inputs" @search="search" :loading :initialForm="initialForm" />
<TorrentSearchInputs v-if="initialForm" ref="searchInputsRef" class="torrent-search-inputs" :loading :initialForm="initialForm" />
<PaginatedResults
v-if="initialForm"
:totalPages
@@ -25,6 +25,8 @@ import { useRoute } from 'vue-router'
import type { VNodeRef } from 'vue'
import PaginatedResults from '@/components/PaginatedResults.vue'
import { computed } from 'vue'
import { watch } from 'vue'
import { nextTick } from 'vue'
const route = useRoute()
@@ -33,26 +35,29 @@ const searchInputsRef = ref<VNodeRef | null>(null)
const search_results = ref<TitleGroupHierarchyLite[]>([])
const titleGroupPreview = ref<titleGroupPreviewMode>('table') // TODO: make a select button to switch from cover-only to table
const loading = ref(false)
const initialForm = ref<TorrentSearch>()
const initialForm = ref<TorrentSearch | null>(null)
const totalResults = ref(0)
const pageSize = ref(0)
const totalPages = computed(() => Math.ceil(totalResults.value / pageSize.value))
const search = async (torrentSearch: TorrentSearch) => {
loading.value = true
const results = await searchTorrentsLite(torrentSearch).finally(() => {
loading.value = false
})
// page.value = torrentSearch.page
pageSize.value = torrentSearch.page_size
totalResults.value = results.total_items
search_results.value = results.results
}
const loadInitialForm = async () => {
const loadFormFromUrl = async () => {
loading.value = true
initialForm.value = null
await nextTick()
const form: TorrentSearch = {
title_group_name: route.query.title_group_name?.toString() ?? '',
page: route.query.page ? parseInt(route.query.page as string) : 1,
page_size: route.query.page_size ? parseInt(route.query.page_size as string) : 20,
page_size: route.query.page_size ? parseInt(route.query.page_size as string) : 10,
torrent_created_by_id: route.query.torrent_created_by_id ? parseInt(route.query.torrent_created_by_id as string) : null,
torrent_snatched_by_id: route.query.torrent_snatched_by_id ? parseInt(route.query.torrent_snatched_by_id as string) : null,
torrent_staff_checked: route.query.torrent_staff_checked === 'true' ? true : null,
@@ -69,8 +74,16 @@ const loadInitialForm = async () => {
}
onMounted(async () => {
loadInitialForm()
loadFormFromUrl()
})
watch(
() => route.query,
() => {
loadFormFromUrl()
},
{ deep: true },
)
</script>
<style scoped>