aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjackyzha0 <[email protected]>2020-07-18 14:51:54 -0700
committerjackyzha0 <[email protected]>2020-07-18 14:51:54 -0700
commitd80bc9f45c4ab06a8a8bc38fc436bb5345225514 (patch)
treee4d0317c70fe487ec85530b65e51982ead61e80a
parentrefactor renderers (diff)
downloadctrl-v-d80bc9f45c4ab06a8a8bc38fc436bb5345225514.tar.xz
ctrl-v-d80bc9f45c4ab06a8a8bc38fc436bb5345225514.zip
refactor newpaste
-rw-r--r--frontend/src/components/Inputs.js233
-rw-r--r--frontend/src/components/NewPaste.js187
-rw-r--r--frontend/src/components/Options.js36
-rw-r--r--frontend/src/helpers/httpHelper.js12
4 files changed, 206 insertions, 262 deletions
diff --git a/frontend/src/components/Inputs.js b/frontend/src/components/Inputs.js
index 08cf3fc..a9b08b7 100644
--- a/frontend/src/components/Inputs.js
+++ b/frontend/src/components/Inputs.js
@@ -15,43 +15,33 @@ const FlexChild = styled.div`
margin-left: 2em;
`
-class TitleInput extends React.Component {
- render() {
- return (
- <RelPositioning>
- <FloatingLabel
- label="title"
- id={this.props.id}
- value={this.props.value} />
- <input
- name="title"
- readOnly={this.props.readOnly}
- className="lt-shadow"
- placeholder="Title"
- id={this.props.id}
- type="text"
- autoFocus
- autoComplete="off"
- onChange={this.props.onChange}
- value={this.props.value} />
- <CharLimit
- content={this.props.value}
- maxLength={this.props.maxLength} />
- </RelPositioning>
- );
- }
+const TitleInput = (props) => {
+ return (
+ <RelPositioning>
+ <FloatingLabel
+ label="title"
+ id={props.id}
+ value={props.value} />
+ <input
+ name="title"
+ readOnly={props.readOnly}
+ className="lt-shadow"
+ placeholder="Title"
+ id={props.id}
+ type="text"
+ autoFocus
+ autoComplete="off"
+ onChange={props.onChange}
+ value={props.value} />
+ <CharLimit
+ content={props.value}
+ maxLength={props.maxLength} />
+ </RelPositioning>
+ );
}
-class PasteInput extends React.Component {
-
- constructor(props) {
- super(props)
-
- this.textArea = React.createRef()
- this.handleKeyDown = this.handleKeyDown.bind(this)
- }
-
- handleKeyDown(e) {
+const PasteInput = (props) => {
+ function handleKeyDown(e) {
if (e.keyCode === 9) { // tab was pressed
// prevent autofocus on next intput
@@ -61,96 +51,83 @@ class PasteInput extends React.Component {
const start = e.target.selectionStart
const end = e.target.selectionEnd
- this.props.insertTabCallback(start, end)
+ props.insertTabCallback(start, end)
// set cursor position to be at start
e.target.selectionEnd = end + 4;
}
}
- render() {
- return (
+ return (
+ <RelPositioning>
+ <FloatingLabel
+ label="content"
+ id={props.id}
+ value={props.content} />
+ <textarea
+ name="content"
+ readOnly={props.readOnly}
+ placeholder="Paste your text here"
+ value={props.content}
+ id={props.id}
+ required
+ onChange={props.onChange}
+ onKeyDown={handleKeyDown}
+ className="lt-shadow" />
+ <CharLimit
+ content={props.content}
+ maxLength={props.maxLength} />
+ </RelPositioning>
+ );
+}
+
+const PassInput = (props) => {
+ return (
+ <FlexChild>
<RelPositioning>
<FloatingLabel
- label="content"
- id={this.props.id}
- value={this.props.content} />
- <textarea
- name="content"
- readOnly={this.props.readOnly}
- placeholder="Paste your text here"
- value={this.props.content}
- id={this.props.id}
- required
- onChange={this.props.onChange}
- onKeyDown={this.handleKeyDown}
- className="lt-shadow" />
- <CharLimit
- content={this.props.content}
- maxLength={this.props.maxLength} />
+ label="password"
+ id={props.id}
+ value={props.value} />
+ <input
+ name="pass"
+ className="lt-shadow"
+ placeholder="password"
+ type="password"
+ autoComplete="off"
+ onChange={props.onChange}
+ value={props.value}
+ id={props.id} />
</RelPositioning>
- );
- }
-}
-
-class PassInput extends React.Component {
- render() {
- return (
- <FlexChild>
- <RelPositioning>
- <FloatingLabel
- label="password"
- id={this.props.id}
- value={this.props.value} />
- <input
- name="pass"
- className="lt-shadow"
- placeholder="password"
- type="password"
- autoComplete="off"
- onChange={this.props.onChange}
- value={this.props.value}
- id={this.props.id} />
- </RelPositioning>
- </FlexChild>
- );
- }
+ </FlexChild>
+ );
}
-class GenericDropdown extends React.Component {
-
- constructor(props) {
- super(props)
-
- this._onSelect = this._onSelect.bind(this)
- }
-
- _onSelect(option) {
- this.props.onChange({
+const GenericDropdown = (props) => {
+ function _onSelect(option) {
+ props.onChange({
target: {
- name: this.props.label,
+ name: props.label,
value: option.label
}
});
}
- render() {
- return (
- <FlexChild>
- <Dropdown
- options={this.props.options}
- onChange={this._onSelect}
- callBackRef={this.props.onChange}
- value={this.props.value}
- placeholder={this.props.placeholder}
- id={this.props.id} />
- <FloatingLabel
- label={this.props.label}
- id={this.props.id}
- value={this.props.value} />
- </FlexChild>
- );
- }
+ return (
+ <FlexChild>
+ <Dropdown
+ options={props.options}
+ onChange={_onSelect}
+ callBackRef={props.onChange}
+ value={props.value}
+ placeholder={props.placeholder}
+ id={props.id} />
+ <FloatingLabel
+ label={props.label}
+ id={props.id}
+ value={props.value} />
+ </FlexChild>
+ );
}
const ExpiryInput = (props) => {
@@ -210,27 +187,25 @@ const ThemeInput = (props) => {
);
}
-class PasteURLInput extends React.Component {
- render() {
- return (
- <FlexChild>
- <RelPositioning>
- <FloatingLabel
- label="url"
- id={this.props.id}
- value={this.props.id} />
- <input
- name="paste_url"
- className="lt-shadow"
- type="text"
- readOnly
- autoFocus
- id={this.props.id}
- value={this.props.fullURL} />
- </RelPositioning>
- </FlexChild>
- );
- }
+const PasteURLInput = ({id, fullURL}) => {
+ return (
+ <FlexChild>
+ <RelPositioning>
+ <FloatingLabel
+ label="url"
+ id={id}
+ value={id} />
+ <input
+ name="paste_url"
+ className="lt-shadow"
+ type="text"
+ readOnly
+ autoFocus
+ id={id}
+ value={fullURL} />
+ </RelPositioning>
+ </FlexChild>
+ );
}
export { TitleInput, PasteInput, PassInput, ExpiryInput, PasteURLInput, LangInput, ThemeInput } \ No newline at end of file
diff --git a/frontend/src/components/NewPaste.js b/frontend/src/components/NewPaste.js
index afe1fc3..9729655 100644
--- a/frontend/src/components/NewPaste.js
+++ b/frontend/src/components/NewPaste.js
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect, useState, useRef } from 'react';
import { TitleInput, PasteInput } from './Inputs'
import OptionsContainer from './Options'
import Error from './Err'
@@ -35,114 +35,85 @@ const PreviewWrapper = styled.div`
margin: 2em;
`
-class NewPaste extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- title: '',
- content: '',
- pass: '',
- language: LANGS.raw,
- expiry: '',
- hash: '',
- error: '',
- preview: false,
- };
-
- this.handleChange = this.handleChange.bind(this);
- this.handleSubmit = this.handleSubmit.bind(this);
- this.togglePreview = this.togglePreview.bind(this);
- this.renderPreview = this.renderPreview.bind(this);
- this.insertTab = this.insertTab.bind(this);
- this.ErrorLabel = React.createRef();
- }
-
- componentDidUpdate() {
- if (this.state.title === "") {
+const NewPaste = () => {
+ const [title, setTitle] = useState('');
+ const [content, setContent] = useState('');
+ const [pass, setPass] = useState('');
+ const [language, setLanguage] = useState(LANGS.raw);
+ const [expiry, setExpiry] = useState('');
+ const [hash, setHash] = useState('');
+ const [isPreview, setIsPreview] = useState(false);
+ const ErrorLabel = useRef(null);
+
+ useEffect(() => {
+ if (title === "") {
document.title = `ctrl-v`;
} else {
- document.title = `ctrl-v | ${this.state.title}`;
+ document.title = `ctrl-v | ${title}`;
}
- }
-
- handleChange(event) {
- const target = event.target;
- const name = target.name;
+ }, [title])
- this.setState({
- [name]: target.value
- });
- }
-
- togglePreview() {
- const state = this.state.preview
- this.setState({ preview: !state })
- }
-
- handleSubmit(event) {
- event.preventDefault();
+ function handleSubmit(e) {
+ e.preventDefault();
// prevent resubmission
- if (!this.state.hash) {
- PostNewPaste(this.state)
+ if (!hash) {
+ PostNewPaste(title, content, language, pass, expiry)
.then((response) => {
// on success, redir
- this.setState({ hash: response.data.hash })
+ setHash(response.data.hash)
}).catch((error) => {
const resp = error.response
// some weird err
if (resp !== undefined) {
const errTxt = `${resp.status}: ${resp.data}`
- this.ErrorLabel.current.showMessage(errTxt)
+ ErrorLabel.current.showMessage(errTxt)
} else {
// some weird err (e.g. network)
- this.ErrorLabel.current.showMessage(error)
+ ErrorLabel.current.showMessage(error)
}
});
}
}
- insertTab(start, end) {
- const oldContent = this.state.content
- this.setState({
- content: oldContent.substring(0, start) + ' ' + oldContent.substring(end)
- })
+ function insertTab(start, end) {
+ setContent(content.substring(0, start) + ' ' + content.substring(end))
}
- renderPreview() {
+ function renderPreview() {
const pasteInput = <PasteInput
- onChange={this.handleChange}
- insertTabCallback={this.insertTab}
- content={this.state.content}
+ onChange={(e) => { setContent(e.target.value) }}
+ insertTabCallback={insertTab}
+ content={content}
maxLength="100000"
id="pasteInput" />
- var preview
- switch (this.state.language) {
- case 'latex':
- preview =
- <PreviewWrapper>
- <Latex
- content={this.state.content} />
- </PreviewWrapper>
- break
- case 'markdown':
- preview =
- <PreviewWrapper>
- <Markdown
- content={this.state.content} />
- </PreviewWrapper>
- break
- default:
- preview =
- <CodeRenderer
- lang={this.state.language}
- theme='atom'
- content={this.state.content} />
- }
+ if (isPreview) {
+ var preview
+ switch (language) {
+ case 'latex':
+ preview =
+ <PreviewWrapper>
+ <Latex
+ content={content} />
+ </PreviewWrapper>
+ break
+ case 'markdown':
+ preview =
+ <PreviewWrapper>
+ <Markdown
+ content={content} />
+ </PreviewWrapper>
+ break
+ default:
+ preview =
+ <CodeRenderer
+ lang={language}
+ theme='atom'
+ content={content} />
+ }
- if (this.state.preview) {
return (
<Flex>
<FlexLeft>
@@ -160,33 +131,33 @@ class NewPaste extends React.Component {
}
}
- render() {
- return (
- <form onSubmit={this.handleSubmit}>
- <PasteModal hash={this.state.hash} />
- <TitleInput
- onChange={this.handleChange}
- value={this.state.title}
- maxLength="100"
- id="titleInput" />
- {this.renderPreview()}
- <OptionsContainer
- pass={this.state.pass}
- expiry={this.state.expiry}
- lang={this.state.language}
- onChange={this.handleChange} />
- <input className="lt-button lt-shadow lt-hover" type="submit" value="new paste" />
- <Button
- className="lt-shadow lt-hover"
- type="button"
- onClick={this.togglePreview} >
- preview
- </Button>
- <br />
- <Error ref={this.ErrorLabel} />
- </form>
- );
- }
+ return (
+ <form onSubmit={handleSubmit}>
+ <PasteModal hash={hash} />
+ <TitleInput
+ onChange={(e) => {setTitle(e.target.value)}}
+ value={title}
+ 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) }} />
+ <input className="lt-button lt-shadow lt-hover" type="submit" value="new paste" />
+ <Button
+ className="lt-shadow lt-hover"
+ type="button"
+ onClick={() => setIsPreview(!isPreview)}>
+ preview
+ </Button>
+ <br />
+ <Error ref={ErrorLabel} />
+ </form>
+ );
}
export default NewPaste \ No newline at end of file
diff --git a/frontend/src/components/Options.js b/frontend/src/components/Options.js
index 26391c1..09f92f3 100644
--- a/frontend/src/components/Options.js
+++ b/frontend/src/components/Options.js
@@ -14,25 +14,23 @@ const Flex = styled.div`
}
`
-class OptionsContainer extends React.Component {
- render() {
- return (
- <Flex>
- <PassInput
- value={this.props.pass}
- onChange={this.props.onChange}
- id="passwordInput" />
- <LangInput
- value={this.props.lang}
- onChange={this.props.onChange}
- id="langInput" />
- <ExpiryInput
- value={this.props.expiry}
- onChange={this.props.onChange}
- id="expiryInput" />
- </Flex>
- );
- }
+const OptionsContainer = ({pass, lang, expiry, onPassChange, onLangChange, onExpiryChange}) => {
+ return (
+ <Flex>
+ <PassInput
+ value={pass}
+ onChange={onPassChange}
+ id="passwordInput" />
+ <LangInput
+ value={lang}
+ onChange={onLangChange}
+ id="langInput" />
+ <ExpiryInput
+ value={expiry}
+ onChange={onExpiryChange}
+ id="expiryInput" />
+ </Flex>
+ );
}
export default OptionsContainer \ No newline at end of file
diff --git a/frontend/src/helpers/httpHelper.js b/frontend/src/helpers/httpHelper.js
index ca77ed7..99b9513 100644
--- a/frontend/src/helpers/httpHelper.js
+++ b/frontend/src/helpers/httpHelper.js
@@ -21,13 +21,13 @@ export function FetchPasswordPaste(hash, pass) {
})
}
-export function PostNewPaste(state) {
+export function PostNewPaste(title, content, language, pass, expiry) {
var bodyFormData = new FormData();
- bodyFormData.set('title', state.title);
- bodyFormData.set('content', state.content);
- bodyFormData.set('language', state.language);
- bodyFormData.set('password', state.pass);
- bodyFormData.set('expiry', parseExpiry(state.expiry));
+ bodyFormData.set('title', title);
+ bodyFormData.set('content', content);
+ bodyFormData.set('language', language);
+ bodyFormData.set('password', pass);
+ bodyFormData.set('expiry', parseExpiry(expiry));
return axios({
method: 'post',