From 0144bfc9cc6c616a00a8171f3950a75ec948427e Mon Sep 17 00:00:00 2001 From: jackyzha0 Date: Sun, 11 Apr 2021 10:27:27 -0700 Subject: base next refactor --- frontend/src/pages/[hash].js | 65 +++++++++++++++++ frontend/src/pages/_app.js | 23 ++++++ frontend/src/pages/_document.js | 30 ++++++++ frontend/src/pages/index.js | 150 ++++++++++++++++++++++++++++++++++++++++ frontend/src/pages/raw/index.js | 14 ++++ 5 files changed, 282 insertions(+) create mode 100644 frontend/src/pages/[hash].js create mode 100644 frontend/src/pages/_app.js create mode 100644 frontend/src/pages/_document.js create mode 100644 frontend/src/pages/index.js create mode 100644 frontend/src/pages/raw/index.js (limited to 'frontend/src/pages') diff --git a/frontend/src/pages/[hash].js b/frontend/src/pages/[hash].js new file mode 100644 index 0000000..27f808b --- /dev/null +++ b/frontend/src/pages/[hash].js @@ -0,0 +1,65 @@ +import React, { useEffect, useState, useRef } from 'react'; +import Error from '../components/Err'; +import { Text } from '../components/Inputs'; +import CodeRenderer from '../components/renderers/Code' +import PasteInfo from '../components/PasteInfo'; +import PasswordModal from '../components/modals/PasswordModal' +import RenderDispatch from '../components/renderers/RenderDispatch' +import useFetchPaste from "../http/useFetchPaste"; + +const ViewPaste = (props) => { + const { err, requiresAuth, validPass, getWithPassword, result } = useFetchPaste(props.hash) + const {content, language, expiry, title} = result ?? {} + const [theme, setTheme] = useState('atom'); + const [isRenderMode, setIsRenderMode] = useState(false); + const [enteredPass, setEnteredPass] = useState(''); + const ErrorLabelRef = useRef(null); + + if (err) { + ErrorLabelRef.current.showMessage(err, -1) + } + + useEffect(() => { + setIsRenderMode(language === 'latex' || language === 'markdown') + }, [language]) + + function getDisplay() { + return isRenderMode ? : + } + + return ( +
+ setEnteredPass(e.target.value)} + validateCallback={getWithPassword} /> + + {getDisplay()} + setIsRenderMode(!isRenderMode)} + isRenderMode={isRenderMode} + onChange={(e) => setTheme(e.target.value)} + err={} + /> +
+ ); +} + +export default ViewPaste \ No newline at end of file diff --git a/frontend/src/pages/_app.js b/frontend/src/pages/_app.js new file mode 100644 index 0000000..7e99f01 --- /dev/null +++ b/frontend/src/pages/_app.js @@ -0,0 +1,23 @@ +import React from 'react' +import ThemeProvider from "../theme/ThemeProvider"; +import GlobalStyle from "../theme/GlobalStyle"; +import '../theme/style.css'; +import {Watermark} from "../components/Watermark"; +import styled from "styled-components"; + +const Main = styled.div` + margin-top: 10vh; + padding: 0 20vw 30px 20vw; +` + +const App = ({ Component, pageProps }) => ( + + + +
+ +
+
+) + +export default App \ No newline at end of file diff --git a/frontend/src/pages/_document.js b/frontend/src/pages/_document.js new file mode 100644 index 0000000..0cbd6a3 --- /dev/null +++ b/frontend/src/pages/_document.js @@ -0,0 +1,30 @@ +import Document from 'next/document' +import { ServerStyleSheet } from 'styled-components' + +export default class StyledDocument extends Document { + static async getInitialProps(ctx) { + const sheet = new ServerStyleSheet() + const originalRenderPage = ctx.renderPage + + try { + ctx.renderPage = () => + originalRenderPage({ + enhanceApp: (App) => (props) => + sheet.collectStyles(), + }) + + const initialProps = await Document.getInitialProps(ctx) + return { + ...initialProps, + styles: ( + <> + {initialProps.styles} + {sheet.getStyleElement()} + + ), + } + } finally { + sheet.seal() + } + } +} \ No newline at end of file diff --git a/frontend/src/pages/index.js b/frontend/src/pages/index.js new file mode 100644 index 0000000..141ebac --- /dev/null +++ b/frontend/src/pages/index.js @@ -0,0 +1,150 @@ +import React, { useEffect, useState, useRef } from 'react'; +import { Text, Code } from '../components/Inputs' +import OptionsContainer from '../components/Options' +import Error from '../components/Err' +import PasteModal from '../components/modals/PasteModal' +import styled from 'styled-components' +import CodeRenderer from '../components/renderers/Code' +import Latex from '../components/renderers/Latex' +import Markdown from '../components/renderers/Markdown' +import {Button, SubmitButton} from "../components/Common/Button"; +import {newPaste} from "../http/shared"; + +const Flex = styled.div` + display: flex; + flex-direction: row; +` + +const FlexLeft = styled.div` + flex: 0 0 calc(50% - 1em - 2px); +` + +const FlexRight = styled.div` + flex: 0 0 50%; + max-width: calc(50% - 1em + 2px); + margin-left: 2em; +` + +const PreviewWrapper = styled.div` + margin: 2em; +` + +const NewPaste = () => { + const [title, setTitle] = useState(''); + const [content, setContent] = useState(''); + const [pass, setPass] = useState(''); + const [language, setLanguage] = useState('detect'); + const [expiry, setExpiry] = useState(''); + const [hash, setHash] = useState(''); + const [isPreview, setIsPreview] = useState(false); + const ErrorLabel = useRef(null); + + useEffect(() => { + document.title = title === "" ? `ctrl-v` : `ctrl-v | ${title}`; + }, [title]) + + function handleSubmit(e) { + e.preventDefault(); + + // prevent resubmission + if (!hash) { + newPaste({title, content, language, pass, expiry}) + .then(resp => {setHash(resp.data.hash)}) + .catch((error) => { + const resp = error.response + + // some weird err (e.g. network) + if (!resp) { + ErrorLabel.current.showMessage(error) + return + } + + // some weird err + const errTxt = `${resp.status}: ${resp.data}` + ErrorLabel.current.showMessage(errTxt) + }); + } + } + + function renderPreview() { + const pasteInput = + + if (isPreview) { + var preview + switch (language) { + case 'latex': + preview = + + + + break + case 'markdown': + preview = + + + + break + default: + preview = + + } + + return ( + + + {pasteInput} + + + {preview} + + + ); + } else { + return ( + pasteInput + ); + } + } + + return ( +
+ + {setTitle(e.target.value)}} + value={title} + autoFocus + maxLength="100" + id="titleInput" /> + {renderPreview()} + { setPass(e.target.value) }} + onLangChange={(e) => { setLanguage(e.target.value) }} + onExpiryChange={(e) => { setExpiry(e.target.value) }} /> +
+ + {language !== 'detect' && } +
+
+ + + ); +} + +export default NewPaste \ No newline at end of file diff --git a/frontend/src/pages/raw/index.js b/frontend/src/pages/raw/index.js new file mode 100644 index 0000000..86db3d4 --- /dev/null +++ b/frontend/src/pages/raw/index.js @@ -0,0 +1,14 @@ +import React from 'react'; +import useFetchPaste from "../../http/useFetchPaste"; +import { useRouter } from 'next/router' + + +export default (req, res) => { + const router = useRouter() + const { hash } = router.query + const { err, result } = useFetchPaste(hash) + res.statusCode = 200 + res.json({ + text: 'Hello World! This is the Next.js starter kit :D', + }) +} \ No newline at end of file -- cgit v1.2.3 From 3f0cdc02b275e24771226417c442125f74bcd8c1 Mon Sep 17 00:00:00 2001 From: jackyzha0 Date: Sun, 11 Apr 2021 10:45:10 -0700 Subject: safely remove style.css --- frontend/src/pages/_app.js | 1 - frontend/src/pages/index.js | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'frontend/src/pages') diff --git a/frontend/src/pages/_app.js b/frontend/src/pages/_app.js index 7e99f01..eb205e3 100644 --- a/frontend/src/pages/_app.js +++ b/frontend/src/pages/_app.js @@ -1,7 +1,6 @@ import React from 'react' import ThemeProvider from "../theme/ThemeProvider"; import GlobalStyle from "../theme/GlobalStyle"; -import '../theme/style.css'; import {Watermark} from "../components/Watermark"; import styled from "styled-components"; diff --git a/frontend/src/pages/index.js b/frontend/src/pages/index.js index 141ebac..36bcad7 100644 --- a/frontend/src/pages/index.js +++ b/frontend/src/pages/index.js @@ -10,6 +10,10 @@ import Markdown from '../components/renderers/Markdown' import {Button, SubmitButton} from "../components/Common/Button"; import {newPaste} from "../http/shared"; +const Container = styled.form` + width: 100%; +` + const Flex = styled.div` display: flex; flex-direction: row; @@ -115,7 +119,7 @@ const NewPaste = () => { } return ( -
+ {
- +
); } -- cgit v1.2.3 From 77c061bc0b8aecce7311ce820b3401c95797a589 Mon Sep 17 00:00:00 2001 From: jackyzha0 Date: Sun, 11 Apr 2021 11:40:44 -0700 Subject: working raw paste fetch --- frontend/src/pages/[hash].js | 3 +++ frontend/src/pages/_app.js | 2 -- frontend/src/pages/index.js | 2 ++ frontend/src/pages/raw/[hash].js | 24 ++++++++++++++++++++++++ frontend/src/pages/raw/index.js | 14 -------------- 5 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 frontend/src/pages/raw/[hash].js delete mode 100644 frontend/src/pages/raw/index.js (limited to 'frontend/src/pages') diff --git a/frontend/src/pages/[hash].js b/frontend/src/pages/[hash].js index 27f808b..5a04e31 100644 --- a/frontend/src/pages/[hash].js +++ b/frontend/src/pages/[hash].js @@ -6,6 +6,8 @@ import PasteInfo from '../components/PasteInfo'; import PasswordModal from '../components/modals/PasswordModal' import RenderDispatch from '../components/renderers/RenderDispatch' import useFetchPaste from "../http/useFetchPaste"; +import {Watermark} from "../components/Watermark"; +import ThemeProvider from "../theme/ThemeProvider"; const ViewPaste = (props) => { const { err, requiresAuth, validPass, getWithPassword, result } = useFetchPaste(props.hash) @@ -58,6 +60,7 @@ const ViewPaste = (props) => { onChange={(e) => setTheme(e.target.value)} err={} /> + ); } diff --git a/frontend/src/pages/_app.js b/frontend/src/pages/_app.js index eb205e3..e013c64 100644 --- a/frontend/src/pages/_app.js +++ b/frontend/src/pages/_app.js @@ -1,7 +1,6 @@ import React from 'react' import ThemeProvider from "../theme/ThemeProvider"; import GlobalStyle from "../theme/GlobalStyle"; -import {Watermark} from "../components/Watermark"; import styled from "styled-components"; const Main = styled.div` @@ -12,7 +11,6 @@ const Main = styled.div` const App = ({ Component, pageProps }) => ( -
diff --git a/frontend/src/pages/index.js b/frontend/src/pages/index.js index 36bcad7..1b550e8 100644 --- a/frontend/src/pages/index.js +++ b/frontend/src/pages/index.js @@ -9,6 +9,7 @@ import Latex from '../components/renderers/Latex' import Markdown from '../components/renderers/Markdown' import {Button, SubmitButton} from "../components/Common/Button"; import {newPaste} from "../http/shared"; +import {Watermark} from "../components/Watermark"; const Container = styled.form` width: 100%; @@ -147,6 +148,7 @@ const NewPaste = () => {
+ ); } diff --git a/frontend/src/pages/raw/[hash].js b/frontend/src/pages/raw/[hash].js new file mode 100644 index 0000000..d0a66a7 --- /dev/null +++ b/frontend/src/pages/raw/[hash].js @@ -0,0 +1,24 @@ +import React from 'react'; +import resolvePaste from "../../http/useFetchPaste"; +import {CodeLike} from "../../components/Common/mixins"; +import styled from 'styled-components' + +const RawText = styled.pre` + ${CodeLike} + padding: 0 1em; +` + +export async function getServerSideProps(ctx) { + const data = await resolvePaste(ctx.params.hash) + + // Pass data to the page via props + return { props: { ...data } } +} + +const Raw = ({error, data}) => { + return + {data?.content || error} + +} + +export default Raw \ No newline at end of file diff --git a/frontend/src/pages/raw/index.js b/frontend/src/pages/raw/index.js deleted file mode 100644 index 86db3d4..0000000 --- a/frontend/src/pages/raw/index.js +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import useFetchPaste from "../../http/useFetchPaste"; -import { useRouter } from 'next/router' - - -export default (req, res) => { - const router = useRouter() - const { hash } = router.query - const { err, result } = useFetchPaste(hash) - res.statusCode = 200 - res.json({ - text: 'Hello World! This is the Next.js starter kit :D', - }) -} \ No newline at end of file -- cgit v1.2.3 From 12c995b6bd501be73b60e3bae6c46c59cebef6c2 Mon Sep 17 00:00:00 2001 From: jackyzha0 Date: Sun, 11 Apr 2021 12:30:02 -0700 Subject: base resolve paste and fetch paste refactor --- frontend/src/pages/[hash].js | 40 ++++++++++++++++++++++++++++++---------- frontend/src/pages/raw/[hash].js | 2 +- 2 files changed, 31 insertions(+), 11 deletions(-) (limited to 'frontend/src/pages') diff --git a/frontend/src/pages/[hash].js b/frontend/src/pages/[hash].js index 5a04e31..bd7fc00 100644 --- a/frontend/src/pages/[hash].js +++ b/frontend/src/pages/[hash].js @@ -5,20 +5,40 @@ import CodeRenderer from '../components/renderers/Code' import PasteInfo from '../components/PasteInfo'; import PasswordModal from '../components/modals/PasswordModal' import RenderDispatch from '../components/renderers/RenderDispatch' -import useFetchPaste from "../http/useFetchPaste"; import {Watermark} from "../components/Watermark"; -import ThemeProvider from "../theme/ThemeProvider"; +import { useRouter } from 'next/router' +import resolvePaste from "../http/resolvePaste"; -const ViewPaste = (props) => { - const { err, requiresAuth, validPass, getWithPassword, result } = useFetchPaste(props.hash) - const {content, language, expiry, title} = result ?? {} +export async function getServerSideProps(ctx) { + const data = await resolvePaste(ctx.params.hash) + + // Pass data to the page via props + return { props: { ...data } } +} + +const ViewPaste = ({data, unauthorized, error}) => { + const router = useRouter() + const { hash } = router.query + const [clientData, setClientData] = useState(data); const [theme, setTheme] = useState('atom'); const [isRenderMode, setIsRenderMode] = useState(false); const [enteredPass, setEnteredPass] = useState(''); + const [correctPass, setCorrectPass] = useState(!unauthorized); const ErrorLabelRef = useRef(null); - if (err) { - ErrorLabelRef.current.showMessage(err, -1) + const {content, language, expiry, title} = clientData; + + if (error) { + ErrorLabelRef.current.showMessage(error, -1) + } + + const getWithPassword = (password, errorCallback) => { + resolvePaste(hash, password) + .then(resp => { + setCorrectPass(true) + setClientData(resp.data) + }) + .catch(e => errorCallback(e.response.data)) } useEffect(() => { @@ -39,8 +59,8 @@ const ViewPaste = (props) => { return (
setEnteredPass(e.target.value)} validateCallback={getWithPassword} /> @@ -51,7 +71,7 @@ const ViewPaste = (props) => { readOnly /> {getDisplay()} Date: Sun, 11 Apr 2021 12:42:42 -0700 Subject: refactor error handling in pasteinfo --- frontend/src/pages/[hash].js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'frontend/src/pages') diff --git a/frontend/src/pages/[hash].js b/frontend/src/pages/[hash].js index bd7fc00..6d65f3e 100644 --- a/frontend/src/pages/[hash].js +++ b/frontend/src/pages/[hash].js @@ -1,5 +1,4 @@ -import React, { useEffect, useState, useRef } from 'react'; -import Error from '../components/Err'; +import React, { useEffect, useState } from 'react'; import { Text } from '../components/Inputs'; import CodeRenderer from '../components/renderers/Code' import PasteInfo from '../components/PasteInfo'; @@ -24,13 +23,10 @@ const ViewPaste = ({data, unauthorized, error}) => { const [isRenderMode, setIsRenderMode] = useState(false); const [enteredPass, setEnteredPass] = useState(''); const [correctPass, setCorrectPass] = useState(!unauthorized); - const ErrorLabelRef = useRef(null); const {content, language, expiry, title} = clientData; - if (error) { - ErrorLabelRef.current.showMessage(error, -1) - } + const getWithPassword = (password, errorCallback) => { resolvePaste(hash, password) @@ -78,7 +74,7 @@ const ViewPaste = ({data, unauthorized, error}) => { toggleRenderCallback={() => setIsRenderMode(!isRenderMode)} isRenderMode={isRenderMode} onChange={(e) => setTheme(e.target.value)} - err={} + err={error} />
-- cgit v1.2.3 From d58c7a3ad5dc83a08e040a855f158f8c6c09e154 Mon Sep 17 00:00:00 2001 From: jackyzha0 Date: Sun, 11 Apr 2021 13:50:20 -0700 Subject: password resolution, dynamic head --- frontend/src/pages/[hash].js | 11 ++++------- frontend/src/pages/_app.js | 26 ++++++++++++++++++++++++++ frontend/src/pages/raw/[hash].js | 13 ++++++++----- 3 files changed, 38 insertions(+), 12 deletions(-) (limited to 'frontend/src/pages') diff --git a/frontend/src/pages/[hash].js b/frontend/src/pages/[hash].js index 6d65f3e..f281621 100644 --- a/frontend/src/pages/[hash].js +++ b/frontend/src/pages/[hash].js @@ -7,27 +7,23 @@ import RenderDispatch from '../components/renderers/RenderDispatch' import {Watermark} from "../components/Watermark"; import { useRouter } from 'next/router' import resolvePaste from "../http/resolvePaste"; +import NextHead from "../components/NextHead"; export async function getServerSideProps(ctx) { const data = await resolvePaste(ctx.params.hash) - - // Pass data to the page via props return { props: { ...data } } } const ViewPaste = ({data, unauthorized, error}) => { const router = useRouter() const { hash } = router.query - const [clientData, setClientData] = useState(data); const [theme, setTheme] = useState('atom'); const [isRenderMode, setIsRenderMode] = useState(false); const [enteredPass, setEnteredPass] = useState(''); const [correctPass, setCorrectPass] = useState(!unauthorized); - + const [clientData, setClientData] = useState(data) const {content, language, expiry, title} = clientData; - - const getWithPassword = (password, errorCallback) => { resolvePaste(hash, password) .then(resp => { @@ -54,6 +50,7 @@ const ViewPaste = ({data, unauthorized, error}) => { return (
+ {!error && } { toggleRenderCallback={() => setIsRenderMode(!isRenderMode)} isRenderMode={isRenderMode} onChange={(e) => setTheme(e.target.value)} - err={error} + err={unauthorized ? '' : error} />
diff --git a/frontend/src/pages/_app.js b/frontend/src/pages/_app.js index e013c64..115f47f 100644 --- a/frontend/src/pages/_app.js +++ b/frontend/src/pages/_app.js @@ -2,6 +2,7 @@ import React from 'react' import ThemeProvider from "../theme/ThemeProvider"; import GlobalStyle from "../theme/GlobalStyle"; import styled from "styled-components"; +import Head from "next/head"; const Main = styled.div` margin-top: 10vh; @@ -11,6 +12,31 @@ const Main = styled.div` const App = ({ Component, pageProps }) => ( + + + + + + + + + ctrl-v | a modern, open-source pastebin +