Compare commits

..

No commits in common. "f543ad1cf406f080dcbcfcbfa57d360eafde5b0d" and "6ed78e6459f87a010e810db2f2b9d5a2a116b171" have entirely different histories.

8 changed files with 5 additions and 144 deletions

View File

@ -1,45 +0,0 @@
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { getBuildInfo } from "../util/env";
import { Clock, GitBranch, GitCommit, Tag } from "lucide-react";
export default function BuildInfoCard() {
const buildInfo = getBuildInfo();
return (
<Card className="w-full">
<CardHeader>
<CardTitle className="text-2xl font-bold">Build Information</CardTitle>
</CardHeader>
<CardContent className="grid gap-4">
<div className="flex items-center space-x-4">
<GitBranch className="h-5 w-5 text-muted-foreground" />
<div>
<p className="text-sm font-medium leading-none">Git Branch</p>
<p className="text-sm text-muted-foreground">{buildInfo.gitBranch}</p>
</div>
</div>
<div className="flex items-center space-x-4">
<GitCommit className="h-5 w-5 text-muted-foreground" />
<div>
<p className="text-sm font-medium leading-none">Git Hash</p>
<p className="text-sm text-muted-foreground">{buildInfo.gitHash}</p>
</div>
</div>
<div className="flex items-center space-x-4">
<Clock className="h-5 w-5 text-muted-foreground" />
<div>
<p className="text-sm font-medium leading-none">Build Time</p>
<p className="text-sm text-muted-foreground">{buildInfo.buildTime}</p>
</div>
</div>
<div className="flex items-center space-x-4">
<Tag className="h-5 w-5 text-muted-foreground" />
<div>
<p className="text-sm font-medium leading-none">Build Version</p>
<p className="text-sm text-muted-foreground">{buildInfo.buildVersion}</p>
</div>
</div>
</CardContent>
</Card>
);
}

View File

