diff --git a/client/App.jsx b/client/App.jsx index c9b1e1c..1862db4 100644 --- a/client/App.jsx +++ b/client/App.jsx @@ -1,10 +1,12 @@ import React from 'react'; + +// importing child components import MainContainer from './src/containers/MainContainer/MainContainer.jsx'; const App = () => ( -
+
); -export default App; \ No newline at end of file +export default App; diff --git a/client/src/components/AddSnippet/AddSnippet.jsx b/client/src/components/AddSnippet/AddSnippet.jsx index 7171ba7..e8edda5 100644 --- a/client/src/components/AddSnippet/AddSnippet.jsx +++ b/client/src/components/AddSnippet/AddSnippet.jsx @@ -1,13 +1,23 @@ +import React, { useState } from 'react'; + +// importing child components +import SaveModal from '../../components/AddSnippet/SaveModal.jsx'; +import TagInput from '../../components/ui/TagInput/TagInput'; + +// importing external functionality import CodeMirror from '@uiw/react-codemirror'; import { markdown, markdownLanguage } from '@codemirror/lang-markdown'; import { languages } from '@codemirror/language-data'; import { langs } from '@uiw/codemirror-extensions-langs'; -import styles from './AddSnippet.module.scss'; -import React, { useState } from 'react'; -import SaveModal from '../../components/AddSnippet/SaveModal.jsx'; -import TagInput from '../../components/ui/TagInput/TagInput'; + +// importing utils import Modal from 'react-bootstrap/Modal'; import Button from 'react-bootstrap/Button'; + +// importing styles +import styles from './AddSnippet.module.scss'; + +// importing data import { LANGUAGES } from '../../data/data.js'; const AddSnippet = ({ closeModal }) => { @@ -47,11 +57,14 @@ const AddSnippet = ({ closeModal }) => { console.log(err); console.log('failed saving snippet'); }); +<<<<<<< HEAD +======= // setTitle(''); // setLanguage(''); // setComments(''); // setStoredCode(''); +>>>>>>> dev } // wrapper function for setTags to send to TagInput @@ -60,18 +73,21 @@ const AddSnippet = ({ closeModal }) => { } return ( -
-
+
+
closeModal(false)} - size="xl" - aria-labelledby="contained-modal-title-vcenter" - centered - > + size='xl' + aria-labelledby='contained-modal-title-vcenter' + centered> +<<<<<<< HEAD + +======= +>>>>>>> dev Add a snippet @@ -84,9 +100,14 @@ const AddSnippet = ({ closeModal }) => { value={title} onChange={(e) => { setTitle(e.target.value); +<<<<<<< HEAD + }}> + {error && Title is required!} +======= }} > {error && Title is required!} +>>>>>>> dev

