Compare commits
No commits in common. "f543ad1cf406f080dcbcfcbfa57d360eafde5b0d" and "6ed78e6459f87a010e810db2f2b9d5a2a116b171" have entirely different histories.
f543ad1cf4
...
6ed78e6459
@ -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>
|
|
||||||
);
|
|
||||||
}
|
|
@ -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>}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -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}`);
|
|
||||||
};
|
|
||||||
}
|
}
|
@ -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}>
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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__,
|
|
||||||
};
|
|
||||||
}
|
|
@ -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'),
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user