aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/Notes/Notes.module.scss10
-rw-r--r--apps/Notes/components/Actions.js2
-rw-r--r--apps/Notes/components/Export.js47
-rw-r--r--apps/Notes/components/List.js98
-rw-r--r--apps/Notes/components/ListItem.js34
-rw-r--r--apps/Notes/components/NoteEdit.js17
-rw-r--r--apps/Notes/components/NoteView.js3
-rw-r--r--apps/Notes/components/Splash.js4
-rw-r--r--apps/Notes/helpers/export.js32
-rw-r--r--apps/Notes/helpers/noteActions.js1
10 files changed, 118 insertions, 130 deletions
diff --git a/apps/Notes/Notes.module.scss b/apps/Notes/Notes.module.scss
index 2e3c68f..fba396a 100644
--- a/apps/Notes/Notes.module.scss
+++ b/apps/Notes/Notes.module.scss
@@ -29,7 +29,7 @@
min-width: 10em;
white-space: nowrap;
padding-bottom: .5em;
- cursor: pointer;
+ // cursor: pointer;
line-height: 1.1em;
&:first-of-type {
@@ -50,10 +50,12 @@
&:first-of-type {
width: 99%;
display: flex;
- padding-right: 1em;
+ margin-right: 1em;
+ // display:inline-block;
& > span:nth-child(1) {
text-overflow: ellipsis;
+ overflow: hidden;
flex-grow: 1;
}
@@ -73,7 +75,7 @@
&:hover {
background: #eee;
border-radius: .5em;
- cursor: pointer;
+ // cursor: pointer;
& > td:first-of-type > span:nth-child(n+2){
color: #666;
@@ -216,7 +218,7 @@
label {
display: inline-block;
- cursor: pointer;
+ // cursor: pointer;
}
li {
diff --git a/apps/Notes/components/Actions.js b/apps/Notes/components/Actions.js
index 1f5d680..9591cfa 100644
--- a/apps/Notes/components/Actions.js
+++ b/apps/Notes/components/Actions.js
@@ -16,13 +16,11 @@ const Actions = ({
)
case 'addNote': return (
<NoteEdit
- action={action}
setAction={setAction}
/>
)
case 'editNote': return (
<NoteEdit
- action={action}
setAction={setAction}
fetchedNote={fetchedNote}
/>
diff --git a/apps/Notes/components/Export.js b/apps/Notes/components/Export.js
index f281d1a..7232632 100644
--- a/apps/Notes/components/Export.js
+++ b/apps/Notes/components/Export.js
@@ -1,45 +1,11 @@
import styles from '../Notes.module.scss'
import React, {useState} from 'react'
import useNotes from '../hooks/useNotes'
-import fetchJson from 'lib/fetchJson'
-import JSZip from 'jszip'
-import saveFile from 'helpers/saveFile'
-import filename from '../helpers/fileName'
-// import {state, color, handleImport, handleChange} from '../helpers/import'
+import {handleSelect, handleSelectAll, handleExport} from '../helpers/export'
const Export = ({setAction}) => {
const {notes} = useNotes()
const [ids, setIds] = useState(notes.map(n => n.noteId))
- // const [files, setFiles] = useState()
- // const [done, setDone] = useState([])
-
- const handleSelect = id => {
- ids.includes(id)
- ? setIds(ids.filter(i => i !== id))
- : setIds([...ids, id])
- }
-
- const handleSelectAll = e => {
- if (e.target.checked) {
- setIds(notes.map(n => n.noteId))
- } else {
- setIds([])
- }
- }
-
- const handleExport = e => {
- e.preventDefault()
- const zip = new JSZip()
-
- Promise.all(ids.map(async id => {
- const title = notes.find(n => n.noteId === id).title
- const {content} = await fetchJson(`/api/note/${id}`)
- zip.folder('notes').file(filename(title), content, {binary: true})
- })).then(() => {
- zip.generateAsync({type:"blob"})
- .then(c => saveFile(c, 'notes.zip', 'application/zip'))
- })
- }
if (!notes) return null
@@ -54,11 +20,16 @@ const Export = ({setAction}) => {
className="window__button"
type="submit"
value="Export"
- onClick={handleExport}
+ onClick={e => handleExport(e, ids, notes)}
/>
<p>Notes to export:</p>
<div className={`${styles.export__select}`}>
- <input type="checkbox" name='selectAll' onChange={handleSelectAll} checked={notes.length === ids.length} />
+ <input
+ type="checkbox"
+ name='selectAll'
+ onChange={e => handleSelectAll(e, notes, setIds)}
+ checked={notes.length === ids.length}
+ />
<label htmlFor='selectAll'>Select all</label>
</div>
{notes.map(note => (
@@ -68,7 +39,7 @@ const Export = ({setAction}) => {
name={note.noteId}
value={note.noteId}
checked={ids.includes(note.noteId)}
- onChange={() => handleSelect(note.noteId)}
+ onChange={() => handleSelect(note.noteId, ids, setIds)}
/>
<label htlmfor={note.noteId}>
{note.title}
diff --git a/apps/Notes/components/List.js b/apps/Notes/components/List.js
index 0f6221e..54f66b5 100644
--- a/apps/Notes/components/List.js
+++ b/apps/Notes/components/List.js
@@ -1,5 +1,5 @@
import styles from '../Notes.module.scss'
-import React, {useState} from 'react'
+import React, {useState, useEffect} from 'react'
import useUser from 'lib/useUser'
import useNotes from '../hooks/useNotes'
import useSort from '../hooks/useSort'
@@ -10,65 +10,67 @@ import Splash from './Splash'
const List = () => {
const [fetchedNote, setFetchedNote] = useState()
const [action, setAction] = useState('')
+ const [loading, setLoading] = useState(false)
const {notes, error} = useNotes()
- const [sortedBy, sortBy, sortFn] = useSort(2)
+ const [sortedBy, sortBy, sortFn] = useSort(3)
const {user} = useUser({
redirectToLogin: true,
redirectToVerify: true,
})
- if (error) return <Splash type='connection' />
+ useEffect(() => {
+ setLoading(false)
+ }, [fetchedNote])
+ if (error) return <Splash type='connection' />
+ if (loading) return <Splash />
if (!user || !user.isLoggedIn || !user.isVerified || !notes || !sortFn) {
return <Splash />
}
return (
- <>
- {
- action === '' ? (
- <>
- <div className='window__submenu'>
- <div onClick={() => setAction('addNote')}>New note</div>
- <div onClick={() => setAction('importNotes')}>Import</div>
- <div onClick={() => setAction('exportNotes')}>Export</div>
- </div>
- <table className={styles.notesList}>
- <thead>
- <tr>
- <th onClick={() => sortBy(1)}>Title {sortedBy(1)}</th>
- <th onClick={() => sortBy(2)}>Created {sortedBy(2)}</th>
- <th onClick={() => sortBy(3)}>Modified {sortedBy(3)}</th>
- </tr>
- </thead>
- <tbody>
- {
- notes.length > 0
- ? (notes.sort(sortFn).map(note => (
- <ListItem
- key={note._id}
- note={note}
- setAction={setAction}
- setFetchedNote={setFetchedNote}
- />
- ))) : (
- <tr>
- <td>Your notes list is empty.</td>
- </tr>
- )}
- </tbody>
- </table>
- </>
- ) : (
- <Actions
- action={action}
- setAction={setAction}
- fetchedNote={fetchedNote}
- setFetchedNote={setFetchedNote}
- />
- )
- }
- </>
+ action === '' ? (
+ <>
+ <div className='window__submenu'>
+ <div onClick={() => setAction('addNote')}>New note</div>
+ <div onClick={() => setAction('importNotes')}>Import</div>
+ <div onClick={() => setAction('exportNotes')}>Export</div>
+ </div>
+ <table className={styles.notesList}>
+ <thead>
+ <tr>
+ <th onClick={() => sortBy(1)}>Title {sortedBy(1)}</th>
+ <th onClick={() => sortBy(2)}>Created {sortedBy(2)}</th>
+ <th onClick={() => sortBy(3)}>Modified {sortedBy(3)}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {
+ notes.length > 0
+ ? (notes.sort(sortFn).map(note => (
+ <ListItem
+ key={note._id}
+ note={note}
+ setAction={setAction}
+ setFetchedNote={setFetchedNote}
+ setLoading={setLoading}
+ />
+ ))) : (
+ <tr>
+ <td>Your notes list is empty.</td>
+ </tr>
+ )}
+ </tbody>
+ </table>
+ </>
+ ) : (
+ <Actions
+ action={action}
+ setAction={setAction}
+ fetchedNote={fetchedNote}
+ setFetchedNote={setFetchedNote}
+ />
+ )
)
}
diff --git a/apps/Notes/components/ListItem.js b/apps/Notes/components/ListItem.js
index caa22e9..0e34ffc 100644
--- a/apps/Notes/components/ListItem.js
+++ b/apps/Notes/components/ListItem.js
@@ -12,47 +12,37 @@ const datestring = date => {
d.getFullYear() + " " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2)
};
-const ListItem = ({note, setAction, setFetchedNote}) => {
+const ListItem = ({note, setAction, setFetchedNote, setLoading}) => {
const {mutateNotes} = useNotes()
const {setPopup} = useContext(Context)
const handleNoteAction = async (a, note, e) => {
if (e) e.stopPropagation()
+ setLoading(true)
await getNote(note, setFetchedNote, setPopup, () => setAction(a))
}
return (
- <tr className={styles.listItem} key={note._id}>
+ <tr
+ className={styles.listItem}
+ key={note._id}
+ onClick={() => handleNoteAction('showNote', note)}
+ >
<td
- onClick={() => handleNoteAction('showNote', note)}
>
<span>{`${note.title}`}</span>
- <span
- onClick={e => handleNoteAction('editNote', note, e)}
- >
+ <span onClick={e => handleNoteAction('editNote', note, e)}>
<FontAwesomeIcon icon={faEdit} />
</span>
- <span
- onClick={e => {e.stopPropagation(); exportNote(note)}}
- >
+ <span onClick={e => {e.stopPropagation(); exportNote(note)}}>
<FontAwesomeIcon icon={faDownload} />
</span>
- <span
- onClick={e => removeNote(e, note._id, mutateNotes, setPopup, setAction)}
- >
+ <span onClick={e => removeNote(e, note._id, mutateNotes, setPopup, setAction)}>
<FontAwesomeIcon icon={faTrash} />
</span>
</td>
- <td
- onClick={() => handleNoteAction('showNote', note)}
- >
- {datestring(note.created_at)}
- </td>
- <td
- onClick={() => handleNoteAction('showNote', note)}
- >
- {datestring(note.updated_at)}
- </td>
+ <td>{datestring(note.created_at)}</td>
+ <td>{datestring(note.updated_at)}</td>
</tr>
)
}
diff --git a/apps/Notes/components/NoteEdit.js b/apps/Notes/components/NoteEdit.js
index 42eee46..4e91654 100644
--- a/apps/Notes/components/NoteEdit.js
+++ b/apps/Notes/components/NoteEdit.js
@@ -1,29 +1,21 @@
import styles from '../Notes.module.scss'
-import React, {useState, useContext} from 'react'
+import React, {useContext} from 'react'
import Context from 'context';
-import fetchJson from 'lib/fetchJson'
import useNotes from '../hooks/useNotes'
import {addNote, updateNote} from '../helpers/noteActions.js'
-const NoteEdit = ({action, setAction, fetchedNote}) => {
- const [text, setText] = useState('')
+const NoteEdit = ({setAction, fetchedNote}) => {
const {mutateNotes} = useNotes()
- const [errorMsg, setErrorMsg] = useState('')
const {setPopup} = useContext(Context)
const handleSubmit = e => {
e.preventDefault()
+
fetchedNote
? updateNote(e, fetchedNote, mutateNotes, setAction, setPopup)
: addNote(e, mutateNotes, setAction, setPopup)
}
- // if (!fetchedNote) return <p>Loading...</p>
- // if (fetchedNote.error) {
- // setFetchedNote()
- // setAction('')
- // }
-
return (
<div className={styles.noteEdit}>
<h2>{fetchedNote ? 'Edit note:' : 'Add new note:'}</h2>
@@ -31,6 +23,7 @@ const NoteEdit = ({action, setAction, fetchedNote}) => {
<input
name='title'
type='text'
+ maxlength={1000}
placeholder='Title'
defaultValue={fetchedNote ? fetchedNote.title : ''}
/>
@@ -54,8 +47,6 @@ const NoteEdit = ({action, setAction, fetchedNote}) => {
/>
</div>
</form>
- <style jsx>{`
- `}</style>
</div>
)
}
diff --git a/apps/Notes/components/NoteView.js b/apps/Notes/components/NoteView.js
index 14ec045..29aba34 100644
--- a/apps/Notes/components/NoteView.js
+++ b/apps/Notes/components/NoteView.js
@@ -4,12 +4,13 @@ import Context from 'context';
import useNotes from '../hooks/useNotes'
import {removeNote, exportNote} from '../helpers/noteActions.js'
import copyToClipboard from '../helpers/copyToClipboard.js'
+import Splash from './Splash'
const NoteView = ({fetchedNote, setFetchedNote, setAction}) => {
const {mutateNotes} = useNotes()
const {setPopup} = useContext(Context)
- if (!fetchedNote) return <p>Loading...</p>
+ if (!fetchedNote) return <Splash />
if (fetchedNote.error) {
setFetchedNote()
setAction('')
diff --git a/apps/Notes/components/Splash.js b/apps/Notes/components/Splash.js
index bc52e1b..b17fa6b 100644
--- a/apps/Notes/components/Splash.js
+++ b/apps/Notes/components/Splash.js
@@ -1,7 +1,7 @@
import styles from '../Notes.module.scss'
import React from 'react'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { faBan, faSpinner } from '@fortawesome/free-solid-svg-icons'
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
+import {faBan, faSpinner} from '@fortawesome/free-solid-svg-icons'
const Splash = ({type}) => (
<div className={type === 'connection' ? styles.connection : styles.loader}>
diff --git a/apps/Notes/helpers/export.js b/apps/Notes/helpers/export.js
new file mode 100644
index 0000000..011dc18
--- /dev/null
+++ b/apps/Notes/helpers/export.js
@@ -0,0 +1,32 @@
+import fetchJson from 'lib/fetchJson'
+import JSZip from 'jszip'
+import saveFile from 'helpers/saveFile'
+import filename from '../helpers/fileName'
+
+export const handleSelect = (id, ids, setIds) => {
+ ids.includes(id)
+ ? setIds(ids.filter(i => i !== id))
+ : setIds([...ids, id])
+}
+
+export const handleSelectAll = (e, notes, setIds) => {
+ if (e.target.checked) {
+ setIds(notes.map(n => n.noteId))
+ } else {
+ setIds([])
+ }
+}
+
+export const handleExport = (e, ids, notes) => {
+ e.preventDefault()
+ const zip = new JSZip()
+
+ Promise.all(ids.map(async id => {
+ const title = notes.find(n => n.noteId === id).title
+ const {content} = await fetchJson(`/api/note/${id}`)
+ zip.folder('notes').file(filename(title), content, {binary: true})
+ })).then(() => {
+ zip.generateAsync({type:"blob"})
+ .then(c => saveFile(c, 'notes.zip', 'application/zip'))
+ })
+}
diff --git a/apps/Notes/helpers/noteActions.js b/apps/Notes/helpers/noteActions.js
index 9588150..7b51e20 100644
--- a/apps/Notes/helpers/noteActions.js
+++ b/apps/Notes/helpers/noteActions.js
@@ -1,5 +1,6 @@
import fetchJson from 'lib/fetchJson'
import filename from '../helpers/fileName'
+import saveFile from 'helpers/saveFile'
export const getNote = async (note, setFetchedNote, setPopup, callback) => {
try {