@@ -94,8 +115,7 @@ const AddSnippet = ({ closeModal }) => { { {openModal && } diff --git a/client/src/components/AddSnippet/SaveModal.jsx b/client/src/components/AddSnippet/SaveModal.jsx index d5c8e25..43a8625 100644 --- a/client/src/components/AddSnippet/SaveModal.jsx +++ b/client/src/components/AddSnippet/SaveModal.jsx @@ -1,13 +1,7 @@ -import React, { useState} from 'react'; -import Modal from 'react-bootstrap/Modal'; +import React from 'react'; function SaveModal() { - - return ( -
- You have successfully saved a snippet! -
- ) + return
You have successfully saved a snippet!
; } export default SaveModal; diff --git a/client/src/components/SnippetDisplay/SnippetDisplay.jsx b/client/src/components/SnippetDisplay/SnippetDisplay.jsx index 6d0b593..6c8a8d5 100644 --- a/client/src/components/SnippetDisplay/SnippetDisplay.jsx +++ b/client/src/components/SnippetDisplay/SnippetDisplay.jsx @@ -1,14 +1,18 @@ import React, { useState } from 'react'; -// import Snippet from + +// importing child components +import TagInput from '../../components/ui/TagInput/TagInput'; + +// importing external functionality import { CopyToClipboard } from 'react-copy-to-clipboard'; import CodeMirror from '@uiw/react-codemirror'; import styles from './SnippetDisplay.module.scss'; import { langs } from '@uiw/codemirror-extensions-langs'; -import TagInput from '../../components/ui/TagInput/TagInput'; + +// importing utils import { Card, Button } from 'react-bootstrap'; + const SnippetDisplay = ({ selectedSnippet, getSnippet }) => { - // indSnippet = this.props - // create delete method using fetch request let snippetTitle = selectedSnippet.title ? selectedSnippet.title : ''; let snippetLanguage = selectedSnippet.language ? selectedSnippet.language @@ -21,17 +25,11 @@ const SnippetDisplay = ({ selectedSnippet, getSnippet }) => { : ''; let snippetTagList = selectedSnippet.tags ? selectedSnippet.tags : []; - // create a state variable for each passed down state and the its setState function - // const [title, setTitle] = useState(snippetTitle); - // const [language, setLanguage] = useState(snippetLanguage); - // const [comments, setComments] = useState(snippetComments); - // const [storedCode, setStoredCode] = useState(snippetStoredCode); - // const [tagList, setTags] = useState(snippetTagList); const [editButtonState, setEditButtonState] = useState(false); const deleteSnippet = (id) => { - fetch(`http://localhost:3000/snippets?id=${id}`, { - method: 'DELETE' + fetch(`/snippets?id=${id}`, { + method: 'DELETE', }) .then((response) => { if (response.ok) { @@ -42,7 +40,7 @@ const SnippetDisplay = ({ selectedSnippet, getSnippet }) => { return { log: `SnippetDisiplay.deleteSnippet: Error: ${err}`, status: err.status || 500, - message: 'There was an error deleting snippet.' + message: 'There was an error deleting snippet.', }; }); }; @@ -56,13 +54,14 @@ const SnippetDisplay = ({ selectedSnippet, getSnippet }) => { comments: snippetComments, storedCode: snippetStoredCode, tags: snippetTagList, - language: snippetLanguage + language: snippetLanguage, }; // within fetch request (post) // body: JSON.stringify(created object) + fetch(`/snippets?id=${id}`, { method: 'PUT', - body: JSON.stringify(updatedSnippet) + body: JSON.stringify(updatedSnippet), }) .then((response) => { response.json(); @@ -72,47 +71,45 @@ const SnippetDisplay = ({ selectedSnippet, getSnippet }) => { return { log: `SnippetDisplay.editSnippet: Error: ${err}`, status: err.status || 500, - message: 'There was an error editing code snippet.' + message: 'There was an error editing code snippet.', }; }); }; // copy code state + // copy code state const [copied, setCopied] = useState(false); const checkEdit = () => { if (editButtonState === true) { return (
-
- Title: +
+ Title: { snippetTitle = e.target.value; - }} - > + }}> - Language: + Language: { snippetLanguage = e.target.value; - }} - > + }}> - Comments: + Comments: { snippetComments = e.target.value; - }} - > + }}> (snippetTagList = e)} tags={snippetTagList} /> @@ -121,28 +118,25 @@ const SnippetDisplay = ({ selectedSnippet, getSnippet }) => { {\n console.log(\'Hello World!)\n}'} - onChange={(e) => (snippetStoredCode = e)} - > + onChange={(e) => (snippetStoredCode = e)}> setCopied(true)} - > + onCopy={() => setCopied(true)}>
@@ -152,40 +146,38 @@ const SnippetDisplay = ({ selectedSnippet, getSnippet }) => { if (editButtonState === false) { return (
-
-

+

+

{' '} - Title: {snippetTitle} + Title: {snippetTitle}

-

+

{' '} Language: {snippetLanguage}

-

+

{' '} Comments: {snippetComments}

- + {/*
{renderTags()}
*/}
{\n console.log(\'Hello World!)\n}'} options={{ - readOnly: true + readOnly: true, }} - onChange={(e) => (snippetStoredCode = e)} - > + onChange={(e) => (snippetStoredCode = e)}> setCopied(true)} - > - + onCopy={() => setCopied(true)}> +
@@ -194,31 +186,29 @@ const SnippetDisplay = ({ selectedSnippet, getSnippet }) => { }; return ( - <> + {checkEdit()}
- +
); }; diff --git a/client/src/components/ui/TagInput/TagInput.jsx b/client/src/components/ui/TagInput/TagInput.jsx index 44f4a78..67a5a6a 100644 --- a/client/src/components/ui/TagInput/TagInput.jsx +++ b/client/src/components/ui/TagInput/TagInput.jsx @@ -1,9 +1,14 @@ -import React, { useEffect } from 'react'; -import { TAGS } from '../../../data/data'; -import styles from './TagInput.module.scss'; +import React, { useState, useEffect } from 'react'; + +// importing utils import { WithContext as ReactTags } from 'react-tag-input'; import PropTypes from 'prop-types'; +// importing data +import { TAGS } from '../../../data/data'; + +// importing styles + const suggestions = TAGS.map((tag) => { return { id: tag, @@ -19,8 +24,7 @@ const KeyCodes = { const delimiters = [KeyCodes.comma, KeyCodes.enter]; const TagInput = (props) => { - - const [tags, setTags] = React.useState([]); + const [tags, setTags] = useState([]); const handleDelete = (i) => { setTags(tags.filter((tag, index) => index !== i)); diff --git a/client/src/components/ui/TagInput/TagInput.module.scss b/client/src/components/ui/TagInput/TagInput.module.scss deleted file mode 100644 index e69de29..0000000 diff --git a/client/src/containers/MainContainer/MainContainer.jsx b/client/src/containers/MainContainer/MainContainer.jsx index 2954daf..73950ba 100644 --- a/client/src/containers/MainContainer/MainContainer.jsx +++ b/client/src/containers/MainContainer/MainContainer.jsx @@ -1,14 +1,17 @@ import React from 'react'; + +// importing child components import Sidebar from '../Sidebar/Sidebar.jsx'; -import styles from './MainContainer.module.scss'; +// importing styles +import styles from './MainContainer.module.scss'; -const MainContainer = () =>{ - return ( +const MainContainer = () => { + return (
- ); -} + ); +}; -export default MainContainer; \ No newline at end of file +export default MainContainer; diff --git a/client/src/containers/Sidebar/Sidebar.jsx b/client/src/containers/Sidebar/Sidebar.jsx index 7177f59..29125c7 100644 --- a/client/src/containers/Sidebar/Sidebar.jsx +++ b/client/src/containers/Sidebar/Sidebar.jsx @@ -1,15 +1,23 @@ import React, { useState, useEffect } from 'react'; + +// importing child components import SnippetDisplay from '../../components/SnippetDisplay/SnippetDisplay.jsx'; import AddSnippet from '../../components/AddSnippet/AddSnippet.jsx'; -import styles from './Sidebar.module.scss'; import SnippetsRadioList from './SnippetsRadioList/SnippetsRadioList.jsx'; + +// importing utils import { Card, Spinner } from 'react-bootstrap'; + +// importing styles +import styles from './Sidebar.module.scss'; + +// importing assets import arrow from '../../assets/arrow.png'; import img from '../../assets/star nose mole.jpeg'; const Sidebar = () => { const [snippets, setSnippets] = useState([]); - const [selectedSnippet, setSelectedSnippet] = useState({}); + const [selectedSnippet, setSelectedSnippet] = useState(); const [openModal, setOpenModal] = useState(false); const [collapse, setCollapse] = useState(false); const [loading, setLoading] = useState(true); @@ -17,49 +25,43 @@ const Sidebar = () => { // getSnippet func const getSnippet = () => { setLoading(true); - fetch('http://localhost:3000/snippets') + fetch('/snippets') .then((res) => res.json()) .then((res) => { - console.log('res', res); - // moved setSnippets to outside of for loop so we arent re-rendering each time a snippet is added to state const newSnippetArray = []; - for (const snippet of res.snippets) newSnippetArray.push(snippet); + + for (const snippet of res.snippets) { + newSnippetArray.push(snippet); + } setSnippets(newSnippetArray); setLoading(false); }) .catch((error) => console.log('Get request failed', error)); }; - - // renderTags function - const renderTabs = () => { - const tabs = []; - - for (let i = 0; i < snippets.length; i++) { - tabs.push(); - } - - return tabs; - }; + + useEffect(() => getSnippet(), []); // wrapper to send to our snippets radio list for updating selected snippet. probably not 100% needed, but want to be able to console log from Sidebar const setSelectedSnippetWrapper = (e) => { setSelectedSnippet(e); }; - // get data from backend at first page load - useEffect(() => getSnippet(), []); const toggleSidebar = () => { setCollapse(() => !collapse); }; return ( - <> + + {/*----- SIDE BAR -----*/}

