Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add sidebar and journal click-to-search #138

Merged
merged 1 commit into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 110 additions & 2 deletions src/views/documents/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import React from "react";
import { Pane } from "evergreen-ui";
import React, { useContext } from "react";
import {
Pane,
SideSheet,
Card,
Heading,
UnorderedList,
ListItem,
FolderCloseIcon,
IconButton,
FolderOpenIcon,
} from "evergreen-ui";
import TagSearch from "./search";
import { Link } from "react-router-dom";
import { SearchV2Store } from "./SearchStore";
import { JournalsStoreContext } from "../../hooks/useJournalsLoader";
import { JournalResponse } from "../../hooks/useClient";

interface Props {
store: SearchV2Store;
Expand All @@ -11,9 +23,23 @@ interface Props {
}

export function Layout(props: Props) {
const [isSidebarOpen, setIsSidebarOpen] = React.useState(false);

return (
<Pane>
<Pane marginBottom={8}>
<IconButton
icon={FolderOpenIcon}
onClick={() => setIsSidebarOpen(true)}
marginRight={8}
>
Select Journals
</IconButton>
<JournalSelectionSidebar
isShown={isSidebarOpen}
setIsShown={setIsSidebarOpen}
search={props.store}
/>
<TagSearch store={props.store} />
</Pane>
<Pane>
Expand All @@ -23,3 +49,85 @@ export function Layout(props: Props) {
</Pane>
);
}

interface SidebarProps {
isShown: boolean;
setIsShown: (isShown: boolean) => void;
search: SearchV2Store;
}

/**
* Sidebar for selecting journals to search.
*/
function JournalSelectionSidebar(props: SidebarProps) {
const { isShown, setIsShown } = props;
const jstore = useContext(JournalsStoreContext);
const searchStore = props.search;

function search(journal: string) {
searchStore.setSearch([`in:${journal}`]);
setIsShown(false);
return false;
}

return (
<React.Fragment>
<SideSheet
position="left"
isShown={isShown}
onCloseComplete={() => setIsShown(false)}
preventBodyScrolling
containerProps={{
display: "flex",
flex: "1",
flexDirection: "column",
}}
>
<Pane zIndex={1} flexShrink={0} elevation={0} backgroundColor="white">
<Pane padding={16}>
<Heading size={600}>Journals</Heading>
</Pane>
</Pane>
<Pane flex="1" overflowY="scroll" background="tint1" padding={16}>
<JournalsCard
journals={jstore.active}
title="Active Journals"
search={search}
/>
<JournalsCard
journals={jstore.archived}
title="Archived Journals"
search={search}
/>
</Pane>
</SideSheet>
</React.Fragment>
);
}

function JournalsCard(props: {
journals: JournalResponse[];
title: string;
search: (journalName: string) => boolean;
}) {
if (!props.journals.length) {
return null;
}

const journals = props.journals.map((j) => {
return (
<ListItem key={j.id} icon={FolderCloseIcon}>
<a href="" onClick={() => props.search(j.name)}>
{j.name}
</a>
</ListItem>
);
});

return (
<Card backgroundColor="white" elevation={0} padding={16} marginBottom={16}>
<Heading>{props.title}</Heading>
<UnorderedList>{journals}</UnorderedList>
</Card>
);
}
12 changes: 11 additions & 1 deletion src/views/documents/SearchStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export class SearchV2Store {
this.tagSeachStore.addTokens(tokens);
}

/**
* NOTE: This should be private, or refactored to trigger a search
*/
@action
setTokens = (tokens: SearchToken[]) => {
// Filter out invalid in: journal tokens
Expand Down Expand Up @@ -86,7 +89,6 @@ export class SearchV2Store {
/**
* Execute a search with the current tokens.
*
* @param limit
* @param resetPagination - By default execute a fresh search. When paginating,
* we don't want to reset the pagination state.
*/
Expand Down Expand Up @@ -146,6 +148,14 @@ export class SearchV2Store {
this.search(100, resetPagination);
};

/**
* Replace the current search with a new one.
*/
setSearch = (searchStr: string[]) => {
this.setTokens([]);
this.addTokens(searchStr);
};

@computed
get searchTokens() {
return this.tagSeachStore.searchTokens;
Expand Down
8 changes: 3 additions & 5 deletions src/views/documents/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { useContext } from "react";
import { observer } from "mobx-react-lite";
import { Heading, Paragraph, Pane } from "evergreen-ui";
import { JournalsStoreContext } from "../../hooks/useJournalsLoader";

import { JournalsStoreContext } from "../../hooks/useJournalsLoader";
import { SearchV2Store } from "./SearchStore";
import { DocumentItem } from "./DocumentItem";
import { useNavigate } from "react-router-dom";
Expand All @@ -25,11 +25,9 @@ function DocumentsContainer(props: { store: SearchV2Store }) {

// When hitting "back" from an edit note, the search state is maintained.
// When navigating to other pages (preferences) and back, the search
// state needs reset. This resets the state in that case. This is
// not the correct place to do this.
// state needs reset. This resets the state in that case.
if (!tokens.length) {
searchStore.setTokens([]);
searchStore.search();
searchStore.setSearch([]);
}
}, []);

Expand Down