fix: add adminGetVideo/adminGetArticle queries to fix 404 on edit pages
The edit page loaders were calling adminListVideos/adminListArticles with the old pre-pagination signatures and filtering by ID client-side, which broke after pagination limited results to 50. Now fetches the single item by ID directly via new adminGetVideo and adminGetArticle backend queries. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,26 @@ builder.queryField("article", (t) =>
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
builder.queryField("adminGetArticle", (t) =>
|
||||||
|
t.field({
|
||||||
|
type: ArticleType,
|
||||||
|
nullable: true,
|
||||||
|
args: {
|
||||||
|
id: t.arg.string({ required: true }),
|
||||||
|
},
|
||||||
|
resolve: async (_root, args, ctx) => {
|
||||||
|
requireAdmin(ctx);
|
||||||
|
const article = await ctx.db
|
||||||
|
.select()
|
||||||
|
.from(articles)
|
||||||
|
.where(eq(articles.id, args.id))
|
||||||
|
.limit(1);
|
||||||
|
if (!article[0]) return null;
|
||||||
|
return enrichArticle(ctx.db, article[0]);
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
// ─── Admin queries & mutations ────────────────────────────────────────────────
|
// ─── Admin queries & mutations ────────────────────────────────────────────────
|
||||||
|
|
||||||
builder.queryField("adminListArticles", (t) =>
|
builder.queryField("adminListArticles", (t) =>
|
||||||
|
|||||||
@@ -188,6 +188,22 @@ builder.queryField("video", (t) =>
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
builder.queryField("adminGetVideo", (t) =>
|
||||||
|
t.field({
|
||||||
|
type: VideoType,
|
||||||
|
nullable: true,
|
||||||
|
args: {
|
||||||
|
id: t.arg.string({ required: true }),
|
||||||
|
},
|
||||||
|
resolve: async (_root, args, ctx) => {
|
||||||
|
requireAdmin(ctx);
|
||||||
|
const video = await ctx.db.select().from(videos).where(eq(videos.id, args.id)).limit(1);
|
||||||
|
if (!video[0]) return null;
|
||||||
|
return enrichVideo(ctx.db, video[0]);
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
builder.queryField("videoLikeStatus", (t) =>
|
builder.queryField("videoLikeStatus", (t) =>
|
||||||
t.field({
|
t.field({
|
||||||
type: VideoLikeStatusType,
|
type: VideoLikeStatusType,
|
||||||
|
|||||||
@@ -1339,6 +1339,51 @@ export async function adminListVideos(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ADMIN_GET_VIDEO_QUERY = gql`
|
||||||
|
query AdminGetVideo($id: String!) {
|
||||||
|
adminGetVideo(id: $id) {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
title
|
||||||
|
description
|
||||||
|
image
|
||||||
|
movie
|
||||||
|
tags
|
||||||
|
upload_date
|
||||||
|
premium
|
||||||
|
featured
|
||||||
|
likes_count
|
||||||
|
plays_count
|
||||||
|
models {
|
||||||
|
id
|
||||||
|
artist_name
|
||||||
|
slug
|
||||||
|
avatar
|
||||||
|
}
|
||||||
|
movie_file {
|
||||||
|
id
|
||||||
|
filename
|
||||||
|
mime_type
|
||||||
|
duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export async function adminGetVideo(
|
||||||
|
id: string,
|
||||||
|
fetchFn?: typeof globalThis.fetch,
|
||||||
|
token?: string,
|
||||||
|
): Promise<Video | null> {
|
||||||
|
return loggedApiCall("adminGetVideo", async () => {
|
||||||
|
const client = token ? getAuthClient(token) : getGraphQLClient(fetchFn);
|
||||||
|
const data = await client.request<{ adminGetVideo: Video | null }>(ADMIN_GET_VIDEO_QUERY, {
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
return data.adminGetVideo;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const CREATE_VIDEO_MUTATION = gql`
|
const CREATE_VIDEO_MUTATION = gql`
|
||||||
mutation CreateVideo(
|
mutation CreateVideo(
|
||||||
$title: String!
|
$title: String!
|
||||||
@@ -1543,6 +1588,44 @@ export async function adminListArticles(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ADMIN_GET_ARTICLE_QUERY = gql`
|
||||||
|
query AdminGetArticle($id: String!) {
|
||||||
|
adminGetArticle(id: $id) {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
title
|
||||||
|
excerpt
|
||||||
|
content
|
||||||
|
image
|
||||||
|
tags
|
||||||
|
publish_date
|
||||||
|
category
|
||||||
|
featured
|
||||||
|
author {
|
||||||
|
id
|
||||||
|
artist_name
|
||||||
|
slug
|
||||||
|
avatar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export async function adminGetArticle(
|
||||||
|
id: string,
|
||||||
|
fetchFn?: typeof globalThis.fetch,
|
||||||
|
token?: string,
|
||||||
|
): Promise<Article | null> {
|
||||||
|
return loggedApiCall("adminGetArticle", async () => {
|
||||||
|
const client = token ? getAuthClient(token) : getGraphQLClient(fetchFn);
|
||||||
|
const data = await client.request<{ adminGetArticle: Article | null }>(
|
||||||
|
ADMIN_GET_ARTICLE_QUERY,
|
||||||
|
{ id },
|
||||||
|
);
|
||||||
|
return data.adminGetArticle;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const CREATE_ARTICLE_MUTATION = gql`
|
const CREATE_ARTICLE_MUTATION = gql`
|
||||||
mutation CreateArticle(
|
mutation CreateArticle(
|
||||||
$title: String!
|
$title: String!
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
import { adminListArticles, adminListUsers } from "$lib/services";
|
import { adminGetArticle, adminListUsers } from "$lib/services";
|
||||||
import { error } from "@sveltejs/kit";
|
import { error } from "@sveltejs/kit";
|
||||||
|
|
||||||
export async function load({ params, fetch, cookies }) {
|
export async function load({ params, fetch, cookies }) {
|
||||||
const token = cookies.get("session_token") || "";
|
const token = cookies.get("session_token") || "";
|
||||||
const [articles, modelsResult] = await Promise.all([
|
const [article, modelsResult] = await Promise.all([
|
||||||
adminListArticles(fetch, token).catch(() => []),
|
adminGetArticle(params.id, fetch, token).catch(() => null),
|
||||||
adminListUsers({ role: "model", limit: 200 }, fetch, token).catch(() => ({
|
adminListUsers({ role: "model", limit: 200 }, fetch, token).catch(() => ({
|
||||||
items: [],
|
items: [],
|
||||||
total: 0,
|
total: 0,
|
||||||
})),
|
})),
|
||||||
]);
|
]);
|
||||||
const article = articles.find((a) => a.id === params.id);
|
|
||||||
if (!article) throw error(404, "Article not found");
|
if (!article) throw error(404, "Article not found");
|
||||||
|
|
||||||
return { article, authors: modelsResult.items };
|
return { article, authors: modelsResult.items };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import { adminListVideos, getModels } from "$lib/services";
|
import { adminGetVideo, getModels } from "$lib/services";
|
||||||
import { error } from "@sveltejs/kit";
|
import { error } from "@sveltejs/kit";
|
||||||
|
|
||||||
export async function load({ params, fetch, cookies }) {
|
export async function load({ params, fetch, cookies }) {
|
||||||
const token = cookies.get("session_token") || "";
|
const token = cookies.get("session_token") || "";
|
||||||
const [allVideos, models] = await Promise.all([
|
const [video, modelsResult] = await Promise.all([
|
||||||
adminListVideos(fetch, token).catch(() => []),
|
adminGetVideo(params.id, fetch, token).catch(() => null),
|
||||||
getModels(fetch).catch(() => []),
|
getModels({}, fetch).catch(() => ({ items: [], total: 0 })),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const video = allVideos.find((v) => v.id === params.id);
|
|
||||||
if (!video) throw error(404, "Video not found");
|
if (!video) throw error(404, "Video not found");
|
||||||
|
|
||||||
return { video, models };
|
return { video, models: modelsResult.items };
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user