Code Snippets

+ + {/* Changes the collapse state, which will render/unrender the sidebar*/} +
+ + {/* Renders the list of snippets fetched from DB */} + + {/* Animation while app is fetching data from DB */}
- {/* render our snippet list, pass down snippets and function to update selectedSnippet */} {loading && (
- +
)} { />
- -

Click me to add a new snippet!

+ +

+ Click me to add a new snippet! +

-
+ + {/*----- ADD SNIPPET MODAL -----*/} + {openModal && } + + {/*----- SNIPPET DISPLAY -----*/} +
- {snippets && ( + }`}> + {selectedSnippet && ( )}
- +
); }; diff --git a/client/src/containers/Sidebar/SnippetsRadioList/SnippetsRadioList.jsx b/client/src/containers/Sidebar/SnippetsRadioList/SnippetsRadioList.jsx index 5fae115..6a9a805 100644 --- a/client/src/containers/Sidebar/SnippetsRadioList/SnippetsRadioList.jsx +++ b/client/src/containers/Sidebar/SnippetsRadioList/SnippetsRadioList.jsx @@ -1,6 +1,10 @@ +import React, { Fragment } from 'react'; + +// importing utils import PropTypes from 'prop-types'; + +// importing styles import styles from './SnippetsRadioList.module.scss'; -import { Fragment } from 'react'; function SnippetsRadioList(props) { // call passed in function on changed button, should find a way to do this without having to iterate through snippet array. store the snippet on the input itself somehow? @@ -16,59 +20,40 @@ function SnippetsRadioList(props) { if (props.snippets) { props.snippets.forEach((el, i) => { - const currButton = - i === 0 ? ( - - - -
-
- ) : ( - - - -
-
- ); + const currButton = ( + + + +
+
+ ); toggleButtons.push(currButton); }); } return ( - <> +
onChangeValue(e)} - > + onChange={(e) => { + onChangeValue(e); + }}> {toggleButtons}
- +
); } diff --git a/server/server.js b/server/server.js index 528aa96..9f77e1b 100644 --- a/server/server.js +++ b/server/server.js @@ -1,4 +1,3 @@ -const path = require('path'); const express = require('express'); const mongoose = require('mongoose'); const cors = require('cors');