diff --git a/components/edit/revisions.vue b/components/edit/revisions.vue index 7b1553e..a2e735d 100644 --- a/components/edit/revisions.vue +++ b/components/edit/revisions.vue @@ -5,8 +5,10 @@ import { computed, inject, ref } from 'vue'; import Avatar from '#/components/edit/avatar.vue'; import Socials from '#/components/edit/revision-socials.vue'; import Checkbox from '#/components/form/checkbox.vue'; +import Pagination from '#/components/pagination/pagination.vue'; import { get, post } from '#/src/api.js'; +import navigate from '#/src/navigate.js'; import { formatDuration } from '#/utils/format.js'; defineProps({ @@ -31,10 +33,14 @@ const moviesById = computed(() => Object.fromEntries(movies.value.map((movie) => const avatarsById = computed(() => Object.fromEntries(avatars.value.map((avatar) => [avatar.id, avatar]))); const feedbacks = ref({}); -const showReviewed = ref(false); +const showReviewed = ref(Object.hasOwn(pageContext.urlParsed.search, 'final')); const reviewedRevisions = ref(new Set()); const expanded = ref(new Set()); +const total = ref(pageContext.pageProps.revisionTotal); +const page = Number(pageContext.routeParams.page) || 1; +const limit = Number(pageContext.urlParsed.search.limit) || 100; + const mappedKeys = { actors: actorsById, // tags: tagsById, @@ -163,7 +169,8 @@ const curatedRevisions = computed(() => revisions.value.map((revision) => { async function reloadRevisions() { const updatedRevisions = await get(`/revisions/${domain}`, { isFinalized: showReviewed.value ? undefined : false, - limit: 50, + page, + limit, }); actors.value = updatedRevisions.actors; @@ -171,6 +178,14 @@ async function reloadRevisions() { movies.value = updatedRevisions.movies; avatars.value = updatedRevisions.avatars; revisions.value = updatedRevisions.revisions; + total.value = updatedRevisions.total; + + navigate(pageContext.urlParsed.pathname, { + ...pageContext.urlParsed.search, + final: showReviewed.value || undefined, + }, { + redirect: false, + }); } async function reviewRevision(revision, isApproved) { @@ -208,10 +223,12 @@ async function banEditor(revision) { @@ -443,13 +466,20 @@ async function banEditor(revision) { .revs-header { display: flex; - margin-bottom: 1rem; + justify-content: space-between; + box-sizing: border-box; + padding: .5rem .5rem .75rem .5rem; + width: 100%; .check-container { display: inline-flex; } } +.revs-total { + color: var(--shadow-strong-10); +} + .revs { width: 100%; flex-grow: 1; diff --git a/components/pagination/pagination.vue b/components/pagination/pagination.vue index 239b5ca..3c44944 100644 --- a/components/pagination/pagination.vue +++ b/components/pagination/pagination.vue @@ -13,6 +13,10 @@ const props = defineProps({ type: Number, default: null, }, + limit: { + type: Number, + default: null, + }, redirect: { type: Boolean, default: true, diff --git a/pages/admin/revisions/actors/+onBeforeRender.js b/pages/admin/revisions/actors/+onBeforeRender.js index b7dd568..7afcd6c 100644 --- a/pages/admin/revisions/actors/+onBeforeRender.js +++ b/pages/admin/revisions/actors/+onBeforeRender.js @@ -10,10 +10,12 @@ export async function onBeforeRender(pageContext) { const { revisions, + total: revisionTotal, avatars, } = await fetchActorRevisions(null, { - isFinalized: false, - limit: 50, + isFinalized: Object.hasOwn(pageContext.urlParsed.search, 'final'), + limit: Number(pageContext.urlParsed.search.limit) || 100, + page: Number(pageContext.routeParams.page) || 1, }, pageContext.user); return { @@ -21,6 +23,7 @@ export async function onBeforeRender(pageContext) { title: pageContext.routeParams.section, pageProps: { revisions, + revisionTotal, avatars, }, }, diff --git a/pages/admin/revisions/actors/+route.js b/pages/admin/revisions/actors/+route.js index 08c00f4..1fc0f57 100644 --- a/pages/admin/revisions/actors/+route.js +++ b/pages/admin/revisions/actors/+route.js @@ -1,6 +1,6 @@ import { match } from 'path-to-regexp'; -const path = '/admin/:section/:domain(actors)'; +const path = '/admin/:section/:domain(actors)/:page?'; const urlMatch = match(path, { decode: decodeURIComponent }); export default (pageContext) => { @@ -11,6 +11,8 @@ export default (pageContext) => { routeParams: { section: matched.params.section, domain: matched.params.domain, + page: matched.params.page || '1', + path, }, }; } diff --git a/pages/admin/revisions/scenes/+onBeforeRender.js b/pages/admin/revisions/scenes/+onBeforeRender.js index 3aa6a3e..ef03d39 100644 --- a/pages/admin/revisions/scenes/+onBeforeRender.js +++ b/pages/admin/revisions/scenes/+onBeforeRender.js @@ -10,12 +10,14 @@ export async function onBeforeRender(pageContext) { const { revisions, + total: revisionTotal, actors, tags, movies, } = await fetchSceneRevisions(null, { - isFinalized: false, - limit: 50, + isFinalized: Object.hasOwn(pageContext.urlParsed.search, 'final'), + limit: Number(pageContext.urlParsed.search.limit) || 100, + page: Number(pageContext.routeParams.page) || 1, }, pageContext.user); return { @@ -23,6 +25,7 @@ export async function onBeforeRender(pageContext) { title: pageContext.routeParams.section, pageProps: { revisions, + revisionTotal, actors, tags, movies, diff --git a/pages/admin/revisions/scenes/+route.js b/pages/admin/revisions/scenes/+route.js index 6ef6184..5ddbad5 100644 --- a/pages/admin/revisions/scenes/+route.js +++ b/pages/admin/revisions/scenes/+route.js @@ -1,6 +1,6 @@ import { match } from 'path-to-regexp'; -const path = '/admin/:section/:domain(scenes)'; +const path = '/admin/:section/:domain(scenes)/:page?'; const urlMatch = match(path, { decode: decodeURIComponent }); export default (pageContext) => { @@ -11,6 +11,8 @@ export default (pageContext) => { routeParams: { section: matched.params.section, domain: matched.params.domain, + page: matched.params.page || '1', + path, }, }; } diff --git a/pages/users/@username/+onBeforeRender.js b/pages/users/@username/+onBeforeRender.js index f818546..87a05ef 100644 --- a/pages/users/@username/+onBeforeRender.js +++ b/pages/users/@username/+onBeforeRender.js @@ -15,14 +15,16 @@ async function fetchRevisions(pageContext) { if (pageContext.routeParams.section === 'revisions' && pageContext.routeParams.domain === 'scenes') { return fetchSceneRevisions(null, { userId: pageContext.user.id, - limit: 100, + limit: Number(pageContext.urlParsed.search.limit) || 100, + page: Number(pageContext.routeParams.page) || 1, }, pageContext.user); } if (pageContext.routeParams.section === 'revisions' && pageContext.routeParams.domain === 'actors') { return fetchActorRevisions(null, { userId: pageContext.user.id, - limit: 100, + limit: Number(pageContext.urlParsed.search.limit) || 100, + page: Number(pageContext.routeParams.page) || 1, }, pageContext.user); } @@ -47,6 +49,7 @@ export async function onBeforeRender(pageContext) { const { revisions, + total: revisionTotal, actors, tags, movies, @@ -63,6 +66,7 @@ export async function onBeforeRender(pageContext) { stashes, alerts, revisions, + revisionTotal, keys, actors, tags, diff --git a/pages/users/@username/+route.js b/pages/users/@username/+route.js index eadf5d5..fc8f912 100644 --- a/pages/users/@username/+route.js +++ b/pages/users/@username/+route.js @@ -1,7 +1,7 @@ import { match } from 'path-to-regexp'; import { redirect } from 'vike/abort'; -const path = '/user/:username/:section?/:domain?'; +const path = '/user/:username/:section?/:domain?/:page?'; const urlMatch = match(path, { decode: decodeURIComponent }); export default (pageContext) => { @@ -18,6 +18,8 @@ export default (pageContext) => { username: matched.params.username, section: matched.params.section || '', domain: matched.params.domain || '', + page: matched.params.page || '1', + path, }, }; } diff --git a/src/actors.js b/src/actors.js index 9cea730..f60da1d 100644 --- a/src/actors.js +++ b/src/actors.js @@ -1059,6 +1059,7 @@ export async function fetchActorRevisions(revisionId, filters = {}, reqUser) { 'actors_revisions.*', 'users.username as username', 'reviewers.username as reviewer_username', + knex.raw('count(*) over() as total'), ) .leftJoin('users', 'users.id', 'actors_revisions.user_id') .leftJoin('users as reviewers', 'reviewers.id', 'actors_revisions.reviewed_by') @@ -1105,6 +1106,7 @@ export async function fetchActorRevisions(revisionId, filters = {}, reqUser) { return { revisions: curatedRevisions, revision: revisionId && curatedRevisions.find((revision) => revision.id === revisionId), + total: Number(revisions[0]?.total) || 0, avatars, }; } diff --git a/src/scenes.js b/src/scenes.js index 052967a..1436b82 100644 --- a/src/scenes.js +++ b/src/scenes.js @@ -766,6 +766,7 @@ export async function fetchSceneRevisions(revisionId, filters = {}, reqUser) { 'scenes_revisions.*', 'users.username as username', 'reviewers.username as reviewer_username', + knexOwner.raw('count(*) over() as total'), ) .leftJoin('users', 'users.id', 'scenes_revisions.user_id') .leftJoin('users as reviewers', 'reviewers.id', 'scenes_revisions.reviewed_by') @@ -824,6 +825,7 @@ export async function fetchSceneRevisions(revisionId, filters = {}, reqUser) { return { revisions: curatedRevisions, revision: revisionId && curatedRevisions.find((revision) => revision.id === revisionId), + total: Number(revisions[0]?.total) || 0, actors, tags, movies,