edit title
This commit is contained in:
parent
ccebb53879
commit
7307f92f55
8 changed files with 182 additions and 10 deletions
|
@ -24,15 +24,19 @@
|
|||
"hast-util-to-mdast": "^10.1.0",
|
||||
"javascript-time-ago": "^2.5.10",
|
||||
"jotai": "^2.8.1",
|
||||
"katex": "^0.16.10",
|
||||
"mdast-util-from-markdown": "^2.0.0",
|
||||
"mdast-util-to-markdown": "^2.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-time-ago": "^7.3.3",
|
||||
"rehype-katex": "^7.0.0",
|
||||
"remark": "^15.0.1",
|
||||
"remark-math": "^6.0.0",
|
||||
"remark-rehype": "^11.1.0",
|
||||
"use-debounce": "^10.0.1",
|
||||
"uuidv7": "^1.0.0",
|
||||
"vfile": "^6.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -3,6 +3,7 @@ import styles from "./App.module.scss";
|
|||
|
||||
import "@fontsource/inter";
|
||||
import "./global.scss";
|
||||
import "katex/dist/katex.min.css";
|
||||
import { useEffect, useState } from "react";
|
||||
import NodeDisplay from "./components/NodeDisplay";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
.body {
|
||||
flex-grow: 1;
|
||||
|
||||
padding: 12px;
|
||||
// padding: 12px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -31,7 +31,10 @@
|
|||
|
||||
.title {
|
||||
padding: 12px;
|
||||
border: none;
|
||||
border-bottom: 1px solid lightgray;
|
||||
outline: none;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.untitled {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { useQuery } from "@tanstack/react-query";
|
|||
import styles from "./NodeDisplay.module.scss";
|
||||
import ReactTimeAgo from "react-time-ago";
|
||||
import JournalPage from "./nodes/JournalPage";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
export interface NodeDisplayProps {
|
||||
id: string;
|
||||
|
@ -19,6 +20,28 @@ export default function NodeDisplay({ id }: NodeDisplayProps) {
|
|||
|
||||
const { isSuccess, status, data } = query;
|
||||
|
||||
const [isEditingTitle, setIsEditingTitle] = useState(false);
|
||||
const [title, setTitle] = useState(() =>
|
||||
isSuccess && data ? data.title : undefined,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setTitle(data.title);
|
||||
}, [data]);
|
||||
|
||||
const saveChangedTitle = useCallback(() => {
|
||||
(async () => {
|
||||
const resp = await fetch(`http://localhost:5195/node/${id}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ title: title }),
|
||||
});
|
||||
setIsEditingTitle(false);
|
||||
})();
|
||||
}, [title, id]);
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.header}>
|
||||
|
@ -28,9 +51,31 @@ export default function NodeDisplay({ id }: NodeDisplayProps) {
|
|||
<>ID {id}</>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.title}>
|
||||
{data?.title ?? <span className={styles.untitled}>(untitled)</span>}
|
||||
{isEditingTitle ? (
|
||||
<form
|
||||
onSubmit={(evt) => {
|
||||
evt.preventDefault();
|
||||
saveChangedTitle();
|
||||
}}
|
||||
>
|
||||
<input
|
||||
className={styles.title}
|
||||
type="text"
|
||||
value={title}
|
||||
onChange={(evt) => setTitle(evt.target.value)}
|
||||
onBlur={() => saveChangedTitle()}
|
||||
// biome-ignore lint/a11y/noAutofocus: <explanation>
|
||||
autoFocus
|
||||
/>
|
||||
</form>
|
||||
) : (
|
||||
<div
|
||||
className={styles.title}
|
||||
onDoubleClick={() => setIsEditingTitle(true)}
|
||||
>
|
||||
{title ?? <span className={styles.untitled}>(untitled)</span>}
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.body}>
|
||||
{isSuccess ? (
|
||||
<NodeDisplayLoaded id={id} data={data} />
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
.mdEditor {
|
||||
flex-grow: 1;
|
||||
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.block {
|
||||
|
|
|
@ -3,6 +3,8 @@ import MDEditor from "@uiw/react-md-editor";
|
|||
import { usePrevious, useDebounce } from "@uidotdev/usehooks";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import styles from "./JournalPage.module.scss";
|
||||
import remarkMath from "remark-math";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
|
||||
export interface JournalPageProps {
|
||||
id: string;
|
||||
|
@ -43,16 +45,16 @@ export default function JournalPage({ id, data }: JournalPageProps) {
|
|||
|
||||
return (
|
||||
<div data-color-mode="light" className={styles.container}>
|
||||
<details>
|
||||
<summary>JSON</summary>
|
||||
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||
</details>
|
||||
|
||||
<MDEditor
|
||||
value={value}
|
||||
className={styles.mdEditor}
|
||||
onChange={(newValue) => newValue && setValue(newValue)}
|
||||
preview="preview"
|
||||
visibleDragbar={false}
|
||||
previewOptions={{
|
||||
remarkPlugins: [remarkMath],
|
||||
rehypePlugins: [rehypeKatex],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -75,6 +75,22 @@ pub async fn update_node(
|
|||
|
||||
let tx = state.db.multi_transaction(true);
|
||||
|
||||
if let Some(title) = update_data.title {
|
||||
let title = DataValue::from(title);
|
||||
|
||||
tx.run_script(
|
||||
"
|
||||
# Always update the time
|
||||
?[ id, title ] <- [[ $node_id, $title ]]
|
||||
:update node { id, title }
|
||||
",
|
||||
btmap! {
|
||||
"node_id".to_owned() => node_id_data.clone(),
|
||||
"title".to_owned() => title,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
if let Some(extra_data) = update_data.extra_data {
|
||||
let result = tx.run_script(
|
||||
"
|
||||
|
@ -133,7 +149,7 @@ pub async fn update_node(
|
|||
btmap! {
|
||||
"node_id".to_owned() => node_id_data,
|
||||
},
|
||||
);
|
||||
)?;
|
||||
|
||||
tx.commit()?;
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ importers:
|
|||
jotai:
|
||||
specifier: ^2.8.1
|
||||
version: 2.8.1(@types/react@18.3.3)(react@18.3.1)
|
||||
katex:
|
||||
specifier: ^0.16.10
|
||||
version: 0.16.10
|
||||
mdast-util-from-markdown:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
|
@ -71,15 +74,24 @@ importers:
|
|||
react-time-ago:
|
||||
specifier: ^7.3.3
|
||||
version: 7.3.3(javascript-time-ago@2.5.10)(react-dom@18.3.1)(react@18.3.1)
|
||||
rehype-katex:
|
||||
specifier: ^7.0.0
|
||||
version: 7.0.0
|
||||
remark:
|
||||
specifier: ^15.0.1
|
||||
version: 15.0.1
|
||||
remark-math:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0
|
||||
remark-rehype:
|
||||
specifier: ^11.1.0
|
||||
version: 11.1.0
|
||||
use-debounce:
|
||||
specifier: ^10.0.1
|
||||
version: 10.0.1(react@18.3.1)
|
||||
uuidv7:
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
vfile:
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1
|
||||
|
@ -1223,6 +1235,10 @@ packages:
|
|||
'@types/unist': 3.0.2
|
||||
dev: false
|
||||
|
||||
/@types/katex@0.16.7:
|
||||
resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==}
|
||||
dev: false
|
||||
|
||||
/@types/mdast@4.0.4:
|
||||
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
|
||||
dependencies:
|
||||
|
@ -1477,6 +1493,11 @@ packages:
|
|||
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
|
||||
dev: false
|
||||
|
||||
/commander@8.3.0:
|
||||
resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
|
||||
engines: {node: '>= 12'}
|
||||
dev: false
|
||||
|
||||
/convert-source-map@1.9.0:
|
||||
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
|
||||
dev: false
|
||||
|
@ -1678,6 +1699,23 @@ packages:
|
|||
hast-util-is-element: 3.0.0
|
||||
dev: false
|
||||
|
||||
/hast-util-from-dom@5.0.0:
|
||||
resolution: {integrity: sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==}
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
hastscript: 8.0.0
|
||||
web-namespaces: 2.0.1
|
||||
dev: false
|
||||
|
||||
/hast-util-from-html-isomorphic@2.0.0:
|
||||
resolution: {integrity: sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==}
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
hast-util-from-dom: 5.0.0
|
||||
hast-util-from-html: 2.0.1
|
||||
unist-util-remove-position: 5.0.0
|
||||
dev: false
|
||||
|
||||
/hast-util-from-html@2.0.1:
|
||||
resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==}
|
||||
dependencies:
|
||||
|
@ -2027,6 +2065,13 @@ packages:
|
|||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/katex@0.16.10:
|
||||
resolution: {integrity: sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
commander: 8.3.0
|
||||
dev: false
|
||||
|
||||
/lines-and-columns@1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
dev: false
|
||||
|
@ -2149,6 +2194,20 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/mdast-util-math@3.0.0:
|
||||
resolution: {integrity: sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==}
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
'@types/mdast': 4.0.4
|
||||
devlop: 1.1.0
|
||||
longest-streak: 3.1.0
|
||||
mdast-util-from-markdown: 2.0.0
|
||||
mdast-util-to-markdown: 2.1.0
|
||||
unist-util-remove-position: 5.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/mdast-util-mdx-expression@2.0.0:
|
||||
resolution: {integrity: sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==}
|
||||
dependencies:
|
||||
|
@ -2332,6 +2391,18 @@ packages:
|
|||
micromark-util-types: 2.0.0
|
||||
dev: false
|
||||
|
||||
/micromark-extension-math@3.0.0:
|
||||
resolution: {integrity: sha512-iJ2Q28vBoEovLN5o3GO12CpqorQRYDPT+p4zW50tGwTfJB+iv/VnB6Ini+gqa24K97DwptMBBIvVX6Bjk49oyQ==}
|
||||
dependencies:
|
||||
'@types/katex': 0.16.7
|
||||
devlop: 1.1.0
|
||||
katex: 0.16.10
|
||||
micromark-factory-space: 2.0.0
|
||||
micromark-util-character: 2.1.0
|
||||
micromark-util-symbol: 2.0.0
|
||||
micromark-util-types: 2.0.0
|
||||
dev: false
|
||||
|
||||
/micromark-factory-destination@2.0.0:
|
||||
resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==}
|
||||
dependencies:
|
||||
|
@ -2736,6 +2807,18 @@ packages:
|
|||
unist-util-visit: 5.0.0
|
||||
dev: false
|
||||
|
||||
/rehype-katex@7.0.0:
|
||||
resolution: {integrity: sha512-h8FPkGE00r2XKU+/acgqwWUlyzve1IiOKwsEkg4pDL3k48PiE0Pt+/uLtVHDVkN1yA4iurZN6UES8ivHVEQV6Q==}
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
'@types/katex': 0.16.7
|
||||
hast-util-from-html-isomorphic: 2.0.0
|
||||
hast-util-to-text: 4.0.2
|
||||
katex: 0.16.10
|
||||
unist-util-visit-parents: 6.0.1
|
||||
vfile: 6.0.1
|
||||
dev: false
|
||||
|
||||
/rehype-minify-whitespace@6.0.0:
|
||||
resolution: {integrity: sha512-i9It4YHR0Sf3GsnlR5jFUKXRr9oayvEk9GKQUkwZv6hs70OH9q3OCZrq9PpLvIGKt3W+JxBOxCidNVpH/6rWdA==}
|
||||
dependencies:
|
||||
|
@ -2833,6 +2916,17 @@ packages:
|
|||
unist-util-visit: 5.0.0
|
||||
dev: false
|
||||
|
||||
/remark-math@6.0.0:
|
||||
resolution: {integrity: sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==}
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
mdast-util-math: 3.0.0
|
||||
micromark-extension-math: 3.0.0
|
||||
unified: 11.0.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/remark-parse@11.0.0:
|
||||
resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
|
||||
dependencies:
|
||||
|
@ -3096,6 +3190,11 @@ packages:
|
|||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/uuidv7@1.0.0:
|
||||
resolution: {integrity: sha512-XkvPwTtSmYwxIE1FSYQTYg79zHL1ZWV5vM/Qyl9ahXCU8enOPPA4bTjzvafvYUB7l2+miv4EqK/qEe75cOXIdA==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/vfile-location@5.0.2:
|
||||
resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==}
|
||||
dependencies:
|
||||
|
|
Loading…
Reference in a new issue