opt(tierlist): parallelize ssr queries
This commit is contained in:
@@ -4,9 +4,9 @@ import Link from "next/link";
|
|||||||
import { useMemo, useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import Avatar from "@/components/avatar";
|
import Avatar from "@/components/avatar";
|
||||||
import SearchBox, { type Filters, type ParsedQuery } from "@/components/search";
|
import SearchBox, { type Filters, type ParsedQuery } from "@/components/search";
|
||||||
|
import { SimpleTooltip } from "@/components/tooltip";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { type characters, element } from "@/lib/db/schema";
|
import { type characters, element } from "@/lib/db/schema";
|
||||||
import { SimpleTooltip } from "@/components/tooltip";
|
|
||||||
|
|
||||||
/** Filters and their value providers */
|
/** Filters and their value providers */
|
||||||
const filters: Filters = {
|
const filters: Filters = {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import {
|
|||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Kbd } from "@/components/ui/kbd";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import { Tooltip, TooltipContent } from "@/components/ui/tooltip";
|
import { Tooltip, TooltipContent } from "@/components/ui/tooltip";
|
||||||
@@ -34,7 +35,6 @@ import { CharacterChooser, ClearCookie, Disclaimer } from "./client";
|
|||||||
import { ArtifactFormWrapper } from "./form";
|
import { ArtifactFormWrapper } from "./form";
|
||||||
import { LiveButton } from "./live";
|
import { LiveButton } from "./live";
|
||||||
import { RulesDialog } from "./rules";
|
import { RulesDialog } from "./rules";
|
||||||
import { Kbd } from "@/components/ui/kbd";
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "เสือกไอดีชาวบ้าน",
|
title: "เสือกไอดีชาวบ้าน",
|
||||||
|
|||||||
+1
-1
@@ -3,9 +3,9 @@ import Link from "next/link";
|
|||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import Banner from "#/banner_t.webp";
|
import Banner from "#/banner_t.webp";
|
||||||
import ArtifactLogo from "#/logos/artifact.webp";
|
import ArtifactLogo from "#/logos/artifact.webp";
|
||||||
|
import GuideLogo from "#/logos/guide.webp";
|
||||||
import RubgramLogo from "#/logos/rubgram.webp";
|
import RubgramLogo from "#/logos/rubgram.webp";
|
||||||
import TierlistLogo from "#/logos/tierlist.webp";
|
import TierlistLogo from "#/logos/tierlist.webp";
|
||||||
import GuideLogo from "#/logos/guide.webp";
|
|
||||||
import Image from "@/components/image";
|
import Image from "@/components/image";
|
||||||
import { SimpleTooltip } from "@/components/tooltip";
|
import { SimpleTooltip } from "@/components/tooltip";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ import {
|
|||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { shared } from "@/lib/comms";
|
import { shared } from "@/lib/comms";
|
||||||
|
import { sse } from "@/lib/db/sse-endpoints";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { setFree, setLimit, toggleCheck, toggleLock } from "../api";
|
import { setFree, setLimit, toggleCheck, toggleLock } from "../api";
|
||||||
import { sse } from "@/lib/db/sse-endpoints";
|
|
||||||
|
|
||||||
export function SidebarLink({
|
export function SidebarLink({
|
||||||
submission,
|
submission,
|
||||||
|
|||||||
@@ -84,21 +84,20 @@ export default async function TierlistPage({
|
|||||||
: ([] as (typeof characters.$inferSelect)[]);
|
: ([] as (typeof characters.$inferSelect)[]);
|
||||||
|
|
||||||
// fetch rows, columns, badges data...
|
// fetch rows, columns, badges data...
|
||||||
const tiers = await tx
|
const [tiers, columns, badgesList] = await Promise.all([
|
||||||
.select()
|
tx.select().from(tierlistTiers).orderBy(tierlistTiers.order),
|
||||||
.from(tierlistTiers)
|
tx.select().from(tierlistColumns).orderBy(tierlistColumns.order),
|
||||||
.orderBy(tierlistTiers.order);
|
tx
|
||||||
const columns = await tx
|
.select()
|
||||||
.select()
|
.from(tierlistBadges)
|
||||||
.from(tierlistColumns)
|
.orderBy(tierlistBadges.order)
|
||||||
.orderBy(tierlistColumns.order);
|
.where(
|
||||||
const badgesList = await tx
|
or(
|
||||||
.select()
|
isNull(tierlistBadges.type),
|
||||||
.from(tierlistBadges)
|
eq(tierlistBadges.type, version.type),
|
||||||
.orderBy(tierlistBadges.order)
|
),
|
||||||
.where(
|
),
|
||||||
or(isNull(tierlistBadges.type), eq(tierlistBadges.type, version.type)),
|
]);
|
||||||
);
|
|
||||||
const badges = badgesList.map((b) => ({
|
const badges = badgesList.map((b) => ({
|
||||||
...b,
|
...b,
|
||||||
tier: tiers.filter((t) => t.badges?.includes(b.id)).map((t) => t.id),
|
tier: tiers.filter((t) => t.badges?.includes(b.id)).map((t) => t.id),
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ import {
|
|||||||
CopyPlus,
|
CopyPlus,
|
||||||
FileQuestionMark,
|
FileQuestionMark,
|
||||||
Home,
|
Home,
|
||||||
TriangleAlert,
|
|
||||||
Pencil,
|
Pencil,
|
||||||
Settings,
|
Settings,
|
||||||
Settings2,
|
Settings2,
|
||||||
Trash2,
|
Trash2,
|
||||||
|
TriangleAlert,
|
||||||
X,
|
X,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
@@ -64,6 +64,7 @@ import {
|
|||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { tlPlacements, tlState } from "@/lib/api";
|
import { tlPlacements, tlState } from "@/lib/api";
|
||||||
|
import { authClient } from "@/lib/auth-client";
|
||||||
import { shared } from "@/lib/comms";
|
import { shared } from "@/lib/comms";
|
||||||
import type {
|
import type {
|
||||||
characters,
|
characters,
|
||||||
@@ -74,12 +75,11 @@ import type {
|
|||||||
tierlistTypes,
|
tierlistTypes,
|
||||||
tierlistVersions,
|
tierlistVersions,
|
||||||
} from "@/lib/db/schema";
|
} from "@/lib/db/schema";
|
||||||
import { authClient } from "@/lib/auth-client";
|
import { tlSse } from "@/lib/db/sse-endpoints";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { TierListCell } from "./cell";
|
import { TierListCell } from "./cell";
|
||||||
import { Draggable } from "./character";
|
import { Draggable } from "./character";
|
||||||
import { TierListContext } from "./context";
|
import { TierListContext } from "./context";
|
||||||
import { tlSse } from "@/lib/db/sse-endpoints";
|
|
||||||
|
|
||||||
function Untiered({
|
function Untiered({
|
||||||
children,
|
children,
|
||||||
|
|||||||
+28
-13
@@ -1,10 +1,10 @@
|
|||||||
import { desc, eq, not } from "drizzle-orm";
|
import { and, eq, getTableColumns, not, sql } from "drizzle-orm";
|
||||||
|
import { ArrowLeft } from "lucide-react";
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Image from "@/components/image";
|
import Image from "@/components/image";
|
||||||
import { db } from "@/lib/db";
|
import { db } from "@/lib/db";
|
||||||
import { tierlistTypes, tierlistVersions } from "@/lib/db/schema";
|
import { tierlistTypes, tierlistVersions } from "@/lib/db/schema";
|
||||||
import { ArrowLeft } from "lucide-react";
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "จัดเทียร์ลิสต์",
|
title: "จัดเทียร์ลิสต์",
|
||||||
@@ -17,19 +17,34 @@ export default async function TierlistSelectionPage({
|
|||||||
params: Promise<{ type: string }>;
|
params: Promise<{ type: string }>;
|
||||||
}) {
|
}) {
|
||||||
const { type: typeId } = await params;
|
const { type: typeId } = await params;
|
||||||
const types = await db
|
const vers = await db
|
||||||
.select()
|
.select({
|
||||||
|
...getTableColumns(tierlistTypes),
|
||||||
|
versions: sql<(typeof tierlistVersions.$inferSelect)[]>`
|
||||||
|
COALESCE(
|
||||||
|
json_agg(
|
||||||
|
json_build_object(
|
||||||
|
'id', ${tierlistVersions.id},
|
||||||
|
'name', ${tierlistVersions.name},
|
||||||
|
'image', ${tierlistVersions.image}
|
||||||
|
) ORDER BY ${tierlistVersions.order} DESC)
|
||||||
|
FILTER (WHERE ${tierlistVersions.id} IS NOT NULL),
|
||||||
|
'[]'
|
||||||
|
)
|
||||||
|
`.as("versions"),
|
||||||
|
})
|
||||||
.from(tierlistTypes)
|
.from(tierlistTypes)
|
||||||
|
.leftJoin(
|
||||||
|
tierlistVersions,
|
||||||
|
and(
|
||||||
|
eq(tierlistVersions.type, tierlistTypes.id),
|
||||||
|
not(tierlistVersions.hidden),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.groupBy(tierlistTypes.id)
|
||||||
|
.orderBy(tierlistTypes.id)
|
||||||
.where(eq(tierlistTypes.id, typeId));
|
.where(eq(tierlistTypes.id, typeId));
|
||||||
const versionsList = await db
|
|
||||||
.select()
|
|
||||||
.from(tierlistVersions)
|
|
||||||
.orderBy(desc(tierlistVersions.order))
|
|
||||||
.where(not(tierlistVersions.hidden));
|
|
||||||
const vers = types.map((t) => ({
|
|
||||||
...t,
|
|
||||||
versions: versionsList.filter((v) => v.type === t.id),
|
|
||||||
}));
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-7xl min-h-full flex flex-col gap-6 mx-auto py-8 px-4">
|
<div className="max-w-7xl min-h-full flex flex-col gap-6 mx-auto py-8 px-4">
|
||||||
{vers.map((t) => (
|
{vers.map((t) => (
|
||||||
|
|||||||
+30
-13
@@ -1,14 +1,14 @@
|
|||||||
import { desc, not } from "drizzle-orm";
|
import { and, eq, getTableColumns, not, sql } from "drizzle-orm";
|
||||||
|
import { ArrowRight } from "lucide-react";
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import TierlistLogo from "#/logos/tierlist.webp";
|
import TierlistLogo from "#/logos/tierlist.webp";
|
||||||
import { HorizontalDiv } from "@/components/horizontal";
|
import { HorizontalDiv } from "@/components/horizontal";
|
||||||
import { SimpleTooltip } from "@/components/tooltip";
|
|
||||||
import Image from "@/components/image";
|
import Image from "@/components/image";
|
||||||
|
import { SimpleTooltip } from "@/components/tooltip";
|
||||||
import { ScrollBar } from "@/components/ui/scroll-area";
|
import { ScrollBar } from "@/components/ui/scroll-area";
|
||||||
import { db } from "@/lib/db";
|
import { db } from "@/lib/db";
|
||||||
import { tierlistTypes, tierlistVersions } from "@/lib/db/schema";
|
import { tierlistTypes, tierlistVersions } from "@/lib/db/schema";
|
||||||
import { ArrowRight } from "lucide-react";
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "จัดเทียร์ลิสต์",
|
title: "จัดเทียร์ลิสต์",
|
||||||
@@ -16,16 +16,33 @@ export const metadata: Metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function TierlistSelectionPage() {
|
export default async function TierlistSelectionPage() {
|
||||||
const types = await db.select().from(tierlistTypes).orderBy(tierlistTypes.id);
|
const vers = await db
|
||||||
const versionsList = await db
|
.select({
|
||||||
.select()
|
...getTableColumns(tierlistTypes),
|
||||||
.from(tierlistVersions)
|
versions: sql<(typeof tierlistVersions.$inferSelect)[]>`
|
||||||
.orderBy(desc(tierlistVersions.order))
|
COALESCE(
|
||||||
.where(not(tierlistVersions.hidden));
|
json_agg(
|
||||||
const vers = types.map((t) => ({
|
json_build_object(
|
||||||
...t,
|
'id', ${tierlistVersions.id},
|
||||||
versions: versionsList.filter((v) => v.type === t.id),
|
'name', ${tierlistVersions.name},
|
||||||
}));
|
'image', ${tierlistVersions.image}
|
||||||
|
) ORDER BY ${tierlistVersions.order} DESC)
|
||||||
|
FILTER (WHERE ${tierlistVersions.id} IS NOT NULL),
|
||||||
|
'[]'
|
||||||
|
)
|
||||||
|
`.as("versions"),
|
||||||
|
})
|
||||||
|
.from(tierlistTypes)
|
||||||
|
.leftJoin(
|
||||||
|
tierlistVersions,
|
||||||
|
and(
|
||||||
|
eq(tierlistVersions.type, tierlistTypes.id),
|
||||||
|
not(tierlistVersions.hidden),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.groupBy(tierlistTypes.id)
|
||||||
|
.orderBy(tierlistTypes.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-full min-h-full flex flex-col justify-center gap-2 mx-2">
|
<div className="max-w-full min-h-full flex flex-col justify-center gap-2 mx-2">
|
||||||
<center className="mb-2">
|
<center className="mb-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user