diff --git a/apps/web/src/common/index.js b/apps/web/src/common/index.js index fa54d861d..8f6d88a1d 100644 --- a/apps/web/src/common/index.js +++ b/apps/web/src/common/index.js @@ -4,3 +4,7 @@ import events from "events"; export const db = new Database(StorageInterface); export const ev = new events.EventEmitter(); + +export function sendNewNoteEvent() { + ev.emit("onNewNote"); +} diff --git a/apps/web/src/components/list-item/index.js b/apps/web/src/components/list-item/index.js new file mode 100644 index 000000000..fce5e1384 --- /dev/null +++ b/apps/web/src/components/list-item/index.js @@ -0,0 +1,73 @@ +import React from "react"; +import { Flex, Box, Text } from "rebass"; +import * as Icon from "react-feather"; +import { ButtonPressedStyle } from "../../theme"; +import Dropdown, { DropdownTrigger, DropdownContent } from "../dropdown"; +import Menu from "../menu"; + +const ListItem = props => ( + { + if (props.onClick) { + props.onClick(); + } + e.stopPropagation(); + }} + alignItems="center" + justifyContent="space-between" + py={1} + sx={{ + borderRadius: "default", + marginBottom: 2, + borderBottom: "1px solid", + borderBottomColor: "navbg", + cursor: "default", + ...ButtonPressedStyle + }} + > + + + + {props.title} + + + + {props.body} + + {props.subBody && props.subBody} + + {props.info} + + + (props.dropdownRefs[props.index] = ref)} + > + + + + + + + + +); + +export default ListItem; diff --git a/apps/web/src/components/note/index.js b/apps/web/src/components/note/index.js new file mode 100644 index 000000000..79856e9a9 --- /dev/null +++ b/apps/web/src/components/note/index.js @@ -0,0 +1,49 @@ +import React from "react"; +import * as Icon from "react-feather"; +import TimeAgo from "timeago-react"; +import { db, ev } from "../../common"; +import { showSnack } from "../snackbar"; +import ListItem from "../list-item"; + +const dropdownRefs = []; +const menuItems = [ + { title: "Favorite", icon: Icon.Heart }, + { title: "Share", icon: Icon.Share2 }, + { + title: "Delete", + icon: Icon.Trash, + color: "red", + onClick: note => { + ev.emit("onClearNote", note.dateCreated); + db.deleteNotes([note]).then( + //TODO implement undo + () => { + showSnack("Note deleted!", Icon.Check); + ev.emit("refreshNotes"); + } + ); + } + } +]; + +function sendOpenNoteEvent(note) { + ev.emit("onOpenNote", note); +} + +const Note = ({ item, index }) => { + const note = item; + return ( + } + menuData={note} + menuItems={menuItems} + dropdownRefs={dropdownRefs} + /> + ); +}; + +export default Note; diff --git a/apps/web/src/components/notebook/index.js b/apps/web/src/components/notebook/index.js new file mode 100644 index 000000000..0cb64c2bb --- /dev/null +++ b/apps/web/src/components/notebook/index.js @@ -0,0 +1,64 @@ +import React from "react"; +import { Flex, Text } from "rebass"; +import * as Icon from "react-feather"; +import ListItem from "../list-item"; + +const dropdownRefs = []; +const menuItems = [ + { title: "Favorite", icon: Icon.Heart }, + { title: "Share", icon: Icon.Share2 }, + { + title: "Delete", + icon: Icon.Trash, + color: "red" + } +]; +const Notebook = ({ item, index, onClick, onTopicClick }) => { + const notebook = item; + return ( + + {notebook.topics.slice(1, 4).map(topic => ( + { + onTopicClick(notebook, topic); + e.stopPropagation(); + }} + key={topic.dateCreated + topic.title} + bg="accent" + px={1} + py={1} + sx={{ + marginRight: 1, + borderRadius: "default", + color: "fontSecondary" + }} + > + + {topic.title} + + + ))} + + } + info={ + + {new Date(notebook.dateCreated).toDateString().substring(4)} + + {" • " + notebook.totalNotes} Notes + + + } + dropdownRefs={dropdownRefs} + index={index} + menuData={notebook} + menuItems={menuItems} + /> + ); +}; + +export default Notebook; diff --git a/apps/web/src/components/search/index.js b/apps/web/src/components/search/index.js index 8ca89029d..38b4fd731 100644 --- a/apps/web/src/components/search/index.js +++ b/apps/web/src/components/search/index.js @@ -2,7 +2,7 @@ import React from "react"; import { Flex, Box } from "rebass"; import { Input } from "@rebass/forms"; import * as Icon from "react-feather"; -import theme, { SHADOW } from "../../theme"; +import theme from "../../theme"; import "./search.css"; const Search = props => ( { + const topic = item; + return ( + + + {topic.totalNotes} Notes + + + } + index={index} + dropdownRefs={dropdownRefs} + menuData={topic} + menuItems={menuItems} + /> + ); +}; + +export default Topic; diff --git a/apps/web/src/navigation/index.js b/apps/web/src/navigation/index.js index ec24561ed..e5ed99da6 100644 --- a/apps/web/src/navigation/index.js +++ b/apps/web/src/navigation/index.js @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState } from "react"; import ReactDOM from "react-dom"; import Home from "../views/Home"; import Notebooks from "../views/Notebooks"; @@ -79,10 +79,13 @@ export function goBack(root) { } function ThemedComponent(props) { + const [title, setTitle] = useState(props.route.title); return ( - {props.route.title} - {props.route.component && } + {title} + {props.route.component && ( + + )} ); } diff --git a/apps/web/src/views/Home.js b/apps/web/src/views/Home.js index c3f32bc6b..a26cf2b29 100644 --- a/apps/web/src/views/Home.js +++ b/apps/web/src/views/Home.js @@ -1,56 +1,22 @@ import React, { useEffect, useState } from "react"; -import { Flex, Box, Text } from "rebass"; +import { Flex, Text } from "rebass"; import * as Icon from "react-feather"; -import { ButtonPressedStyle } from "../theme"; -import Dropdown, { - DropdownTrigger, - DropdownContent -} from "../components/dropdown"; -import TimeAgo from "timeago-react"; -import { db, ev } from "../common"; +import { db, ev, sendNewNoteEvent } from "../common"; import { Virtuoso as List } from "react-virtuoso"; -import { showSnack } from "../components/snackbar"; -import Menu from "../components/menu"; import Button from "../components/button"; import Search from "../components/search"; +import Note from "../components/note"; -const dropdownRefs = []; -const menuItems = [ - { title: "Favorite", icon: Icon.Heart }, - { title: "Share", icon: Icon.Share2 }, - { - title: "Delete", - icon: Icon.Trash, - color: "red", - onClick: note => { - ev.emit("onClearNote", note.dateCreated); - db.deleteNotes([note]).then( - //TODO implement undo - () => { - showSnack("Note deleted!", Icon.Check); - //TODO very crude but works. - Home.onRefresh(); - } - ); - } - } -]; - -function sendNewNoteEvent() { - ev.emit("onNewNote"); -} -function sendOpenNoteEvent(note) { - ev.emit("onOpenNote", note); -} function Home() { const [notes, setNotes] = useState([]); useEffect(() => { - Home.onRefresh = () => { + function onRefreshNotes() { setNotes(db.getNotes()); - }; - Home.onRefresh(); + } + onRefreshNotes(); + ev.addListener("refreshNotes", onRefreshNotes); return () => { - Home.onRefresh = undefined; + ev.removeListener("refreshNotes", onRefreshNotes); }; }, []); return ( @@ -66,62 +32,7 @@ function Home() { overflowX: "hidden" }} totalCount={notes.length} - item={index => { - const note = notes[index]; - return ( - { - sendOpenNoteEvent(note); - e.stopPropagation(); - }} - py={3} - sx={{ - borderRadius: "default", - marginBottom: 2, - borderBottom: "1px solid", - borderBottomColor: "navbg", - cursor: "default", - ...ButtonPressedStyle - }} - > - - - {note.title} - - (dropdownRefs[index] = ref)} - > - - - - - - - - - - {note.headline} - - - - - - ); - }} + item={index => } />