@ -22,7 +22,7 @@ export function DescTagItem({
{items.length === 0 ? "N/A" : items.map( {items.length === 0 ? "N/A" : items.map(
(x, i) => (x, i) =>
<> <>
<StyledLink key={x} to={`/search?allow_tag=${name.toLowerCase()}:${x}`}>{x}</StyledLink> <StyledLink key={x} to={`/search?allow_tag=${name}:${x}`}>{x}</StyledLink>
{i + 1 < items.length && <span className="">, </span>} {i + 1 < items.length && <span className="">, </span>}
</> </>
)} )}

View File

@ -1,17 +1,7 @@
import useSWR, { useSWRConfig } from "swr"; import useSWR from "swr";
import type { Document } from "dbtype"; import type { Document } from "dbtype";
import { fetcher } from "./fetcher"; import { fetcher } from "./fetcher";
export function useGalleryDoc(id: string) { export function useGalleryDoc(id: string) {
return useSWR<Document>(`/api/doc/${id}`, fetcher); return useSWR<Document>(`/api/doc/${id}`, fetcher);
}
export function useRehashDoc() {
const { mutate } = useSWRConfig();
return async (id: string) => {
await fetch(`/api/doc/${id}/_rehash`, {
method: "POST",
});
mutate(`/api/doc/${id}`);
};
} }

View File

@ -1,11 +1,10 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { useGalleryDoc, useRehashDoc } from "../hook/useGalleryDoc.ts"; import { useGalleryDoc } from "../hook/useGalleryDoc.ts";
import TagBadge from "@/components/gallery/TagBadge"; import TagBadge from "@/components/gallery/TagBadge";
import StyledLink from "@/components/gallery/StyledLink"; import StyledLink from "@/components/gallery/StyledLink";
import { Link } from "wouter"; import { Link } from "wouter";
import { classifyTags } from "../lib/classifyTags.tsx"; import { classifyTags } from "../lib/classifyTags.tsx";
import { DescTagItem, DescItem } from "../components/gallery/DescItem.tsx"; import { DescTagItem, DescItem } from "../components/gallery/DescItem.tsx";
import { Button } from "@/components/ui/button.tsx";
export interface ContentInfoPageProps { export interface ContentInfoPageProps {
params: { params: {
@ -15,7 +14,6 @@ export interface ContentInfoPageProps {
export function ContentInfoPage({ params }: ContentInfoPageProps) { export function ContentInfoPage({ params }: ContentInfoPageProps) {
const { data, error, isLoading } = useGalleryDoc(params.id); const { data, error, isLoading } = useGalleryDoc(params.id);
const rehashDoc = useRehashDoc();
if (isLoading) { if (isLoading) {
return <div className="p-4">Loading...</div> return <div className="p-4">Loading...</div>
@ -45,13 +43,7 @@ export function ContentInfoPage({ params }: ContentInfoPageProps) {
alt={data.title} /> alt={data.title} />
</div> </div>
</Link> </Link>
<Card className="flex-1 relative"> <Card className="flex-1">
<div className="absolute top-0 right-0 p-2">
<Button variant="ghost" onClick={async () => {
// Rehash
await rehashDoc(params.id);
}}>Rehash</Button>
</div>
<CardHeader> <CardHeader>
<CardTitle> <CardTitle>
<StyledLink to={contentLocation}> <StyledLink to={contentLocation}>

View File

@ -2,7 +2,6 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { type TernaryDarkMode, useTernaryDarkMode, useMediaQuery } from "usehooks-ts"; import { type TernaryDarkMode, useTernaryDarkMode, useMediaQuery } from "usehooks-ts";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import BuildInfoCard from "@/components/BuildInfoCard";
function LightModeView() { function LightModeView() {
return <div className="items-center rounded-md border-2 border-muted p-1 hover:border-accent"> return <div className="items-center rounded-md border-2 border-muted p-1 hover:border-accent">
@ -47,7 +46,7 @@ export function SettingPage() {
const isSystemDarkMode = useMediaQuery("(prefers-color-scheme: dark)"); const isSystemDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
return ( return (
<div className="p-4 space-y-2"> <div className="p-4">
<Card> <Card>
<CardHeader> <CardHeader>
<CardTitle className="text-2xl">Settings</CardTitle> <CardTitle className="text-2xl">Settings</CardTitle>
@ -86,7 +85,6 @@ export function SettingPage() {
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
<BuildInfoCard />
</div> </div>
) )
} }

View File

@ -1,13 +0,0 @@
declare const __GIT_BRANCH__: string;
declare const __GIT_HASH__: string;
declare const __BUILD_TIME__: string;
declare const __BUILD_VERSION__: string;
export function getBuildInfo() {
return {
gitBranch: __GIT_BRANCH__,
gitHash: __GIT_HASH__,
buildTime: __BUILD_TIME__,
buildVersion: __BUILD_VERSION__,
};
}

View File

@ -2,41 +2,11 @@ import { defineConfig, loadEnv } from 'vite'
import path from 'node:path' import path from 'node:path'
import react from '@vitejs/plugin-react-swc' import react from '@vitejs/plugin-react-swc'
import { execSync } from "child_process";
function getCurrentGitHash(): string {
const gitHash = execSync("git rev-parse HEAD")
.toString()
.trim();
return gitHash;
}
function getBuildTime(): string {
return new Date().toISOString();
}
function getBuildVersion(): string {
return process.env.BUILD_VERSION ?? getCurrentGitHash();
}
function getCurrentGitBranch(): string {
const gitBranch = execSync("git rev-parse --abbrev-ref HEAD")
.toString()
.trim();
return gitBranch;
}
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig(({ mode }) => { export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), ""); const env = loadEnv(mode, process.cwd(), "");
return { return {
plugins: [react()], plugins: [react()],
define: {
__BUILD_TIME__: `"${getBuildTime()}"`,
__BUILD_VERSION__: `"${getBuildVersion()}"`,
__GIT_BRANCH__: `"${getCurrentGitBranch()}"`,
__GIT_HASH__: `"${getCurrentGitHash()}"`,
},
resolve: { resolve: {
alias: { alias: {
'@': path.resolve(__dirname, './src'), '@': path.resolve(__dirname, './src'),

View File

@ -15,8 +15,6 @@ import { AllContentRouter } from "./all.ts";
import type { ContentLocation } from "./context.ts"; import type { ContentLocation } from "./context.ts";
import { sendError } from "./error_handler.ts"; import { sendError } from "./error_handler.ts";
import { ParseQueryArgString, ParseQueryArray, ParseQueryBoolean, ParseQueryNumber } from "./util.ts"; import { ParseQueryArgString, ParseQueryArray, ParseQueryBoolean, ParseQueryNumber } from "./util.ts";
import { oshash } from "src/util/oshash.ts";
const ContentIDHandler = (controller: DocumentAccessor) => async (ctx: Context, next: Next) => { const ContentIDHandler = (controller: DocumentAccessor) => async (ctx: Context, next: Next) => {
const num = Number.parseInt(ctx.params.num); const num = Number.parseInt(ctx.params.num);
@ -156,34 +154,6 @@ const ContentHandler = (controller: DocumentAccessor) => async (ctx: Context, ne
await next(); await next();
}; };
function RehashContentHandler(controller: DocumentAccessor) {
return async (ctx: Context, next: Next) => {
const num = Number.parseInt(ctx.params.num);
const c = await controller.findById(num);
if (c === undefined || c.deleted_at !== null) {
return sendError(404);
}
const filepath = join(c.basepath, c.filename);
let new_hash: string;
try {
new_hash = (await oshash(filepath)).toString();
}
catch (e) {
// if file is not found, return 404
if ( (e as NodeJS.ErrnoException).code === "ENOENT") {
return sendError(404, "file not found");
}
throw e;
}
const r = await controller.update({
id: num,
content_hash: new_hash,
});
ctx.body = JSON.stringify(r);
ctx.type = "json";
};
}
export const getContentRouter = (controller: DocumentAccessor) => { export const getContentRouter = (controller: DocumentAccessor) => {
const ret = new Router(); const ret = new Router();
ret.get("/search", PerCheck(Per.QueryContent), ContentQueryHandler(controller)); ret.get("/search", PerCheck(Per.QueryContent), ContentQueryHandler(controller));
@ -197,7 +167,6 @@ export const getContentRouter = (controller: DocumentAccessor) => {
ret.del("/:num(\\d+)", AdminOnly, DeleteContentHandler(controller)); ret.del("/:num(\\d+)", AdminOnly, DeleteContentHandler(controller));
ret.all("/:num(\\d+)/(.*)", PerCheck(Per.QueryContent), ContentHandler(controller)); ret.all("/:num(\\d+)/(.*)", PerCheck(Per.QueryContent), ContentHandler(controller));
ret.use("/:num(\\d+)", PerCheck(Per.QueryContent), new AllContentRouter().routes()); ret.use("/:num(\\d+)", PerCheck(Per.QueryContent), new AllContentRouter().routes());
ret.post("/:num(\\d+)/_rehash", AdminOnly, RehashContentHandler(controller));
return ret; return ret;
}; };