This commit is contained in:
Michael Zhang 2024-05-27 02:02:19 -05:00
parent 66a770faec
commit 4f31d10da4
6 changed files with 33 additions and 16 deletions

View file

@ -24,6 +24,7 @@
"date-fns": "^3.6.0", "date-fns": "^3.6.0",
"hast-util-to-jsx-runtime": "^2.3.0", "hast-util-to-jsx-runtime": "^2.3.0",
"hast-util-to-mdast": "^10.1.0", "hast-util-to-mdast": "^10.1.0",
"immutable": "^4.3.6",
"javascript-time-ago": "^2.5.10", "javascript-time-ago": "^2.5.10",
"jotai": "^2.8.1", "jotai": "^2.8.1",
"katex": "^0.16.10", "katex": "^0.16.10",

View file

@ -11,36 +11,38 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import TimeAgo from "javascript-time-ago"; import TimeAgo from "javascript-time-ago";
import en from "javascript-time-ago/locale/en"; import en from "javascript-time-ago/locale/en";
import Sidebar from "./components/Sidebar"; import Sidebar from "./components/Sidebar";
import { atom, useAtom } from "jotai"; import { atom, useAtom, useAtomValue } from "jotai";
import { OrderedMap, OrderedSet } from "immutable";
const queryClient = new QueryClient(); const queryClient = new QueryClient();
TimeAgo.addDefaultLocale(en); TimeAgo.addDefaultLocale(en);
export const nodesOpenedAtom = atom<string[]>([]); export const nodesOpenedAtom = atom<OrderedSet<string>>(OrderedSet<string>());
function App() { function App() {
const [nodesOpened, setNodesOpened] = useAtom(nodesOpenedAtom); const nodesOpened = useAtomValue(nodesOpenedAtom);
const openNode = useOpenNode();
// Open today's journal entry if it's not already opened // Open today's journal entry if it's not already opened
useEffect(() => { useEffect(() => {
(async () => { (async () => {
console.log("ndoes", nodesOpened); console.log("ndoes", nodesOpened);
if (nodesOpened.length === 0) { if (nodesOpened.size === 0) {
console.log("Opening today's entry."); console.log("Opening today's entry.");
const resp = await fetch( const resp = await fetch(
"http://localhost:5195/journal/get_todays_journal_id", "http://localhost:5195/journal/get_todays_journal_id",
); );
const data = await resp.json(); const data = await resp.json();
console.log("resp", data); console.log("resp", data);
setNodesOpened([data.node_id]); openNode(data.node_id);
} }
})(); })();
}, [nodesOpened]); }, [nodesOpened, openNode]);
const nodes = nodesOpened.map((nodeId) => ( const nodes = nodesOpened
<NodeDisplay key={nodeId} id={nodeId} /> .reverse()
)); .map((nodeId) => <NodeDisplay key={nodeId} id={nodeId} />);
return ( return (
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
@ -57,3 +59,10 @@ function App() {
} }
export default App; export default App;
export function useOpenNode() {
const [nodesOpened, setNodesOpened] = useAtom(nodesOpenedAtom);
return (node_id: string) => {
setNodesOpened(nodesOpened.remove(node_id).add(node_id));
};
}

View file

@ -49,5 +49,6 @@
.subtitle { .subtitle {
font-size: .75rem; font-size: .75rem;
color: rgba(0, 0, 0, 0.8);
} }
} }

View file

@ -14,7 +14,7 @@ import {
import { useDebounce } from "use-debounce"; import { useDebounce } from "use-debounce";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { atom, useAtom, useSetAtom } from "jotai"; import { atom, useAtom, useSetAtom } from "jotai";
import { nodesOpenedAtom } from "../App"; import { nodesOpenedAtom, useOpenNode } from "../App";
const searchQueryAtom = atom(""); const searchQueryAtom = atom("");
const showMenuAtom = atom(false); const showMenuAtom = atom(false);
@ -87,25 +87,25 @@ export default function SearchBar() {
} }
function SearchMenu({ results }) { function SearchMenu({ results }) {
const setNodesOpened = useSetAtom(nodesOpenedAtom);
const setSearchQuery = useSetAtom(searchQueryAtom); const setSearchQuery = useSetAtom(searchQueryAtom);
const setShowMenu = useSetAtom(showMenuAtom); const setShowMenu = useSetAtom(showMenuAtom);
const openNode = useOpenNode();
return ( return (
<div className={styles.searchResults}> <div className={styles.searchResults}>
{results.map((result) => ( {results.map((result) => (
<button <button
type="button" type="button"
key={result.score.toString()} key={result.node_id}
className={styles.searchResult} className={styles.searchResult}
onClick={() => { onClick={() => {
setSearchQuery(""); setSearchQuery("");
setShowMenu(false); setShowMenu(false);
setNodesOpened((prev) => [result.node_id, ...prev]); openNode(result.node_id);
}} }}
> >
<div className={styles.title}>{result.title}</div> <div className={styles.title}>{result.title}</div>
<div className={styles.subtitle}>{result.score}</div> <div className={styles.subtitle}>{result.content}</div>
</button> </button>
))} ))}
</div> </div>

View file

@ -233,6 +233,10 @@ pub async fn search_nodes(
State(state): State<AppState>, State(state): State<AppState>,
Query(query): Query<SearchQuery>, Query(query): Query<SearchQuery>,
) -> AppResult<Json<Value>> { ) -> AppResult<Json<Value>> {
// TODO: This is temporary, there may be more ways to search so tacking on *
// at the end may destroy some queries
let query = format!("{}*", query.query);
let results = state.db.run_script( let results = state.db.run_script(
" "
results[node_id, content, score] := ~journal:text_index {node_id, content, | results[node_id, content, score] := ~journal:text_index {node_id, content, |
@ -249,7 +253,7 @@ pub async fn search_nodes(
:order -score :order -score
", ",
btmap! { btmap! {
"q".to_owned() => DataValue::from(query.query), "q".to_owned() => DataValue::from(query),
}, },
ScriptMutability::Immutable, ScriptMutability::Immutable,
)?; )?;

View file

@ -53,6 +53,9 @@ importers:
hast-util-to-mdast: hast-util-to-mdast:
specifier: ^10.1.0 specifier: ^10.1.0
version: 10.1.0 version: 10.1.0
immutable:
specifier: ^4.3.6
version: 4.3.6
javascript-time-ago: javascript-time-ago:
specifier: ^2.5.10 specifier: ^2.5.10
version: 2.5.10 version: 2.5.10
@ -1975,7 +1978,6 @@ packages:
/immutable@4.3.6: /immutable@4.3.6:
resolution: {integrity: sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==} resolution: {integrity: sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==}
dev: true
/import-fresh@3.3.0: /import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}