aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/Notes/components/Export.js12
-rw-r--r--apps/Notes/components/Import.js15
-rw-r--r--apps/Notes/components/List.js18
-rw-r--r--apps/Notes/components/ListItem.js8
-rw-r--r--apps/Notes/components/NoteEdit.js16
-rw-r--r--apps/Notes/components/NoteView.js16
-rw-r--r--apps/Notes/helpers/copyToClipboard.js6
-rw-r--r--apps/Notes/helpers/export.js2
-rw-r--r--apps/Notes/helpers/import.js2
-rw-r--r--apps/Notes/helpers/noteActions.js32
-rw-r--r--apps/Settings/api.js10
-rw-r--r--apps/Settings/components/Settings.js64
-rw-r--r--apps/Settings/styles/Settings.module.scss18
-rw-r--r--components/App.js18
-rw-r--r--components/Form.js74
-rw-r--r--components/Header.js34
-rw-r--r--components/Layout.js34
-rw-r--r--components/Splash.js17
-rw-r--r--configs/appList.js (renamed from helpers/appList.js)0
-rw-r--r--configs/dbConnect.js (renamed from lib/dbConnect.js)6
-rw-r--r--configs/sendMail.js (renamed from lib/sendMail.js)0
-rw-r--r--configs/translations.js284
-rw-r--r--context/index.js3
-rw-r--r--helpers/crypt.js (renamed from lib/crypt.js)0
-rw-r--r--helpers/email.js8
-rw-r--r--helpers/fetchJson.js (renamed from lib/fetchJson.js)0
-rw-r--r--helpers/submitForm.js26
-rw-r--r--hocs/withSession.js (renamed from lib/withSession.js)0
-rw-r--r--hooks/useApps.js17
-rw-r--r--hooks/useMediaQuery.js19
-rw-r--r--hooks/useSettings.js50
-rw-r--r--hooks/useUser.js (renamed from lib/useUser.js)0
-rw-r--r--models/Note.js2
-rw-r--r--models/NoteList.js2
-rw-r--r--pages/_app.js14
-rw-r--r--pages/api/login.js4
-rw-r--r--pages/api/logout.js2
-rw-r--r--pages/api/note/[id].js4
-rw-r--r--pages/api/notes.js4
-rw-r--r--pages/api/register.js9
-rw-r--r--pages/api/settings.js4
-rw-r--r--pages/api/user.js4
-rw-r--r--pages/api/verify.js11
-rw-r--r--pages/index.js81
-rw-r--r--pages/login.js29
-rw-r--r--pages/register.js29
-rw-r--r--pages/verify.js42
-rw-r--r--styles/Main.module.scss94
-rw-r--r--styles/_window.scss32
49 files changed, 885 insertions, 291 deletions
diff --git a/apps/Notes/components/Export.js b/apps/Notes/components/Export.js
index e7966e4..0838cea 100644
--- a/apps/Notes/components/Export.js
+++ b/apps/Notes/components/Export.js
@@ -1,10 +1,12 @@
import styles from '../Notes.module.scss'
import React, {useState} from 'react'
+import useSettings from 'hooks/useSettings'
import useNotes from '../hooks/useNotes'
import {handleSelect, handleSelectAll, handleExport} from '../helpers/export'
const Export = ({setAction}) => {
const {notes} = useNotes()
+ const {t} = useSettings()
const [ids, setIds] = useState(notes.map(n => n.noteId))
const sortFn = (a, b) => new Date(b.updated_at) - new Date(a.updated_at)
@@ -13,17 +15,17 @@ const Export = ({setAction}) => {
return (
<section>
<div className='window__submenu'>
- <div onClick={() => {setAction('')}}>Back</div>
+ <div onClick={() => {setAction('')}}>{t('back')}</div>
</div>
<div className={`window__scroll ${styles.export}`}>
- <h3>Click to export your notes:</h3>
+ <h3>{t('notes_click_to_export')}</h3>
<input
className="window__button"
type="submit"
- value="Export"
+ value={t('export')}
onClick={e => handleExport(e, ids, notes)}
/>
- <p>Notes to export:</p>
+ <p>{t('notes_to_export')}</p>
<div className={styles.export__select}>
<input
type="checkbox"
@@ -31,7 +33,7 @@ const Export = ({setAction}) => {
onChange={e => handleSelectAll(e, notes, setIds)}
checked={notes.length === ids.length}
/>
- <label htmlFor='selectAll'>Select all</label>
+ <label htmlFor='selectAll'>{t('select_all')}</label>
</div>
<ul>
{notes.sort(sortFn).map(note => (
diff --git a/apps/Notes/components/Import.js b/apps/Notes/components/Import.js
index 700acb4..ad2b831 100644
--- a/apps/Notes/components/Import.js
+++ b/apps/Notes/components/Import.js
@@ -1,10 +1,11 @@
import styles from '../Notes.module.scss'
import React, {useState} from 'react'
-import fetchJson from 'lib/fetchJson'
+import useSettings from 'hooks/useSettings'
import useNotes from '../hooks/useNotes'
import {state, color, handleImport, handleChange} from '../helpers/import'
const Import = ({setAction}) => {
+ const {t} = useSettings()
const [files, setFiles] = useState()
const [done, setDone] = useState([])
const {mutateNotes} = useNotes()
@@ -12,14 +13,14 @@ const Import = ({setAction}) => {
return (
<section className={styles.import}>
<div className='window__submenu'>
- <div onClick={() => {setAction('')}}>Back</div>
+ <div onClick={() => {setAction('')}}>{t('back')}</div>
</div>
<div className='window__scroll'>
<form onSubmit={e => handleImport(e, files, mutateNotes, setDone)}>
- Import new notes:
+ {t('notes_import')}
<div>
<label className="window__button">
- Choose files
+ {t('choose_files')}
<input
name="import"
type="file"
@@ -31,14 +32,14 @@ const Import = ({setAction}) => {
</div>
{files && (
<>
- <p>Notes to import:</p>
+ <p>{t('notes_to_import')}</p>
<ul>
{[...files].map((f, i) => <li style={color(done[i])} key={f.name}>{f.name} {state(done[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>
+ ? <input type="submit" value={t('import')} className="window__button" />
+ : <p>{t('import_finished')}<br/><br/>{t('notes_import_go_back')}</p>
}
</>
)}
diff --git a/apps/Notes/components/List.js b/apps/Notes/components/List.js
index 1fd03af..9655d74 100644
--- a/apps/Notes/components/List.js
+++ b/apps/Notes/components/List.js
@@ -1,6 +1,7 @@
import styles from '../Notes.module.scss'
import React, {useState, useEffect} from 'react'
-import useUser from 'lib/useUser'
+import useUser from 'hooks/useUser'
+import useSettings from 'hooks/useSettings'
import useNotes from '../hooks/useNotes'
import useSort from '../hooks/useSort'
import ListItem from './ListItem'
@@ -13,6 +14,7 @@ const List = () => {
const [loading, setLoading] = useState(false)
const {notes, error} = useNotes()
const [sortedBy, sortBy, sortFn] = useSort(3)
+ const {t} = useSettings()
const {user} = useUser({
redirectToLogin: true,
redirectToVerify: true,
@@ -32,16 +34,16 @@ const List = () => {
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 onClick={() => setAction('addNote')}>{t('notes_new')}</div>
+ <div onClick={() => setAction('importNotes')}>{t('import')}</div>
+ <div onClick={() => setAction('exportNotes')}>{t('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>
+ <th onClick={() => sortBy(1)}>{t('title')} {sortedBy(1)}</th>
+ <th onClick={() => sortBy(2)}>{t('created')} {sortedBy(2)}</th>
+ <th onClick={() => sortBy(3)}>{t('modified')} {sortedBy(3)}</th>
</tr>
</thead>
<tbody>
@@ -57,7 +59,7 @@ const List = () => {
/>
))) : (
<tr>
- <td>Your notes list is empty.</td>
+ <td>{t('notes_list_empty')}</td>
</tr>
)}
</tbody>
diff --git a/apps/Notes/components/ListItem.js b/apps/Notes/components/ListItem.js
index 4a404db..4a2d6f6 100644
--- a/apps/Notes/components/ListItem.js
+++ b/apps/Notes/components/ListItem.js
@@ -1,8 +1,9 @@
import styles from '../Notes.module.scss'
import React from 'react'
import {getNote, exportNote, removeNote} from '../helpers/noteActions.js'
-import useNotes from '../hooks/useNotes'
+import useSettings from 'hooks/useSettings'
import usePopup from 'hooks/usePopup'
+import useNotes from '../hooks/useNotes'
import {faEdit, faDownload, faTrash } from '@fortawesome/free-solid-svg-icons'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
@@ -13,13 +14,14 @@ const datestring = date => {
};
const ListItem = ({note, setAction, setFetchedNote, setLoading}) => {
+ const {t} = useSettings()
const {setPopup} = usePopup()
const {mutateNotes} = useNotes()
const handleNoteAction = async (a, note, e) => {
if (e) e.stopPropagation()
setLoading(true)
- await getNote(note, setFetchedNote, setPopup, () => setAction(a))
+ await getNote(note, setFetchedNote, t, setPopup, () => setAction(a))
}
return (
@@ -36,7 +38,7 @@ const ListItem = ({note, setAction, setFetchedNote, setLoading}) => {
<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, t, setPopup, setAction)}>
<FontAwesomeIcon icon={faTrash} />
</span>
</td>
diff --git a/apps/Notes/components/NoteEdit.js b/apps/Notes/components/NoteEdit.js
index 40a33c0..f9cc3f2 100644
--- a/apps/Notes/components/NoteEdit.js
+++ b/apps/Notes/components/NoteEdit.js
@@ -1,24 +1,26 @@
import styles from '../Notes.module.scss'
import React from 'react'
-import useNotes from '../hooks/useNotes'
import usePopup from 'hooks/usePopup'
+import useSettings from 'hooks/useSettings'
+import useNotes from '../hooks/useNotes'
import {addNote, updateNote} from '../helpers/noteActions.js'
const NoteEdit = ({setAction, fetchedNote}) => {
- const {mutateNotes} = useNotes()
+ const {t} = useSettings()
const {setPopup} = usePopup()
+ const {mutateNotes} = useNotes()
const handleSubmit = e => {
e.preventDefault()
fetchedNote
- ? updateNote(e, fetchedNote, mutateNotes, setAction, setPopup)
- : addNote(e, mutateNotes, setAction, setPopup)
+ ? updateNote(e, fetchedNote, mutateNotes, setAction, t, setPopup)
+ : addNote(e, mutateNotes, setAction, t, setPopup)
}
return (
<div className={styles.noteEdit}>
- <h2>{fetchedNote ? 'Edit note:' : 'Add new note:'}</h2>
+ <h2>{fetchedNote ? t('notes_edit') : t('notes_add_new')}</h2>
<form onSubmit={handleSubmit}>
<input
name='title'
@@ -38,12 +40,12 @@ const NoteEdit = ({setAction, fetchedNote}) => {
className='window__button'
onClick={() => {setAction(fetchedNote ? 'showNote' : '')}}
>
- Cancel
+ {t('cancel')}
</span>
<input
className='window__button'
type="submit"
- value={fetchedNote ? 'Save note' : 'Add note'}
+ value={fetchedNote ? t('notes_save') : t('notes_add')}
/>
</div>
</form>
diff --git a/apps/Notes/components/NoteView.js b/apps/Notes/components/NoteView.js
index 6926b09..02937f8 100644
--- a/apps/Notes/components/NoteView.js
+++ b/apps/Notes/components/NoteView.js
@@ -1,12 +1,14 @@
import styles from '../Notes.module.scss'
import React from 'react';
-import useNotes from '../hooks/useNotes'
+import useSettings from 'hooks/useSettings'
import usePopup from 'hooks/usePopup'
+import useNotes from '../hooks/useNotes'
import {removeNote, exportNote} from '../helpers/noteActions.js'
import copyToClipboard from '../helpers/copyToClipboard.js'
import Splash from 'components/Splash'
const NoteView = ({fetchedNote, setFetchedNote, setAction}) => {
+ const {t} = useSettings()
const {setPopup} = usePopup()
const {mutateNotes} = useNotes()
@@ -21,19 +23,17 @@ const NoteView = ({fetchedNote, setFetchedNote, setAction}) => {
return (
<section className={styles.noteView}>
<div className='window__submenu'>
- <div onClick={() => {setFetchedNote(); setAction('')}}>Back</div>
- <div onClick={() => copyToClipboard(content, setPopup)}>Copy</div>
- <div onClick={() => {setAction('editNote')}}>Edit</div>
- <div onClick={() => exportNote(fetchedNote)}>Export</div>
- <div onClick={e => {removeNote(e, _id, mutateNotes, setPopup, setAction)}}>Remove</div>
+ <div onClick={() => {setFetchedNote(); setAction('')}}>{t('back')}</div>
+ <div onClick={() => copyToClipboard(content, t, setPopup)}>{t('copy')}</div>
+ <div onClick={() => {setAction('editNote')}}>{t('edit')}</div>
+ <div onClick={() => exportNote(fetchedNote)}>{t('export')}</div>
+ <div onClick={e => {removeNote(e, _id, mutateNotes, t, setPopup, setAction)}}>{t('remove')}</div>
</div>
<div className='window__scroll'>
<h2>{title}</h2>
<p>{content}</p>
</div>
- <style jsx>{`
- `}</style>
</section>
)
}
diff --git a/apps/Notes/helpers/copyToClipboard.js b/apps/Notes/helpers/copyToClipboard.js
index 608d299..afaf7f6 100644
--- a/apps/Notes/helpers/copyToClipboard.js
+++ b/apps/Notes/helpers/copyToClipboard.js
@@ -1,15 +1,15 @@
-const copyToClipboard = (text, setPopup) => {
+const copyToClipboard = (text, t, setPopup) => {
navigator
.clipboard.writeText(text)
.then(() => {
setPopup({
- content: 'Note content was copied to clipboard',
+ content: t('notes_copy_success'),
time: 2000,
})
})
.catch(() => {
setPopup({
- content: 'Could not copy to clipboard',
+ content: t('notes_copy_error'),
time: 2000,
error: true
})
diff --git a/apps/Notes/helpers/export.js b/apps/Notes/helpers/export.js
index 011dc18..80fa100 100644
--- a/apps/Notes/helpers/export.js
+++ b/apps/Notes/helpers/export.js
@@ -1,4 +1,4 @@
-import fetchJson from 'lib/fetchJson'
+import fetchJson from 'helpers/fetchJson'
import JSZip from 'jszip'
import saveFile from 'helpers/saveFile'
import filename from '../helpers/fileName'
diff --git a/apps/Notes/helpers/import.js b/apps/Notes/helpers/import.js
index b05a458..c0c3714 100644
--- a/apps/Notes/helpers/import.js
+++ b/apps/Notes/helpers/import.js
@@ -1,4 +1,4 @@
-import fetchJson from 'lib/fetchJson'
+import fetchJson from 'helpers/fetchJson'
import {faCheck, faTimes} from '@fortawesome/free-solid-svg-icons'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
diff --git a/apps/Notes/helpers/noteActions.js b/apps/Notes/helpers/noteActions.js
index 4b47011..f67e7a4 100644
--- a/apps/Notes/helpers/noteActions.js
+++ b/apps/Notes/helpers/noteActions.js
@@ -1,8 +1,8 @@
-import fetchJson from 'lib/fetchJson'
-import filename from '../helpers/fileName'
+import fetchJson from 'helpers/fetchJson'
import saveFile from 'helpers/saveFile'
+import filename from '../helpers/fileName'
-export const getNote = async (note, setFetchedNote, setPopup, callback) => {
+export const getNote = async (note, setFetchedNote, t, setPopup, callback) => {
try {
const {content} = await fetchJson(`/api/note/${note.noteId}`)
setFetchedNote({ ...note, content})
@@ -10,14 +10,14 @@ export const getNote = async (note, setFetchedNote, setPopup, callback) => {
} catch (err) {
setFetchedNote()
setPopup({
- content: 'Could not open note',
+ content: t('notes_open_error'),
time: 2000,
error: true,
})
}
}
-export const addNote = async (e, mutateNotes, setAction, setPopup) => {
+export const addNote = async (e, mutateNotes, setAction, t, setPopup) => {
const content = e.currentTarget.content.value
const title = e.currentTarget.title.value
@@ -30,20 +30,20 @@ export const addNote = async (e, mutateNotes, setAction, setPopup) => {
})
)
setPopup({
- content: 'New note added',
+ content: t('notes_added'),
time: 2000,
})
setAction('')
} catch (e) {
setPopup({
- content: 'Could not save note',
+ content: t(notes_added_error),
time: 2000,
error: true,
})
}
}
-export const updateNote = async (e, note, mutateNotes, setAction, setPopup) => {
+export const updateNote = async (e, note, mutateNotes, setAction, t, setPopup) => {
const content = e.currentTarget.content.value
const title = e.currentTarget.title.value
const {_id, noteId} = note
@@ -57,20 +57,20 @@ export const updateNote = async (e, note, mutateNotes, setAction, setPopup) => {
})
)
setPopup({
- content: 'Note updated',
+ content: t('notes_updated'),
time: 2000,
})
setAction('')
} catch (e) {
setPopup({
- content: 'Could not update note',
+ content: t('notes_updated_error'),
time: 2000,
error: true,
})
}
}
-export const removeNote = (e, _id, mutateNotes, setPopup, setAction) => {
+export const removeNote = (e, _id, mutateNotes, t, setPopup, setAction) => {
e.stopPropagation()
const remove = async () => {
@@ -83,13 +83,13 @@ export const removeNote = (e, _id, mutateNotes, setPopup, setAction) => {
})
)
setPopup({
- content: 'Note was removed',
+ content: t('notes_removed'),
time: 2000,
})
setAction('')
} catch (err) {
setPopup({
- content: 'Could not remove note',
+ content: t('notes_removed_error'),
time: 2000,
error: true,
})
@@ -97,9 +97,9 @@ export const removeNote = (e, _id, mutateNotes, setPopup, setAction) => {
}
setPopup({
- content: 'Do you want to remove note?',
- yes: { label: 'Remove', action: remove },
- no: { label: 'Cancel', action: async () => {} },
+ content: t('notes_remove_confirm'),
+ yes: { label: t('remove'), action: remove },
+ no: { label: t('cancel'), action: async () => {} },
error: true,
})
}
diff --git a/apps/Settings/api.js b/apps/Settings/api.js
new file mode 100644
index 0000000..559486f
--- /dev/null
+++ b/apps/Settings/api.js
@@ -0,0 +1,10 @@
+import fetchJson from 'helpers/fetchJson'
+
+export const saveSettings = async (data) => {
+ fetchJson('/api/settings', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(data),
+ })
+}
+
diff --git a/apps/Settings/components/Settings.js b/apps/Settings/components/Settings.js
index 2d7f238..c09a1bd 100644
--- a/apps/Settings/components/Settings.js
+++ b/apps/Settings/components/Settings.js
@@ -1,64 +1,64 @@
import styles from '../styles/Settings.module.scss'
-import React, {useContext} from 'react'
-import fetchJson from 'lib/fetchJson'
-import useUser from 'lib/useUser'
-import usePopup from 'hooks/usePopup'
-import Context from 'context';
+import React from 'react'
import {close} from 'helpers/windowActions'
+import useUser from 'hooks/useUser'
+import usePopup from 'hooks/usePopup'
+import useSettings from 'hooks/useSettings'
+import useApps from 'hooks/useApps'
+import {saveSettings} from '../api'
const Settings = () => {
const {setPopup} = usePopup()
- const {settings: {theme, language}, setSettings, setApps} = useContext(Context)
+ const {setApps} = useApps()
+ const {settings: {theme, language}, setSettings, t} = useSettings()
const {user} = useUser()
const handleSave = e => {
e.preventDefault;
- try {
- fetchJson('/api/settings', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({_id: user._id, theme, language}),
- })
+ saveSettings({_id: user._id, theme, language})
+ .then(() => {
setPopup({
- content: 'Settings saved',
+ content: t('settings_saved'),
time: 2000,
})
close('Settings', setApps)
- } catch (err) {
+ })
+ .catch(() => {
setpopup({
- content: 'could not save settings',
+ content: t('settings_save_error'),
time: 2000,
error: true,
})
- }
+ })
}
return (
<div className={styles.settings}>
- <div>Language:</div>
+ <div>{t('language')}</div>
<div>
- <span className={styles.settings__active}>English</span>
+ {['en', 'pl', 'es', 'de'].map(l => (
+ <span
+ key={l}
+ className={language === l ? styles.settings__langactive : ''}
+ onClick={()=>{setSettings(prev => ({...prev, language: l}))}}
+ >{l.toUpperCase()}</span>
+ ))}
</div>
- <div>Theme: </div>
+ <div>{t('color_theme')}</div>
<div>
- <span
- onClick={()=>{setSettings({language, theme:'green'})}}
- className={theme === 'green' ? styles.settings__active : ''}
- />
- <span
- onClick={()=>{setSettings({language, theme:'blue'})}}
- className={theme === 'blue' ? styles.settings__active : ''}
- />
- <span
- onClick={()=>{setSettings({language, theme:'black'})}}
- className={theme === 'black' ? styles.settings__active : ''}
- />
+ {['green', 'blue', 'black'].map(c => (
+ <span
+ key={c}
+ onClick={()=>{setSettings(prev => ({...prev, theme: c}))}}
+ className={theme === c ? styles.settings__active : ''}
+ />
+ ))}
</div>
<input
type="button"
className="window__button"
- value="Save"
+ value={t('save')}
onClick={handleSave}
/>
</div>
diff --git a/apps/Settings/styles/Settings.module.scss b/apps/Settings/styles/Settings.module.scss
index 9edef38..0944dcc 100644
--- a/apps/Settings/styles/Settings.module.scss
+++ b/apps/Settings/styles/Settings.module.scss
@@ -14,6 +14,24 @@
margin-top: .5em;
}
+ &:nth-of-type(2) {
+ span {
+ padding: 0 .75em;
+ transition: .3s color;
+ display: inline-block;
+ color: var(--color-decor);
+
+ &:hover {
+ color: #666;
+ }
+ }
+
+ .settings__langactive {
+ color: var(--color-text);
+ font-weight: 600;
+ }
+ }
+
&:nth-of-type(3) {
margin-top: 3em;
}
diff --git a/components/App.js b/components/App.js
index 59fd5a0..210e0e0 100644
--- a/components/App.js
+++ b/components/App.js
@@ -1,10 +1,14 @@
import React, {useEffect, useRef} from 'react'
+import useSettings from 'hooks/useSettings'
+import useMediaQuery from 'hooks/useMediaQuery'
import {close, toggleMin, toggleMax, move} from 'helpers/windowActions'
import {faArrowUp, faExpandAlt, faTimes, faCompressAlt} from '@fortawesome/free-solid-svg-icons'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
const App = ({children, app, setApps}) => {
+ const {t} = useSettings()
const winRef = useRef(null);
+ const forceMax = useMediaQuery(`(max-width: ${app.width}) or (max-height: ${app.height})`);
useEffect(() => {
move(app.name, winRef, setApps)
@@ -17,20 +21,20 @@ const App = ({children, app, setApps}) => {
className={
'window'
+ (app.min ? ' hidden' : '')
- + (app.max ? ' maximized' : '')
+ + (app.max || forceMax ? ' maximized' : '')
}
style={{
- maxHeight: app.height,
- maxWidth: app.width,
+ height: app.height,
+ width: app.width,
...app.pos.length
? {top: app.pos[1], left: app.pos[0]}
: {
- // top: `calc((( 100vh - ${app.height} ) / 2) + 2em)`,
- // left: `calc(( 100vw - ${app.width} ) / 2)`,
+ top: `calc((( 100vh - ${app.height} ) / 2) + 2em)`,
+ left: `calc(( 100vw - ${app.width} ) / 2)`,
}
}}
>
- <h2 className='window__title'>{app.name}</h2>
+ <h2 className='window__title'>{t(app.name)}</h2>
<div className='window__content'>{children}</div>
<div className='window__title-buttons'>
{ app.buttons.includes('min') && (
@@ -38,7 +42,7 @@ const App = ({children, app, setApps}) => {
<FontAwesomeIcon icon={faArrowUp} />
</span>
)}
- { app.buttons.includes('max') && (
+ { app.buttons.includes('max') && !forceMax && (
<span onClick={() => toggleMax(app.name, setApps)}>
<FontAwesomeIcon icon={app.max ? faCompressAlt : faExpandAlt} />
</span>
diff --git a/components/Form.js b/components/Form.js
index f41c958..59f9710 100644
--- a/components/Form.js
+++ b/components/Form.js
@@ -1,20 +1,72 @@
import styles from 'styles/Main.module.scss'
import React from 'react'
import PropTypes from 'prop-types'
+import useSettings from 'hooks/useSettings'
-const Form = ({errorMessage, onSubmit, isLogin}) => (
- <form className={`window window--popup ${styles.userForm}`} onSubmit={onSubmit}>
- <div className="window__content--popup">
- {isLogin ? 'Login to access your notes' : 'Register new user'}
- </div>
- <input type="email" name="email" placeholder="email" required />
- <input type="password" name="password" minLength="6" placeholder="password" required />
+const Form = ({errorMessage, onSubmit, isLogin}) => {
+ const {settings, setSettings, t} = useSettings()
- <input className='window__button' type="submit" value={isLogin ? 'Login' : 'Register'} />
+ const themeChange = c => {
+ setSettings(prev => ({...prev, theme: c}))
+ }
- {errorMessage && <p className="error">{errorMessage}</p>}
- </form>
-)
+ const languageChange = l => {
+ setSettings(prev => ({...prev, language: l}))
+ }
+
+ return (
+ <form className={`window window--popup ${styles.userForm}`} onSubmit={onSubmit}>
+ <div className="window__content--popup">
+ {isLogin ? t('log_in') : t('register_user')}
+ </div>
+ <input type="email" name="email" placeholder="email" required />
+ <input type="password" name="password" minLength="6" placeholder={t('password')} required />
+ {!isLogin && (
+ <>
+ <input type="password" name="password_confirm" placeholder={t('confirm_password')} required />
+ <fieldset>
+ <legend>{t('language')}</legend>
+ {['en', 'pl', 'es', 'de'].map(l => (
+ <>
+ <input
+ key={`i_${l}`}
+ id={`language_${l}`}
+ type="radio"
+ name="language"
+ value={l}
+ defaultChecked={settings.language === l}
+ onChange={() => languageChange(l)}
+ />
+ <label key={`l_${l}`} htmlFor={`language_${l}`}>{l.toUpperCase()}</label>
+ </>
+ ))}
+ </fieldset>
+ <fieldset>
+ <legend>{t('color_theme')}</legend>
+ {['green', 'blue', 'black'].map(c => (
+ <>
+ <input
+ key={`i_${c}`}
+ id={`theme_${c}`}
+ type="radio"
+ name="theme"
+ value={c}
+ defaultChecked={settings.theme === c}
+ onChange={() => themeChange(c)}
+ />
+ <label key={`l_${c}`} htmlFor={`theme_${c}`} />
+ </>
+ ))}
+ </fieldset>
+ </>
+ )}
+
+ <input className='window__button' type="submit" value={isLogin ? t('login') : t('register')} />
+
+ {errorMessage && <p className="error">{t(errorMessage)}</p>}
+ </form>
+ )
+}
export default Form
diff --git a/components/Header.js b/components/Header.js
index 5279c80..9ff3d75 100644
--- a/components/Header.js
+++ b/components/Header.js
@@ -2,15 +2,17 @@ import styles from 'styles/Main.module.scss'
import React, {useState} from 'react'
import {useRouter} from 'next/router'
import Link from 'next/link'
-import useUser from 'lib/useUser'
-import fetchJson from 'lib/fetchJson'
+import useUser from 'hooks/useUser'
+import fetchJson from 'helpers/fetchJson'
import {focus, toggleMin} from 'helpers/windowActions'
import {open} from 'helpers/windowActions'
-import appList from 'helpers/appList'
+import appList from 'configs/appList'
+import useSettings from 'hooks/useSettings'
const Header = ({apps, setApps}) => {
const [userMenu, setUserMenu] = useState(false);
const {user, mutateUser} = useUser()
+ const {t} = useSettings()
const router = useRouter()
const handleLogout = async (e) => {
@@ -46,7 +48,7 @@ const Header = ({apps, setApps}) => {
...app.min ? {color: '#888'} : {}
}}
>
- {app.name}
+ {t(app.name)}
</span>
</li>
))
@@ -56,14 +58,14 @@ const Header = ({apps, setApps}) => {
{!user?.isLoggedIn && (
<li>
<Link href="/register">
- <a>Register</a>
+ <a>{t('register')}</a>
</Link>
</li>
)}
{!user?.isLoggedIn && (
<li>
<Link href="/login">
- <a>Login</a>
+ <a>{t('login')}</a>
</Link>
</li>
)}
@@ -79,17 +81,19 @@ const Header = ({apps, setApps}) => {
<>
<div className={styles.headerOverlay} onClick={() => setUserMenu(false)} />
<ul className={styles.submenu}>
- <li>
- <span onClick={() => {
- open({appName: 'Settings', ...appList.Settings}, setApps)
- setUserMenu()
- }}>
- Settings
- </span>
- </li>
+ {user.isVerified && (
+ <li>
+ <span onClick={() => {
+ open({appName: 'Settings', ...appList.Settings}, setApps)
+ setUserMenu()
+ }}>
+ {t('Settings')}
+ </span>
+ </li>
+ )}
<li>
<a href="/api/logout" onClick={handleLogout}>
- Logout
+ {t('logout')}
</a>
</li>
</ul>
diff --git a/components/Layout.js b/components/Layout.js
index e915285..d5627e3 100644
--- a/components/Layout.js
+++ b/components/Layout.js
@@ -1,26 +1,32 @@
import styles from 'styles/Main.module.scss'
import React from 'react'
import Head from 'next/head'
-import {Header, Popup} from 'components'
+import {Header, Popup, Splash} from 'components'
+import useSettings from 'hooks/useSettings'
import PropTypes from 'prop-types'
const Layout = ({
children,
apps,
setApps,
- settings,
-}) => (
- <section className={styles.layout +' '+ (settings ? settings.theme : 'green')}>
- <Head>
- <title>My Apps</title>
- </Head>
- <main>
- <div className="container">{children}</div>
- </main>
- <Header apps={apps} setApps={setApps} />
- <Popup/>
- </section>
-)
+}) => {
+ const {settings} = useSettings()
+
+ if (!settings || !settings.theme || !settings.language) return <Splash fixed />
+
+ return (
+ <section className={styles.layout +' '+ settings.theme}>
+ <Head>
+ <title>My Apps</title>
+ </Head>
+ <main>
+ <div className="container">{children}</div>
+ </main>
+ <Header apps={apps} setApps={setApps} />
+ <Popup/>
+ </section>
+ )
+}
export default Layout
diff --git a/components/Splash.js b/components/Splash.js
index 7976de4..f807202 100644
--- a/components/Splash.js
+++ b/components/Splash.js
@@ -1,13 +1,18 @@
import styles from 'styles/Main.module.scss'
import React from 'react'
+import useSettings from 'hooks/useSettings'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
import {faBan, faSpinner} from '@fortawesome/free-solid-svg-icons'
-const Splash = ({type, fixed = false}) => (
- <div className={`${type === 'connection' ? styles.connection : styles.loader} ${fixed ? styles.fixed : ''}`}>
- <FontAwesomeIcon icon={type === 'connection' ? faBan : faSpinner} />
- <p>{type === 'connection' ? 'No connection' : 'Loading...'}</p>
- </div>
-)
+const Splash = ({type, fixed = false}) => {
+ const {t} = useSettings()
+
+ return (
+ <div className={`${type === 'connection' ? styles.connection : styles.loader} ${fixed ? styles.fixed : ''}`}>
+ <FontAwesomeIcon icon={type === 'connection' ? faBan : faSpinner} />
+ <p>{type === 'connection' ? t('no_connection') : t('loading')}</p>
+ </div>
+ )
+}
export default Splash
diff --git a/helpers/appList.js b/configs/appList.js
index a114a70..a114a70 100644
--- a/helpers/appList.js
+++ b/configs/appList.js
diff --git a/lib/dbConnect.js b/configs/dbConnect.js
index a58ef79..0a0d200 100644
--- a/lib/dbConnect.js
+++ b/configs/dbConnect.js
@@ -1,11 +1,11 @@
import mongoose from 'mongoose'
-// const MONGODB_URI = process.env.MYAPPS_MONGODB_URI
-const MONGODB_URI = 'mongodb://localhost:27017/myapps'
+const MONGODB_URI = process.env.MYAPPS_MONGODB_URI
+// const MONGODB_URI = 'mongodb://localhost:27017/myapps'
if (!MONGODB_URI) {
throw new Error(
- 'Please define the MONGODB_URI environment variable inside .env.local'
+ 'MONGODB_URI missing in dbConnect'
)
}
diff --git a/lib/sendMail.js b/configs/sendMail.js
index f50eaf1..f50eaf1 100644
--- a/lib/sendMail.js
+++ b/configs/sendMail.js
diff --git a/configs/translations.js b/configs/translations.js
new file mode 100644
index 0000000..4d204ea
--- /dev/null
+++ b/configs/translations.js
@@ -0,0 +1,284 @@
+const translations = {
+ en: {
+ register_user: 'Register new user',
+ log_in: 'Log in to My Apps',
+ password: 'password',
+ confirm_password: 'confirm password',
+ color_theme: 'Color theme:',
+ language: 'Language:',
+ login: 'Login',
+ login_error: 'Could not log in',
+ logout: 'Logout',
+ register: 'Register',
+ register_error: 'Could not register user',
+ edit: 'Edit',
+ remove: 'Remove',
+ copy: 'Copy',
+ save: 'Save',
+ back: 'Back',
+ cancel: 'Cancel',
+ select_all: 'Select all',
+ import: 'Import',
+ export: 'Export',
+ choose_files: 'Choose files',
+ import_finished: 'Import finished.',
+ no_connection: 'No connection',
+ loading: 'Loading...',
+ sending: 'Sending...',
+ title: 'Title',
+ created: 'Created',
+ modified: 'Modified',
+ Notes: 'Notes',
+ Settings: 'Settings',
+ mail_ver_subject: 'Verification of your new My Apps account',
+ mail_ver_t1: 'Thank you for creating an account in My Apps.',
+ mail_ver_t2: 'We are sending you the verification code:',
+ mail_ver_t3: 'To finish verification log in and paste this code.',
+ verification_mail_error: 'Could not send verification email',
+ verification_error: 'Could not verify user',
+ verification_title: 'One last step missing!',
+ verification_text: 'To start using My Apps type the verification code we sent to your email',
+ verification_key: 'Verification key',
+ verify: 'Verify',
+ verification_not_received: 'If you did not receive the verification email',
+ verification_send_again: 'send it again',
+ verification_sent_again: 'Mail was successfully sent again, check your mailbox!',
+ settings_saved: 'Settings saved',
+ settings_save_error: 'Could not save settings',
+ passwords_not_match: 'Passwords do not match',
+ notes_new: 'New note',
+ notes_edit: 'Edit note:',
+ notes_add: 'Add note',
+ notes_save: 'Save note',
+ notes_add_new: 'Add new note:',
+ notes_list_empty: 'Your notes list is empty.',
+ notes_click_to_export: 'Click to export your notes:',
+ notes_to_export: 'Notes to export:',
+ notes_import: 'Import new notes:',
+ notes_to_import: 'Notes to import:',
+ notes_import_go_back: 'Go back to notes list or choose other notes to import.',
+ notes_copy_success: 'Note content was copied to clipboard',
+ notes_copy_error: 'Could not copy to clipboard',
+ notes_open_error: 'Could not open note',
+ notes_added: 'New note added',
+ notes_added_error: 'Could not save note',
+ notes_updated: 'Note updated',
+ notes_updated_error: 'Could not update note',
+ notes_removed: 'Note was removed',
+ notes_removed_error: 'Could not remove note',
+ notes_remove_confirm: 'Do you want to remove note?',
+ },
+ pl: {
+ register_user: 'Zarejestruj użytkownika',
+ log_in: 'Zaloguj się do My Apps',
+ password: 'hasło',
+ confirm_password: 'potwierdź hasło',
+ color_theme: 'Wybierz motyw:',
+ language: 'Język:',
+ login: 'Zaloguj',
+ login_error: 'Błąd podczas logowania',
+ logout: 'Wyloguj',
+ register: 'Zarejestruj',
+ register_error: 'Błąd podczas rejestracji',
+ edit: 'Edytuj',
+ remove: 'Usuń',
+ copy: 'Kopiuj',
+ save: 'Zapisz',
+ back: 'Powrót',
+ cancel: 'Anuluj',
+ select_all: 'Wybierz wszystkie',
+ import: 'Wyślij',
+ export: 'Pobierz',
+ choose_files: 'Wybierz pliki',
+ import_finished: 'Wysyłanie zakończone.',
+ no_connection: 'Brak połączenia',
+ loading: 'Ładowanie...',
+ sending: 'Wysyłanie...',
+ title: 'Tytuł',
+ created: 'Utworzono',
+ modified: 'Zmodyfikowano',
+ Notes: 'Notatki',
+ Settings: 'Ustawienia',
+ mail_ver_subject: 'Weryfikacja Twojego nowego konta w aplikacji My Apps.',
+ mail_ver_t1: 'Dziękujemy za założenie konta w My Apps',
+ mail_ver_t2: 'Przesyłamy Ci kod weryfikacyjny:',
+ mail_ver_t3: 'W celu zakończenia weryfikacji zaloguj się i podaj ten kod.',
+ verification_mail_error: 'Błąd podczas wysyłania maila z kodem weryfikacyjnym',
+ verification_error: 'Błąd podczas weryfikacji użytkownika',
+ verification_title: 'Pozostał ostatni krok!',
+ verification_text: 'Aby rozpocząć korzystanie z My Apps wpisz kod weryfikacyjny, który wysłaliśmy Ci mailem na adres',
+ verification_key: 'Kod weryfikacyjny',
+ verify: 'Weryfikuj',
+ verification_not_received: 'Jeżeli nie otrzymałeś maila z kodem weryfikacyjnym',
+ verification_send_again: 'wyślij go ponownie',
+ verification_sent_again: 'Mail został wysłany ponownie, sprawdź skrzynkę!',
+ settings_saved: 'Ustawienia zapisane',
+ settings_save_error: 'Błąd podczas zapisu ustawień',
+ passwords_not_match: 'Podane hasła nie są identyczne',
+ notes_new: 'Nowa notatka',
+ notes_edit: 'Edytuj notatkę:',
+ notes_add: 'Dodaj notatkę',
+ notes_save: 'Zapisz notatkę',
+ notes_add_new: 'Dodaj nową notatkę:',
+ notes_list_empty: 'Twoja lista notatek jest pusta.',
+ notes_click_to_export: 'Kliknij aby pobrać Twoje notatki:',
+ notes_to_export: 'Notatki, które zostaną pobrane:',
+ notes_import: 'Wyślij nowe notatki:',
+ notes_to_import: 'Notatki do wysłania:',
+ notes_import_go_back: 'Wróć do listy notatek lub wyślij więcej plików.',
+ notes_copy_success: 'Skopiowano notatkę do schowka',
+ notes_copy_error: 'Błąd podczas kopiowania notatki',
+ notes_open_error: 'Błąd podczas otwierania notatki',
+ notes_added: 'Dodano nową notatkę',
+ notes_added_error: 'Błąd podczas dodawania notatki',
+ notes_updated: 'Notatka zmieniona',
+ notes_updated_error: 'Błąd podczas zapisu zmian w notatce',
+ notes_removed: 'Usunięto notatkę',
+ notes_removed_error: 'Błąd podczas usuwania notatki',
+ notes_remove_confirm: 'Czy na pewno chcesz usunąć notatkę?',
+ },
+ es: {
+ register_user: 'Registrar al usuario',
+ log_in: 'Iniciar sesión en Mis aplicaciones',
+ password: 'contraseña',
+ confirm_password: 'confirmar la contraseña',
+ color_theme: 'Elige un tema: ',
+ language: 'Lengua: ',
+ login: 'Acceso',
+ login_error: 'Error de inicio de sesión',
+ logout: 'Cerrar sesión',
+ register: 'Registrarse',
+ register_error: 'Error durante el registro',
+ edit: 'Editar',
+ remove: 'Borrar',
+ copy: 'Dupdo',
+ save: 'Ahorrar',
+ back: 'Regreso',
+ cancel: 'Cancelar',
+ select_all: 'Elegir todos',
+ import: 'Enviar',
+ export: 'Descargar',
+ choose_files: 'Seleccione archivos',
+ import_finished: 'Envío completo.',
+ no_connection: 'Sin conexión',
+ loading: 'Aterrizaje...',
+ sending: 'Enviando ...',
+ title: 'Título',
+ created: 'Creado',
+ modified: 'Modificado',
+ Notes: 'Notas',
+ Settings: 'Ajustes',
+ mail_ver_subject: 'Verificación de su nueva cuenta en la aplicación My Apps.',
+ mail_ver_t1: 'Gracias por crear una cuenta con Mis aplicaciones',
+ mail_ver_t2: 'Te enviamos un código de verificación: ',
+ mail_ver_t3: 'Para completar la verificación, inicie sesión e ingrese este código.',
+ verification_mail_error: 'Error al enviar el correo electrónico con el código de verificación',
+ verification_error: 'Error de verificación del usuario',
+ verification_title: '¡Queda un último paso!',
+ verification_text: 'Para comenzar a usar Mis aplicaciones, ingrese el código de verificación que le enviamos por correo electrónico a la dirección',
+ verification_key: 'Código de verificación',
+ verify: 'Verificar',
+ verification_not_received: 'Si no ha recibido el correo electrónico con el código de verificación',
+ verification_send_again: 'reenvialo',
+ verification_sent_again: 'El correo ha sido enviado de nuevo, por favor revise su bandeja de entrada.',
+ settings_saved: 'Se guardó la configuración',
+ settings_save_error: 'No se pudo guardar la configuración',
+ passwords_not_match: 'Las contraseñas proporcionadas no coinciden',
+ notes_new: 'Nueva nota',
+ notes_edit: 'Edita la nota: ',
+ notes_add: 'Agrega una nota',
+ notes_save: 'Guardar la nota',
+ notes_add_new: 'Agrega una nota nueva: ',
+ notes_list_empty: 'Tu lista de notas está vacía.',
+ notes_click_to_export: 'Haz clic para descargar tus notas: ',
+ notes_to_export: 'Notas que se descargarán: ',
+ notes_import: 'Enviar nuevas notas: ',
+ notes_to_import: 'Notas a enviar: ',
+ notes_import_go_back: 'Regrese a la lista de notas o envíe más archivos.',
+ notes_copy_success: 'La nota se copió en el portapapeles.',
+ notes_copy_error: 'Error al copiar la nota',
+ notes_open_error: 'Error al abrir la nota',
+ notes_added: 'Se ha agregado una nueva nota',
+ notes_added_error: 'Error al agregar la nota',
+ notes_updated: 'Nota modificada',
+ notes_updated_error: 'Error al guardar cambios en la nota',
+ notes_removed: 'Nota eliminada',
+ notes_removed_error: 'Error al eliminar la nota',
+ notes_remove_confirm: '¿Estás seguro de que deseas eliminar la nota?',
+ },
+ de: {
+ register_user: 'Registrieren Sie den Benutzer',
+ log_in: 'Melden Sie sich bei Meine Apps an',
+ password: 'Passwort',
+ confirm_password: 'Bestätige das Passwort',
+ color_theme: 'Wähle ein Thema: ',
+ language: 'Zunge: ',
+ login: 'Anmeldung',
+ login_error: 'Login Fehler',
+ logout: 'Ausloggen',
+ register: 'Registrieren',
+ register_error: 'Fehler bei der Registrierung',
+ edit: 'Bearbeiten',
+ remove: 'Löschen',
+ copy: 'Kopieren',
+ save: 'Speichern',
+ back: 'Zurückkehren',
+ cancel: 'Abbrechen',
+ select_all: 'Alles auswählen',
+ import: 'Senden',
+ export: 'Herunterladen',
+ choose_files: 'Dateien auswählen',
+ import_finished: 'Senden abgeschlossen.',
+ no_connection: 'Keine Verbindung',
+ loading: 'Landung...',
+ sending: 'Senden ...',
+ title: 'Titel',
+ created: 'Erstellt',
+ modified: 'Geändert',
+ Notes: 'Anmerkungen',
+ Settings: 'Einstellungen',
+ mail_ver_subject: 'Bestätigen Ihres neuen Kontos in der Anwendung „Meine Apps“.',
+ mail_ver_t1: 'Vielen Dank, dass Sie ein Konto bei My Apps erstellt haben',
+ mail_ver_t2: 'Wir senden Ihnen einen Bestätigungscode: ',
+ mail_ver_t3: 'Um die Verifizierung abzuschließen, loggen Sie sich ein und geben Sie diesen Code ein.',
+ verification_mail_error: 'Fehler beim Senden der E-Mail mit dem Bestätigungscode',
+ verification_error: 'Fehler bei der Benutzerüberprüfung',
+ verification_title: 'Ein letzter Schritt bleibt!',
+ verification_text: 'Um mit der Nutzung von Meine Apps zu beginnen, geben Sie den Bestätigungscode ein, den wir Ihnen per E-Mail an die Adresse gesendet haben',
+ verification_key: 'Verifizierungs-Schlüssel',
+ verify: 'Verifizieren',
+ verification_not_received: 'Wenn Sie die E-Mail mit dem Bestätigungscode nicht erhalten haben',
+ verification_send_again: 'Sende es erneut',
+ verification_sent_again: 'E-Mail wurde erneut gesendet, bitte überprüfen Sie Ihren Posteingang!',
+ settings_saved: 'Einstellungen gespeichert',
+ settings_save_error: 'Einstellungen konnten nicht gespeichert werden',
+ passwords_not_match: 'Die angegebenen Passwörter stimmen nicht überein',
+ notes_new: 'Neue Notiz',
+ notes_edit: 'Bearbeiten Sie die Notiz: ',
+ notes_add: 'Füg ein Notiz hinzu',
+ notes_save: 'Notiz speichern',
+ notes_add_new: 'Fügen Sie eine neue Notiz hinzu: ',
+ notes_list_empty: 'Ihre Notizenliste ist leer.',
+ notes_click_to_export: 'Klicken Sie hier, um Ihre Notizen herunterzuladen: ',
+ notes_to_export: 'Notizen, die heruntergeladen werden: ',
+ notes_import: 'Neue Notizen senden: ',
+ notes_to_import: 'Zu sendende Hinweise: ',
+ notes_import_go_back: 'Kehren Sie zur Notizliste zurück oder senden Sie weitere Dateien.',
+ notes_copy_success: 'Die Notiz wurde in die Zwischenablage kopiert',
+ notes_copy_error: 'Fehler beim Kopieren der Notiz',
+ notes_open_error: 'Fehler beim Öffnen der Notiz',
+ notes_added: 'Eine neue Notiz wurde hinzugefügt',
+ notes_added_error: 'Fehler beim Hinzufügen einer Notiz',
+ notes_updated: 'Hinweis geändert',
+ notes_updated_error: 'Fehler beim Speichern der Änderungen an der Notiz',
+ notes_removed: 'Notiz gelöscht',
+ notes_removed_error: 'Fehler beim Löschen der Notiz',
+ notes_remove_confirm: 'Möchten Sie die Notiz wirklich löschen? ',
+ }
+}
+
+export const t = (l, k) => translations[l][k]
+ ? translations[l][k]
+ : translations.en[k]
+
+export default translations
diff --git a/context/index.js b/context/index.js
deleted file mode 100644
index a802bf6..0000000
--- a/context/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import React from 'react';
-
-export default React.createContext()
diff --git a/lib/crypt.js b/helpers/crypt.js
index 5d3d79e..5d3d79e 100644
--- a/lib/crypt.js
+++ b/helpers/crypt.js
diff --git a/helpers/email.js b/helpers/email.js
index d79426c..30e95c8 100644
--- a/helpers/email.js
+++ b/helpers/email.js
@@ -1,4 +1,6 @@
-export const subject = 'Verification of your new Notes App account'
-export const text = key => `Thank you for creating an account in Notes App.\nWe are sending you the verification code:\n\n${key}\n\nTo finish verification log in and paste this code.`
-export const html = key => `<p>Thank you for creating an account in Notes App.<br/>We are sending you the verification code:</p><p style="font-size: 150%;padding: 1em;border: 1px solid black">${key}</p><p>To finish verification log in and paste this code.</p></br>`
+import {t} from 'configs/translations'
+
+export const subject = l => t(l, 'mail_ver_subject')
+export const text = (l, key) => `${t(l, 'mail_ver_t1')}\n${t(l, 'mail_ver_t2')}\n\n${key}\n\n${t(l, 'mail_ver_t3')}`
+export const html = (l, key) => `<p>${t(l, 'mail_ver_t1')}<br/>${t(l, 'mail_ver_t2')}</p><p style="font-size: 150%;padding: 1em;border: 1px solid black">${key}</p><p>${t(l, 'mail_ver_t3')}</p></br>`
diff --git a/lib/fetchJson.js b/helpers/fetchJson.js
index 5db80b5..5db80b5 100644
--- a/lib/fetchJson.js
+++ b/helpers/fetchJson.js
diff --git a/helpers/submitForm.js b/helpers/submitForm.js
index 77b283d..631c174 100644
--- a/helpers/submitForm.js
+++ b/helpers/submitForm.js
@@ -1,11 +1,31 @@
-import fetchJson from 'lib/fetchJson'
+import fetchJson from 'helpers/fetchJson'
const submitForm = async (e, url, mutateUser, setErrorMsg) => {
e.preventDefault()
+ const isRegister = url.includes('register')
+ if (
+ isRegister && e.currentTarget.password_confirm
+ && e.currentTarget.password_confirm.value
+ !== e.currentTarget.password.value
+ ) {
+ setErrorMsg('passwords_not_match')
+ return
+ } else {
+ setErrorMsg()
+ }
+
const body = {
email: e.currentTarget.email.value,
password: e.currentTarget.password.value,
+ ...(e.currentTarget.language
+ ? {language: e.currentTarget.language.value}
+ : {}
+ ),
+ ...(e.currentTarget.theme
+ ? {theme: e.currentTarget.theme.value}
+ : {}
+ ),
}
try {
@@ -17,9 +37,7 @@ const submitForm = async (e, url, mutateUser, setErrorMsg) => {
})
)
} catch (err) {
- url.includes('login')
- ? setErrorMsg('Could not log in')
- : setErrorMsg('Could not register user')
+ setErrorMsg(isRegister ? 'register_error' : 'login_error')
}
}
diff --git a/lib/withSession.js b/hocs/withSession.js
index 0361db3..0361db3 100644
--- a/lib/withSession.js
+++ b/hocs/withSession.js
diff --git a/hooks/useApps.js b/hooks/useApps.js
new file mode 100644
index 0000000..babf712
--- /dev/null
+++ b/hooks/useApps.js
@@ -0,0 +1,17 @@
+import React, { createContext, useState, useContext } from 'react'
+
+const AppsContext = createContext()
+
+export const AppsProvider = ({children}) => {
+ const [apps, setApps] = useState([])
+
+ return (
+ <AppsContext.Provider value={{apps, setApps}}>
+ {children}
+ </AppsContext.Provider>
+ )
+}
+
+const useApps = () => useContext(AppsContext)
+
+export default useApps
diff --git a/hooks/useMediaQuery.js b/hooks/useMediaQuery.js
new file mode 100644
index 0000000..1adb499
--- /dev/null
+++ b/hooks/useMediaQuery.js
@@ -0,0 +1,19 @@
+import { useState, useEffect } from "react";
+
+const useMediaQuery = (query) => {
+ const [matches, setMatches] = useState(false);
+
+ useEffect(() => {
+ const media = window.matchMedia(query);
+ if (media.matches !== matches) {
+ setMatches(media.matches);
+ }
+ const listener = () => setMatches(media.matches);
+ window.addEventListener("resize", listener);
+ return () => window.removeEventListener("resize", listener);
+ }, [matches, query]);
+
+ return matches;
+}
+
+export default useMediaQuery;
diff --git a/hooks/useSettings.js b/hooks/useSettings.js
new file mode 100644
index 0000000..90ee72d
--- /dev/null
+++ b/hooks/useSettings.js
@@ -0,0 +1,50 @@
+import React, { createContext, useState, useEffect, useContext } from 'react'
+import translations from 'configs/translations'
+import useUser from 'hooks/useUser'
+
+const SettingsContext = createContext()
+
+export const SettingsProvider = ({children}) => {
+ const defaultSettings = {theme: 'green', language: 'en'}
+ const {user} = useUser()
+ const [data, setData] = useState()
+
+ const setSettings = s => {
+ if (typeof window !== "undefined") {
+ window.localStorage.setItem('loggedOutSettings', JSON.stringify(s(data)))
+ }
+ setData(s)
+ }
+
+ const t = key => data && data.language && translations[data.language][key]
+ ? translations[data.language][key]
+ ? translations[data.language][key]
+ : translations.en[key]
+ : '...'
+
+ useEffect(() => {
+ const loggedOutSettings = JSON.parse(localStorage.getItem('loggedOutSettings'))
+
+ if (user && user.isLoggedIn) {
+ const settings = {theme: user.theme, language: user.language}
+ if (typeof window !== "undefined") {
+ window.localStorage.setItem('loggedOutSettings', JSON.stringify(settings))
+ }
+ setData(settings)
+ } else if (loggedOutSettings) {
+ setData(loggedOutSettings)
+ } else {
+ setData(defaultSettings)
+ }
+ }, [user])
+
+ return (
+ <SettingsContext.Provider value={{settings: data, setSettings, t}}>
+ {children}
+ </SettingsContext.Provider>
+ )
+}
+
+const useSettings = () => useContext(SettingsContext)
+
+export default useSettings
diff --git a/lib/useUser.js b/hooks/useUser.js
index 16833aa..16833aa 100644
--- a/lib/useUser.js
+++ b/hooks/useUser.js
diff --git a/models/Note.js b/models/Note.js
index 4e1956e..d19eae8 100644
--- a/models/Note.js
+++ b/models/Note.js
@@ -1,4 +1,4 @@
-const {encrypt, decrypt} = require('lib/crypt')
+const {encrypt, decrypt} = require('helpers/crypt')
const mongoose = require('mongoose')
const noteSchema = new mongoose.Schema({
diff --git a/models/NoteList.js b/models/NoteList.js
index 159364f..bf7b155 100644
--- a/models/NoteList.js
+++ b/models/NoteList.js
@@ -1,4 +1,4 @@
-const {encrypt, decrypt} = require('lib/crypt')
+const {encrypt, decrypt} = require('helpers/crypt')
const mongoose = require("mongoose")
const decryptTitles = l => ({notes: l.notes.map(n => ({ ...n, title: decrypt(n.title)}))})
diff --git a/pages/_app.js b/pages/_app.js
index 0fec9f6..637b096 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -1,6 +1,8 @@
import { SWRConfig } from 'swr'
+import {SettingsProvider} from 'hooks/useSettings'
import {PopupProvider} from 'hooks/usePopup'
-import fetchJson from 'lib/fetchJson'
+import {AppsProvider} from 'hooks/useApps'
+import fetchJson from 'helpers/fetchJson'
import '/styles/global.scss'
function MyApp({Component, pageProps}) {
@@ -13,9 +15,13 @@ function MyApp({Component, pageProps}) {
},
}}
>
- <PopupProvider>
- <Component {...pageProps} />
- </PopupProvider>
+ <SettingsProvider>
+ <PopupProvider>
+ <AppsProvider>
+ <Component {...pageProps} />
+ </AppsProvider>
+ </PopupProvider>
+ </SettingsProvider>
</SWRConfig>
)
}
diff --git a/pages/api/login.js b/pages/api/login.js
index db39bda..038097c 100644
--- a/pages/api/login.js
+++ b/pages/api/login.js
@@ -1,5 +1,5 @@
-import withSession from 'lib/withSession'
-import dbConnect from 'lib/dbConnect'
+import withSession from 'hocs/withSession'
+import dbConnect from 'configs/dbConnect'
import User from 'models/User'
export default withSession(async (req, res) => {
diff --git a/pages/api/logout.js b/pages/api/logout.js
index 8c7a766..04e5160 100644
--- a/pages/api/logout.js
+++ b/pages/api/logout.js
@@ -1,4 +1,4 @@
-import withSession from 'lib/withSession'
+import withSession from 'hocs/withSession'
export default withSession(async (req, res) => {
req.session.destroy()
diff --git a/pages/api/note/[id].js b/pages/api/note/[id].js
index 46278c8..1781210 100644
--- a/pages/api/note/[id].js
+++ b/pages/api/note/[id].js
@@ -1,5 +1,5 @@
-import dbConnect from 'lib/dbConnect'
-import withSession from 'lib/withSession'
+import dbConnect from 'configs/dbConnect'
+import withSession from 'hocs/withSession'
import Note from 'models/Note'
export default withSession(async (req, res) => {
diff --git a/pages/api/notes.js b/pages/api/notes.js
index 79ab281..0439a7a 100644
--- a/pages/api/notes.js
+++ b/pages/api/notes.js
@@ -1,5 +1,5 @@
-import dbConnect from 'lib/dbConnect'
-import withSession from 'lib/withSession'
+import dbConnect from 'configs/dbConnect'
+import withSession from 'hocs/withSession'
import NoteList from 'models/NoteList'
import Note from 'models/Note'
diff --git a/pages/api/register.js b/pages/api/register.js
index 1407146..e14044e 100644
--- a/pages/api/register.js
+++ b/pages/api/register.js
@@ -1,6 +1,6 @@
-import dbConnect from 'lib/dbConnect'
-import withSession from 'lib/withSession'
-import sendMail from 'lib/sendMail'
+import dbConnect from 'configs/dbConnect'
+import sendMail from 'configs/sendMail'
+import withSession from 'hocs/withSession'
import {subject, text, html} from 'helpers/email'
import User from 'models/User'
import NoteList from 'models/NoteList'
@@ -16,14 +16,13 @@ export default withSession(async (req, res) => {
const {_id, email, verificationKey: key, theme, language} = await User.create({...req.body, noteList})
if (!email) { throw new Error('Something went wrong') }
- sendMail(req.body.email, subject, text(key), html(key))
+ sendMail(req.body.email, subject(language), text(language, key), html(language, key))
const user = {_id, email, noteList, theme, language, isVerified: false, isLoggedIn: true}
req.session.set('user', user)
await req.session.save()
res.status(201).json(user)
} catch (error) {
- console.log(error)
res.status(400).json({isLoggedIn: false})
}
break
diff --git a/pages/api/settings.js b/pages/api/settings.js
index e70868e..0de5e73 100644
--- a/pages/api/settings.js
+++ b/pages/api/settings.js
@@ -1,6 +1,6 @@
-import withSession from 'lib/withSession'
+import dbConnect from 'configs/dbConnect'
+import withSession from 'hocs/withSession'
import User from 'models/User'
-import dbConnect from 'lib/dbConnect'
export default withSession(async (req, res) => {
await dbConnect()
diff --git a/pages/api/user.js b/pages/api/user.js
index 59db3b6..44c7fc3 100644
--- a/pages/api/user.js
+++ b/pages/api/user.js
@@ -1,5 +1,5 @@
-import dbConnect from 'lib/dbConnect'
-import withSession from 'lib/withSession'
+import dbConnect from 'configs/dbConnect'
+import withSession from 'hocs/withSession'
import User from 'models/User'
export default withSession(async (req, res) => {
diff --git a/pages/api/verify.js b/pages/api/verify.js
index 1606dbc..bdad434 100644
--- a/pages/api/verify.js
+++ b/pages/api/verify.js
@@ -1,7 +1,7 @@
-import withSession from 'lib/withSession'
-import dbConnect from 'lib/dbConnect'
-import sendMail from 'lib/sendMail'
+import dbConnect from 'configs/dbConnect'
+import sendMail from 'configs/sendMail'
import User from 'models/User'
+import withSession from 'hocs/withSession'
import {subject, text, html} from 'helpers/email'
export default withSession(async (req, res) => {
@@ -10,13 +10,13 @@ export default withSession(async (req, res) => {
switch (req.method) {
case 'GET':
try {
- const {email} = req.session.get('user')
+ const {email, language: l} = req.session.get('user')
if (!email) { throw new Error('Something went wrong') }
const key = await User.getVerificationKey(email)
if (!key) { throw new Error('Something went wrong') }
- const response = await sendMail(email, subject, text(key), html(key))
+ const response = await sendMail(email, subject(l), text(l, key), html(l, key))
if (!response?.accepted?.length) { throw new Error('Something went wrong') }
res.status(204).send()
@@ -33,7 +33,6 @@ export default withSession(async (req, res) => {
res.status(200).json(user)
}
} catch (error) {
- console.log(error)
res.status(400).send()
}
break
diff --git a/pages/index.js b/pages/index.js
index ee1c277..b441362 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -1,26 +1,21 @@
import styles from 'styles/Main.module.scss'
-import React, {useState, useEffect} from 'react'
-import useUser from 'lib/useUser'
+import React from 'react'
+import useUser from 'hooks/useUser'
+import useSettings from 'hooks/useSettings'
+import useApps from 'hooks/useApps'
import {Layout, App, Splash} from 'components'
import {open} from 'helpers/windowActions'
-import appList from 'helpers/appList'
-import Context from '../context';
+import appList from 'configs/appList'
const Home = () => {
- const [settings, setSettings] = useState()
- const [apps, setApps] = useState([])
+ const {t} = useSettings()
+ const {apps, setApps} = useApps()
const {user} = useUser({
redirectToLogin: true,
redirectToVerify: true,
redirectToApps: true,
})
- useEffect(() => {
- if (user) {
- setSettings({theme: user.theme, language: user.language})
- }
- }, [user])
-
if (!user) return (
<Layout><Splash fixed /></Layout>
)
@@ -44,39 +39,37 @@ const Home = () => {
}
return (
- <Context.Provider value={{settings, setSettings, setApps}}>
- <Layout apps={apps} setApps={setApps} settings={settings}>
- <>
- {
- Object.entries(appList).filter(a => a[1].icon).map(a => (
- <div
- key={`${a[0]}_icon`}
- className={styles.icon}
- onClick={e => handleClick(e, {appName: a[0], ...a[1]})}
- onKeyDown={e => handleKey(e, {appName: a[0], ...a[1]})}
- tabIndex="0"
- >
- <img src={`./${a[0].toLowerCase()}.svg`} alt={`${a[0]} Icon`} />
- <p>{a[0]}</p>
- </div>
- ))
- }
- {apps && apps.map(app => {
- const AppComponent = appList[app.name].component
+ <Layout apps={apps} setApps={setApps}>
+ <>
+ {
+ Object.entries(appList).filter(a => a[1].icon).map(a => (
+ <div
+ key={`${a[0]}_icon`}
+ className={styles.icon}
+ onClick={e => handleClick(e, {appName: a[0], ...a[1]})}
+ onKeyDown={e => handleKey(e, {appName: a[0], ...a[1]})}
+ tabIndex="0"
+ >
+ <img src={`./${a[0].toLowerCase()}.svg`} alt={`${a[0]} Icon`} />
+ <p>{t(a[0])}</p>
+ </div>
+ ))
+ }
+ {apps && apps.map(app => {
+ const AppComponent = appList[app.name].component
- return (
- <App
- key={`${app.name}_app`}
- app={app}
- setApps={setApps}
- >
- <AppComponent />
- </App>
- );
- })}
- </>
- </Layout>
- </Context.Provider>
+ return (
+ <App
+ key={`${app.name}_app`}
+ app={app}
+ setApps={setApps}
+ >
+ <AppComponent />
+ </App>
+ );
+ })}
+ </>
+ </Layout>
)
}
diff --git a/pages/login.js b/pages/login.js
index 3fb2df6..533e8e8 100644
--- a/pages/login.js
+++ b/pages/login.js
@@ -1,24 +1,33 @@
-import { useState } from 'react'
-import useUser from 'lib/useUser'
+import {useState} from 'react'
+import useUser from 'hooks/useUser'
import submitForm from 'helpers/submitForm'
-import {Layout, Form} from 'components'
+import {Layout, Form, Splash} from 'components'
const Login = () => {
+ const [errorMsg, setErrorMsg] = useState('')
+ const [loading, setLoading] = useState(false)
const {mutateUser} = useUser({
redirectToVerify: true,
redirectToApps: true,
})
- const [errorMsg, setErrorMsg] = useState('')
- const handleSubmit = e => submitForm(e, '/api/login', mutateUser, setErrorMsg)
+ const handleSubmit = async e => {
+ setLoading(true)
+ await submitForm(e, '/api/login', mutateUser, setErrorMsg)
+ setLoading(false)
+ }
return (
<Layout>
- <Form
- isLogin
- errorMessage={errorMsg}
- onSubmit={handleSubmit}
- />
+ {loading
+ ? <Splash fixed />
+ : (
+ <Form
+ isLogin
+ errorMessage={errorMsg}
+ onSubmit={handleSubmit}
+ />
+ )}
</Layout>
)
}
diff --git a/pages/register.js b/pages/register.js
index 3a00504..5405432 100644
--- a/pages/register.js
+++ b/pages/register.js
@@ -1,22 +1,31 @@
-import {useState } from 'react'
-import useUser from 'lib/useUser'
+import {useState} from 'react'
+import useUser from 'hooks/useUser'
import submitForm from 'helpers/submitForm'
-import {Layout, Form} from 'components'
+import {Layout, Form, Splash} from 'components'
const Register = () => {
- const { mutateUser } = useUser({
+ const [errorMsg, setErrorMsg] = useState('')
+ const [loading, setLoading] = useState(false)
+ const {mutateUser} = useUser({
redirectToVerify: true,
})
- const [errorMsg, setErrorMsg] = useState('')
- const handleSubmit = e => submitForm(e, '/api/register', mutateUser, setErrorMsg)
+ const handleSubmit = async e => {
+ setLoading(true)
+ await submitForm(e, '/api/register', mutateUser, setErrorMsg)
+ setLoading(false)
+ }
return (
<Layout>
- <Form
- errorMessage={errorMsg}
- onSubmit={handleSubmit}
- />
+ {loading
+ ? <Splash fixed />
+ : (
+ <Form
+ errorMessage={errorMsg}
+ onSubmit={handleSubmit}
+ />
+ )}
</Layout>
)
}
diff --git a/pages/verify.js b/pages/verify.js
index 5991035..2f7c863 100644
--- a/pages/verify.js
+++ b/pages/verify.js
@@ -1,18 +1,21 @@
import styles from 'styles/Main.module.scss'
import {useState} from 'react'
-import useUser from 'lib/useUser'
-import fetchJson from 'lib/fetchJson'
+import useUser from 'hooks/useUser'
+import useSettings from 'hooks/useSettings'
+import fetchJson from 'helpers/fetchJson'
import {Layout} from 'components'
import Splash from 'components/Splash'
const Verify = () => {
+ const {t} = useSettings()
+ const [errorMsg, setErrorMsg] = useState('')
+ const [loading, setLoading] = useState(false)
+ const [sending, setSending] = useState(false)
+ const [resent, setResent] = useState(false)
const {user, mutateUser} = useUser({
redirectToLogin: true,
redirectToApps: true,
})
- const [errorMsg, setErrorMsg] = useState('')
- const [sending, setSending] = useState(false)
- const [resent, setResent] = useState(false)
const handleSendMail = async e => {
e.preventDefault()
@@ -22,7 +25,7 @@ const Verify = () => {
await fetch('/api/verify')
setResent(true)
} catch (error) {
- setErrorMsg('Could not send verification email')
+ setErrorMsg(t('verification_mail_error'))
} finally {
setSending(false)
}
@@ -30,6 +33,7 @@ const Verify = () => {
const handleKey = async e => {
e.preventDefault()
+ setLoading(true)
const key = e.currentTarget.key.value
try {
mutateUser(
@@ -40,36 +44,36 @@ const Verify = () => {
})
)
} catch (err) {
- setErrorMsg('Could not verify user')
+ setErrorMsg(t('verification_error'))
+ } finally {
+ setLoading(false)
}
}
return (
<Layout>
- {!user
+ {!user || loading
? (
- <div className="window window--popup">
- <Splash />
- </div>
+ <Splash fixed />
) : (
<div className={`window window--popup ${styles.verify}`}>
- <p>One last step missing</p>
- <p>{`To start using Notes App type the verification code we sent to your email (${user.email}):`}</p>
+ <p>{t('verification_title')}</p>
+ <p>{`${t('verification_text')} ${user.email}`}</p>
<form onSubmit={handleKey}>
- <input type="text" placeholder="Verification key" name="key" />
- <button className="window__button" type="submit">Verify</button>
+ <input type="text" placeholder={t('verification_key')} name="key" />
+ <button className="window__button" type="submit">{t('verify')}</button>
</form>
{
sending
? (
- <p>Sending...</p>
+ <p>{t('sending')}</p>
) : (
resent
? (
- <p>Mail was successfully sent again, check your mailbox!</p>
+ <p>{t('verification_sent_again')}</p>
) : (
- <p>If you didn't get verification email&nbsp;
- <span className={styles.email} onClick={handleSendMail}>send it again</span>.
+ <p>{t('verification_not_received')}&nbsp;
+ <span className={styles.email} onClick={handleSendMail}>{t('verification_send_again')}</span>.
</p>
)
)
diff --git a/styles/Main.module.scss b/styles/Main.module.scss
index 3f0230c..bac6a97 100644
--- a/styles/Main.module.scss
+++ b/styles/Main.module.scss
@@ -9,8 +9,8 @@
.icon {
text-decoration: none;
display: inline-block;
- width: 4.5em;
padding: .5em;
+ text-align: center;
img {
width: 3em;
@@ -19,7 +19,6 @@
p {
margin-top: .25em;
padding: .25em;
- text-align: center;
transition: .2s background;
border-radius: .5em;
}
@@ -30,6 +29,8 @@
}
.userForm {
+ padding: 2em;
+
label,
& {
display: flex;
@@ -50,11 +51,77 @@
border-radius: .5px;
}
+
+ input[type=password]:nth-of-type(2) {
+ margin-top: 1em;
+ }
+
p {
text-align: center;
color: var(--color-error);
margin: 1rem 0 0;
}
+
+ legend {
+ font-size: .8em;
+ padding: 2em 0 1.5em;
+ }
+
+ fieldset:nth-of-type(1) {
+ input {
+ display: none;
+ }
+
+ label {
+ padding: 0 .75em;
+ transition: .3s color;
+ display: inline-block;
+ color: var(--color-decor);
+
+ &:hover {
+ color: #666;
+ }
+ }
+
+ input:checked + label {
+ font-weight: 600;
+ color: var(--color-text);
+ }
+ }
+
+ fieldset:nth-of-type(2) {
+ input {
+ display: none;
+ }
+
+ label {
+ width: 2em;
+ height: 2em;
+ display: inline-block;
+ margin: 0 1em;
+ outline-offset: 4px;
+
+ &:nth-of-type(1) {
+ background-color: #53e3a6;
+ }
+
+ &:nth-of-type(2) {
+ background-color: #2986b3;
+ }
+
+ &:nth-of-type(3) {
+ background-color: #000;
+ }
+ }
+
+ input:checked + label {
+ outline: 3px solid var(--color-window-buttons);
+ }
+ }
+
+ input[type=submit] {
+ margin-top: 1.5em;
+ }
}
.header {
@@ -70,7 +137,7 @@
overflow: auto;
}
- ul {
+ & > ul {
display: block;
& > li {
@@ -119,21 +186,34 @@
color: var(--color-text-alt);
background-color: var(--color-selected);
}
-
}
.submenu {
position: absolute;
right: 4px;
top: 2.1em;
- width: 8em;
- padding: .5em;
+ padding: .75em;
background-color: var(--color-window-content);
border-bottom: 1px solid var(--color-window-border-bottom);
border-radius: .5em;
+ display: flex;
+ flex-direction: column;
- & > li > span {
+ & > li > span,
+ & > li > a {
+ display: block;
+ color: var(--color-text);
+ padding: .5em;
+ margin: .25em;
+ white-space: nowrap;
text-decoration: none;
+ transition: .3s background, .3s color;
+ border-radius: .5em;
+
+ &:hover {
+ color: var(--color-text-alt);
+ background-color: var(--color-selected);
+ }
}
}
diff --git a/styles/_window.scss b/styles/_window.scss
index a2d0438..08ddfaf 100644
--- a/styles/_window.scss
+++ b/styles/_window.scss
@@ -26,22 +26,22 @@
}
&:not(.window--popup) {
- height: 80vh;
- width: 80vw;
- top: 10vh;
- left: 10vw;
+ height: 100%;
+ width: 100%;
+ }
+ // top: 50%;
+ // left: 50%;
+ // @media (min-width: 80em) {
+ // width: 64em;
+ // left: calc((100vw - 64em) / 2)
+ // }
- @media (min-width: 80em) {
- width: 64em;
- left: calc((100vw - 64em) / 2)
- }
-
- @media (min-height: 80em) {
- width: 64em;
- left: calc((100vh - 64em) / 2)
- }
- }
+ // @media (min-height: 80em) {
+ // width: 64em;
+ // left: calc((100vh - 64em) / 2)
+ // }
+ // }
&__title {
position: absolute;
@@ -181,8 +181,8 @@
right: 0!important;
bottom: 0!important;
left: 0!important;
- width: 100%;
- height: 100%;
+ width: 100%!important;
+ height: 100%!important;
& > .window__content {
top: 0;