diff --git a/README.md b/README.md index a92fe2b..ea73e6a 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ Sol Journal is a simple, minimal, journaling platform that works offline and acr ## Introduction +Sol Journal - A simple, open-source personal journaling platform | Product Hunt Embed + Journaling is a keystone habit that can improve your happiness and [overall health](https://psycnet.apa.org/record/2004-16777-010). Writing in a journal with pen and paper is effective, but not as easily accessible, maintained, or preserved as taking advantage of digital platforms. Having a journal that is available on any device makes journaling easier. Being tailored specifically to journaling makes it less cumbersome than trying to utilize a note taking app or document for recording thoughts and impressions. @@ -34,7 +36,7 @@ Sol Journal uses firebase to support offline functionality and authentication, m In the spirit of minimalism, key features are what are in place for a quick, lightweight journaling experience that can work across devices, including: - 🔥 Authentication: Cloud firestore persists registered users to a users document and saved journal entries to an entries document -- 🎨 Theming: the `src/styles/theme.js` file contains a set of colors and default styles that are applied to components with Emotion. A default light and dark theme are already in the file +- 🎨 Theming: the `src/styles/theme.js` file contains a set of colors and default styles that are applied to components with Emotion. A default light and dark theme are already in the file (adding [theme-ui](https://theme-ui.com/) support would be a great future addition) - 🔍 Search: full-text search of a user's entries stored in Firestore for quick access to past entries - 🖥 Mobile Friendly: designed to look great on mobile as well as desktop, with easy navigation on both - 💡 PWA: being a progressive web app makes it installable from Chrome/Safari on desktop, or be added to the homescreen on iOS/Android @@ -46,7 +48,7 @@ In the spirit of minimalism, key features are what are in place for a quick, lig Files are organized into these folders: `/components`: user interface pieces to construct the design and layout of the site -`/data`: local data transformed by gatsby to become queryable by Gatsby's GraphQL data layer +`/data`: local data transformed by Gatsby to become queryable by Gatsby's GraphQL data layer `/img`: images used by places like landing pages that are optimized by gatsby-image and then queryable in the GraphQL layer `/pages`: public pages that can be seen by unauthenticated users and are completely server side rendered by Gatsby during `gatsby build` `/routes`: private, client only routes only visible to authenticated users that are used by the app section of the journal @@ -114,6 +116,8 @@ It can be deployed to firebase with this command: firebase deploy -p public ``` -## Inspiration +## Inspiration and Other Projects Sol Journal is inspired by [JournalBook](https://github.com/trys/JournalBook) and borrows much of its design and navigation. + +If you're interested in a comparable version of the project, you can check out [this fork that adds rich text support](https://github.com/garrowp/sol-journal) to the journaling block. diff --git a/functions/package-lock.json b/functions/package-lock.json index 9110710..a1719ba 100644 --- a/functions/package-lock.json +++ b/functions/package-lock.json @@ -394,9 +394,9 @@ } }, "acorn": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", "dev": true }, "acorn-jsx": { @@ -405,15 +405,6 @@ "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", "dev": true }, - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "optional": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, "ajv": { "version": "6.10.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", @@ -1069,10 +1060,13 @@ } }, "eslint-utils": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", - "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", - "dev": true + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", + "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.0.0" + } }, "eslint-visitor-keys": { "version": "1.0.0", @@ -2130,13 +2124,24 @@ "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==" }, "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "optional": true, "requires": { - "agent-base": "^4.1.0", + "agent-base": "^4.3.0", "debug": "^3.1.0" + }, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "optional": true, + "requires": { + "es6-promisify": "^5.0.0" + } + } } }, "iconv-lite": { @@ -2399,9 +2404,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" }, "lodash.at": { "version": "4.6.0", @@ -2458,9 +2463,9 @@ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" }, "lodash.merge": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", - "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "optional": true }, "lodash.once": { @@ -2599,9 +2604,9 @@ "dev": true }, "node-fetch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", - "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", "optional": true }, "node-forge": { @@ -3354,9 +3359,9 @@ } }, "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" }, "which": { "version": "1.3.1", diff --git a/src/pages/login.js b/src/pages/login.js index 155e82c..63f793b 100644 --- a/src/pages/login.js +++ b/src/pages/login.js @@ -34,6 +34,11 @@ const LoginPage = ({ theme }) => ( Sign Up +
+ Or{" "} + + Reset Password +

diff --git a/src/pages/resetpassword.js b/src/pages/resetpassword.js new file mode 100644 index 0000000..78c302a --- /dev/null +++ b/src/pages/resetpassword.js @@ -0,0 +1,103 @@ +import React, { Component } from "react" +import { navigate, Link } from "gatsby" +import styled from "@emotion/styled" +import { compose } from "recompose" +import { format } from "date-fns" +import { withTheme } from "emotion-theming" + +import { SimpleNavbar } from "components/Navbar" +import { Input, Button, P } from "components/elements" +import Layout from "components/Layout" +import { FirebaseContext } from "components/firebase" +import { SIZES } from "styles/constants" + +const LoginGrid = styled.div` + display: grid; + grid-template-columns: 1fr; + grid-gap: 10px; +` +const LoginLayout = styled.div` + max-width: ${SIZES.smallWidth}; + width: 100%; + margin: 20px auto; +` + +const LoginPage = ({ theme }) => ( + + + +

+ Enter your email and we'll email you a password reset link! +

+ + {firebase => } + +

+ Don't have an account?{" "} + + Sign Up + +

+
+
+) + +class LoginFormBase extends Component { + constructor(props) { + super(props) + + this.state = { email: "", error: null } + } + + onSubmit = event => { + event.preventDefault() + const { email } = this.state + + this.props.firebase + .doPasswordReset(email) + .then(() => { + this.setState({ email: "", error: null }) + navigate(`index`) + }) + .catch(error => { + this.setState({ error }) + }) + } + + onChange = event => { + this.setState({ [event.target.name]: event.target.value }) + } + + render() { + const { email, error } = this.state + const { theme } = this.props + + const isInvalid = email === "" + + return ( +
+ + + + + + {error &&

{error.message}

} +
+ ) + } +} + +const LoginForm = compose(withTheme)(LoginFormBase) + +export default withTheme(LoginPage) + +export { LoginForm } diff --git a/src/routes/Search.js b/src/routes/Search.js index 0306247..8711d34 100644 --- a/src/routes/Search.js +++ b/src/routes/Search.js @@ -124,7 +124,7 @@ class Search extends Component { entry.text.length > 1 && ( =0.5.1: websocket-extensions ">=0.1.1" websocket-extensions@>=0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" - integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: version "1.0.5"