initial commit
This commit is contained in:
110
components/PublishPanel.tsx
Normal file
110
components/PublishPanel.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { api } from "@/lib/client";
|
||||
import type { GitStatus } from "@/lib/git";
|
||||
import type { PublishStep } from "@/lib/publish";
|
||||
|
||||
type Config = { push: boolean; pushAuth: string; deploy: boolean; deployUrl: string | null };
|
||||
|
||||
function defaultMessage(status: GitStatus): string {
|
||||
const n = status.changes.length;
|
||||
return n === 1 && status.changes[0].path.endsWith("blog-posts.json") ? "blog: update posts" : `blog: update posts (${n} files)`;
|
||||
}
|
||||
|
||||
export default function PublishPanel({ status: initial, config }: { status: GitStatus; config: Config }) {
|
||||
const router = useRouter();
|
||||
const [status, setStatus] = useState(initial);
|
||||
const [message, setMessage] = useState(() => defaultMessage(initial));
|
||||
const [running, setRunning] = useState(false);
|
||||
const [result, setResult] = useState<{ ok: boolean; steps: PublishStep[] } | null>(null);
|
||||
|
||||
if (!status.available) {
|
||||
return (
|
||||
<div className="notice error">
|
||||
git isn't usable on the portfolio checkout: <code>{status.error}</code>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const ahead = status.ahead ?? 0;
|
||||
const nothingToDo = status.changes.length === 0 && ahead === 0;
|
||||
|
||||
async function run() {
|
||||
setRunning(true);
|
||||
setResult(null);
|
||||
try {
|
||||
const res = await api<{ ok: boolean; steps: PublishStep[]; status: GitStatus }>("/api/publish", {
|
||||
method: "POST",
|
||||
json: { message },
|
||||
});
|
||||
setResult(res);
|
||||
setStatus(res.status);
|
||||
} catch (err) {
|
||||
setResult({ ok: false, steps: [{ step: "stage", status: "failed", output: (err as Error).message }] });
|
||||
} finally {
|
||||
setRunning(false);
|
||||
router.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className="muted">
|
||||
Branch <code>{status.branch}</code>
|
||||
{status.ahead !== undefined && (
|
||||
<>
|
||||
{" "}· {status.ahead} ahead / {status.behind} behind upstream (as of last fetch)
|
||||
</>
|
||||
)}
|
||||
. Only <code>data/blog-posts.json</code> and <code>public/img/blog/</code> are committed.
|
||||
</p>
|
||||
|
||||
<h2>Pending changes</h2>
|
||||
{status.changes.length === 0 ? (
|
||||
<p className="muted">No uncommitted blog changes.{ahead > 0 && ` ${ahead} commit(s) waiting to be pushed.`}</p>
|
||||
) : (
|
||||
<table className="list" style={{ marginBottom: 12 }}>
|
||||
<tbody>
|
||||
{status.changes.map((c) => (
|
||||
<tr key={c.path}>
|
||||
<td className="mono small" style={{ width: 40 }}>
|
||||
{c.code}
|
||||
</td>
|
||||
<td className="mono small">{c.path}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
{status.diffStat && <pre className="log">{status.diffStat}</pre>}
|
||||
|
||||
<h2 style={{ marginTop: 24 }}>Publish</h2>
|
||||
<p className="muted small">
|
||||
commit → {config.push ? `push (${config.pushAuth})` : "push disabled (GIT_PUSH=false)"} →{" "}
|
||||
{config.deploy ? `trigger redeploy at ${config.deployUrl}` : "redeploy trigger not configured"}
|
||||
</p>
|
||||
<div className="row" style={{ marginBottom: 16 }}>
|
||||
<input
|
||||
style={{ flex: 1, minWidth: 260 }}
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
placeholder="commit message"
|
||||
/>
|
||||
<button className="primary" disabled={running || nothingToDo || !message.trim()} onClick={run}>
|
||||
{running ? "Publishing…" : "Publish"}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{result && (
|
||||
<>
|
||||
<div className={`notice ${result.ok ? "ok" : "error"}`}>{result.ok ? "Published." : "Publish failed. See log."}</div>
|
||||
<pre className="log">
|
||||
{result.steps.map((s) => `[${s.status}] ${s.step}${s.output ? `\n${s.output}` : ""}`).join("\n\n")}
|
||||
</pre>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user