Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export const server = {
save: defineAction({
input: checkInsertSchema.pick({ template_id: true, template_revision: true, data: true }),
handler: async (input) => {
if (!input.template_revision) {
throw new ActionError({ code: "BAD_REQUEST", message: "template revision is required" });
}
const template = await getTemplateVersion(input.template_id, input.template_revision);
if (!template) {
throw new ActionError({ code: "NOT_FOUND", message: `template revision ${input.template_id}@${input.template_revision} not found` });
Expand Down
10 changes: 3 additions & 7 deletions src/db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,12 @@ export async function getTemplate(id: string): Promise<template | null> {
return e ? e.data : null;
}

export async function getCurrentTemplate(id: string): Promise<template & template_revision | null> {
const t = await getTemplate(id);
return t && t.revisions.length ? { ...t, ...t.revisions[0] } : null;
}

export async function getTemplateVersion(id: string, revision: string):
/** Falsy revision resolves to the current (most recent) one. */
export async function getTemplateVersion(id: string, revision?: string | null):
Promise<template & template_revision | null> {
const t = await getTemplate(id);
if (!t) return null;
const rs = t.revisions.filter((r) => r.revision === revision);
const rs = revision ? t.revisions.filter((r) => r.revision === revision) : t.revisions;
return rs.length ? { ...t, ...rs[0] } : null;
}

Expand Down
4 changes: 2 additions & 2 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import Layout from "../layouts/Layout.astro";
import HeaderLogo from "../components/HeaderLogo.astro";
import KinkCheck from "../components/KinkCheck";
import RatingOverview from "../components/RatingOverview.astro";
import { getCurrentTemplate } from "../db";
import { getTemplateVersion } from "../db";
import ClearButton from "../components/ClearButton";

const template = await getCurrentTemplate("kcc");
const template = await getTemplateVersion("kcc");
if (!template) {
throw new Error(`cant find template (should never happen, our db is f-ed)`);
}
Expand Down
4 changes: 2 additions & 2 deletions src/pages/internal/smol.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import Layout from "../../layouts/Layout.astro";
import HeaderLogo from "../../components/HeaderLogo.astro";
import KinkCheck from "../../components/KinkCheck";
import RatingOverview from "../../components/RatingOverview.astro";
import { getCurrentTemplate } from "../../db";
import { getTemplateVersion } from "../../db";

const template = await getCurrentTemplate("kcc");
const template = await getTemplateVersion("kcc");
if (!template) {
throw new Error(`cant find template (should never happen, our db is f-ed)`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,43 @@ import { getCollection } from "astro:content";
import HeaderLogo from "../../../../components/HeaderLogo.astro";
import KinkCheck from "../../../../components/KinkCheck";
import RatingOverview from "../../../../components/RatingOverview.astro";
import { getCurrentTemplate } from "../../../../db";
import { getTemplateVersion } from "../../../../db";
import Layout from "../../../../layouts/Layout.astro";
import ClearButton from "../../../../components/ClearButton";
import SaveButton from "../../../../components/SaveButton";

const { id } = Astro.params;
const template = id && (await getCurrentTemplate(id));
const { id, rev } = Astro.params;
const template = id && (await getTemplateVersion(id, rev));

if (!template) {
return new Response("Template not found", { status: 404 });
}

export async function getStaticPaths() {
const templates = await getCollection("templates");
return templates.map(({ id }) => ({ params: { id } }));
return templates.flatMap((t) => [
{ params: { id: t.id } },
...t.data.revisions.map(({ revision }) => ({ params: { id: t.id, rev: revision } })),
]);
}
---

<Layout title={`${template.name} ${template.revision}`} screenshotOptions={{ width: 1500 }}>
<HeaderLogo slot="header">
<span class="smol">{template.name}&nbsp;v{template.revision}</span>
</HeaderLogo>
<select class="versionselector" slot="header" aria-label="Template version">
<option value={`/internal/templates/${template.id}/`} selected={!rev}>
latest ({template.revisions[0].revision})
</option>
<optgroup label="Versions">
{template.revisions.map(({ revision }) => (
<option value={`/internal/templates/${template.id}/${revision}/`} selected={rev === revision}>
{revision}
</option>
))}
</optgroup>
</select>
<RatingOverview slot="header" />
<KinkCheck kinks={template.kinks} store={template.id} client:load />
<ClearButton store={template.id} slot="bottom-nav" client:load />
Expand All @@ -36,6 +51,12 @@ export async function getStaticPaths() {
/>
</Layout>

<script>
document.querySelector<HTMLSelectElement>("select.versionselector")?.addEventListener("change", (event) => {
window.location.href = (event.currentTarget as HTMLSelectElement).value;
});
</script>

<style>
:global(div#content) {
min-width: 475px;
Expand All @@ -44,4 +65,7 @@ export async function getStaticPaths() {
:global(dialog::backdrop) {
background-color: rgba(0, 0, 0, 0.5);
}
select {
margin: auto 0;
}
</style>
19 changes: 19 additions & 0 deletions test/templates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getCollection } from "astro:content";
import { assert, expect, test } from "vitest";
import type { template } from "../src/zod";
import { tMeta } from "../src/content.config";
import { getTemplateVersion } from "../src/db";
import { readdir } from "node:fs/promises";

test("every template directory has tMeta metadata and vice versa", async () => {
Expand Down Expand Up @@ -34,3 +35,21 @@ test("kink ids are unique", () => {
}
}
});

test("getTemplateVersion resolves falsy revisions to the current one", async () => {
for (const t of templates) {
for (const rev of [undefined, null, ""] as const) {
expect(await getTemplateVersion(t.id, rev)).toStrictEqual({ ...t, ...t.revisions[0] });
}
}
});

test("getTemplateVersion resolves named revisions and rejects unknown ones", async () => {
for (const t of templates) {
for (const r of t.revisions) {
expect(await getTemplateVersion(t.id, r.revision)).toMatchObject({ id: t.id, revision: r.revision });
}
expect(await getTemplateVersion(t.id, "no-such-revision")).toBeNull();
expect(await getTemplateVersion("no-such-template", t.revisions[0]?.revision)).toBeNull();
}
});
Loading