diff options
-rw-r--r-- | apps/Notes/components/Import.js | 104 | ||||
-rw-r--r-- | apps/Notes/components/List.js | 4 | ||||
-rw-r--r-- | apps/Notes/components/NoteView.js | 6 | ||||
-rw-r--r-- | apps/Notes/helpers/sortNotes.js | 0 | ||||
-rwxr-xr-x | styles/_reset.scss | 8 |
5 files changed, 112 insertions, 10 deletions
diff --git a/apps/Notes/components/Import.js b/apps/Notes/components/Import.js index 6182ca6..71c08d6 100644 --- a/apps/Notes/components/Import.js +++ b/apps/Notes/components/Import.js @@ -1,10 +1,85 @@ +import React, {useState} from 'react' +import fetchJson from 'lib/fetchJson' +import useNotes from '../hooks/useNotes' +import {faCheck, faTimes} from '@fortawesome/free-solid-svg-icons' +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome' + const Import = ({action, setAction}) => { + const [files, setFiles] = useState() + const [done, setDone] = useState([]) + const {mutateNotes} = useNotes() + + const state = i => done[i] && <span><FontAwesomeIcon icon={done[i] === 1 ? faCheck : faTimes} /></span> + + const readFileAsText = (file) => new Promise((resolve,reject) => { + let fr = new FileReader() + + fr.onload = () => resolve(fr.result) + fr.onerror = () => reject(fr) + + fr.readAsText(file) + }) + + const handleImport = async e => { + e.preventDefault(); + + Array.from(files).forEach(async (file, i) => { + const title = file.name.replace(/\.[^/.]+$/, "") + const content = await readFileAsText(file); + + try { + const notes = await fetchJson('/api/notes', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({title, content}), + }) + if (i === files.length - 1) await mutateNotes(notes) + setDone((prev) => ({...prev, [i]: 1})) + } catch (e) { + setDone((prev) => ({...prev, [i]: 0})) + } + }) + } + + const handleChange = e => { + setFiles(e.currentTarget.files) + setDone([]) + } + return ( <section> <div className='window__submenu'> <div onClick={() => { setAction('') }}>Back</div> - <div>From txt</div> - <div>From JSON</div> + </div> + <div className='window__scroll'> + <form onSubmit={handleImport}> + Import new notes: + <div> + <label className="window__button"> + Choose files + <input + name="import" + type="file" + multiple="multiple" + accept="text/plain" + onChange={handleChange} + /> + </label> + </div> + {files && ( + <> + <p>Notes to import:</p> + <ul> + {[...files].map((f, i) => <li key={f.name}>{f.name} {state(i)}</li>)} + </ul> + { + done.length === 0 + ? <input type="submit" value="Import" className="window__button" /> + : <p>Import finished.<br/><br/>Go back to notes list or choose other notes to import.</p> + } + </> + )} + </form> </div> <style jsx>{` section { @@ -17,6 +92,31 @@ const Import = ({action, setAction}) => { left: 0; animation: fade-in .3s; } + + form { + padding: 1em; + } + + input[type=file] { + display: none; + } + + label { + display: inline-block; + cursor: pointer; + } + + ul { + list-style: disc inside none; + } + + li { + padding: .25em; + } + + p { + padding: 1em 0; + } `}</style> </section> ) diff --git a/apps/Notes/components/List.js b/apps/Notes/components/List.js index a4e0e8f..ec19639 100644 --- a/apps/Notes/components/List.js +++ b/apps/Notes/components/List.js @@ -30,8 +30,8 @@ const List = () => { <> <div className='window__submenu'> <div onClick={() => setAction('addNote')}>New note</div> - {/*<div onClick={() => setAction('import')}>Import</div> - <div onClick={() => {}}>Export</div>*/} + <div onClick={() => setAction('import')}>Import</div> + <div onClick={() => {}}>Export</div> </div> <table className="list"> <thead> diff --git a/apps/Notes/components/NoteView.js b/apps/Notes/components/NoteView.js index 83b1a2a..1735579 100644 --- a/apps/Notes/components/NoteView.js +++ b/apps/Notes/components/NoteView.js @@ -26,8 +26,8 @@ const NoteView = ({fetchedNote, setFetchedNote, setAction}) => { </div> <div className='window__scroll'> - <h2 className='selectable'>{title}</h2> - <p className='selectable'>{content}</p> + <h2>{title}</h2> + <p>{content}</p> </div> <style jsx>{` section { @@ -50,11 +50,13 @@ const NoteView = ({fetchedNote, setFetchedNote, setAction}) => { font-size: 1.25em; font-weight: 600; padding: 1rem; + user-select: text; } p { padding: 0 1rem 1rem; white-space: pre-line; + user-select: text; } `}</style> </section> diff --git a/apps/Notes/helpers/sortNotes.js b/apps/Notes/helpers/sortNotes.js deleted file mode 100644 index e69de29..0000000 --- a/apps/Notes/helpers/sortNotes.js +++ /dev/null diff --git a/styles/_reset.scss b/styles/_reset.scss index c979f31..a5f98fb 100755 --- a/styles/_reset.scss +++ b/styles/_reset.scss @@ -21,10 +21,10 @@ time, mark, audio, video { font-size: 100%; font: inherit; vertical-align: baseline; - // moz-user-select: none; - // webkit-user-select: none; - // ms-user-select: none; - // user-select: none; + moz-user-select: none; + webkit-user-select: none; + ms-user-select: none; + user-select: none; } article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { |