From aae847791cca7cc89dd9bc7784d99a2931ddf540 Mon Sep 17 00:00:00 2001 From: Christopher Loverich <1010084+cloverich@users.noreply.github.com> Date: Sun, 21 Jan 2024 07:33:55 -0800 Subject: [PATCH] pre-select current or active journals - put search store into context (todo: refactor component drilling to pull from context) - when creating new documents, if the search is scoped to a journal, default the new document to the selected journal - when creating new documents, if search is NOT scoped, default to the first ACTIVE journal --- src/container.tsx | 30 ++++++++++++++++---------- src/preload/client/journals.ts | 1 + src/views/documents/SearchStore.ts | 11 ++++++++++ src/views/edit/index.tsx | 6 +++++- src/views/edit/useEditableDocument.ts | 31 ++++++++++++++++++++++----- 5 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/container.tsx b/src/container.tsx index 53f7751..eddcf16 100644 --- a/src/container.tsx +++ b/src/container.tsx @@ -13,7 +13,10 @@ import { Alert, Pane } from "evergreen-ui"; import { Routes, Route, Navigate } from "react-router-dom"; import { useSearchParams } from "react-router-dom"; import useClient from "./hooks/useClient"; -import { SearchV2Store } from "./views/documents/SearchStore"; +import { + SearchV2Store, + SearchStoreContext, +} from "./views/documents/SearchStore"; export default observer(function Container() { const { journalsStore, loading, loadingErr } = useJournalsLoader(); @@ -63,16 +66,21 @@ export default observer(function Container() { return ( - - - } path="journals" /> - } path="preferences" /> - } path="edit/new" /> - } path="edit/:document" /> - } path="documents" /> - } /> - - + + + + } path="journals" /> + } path="preferences" /> + } path="edit/new" /> + } path="edit/:document" /> + } + path="documents" + /> + } /> + + + ); }); diff --git a/src/preload/client/journals.ts b/src/preload/client/journals.ts index 0177352..9c42c59 100644 --- a/src/preload/client/journals.ts +++ b/src/preload/client/journals.ts @@ -48,6 +48,7 @@ export class JournalsClient { }; remove = (journal: { id: string }): Promise => { + // TODO: ensure there is always at least one journal. Deleting the last journal breaks the app. this.db .prepare("delete from journals where id = :id") .run({ id: journal.id }); diff --git a/src/views/documents/SearchStore.ts b/src/views/documents/SearchStore.ts index d6b6e5a..0893d4f 100644 --- a/src/views/documents/SearchStore.ts +++ b/src/views/documents/SearchStore.ts @@ -1,3 +1,4 @@ +import { createContext } from "react"; import { IClient } from "../../hooks/useClient"; import { observable, IObservableArray, computed, action } from "mobx"; import { JournalsStore } from "../../hooks/stores/journals"; @@ -19,6 +20,8 @@ interface SearchQuery { limit?: number; } +export const SearchStoreContext = createContext(null as any); + export class SearchV2Store { @observable docs: SearchItem[] = []; @observable loading = true; @@ -156,6 +159,14 @@ export class SearchV2Store { this.addTokens(searchStr); }; + @computed get selectedJournals(): string[] { + // Grab the journal names from the tokens + // todo: Typescript doesn't know when I filter to type === 'in' its InTokens + return this._tokens + .filter((t) => t.type === "in") + .map((t) => t.value) as string[]; + } + @computed get searchTokens() { return this.tagSeachStore.searchTokens; diff --git a/src/views/edit/index.tsx b/src/views/edit/index.tsx index d21ae04..b82c2cf 100644 --- a/src/views/edit/index.tsx +++ b/src/views/edit/index.tsx @@ -14,13 +14,17 @@ import { JournalsStoreContext } from "../../hooks/useJournalsLoader"; import Toolbar from "./toolbar"; import { useParams, useNavigate } from "react-router-dom"; import { DebugView } from "./DebugView"; +import { SearchStoreContext } from "../documents/SearchStore"; // Loads document, with loading and error placeholders function DocumentLoadingContainer() { const journalsStore = useContext(JournalsStoreContext); + const searchStore = useContext(SearchStoreContext); const { document: documentId } = useParams(); + const { document, loadingError } = useEditableDocument( - journalsStore.journals, + searchStore, + journalsStore, documentId, ); diff --git a/src/views/edit/useEditableDocument.ts b/src/views/edit/useEditableDocument.ts index be80d93..a97714b 100644 --- a/src/views/edit/useEditableDocument.ts +++ b/src/views/edit/useEditableDocument.ts @@ -2,12 +2,36 @@ import React from "react"; import { JournalResponse } from "../../preload/client/journals"; import useClient from "../../hooks/useClient"; import { EditableDocument } from "./EditableDocument"; +import { SearchV2Store } from "../documents/SearchStore"; +import { JournalsStore } from "../../hooks/stores/journals"; + +/** + * Determines the default journal to use when creating a new document. + * + * todo(test): When one or multiple journals are selected, returns the first + * todo(test): When no journals are selected, returns the first active journal + * todo(test): When archived journal selected, returns the selected (archived) journal + */ +function defaultJournal(selectedJournals: string[], jstore: JournalsStore) { + const selectedId = jstore.journals.find((j) => + selectedJournals.includes(j.name), + )?.id; + + if (selectedId) { + return selectedId; + } else { + // todo: defaulting to first journal, but could use logic such as the last selected + // journal, etc, once that is in place + return jstore.active[0].id; + } +} /** * Load a new or existing document into a view model */ export function useEditableDocument( - journals: JournalResponse[], + search: SearchV2Store, + jstore: JournalsStore, documentId?: string, ) { const [document, setDocument] = React.useState(null); @@ -31,9 +55,7 @@ export function useEditableDocument( setDocument( new EditableDocument(client, { content: "", - // todo: defaulting to first journal, but could use logic such as the last selected - // journal, etc, once that is in place - journalId: journals[0].id, + journalId: defaultJournal(search.selectedJournals, jstore), }), ); } @@ -51,7 +73,6 @@ export function useEditableDocument( }, [documentId]); return { - journals, document, loadingError: loadingError, };