aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/pages
diff options
context:
space:
mode:
authorjackyzha0 <[email protected]>2021-04-11 10:27:27 -0700
committerjackyzha0 <[email protected]>2021-04-11 10:27:27 -0700
commit0144bfc9cc6c616a00a8171f3950a75ec948427e (patch)
tree101d6c12471d411e9266cffa8e90176aff2e6fdb /frontend/src/pages
parentbase next bump (diff)
downloadctrl-v-0144bfc9cc6c616a00a8171f3950a75ec948427e.tar.xz
ctrl-v-0144bfc9cc6c616a00a8171f3950a75ec948427e.zip
base next refactor
Diffstat (limited to 'frontend/src/pages')
-rw-r--r--frontend/src/pages/[hash].js65
-rw-r--r--frontend/src/pages/_app.js23
-rw-r--r--frontend/src/pages/_document.js30
-rw-r--r--frontend/src/pages/index.js150
-rw-r--r--frontend/src/pages/raw/index.js14
5 files changed, 282 insertions, 0 deletions
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 ? <RenderDispatch
+ language={language}
+ content={content}
+ /> : <CodeRenderer
+ content={content}
+ lang={language}
+ theme={theme}
+ id="pasteInput" />
+ }
+
+ return (
+ <div>
+ <PasswordModal
+ hasPass={requiresAuth}
+ validPass={validPass}
+ value={enteredPass}
+ onChange={(e) => setEnteredPass(e.target.value)}
+ validateCallback={getWithPassword} />
+ <Text
+ label="title"
+ value={title}
+ id="titleInput"
+ readOnly />
+ {getDisplay()}
+ <PasteInfo
+ hash={props.hash}
+ lang={language}
+ theme={theme}
+ expiry={expiry}
+ toggleRenderCallback={() => setIsRenderMode(!isRenderMode)}
+ isRenderMode={isRenderMode}
+ onChange={(e) => setTheme(e.target.value)}
+ err={<Error ref={ErrorLabelRef} />}
+ />
+ </div>
+ );
+}
+
+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 }) => (
+ <ThemeProvider>
+ <GlobalStyle />
+ <Watermark/>
+ <Main id="appElement">
+ <Component {...pageProps} />
+ </Main>
+ </ThemeProvider>
+)
+
+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(<App {...props} />),
+ })
+
+ 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 = <Code
+ setContentCallback={setContent}
+ content={content}
+ maxLength="100000" />
+
+ if (isPreview) {
+ var preview
+ switch (language) {
+ case 'latex':
+ preview =
+ <PreviewWrapper>
+ <Latex
+ content={content} />
+ </PreviewWrapper>
+ break
+ case 'markdown':
+ preview =
+ <PreviewWrapper className='md' >
+ <Markdown
+ content={content} />
+ </PreviewWrapper>
+ break
+ default:
+ preview =
+ <CodeRenderer
+ lang={language}
+ theme='atom'
+ content={content} />
+ }
+
+ return (
+ <Flex>
+ <FlexLeft>
+ {pasteInput}
+ </FlexLeft>
+ <FlexRight className='preview' >
+ {preview}
+ </FlexRight>
+ </Flex>
+ );
+ } else {
+ return (
+ pasteInput
+ );
+ }
+ }
+
+ return (
+ <form onSubmit={handleSubmit}>
+ <PasteModal hash={hash} />
+ <Text
+ label="title"
+ onChange={(e) => {setTitle(e.target.value)}}
+ value={title}
+ autoFocus
+ maxLength="100"
+ id="titleInput" />
+ {renderPreview()}
+ <OptionsContainer
+ pass={pass}
+ expiry={expiry}
+ lang={language}
+ onPassChange={(e) => { setPass(e.target.value) }}
+ onLangChange={(e) => { setLanguage(e.target.value) }}
+ onExpiryChange={(e) => { setExpiry(e.target.value) }} />
+ <div>
+ <SubmitButton type="submit" value="new paste" />
+ {language !== 'detect' && <Button
+ secondary
+ type="button"
+ onClick={() => setIsPreview(!isPreview)}>
+ preview
+ </Button>}
+ </div>
+ <br />
+ <Error ref={ErrorLabel} />
+ </form>
+ );
+}
+
+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