v3: added content slugs, fixed real-time updates in client, added @mentions across the app, added new file selector and drop zone

This commit is contained in:
khannurien
2026-03-22 16:06:26 +00:00
parent 39a0cc397e
commit 34e908d1bc
42 changed files with 2170 additions and 628 deletions

View File

@@ -6,12 +6,15 @@ import type { Dump, UpdateDumpRequest } from "../model.ts";
import { deserializeDump } from "../model.ts";
import { useRequiredAuth } from "../hooks/useAuth.ts";
import { formatBytes } from "../utils/format.ts";
import { dumpUrl } from "../utils/urls.ts";
import { PageShell } from "../components/PageShell.tsx";
import { PageError } from "../components/PageError.tsx";
import { friendlyFetchError } from "../utils/apiError.ts";
import { ConfirmModal } from "../components/ConfirmModal.tsx";
import RichContentCard from "../components/RichContentCard.tsx";
import FilePreview from "../components/FilePreview.tsx";
import { TextEditor } from "../components/TextEditor.tsx";
import { FileDropZone } from "../components/FileDropZone.tsx";
type DumpEditState =
| { status: "loading" }
@@ -101,7 +104,7 @@ export function DumpEdit() {
const updatedDump: Dump = deserializeDump(apiResponse.data);
setState({ status: "loaded", dump: updatedDump });
setNewFile(null);
navigate(`/dumps/${updatedDump.id}`, { state: { dump: updatedDump } });
navigate(dumpUrl(updatedDump), { state: { dump: updatedDump } });
};
const handleRefreshMetadata = async () => {
@@ -236,26 +239,22 @@ export function DumpEdit() {
<strong>{dump.fileName}</strong>
{dump.fileSize != null && `${formatBytes(dump.fileSize)}`}
</p>
<label htmlFor="replace-file">Replace file</label>
<input
id="replace-file"
type="file"
onChange={(e) => setNewFile(e.target.files?.[0] ?? null)}
<FileDropZone
file={newFile}
onChange={setNewFile}
label="Replace file"
hint="Drop a replacement here"
showLimit={false}
/>
{newFile && (
<p className="file-input-info">
{newFile.name} {formatBytes(newFile.size)}
</p>
)}
</div>
)}
<div className="form-group">
<label htmlFor="comment">Why are you dumping this?</label>
<textarea
<TextEditor
id="comment"
value={comment}
onChange={(e) => setComment(e.currentTarget.value)}
onChange={setComment}
placeholder="Tell the community what makes this worth their time..."
rows={3}
/>
@@ -287,7 +286,7 @@ export function DumpEdit() {
Delete dump
</button>
<div className="form-actions-right">
<Link to={`/dumps/${dump.id}`} className="form-cancel">
<Link to={dumpUrl(dump)} className="form-cancel">
Cancel
</Link>
<button type="submit" className="btn-primary">Save</button>