From b0b349c1fdba85bb681c5c33dd10ae8d4e1dc45a Mon Sep 17 00:00:00 2001 From: Tania Rascia Date: Tue, 6 Oct 2020 21:08:58 -0500 Subject: [PATCH 1/3] Fix settings --- .eslintrc.js | 3 + src/client/api/index.ts | 9 +-- src/client/containers/NoteList.tsx | 5 +- src/client/containers/SettingsModal.tsx | 1 + src/client/sagas/index.ts | 27 +++++---- src/client/slices/auth.ts | 49 ++++++++-------- src/client/slices/category.ts | 75 ++++++++++++------------- src/client/slices/note.ts | 19 ++++--- src/client/slices/settings.ts | 70 +++++++++-------------- src/client/slices/sync.ts | 38 ++++++------- src/client/utils/notesSortStrategies.ts | 34 +++++------ 11 files changed, 156 insertions(+), 174 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index b0c67502..ed39d68c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -30,6 +30,9 @@ module.exports = { ], 'no-console': 1, // Warning to reduce console logs used throughout app 'react/prop-types': 0, // Not using prop-types because we have TypeScript + 'newline-before-return': 1, + 'no-useless-return': 1, + 'prefer-const': 1, }, settings: { 'import/resolver': { diff --git a/src/client/api/index.ts b/src/client/api/index.ts index 92d63ece..9198d514 100644 --- a/src/client/api/index.ts +++ b/src/client/api/index.ts @@ -6,9 +6,10 @@ import { scratchpadNote } from '@/api/scratchpadNote' type PromiseCallback = (value?: any) => void type GetLocalStorage = ( key: string, - errorMsg?: string + errorMessage?: string ) => (resolve: PromiseCallback, reject: PromiseCallback) => void -const getLocalStorage: GetLocalStorage = (key, errorMsg = 'Something went wrong') => ( + +const getLocalStorage: GetLocalStorage = (key, errorMessage = 'Something went wrong') => ( resolve, reject ) => { @@ -18,7 +19,7 @@ const getLocalStorage: GetLocalStorage = (key, errorMsg = 'Something went wrong' resolve(JSON.parse(data)) } else { reject({ - message: errorMsg, + message: errorMessage, }) } } @@ -50,7 +51,7 @@ export const requestNotes = () => new Promise(getUserNotes()) export const requestCategories = () => new Promise(getLocalStorage('categories')) export const requestSettings = () => - new Promise(getLocalStorage('settings', 'Could not load code mirror options. An error occurred')) + new Promise(getLocalStorage('settings', 'Could not load settings')) export const saveState = ({ categories, notes }: SyncStatePayload) => new Promise((resolve) => { diff --git a/src/client/containers/NoteList.tsx b/src/client/containers/NoteList.tsx index 06d2a7d4..870e4a51 100644 --- a/src/client/containers/NoteList.tsx +++ b/src/client/containers/NoteList.tsx @@ -96,7 +96,7 @@ export const NoteList: React.FC = () => { const handleNoteOptionsClick = (event: ReactMouseEvent, noteId: string = '') => { const clicked = event.target - // Make sure we aren't getting any null values .. any element clicked should be a sub-class of element + // Make sure we aren't getting any null values. Any element clicked should be a sub-class of element if (!clicked) return // Ensure the clicked target is supposed to open the context menu @@ -110,7 +110,6 @@ export const NoteList: React.FC = () => { event.stopPropagation() if (contextMenuRef.current && contextMenuRef.current.contains(clicked as HTMLDivElement)) { - return } else { setOptionsId(!optionsId || optionsId !== noteId ? noteId : '') } @@ -140,7 +139,6 @@ export const NoteList: React.FC = () => { event.stopPropagation() if (contextMenuRef.current && contextMenuRef.current.contains(clicked as HTMLDivElement)) { - return } else { setOptionsId(!optionsId || optionsId !== noteId ? noteId : '') } @@ -154,6 +152,7 @@ export const NoteList: React.FC = () => { useEffect(() => { document.addEventListener('mousedown', handleNoteOptionsClick) + return () => { document.removeEventListener('mousedown', handleNoteOptionsClick) } diff --git a/src/client/containers/SettingsModal.tsx b/src/client/containers/SettingsModal.tsx index a100960e..2ea76538 100644 --- a/src/client/containers/SettingsModal.tsx +++ b/src/client/containers/SettingsModal.tsx @@ -88,6 +88,7 @@ export const SettingsModal: React.FC = () => { useEffect(() => { document.addEventListener('mousedown', handleDomClick) document.addEventListener('keydown', handleEscPress) + return () => { document.removeEventListener('mousedown', handleDomClick) document.removeEventListener('keydown', handleEscPress) diff --git a/src/client/sagas/index.ts b/src/client/sagas/index.ts index 96c153f9..8b4a9de4 100644 --- a/src/client/sagas/index.ts +++ b/src/client/sagas/index.ts @@ -3,7 +3,7 @@ import { all, put, takeLatest, select } from 'redux-saga/effects' import dayjs from 'dayjs' import axios from 'axios' -import { requestCategories, requestNotes, saveState, saveSettings, requestSettings } from '@/api' +import { requestCategories, requestNotes, requestSettings, saveState, saveSettings } from '@/api' import { loadCategories, loadCategoriesError, loadCategoriesSuccess } from '@/slices/category' import { loadNotes, loadNotesError, loadNotesSuccess } from '@/slices/note' import { syncState, syncStateError, syncStateSuccess } from '@/slices/sync' @@ -79,6 +79,19 @@ function* fetchCategories() { } } +/** + * Get settings from API + */ +function* fetchSettings() { + try { + const settings = yield requestSettings() + + yield put(loadSettingsSuccess(settings)) + } catch (error) { + yield put(loadSettingsError()) + } +} + function* postState({ payload }: SyncStateAction) { try { yield saveState(payload) @@ -93,17 +106,7 @@ function* syncSettings() { const settings = yield select(getSettings) yield saveSettings(settings) - } catch {} -} - -function* fetchSettings() { - try { - const settings = yield requestSettings() - - yield put(loadSettingsSuccess(settings)) - } catch { - yield put(loadSettingsError()) - } + } catch (error) {} } // If any of these functions are dispatched, invoke the appropriate saga diff --git a/src/client/slices/auth.ts b/src/client/slices/auth.ts index 794d41d3..71ba31d6 100644 --- a/src/client/slices/auth.ts +++ b/src/client/slices/auth.ts @@ -13,33 +13,28 @@ const authSlice = createSlice({ name: 'auth', initialState, reducers: { - login: (state) => ({ - ...state, - loading: true, - }), - loginSuccess: (state, { payload }: PayloadAction) => ({ - ...state, - currentUser: payload, - isAuthenticated: true, - loading: false, - }), - loginError: (state, { payload }: PayloadAction) => ({ - ...state, - error: payload, - isAuthenticated: false, - loading: false, - }), - logout: (state) => ({ - ...state, - loading: true, - }), - logoutSuccess: (state) => ({ - ...state, - isAuthenticated: false, - currentUser: {}, - error: '', - loading: false, - }), + login: (state) => { + state.loading = true + }, + loginSuccess: (state, { payload }: PayloadAction) => { + state.currentUser = payload + state.isAuthenticated = true + state.loading = false + }, + loginError: (state, { payload }: PayloadAction) => { + state.error = payload + state.isAuthenticated = false + state.loading = false + }, + logout: (state) => { + state.loading = true + }, + logoutSuccess: (state) => { + state.isAuthenticated = false + state.currentUser = {} + state.error = '' + state.loading = false + }, }, }) diff --git a/src/client/slices/category.ts b/src/client/slices/category.ts index 15f0e82e..8075ec8c 100644 --- a/src/client/slices/category.ts +++ b/src/client/slices/category.ts @@ -6,6 +6,7 @@ const _swapCategories = (categories: CategoryItem[], categoryId: number, destina const newCategories = [...categories] newCategories.splice(categoryId, 1) newCategories.splice(destinationId, 0, categories[categoryId]) + return newCategories } @@ -23,54 +24,50 @@ const categorySlice = createSlice({ name: 'category', initialState, reducers: { - addCategory: (state, { payload }: PayloadAction) => ({ - ...state, - categories: [...state.categories, payload], - }), - categoryDragEnter: (state, { payload }: PayloadAction) => ({ + addCategory: (state, { payload }: PayloadAction) => { + state.categories.push(payload) + }, + updateCategory: (state, { payload }: PayloadAction) => ({ ...state, categories: state.categories.map((category) => - category.id === payload.id ? { ...category, draggedOver: true } : category + category.id === payload.id ? { ...category, name: payload.name } : category ), }), - categoryDragLeave: (state, { payload }: PayloadAction) => ({ - ...state, - categories: state.categories.map((category) => + categoryDragEnter: (state, { payload }: PayloadAction) => { + state.categories = state.categories.map((category) => + category.id === payload.id ? { ...category, draggedOver: true } : category + ) + }, + categoryDragLeave: (state, { payload }: PayloadAction) => { + state.categories = state.categories.map((category) => category.id === payload.id ? { ...category, draggedOver: false } : category - ), - }), + ) + }, swapCategories: ( state, { payload }: PayloadAction<{ categoryId: number; destinationId: number }> - ) => ({ - ...state, - categories: _swapCategories(state.categories, payload.categoryId, payload.destinationId), - }), - deleteCategory: (state, { payload }: PayloadAction) => ({ - ...state, - categories: state.categories.filter((category) => category.id !== payload), - }), + ) => { + state.categories = _swapCategories( + state.categories, + payload.categoryId, + payload.destinationId + ) + }, + deleteCategory: (state, { payload }: PayloadAction) => { + state.categories = state.categories.filter((category) => category.id !== payload) + }, + setCategoryEdit: (state, { payload }: PayloadAction<{ id: string; tempName: string }>) => { + state.editingCategory = payload + }, loadCategories: () => initialState, - loadCategoriesError: (state, { payload }: PayloadAction) => ({ - ...state, - loading: false, - error: payload, - }), - loadCategoriesSuccess: (state, { payload }: PayloadAction) => ({ - ...state, - categories: payload, - loading: false, - }), - updateCategory: (state, { payload }: PayloadAction) => ({ - ...state, - categories: state.categories.map((category) => - category.id === payload.id ? { ...category, name: payload.name } : category - ), - }), - setCategoryEdit: (state, { payload }: PayloadAction<{ id: string; tempName: string }>) => ({ - ...state, - editingCategory: payload, - }), + loadCategoriesError: (state, { payload }: PayloadAction) => { + state.loading = false + state.error = payload + }, + loadCategoriesSuccess: (state, { payload }: PayloadAction) => { + state.categories = payload + state.loading = false + }, }, }) diff --git a/src/client/slices/note.ts b/src/client/slices/note.ts index 39023445..6a851dfa 100644 --- a/src/client/slices/note.ts +++ b/src/client/slices/note.ts @@ -22,14 +22,16 @@ const getNewActiveNoteId = ( } export const getFirstNoteId = (folder: Folder, notes: NoteItem[], categoryId?: string): string => { - const notesNotTrash = notes.filter((note) => !note.trash) + const availableNotes = notes.filter((note) => !note.trash) + const firstNote = { - [Folder.ALL]: () => notesNotTrash.find((note) => !note.scratchpad), - [Folder.CATEGORY]: () => notesNotTrash.find((note) => note.category === categoryId), - [Folder.FAVORITES]: () => notesNotTrash.find((note) => note.favorite), - [Folder.SCRATCHPAD]: () => notesNotTrash.find((note) => note.scratchpad), + [Folder.ALL]: () => availableNotes.find((note) => !note.scratchpad), + [Folder.CATEGORY]: () => availableNotes.find((note) => note.category === categoryId), + [Folder.FAVORITES]: () => availableNotes.find((note) => note.favorite), + [Folder.SCRATCHPAD]: () => availableNotes.find((note) => note.scratchpad), [Folder.TRASH]: () => notes.find((note) => note.trash), }[folder]() + return firstNote ? firstNote.id : '' } @@ -48,6 +50,9 @@ const noteSlice = createSlice({ name: 'note', initialState, reducers: { + addNote: (state, { payload }: PayloadAction) => { + state.notes.push(payload) + }, addCategoryToNote: ( state, { payload }: PayloadAction<{ categoryId: string; noteId: string }> @@ -63,10 +68,6 @@ const noteSlice = createSlice({ note.id === payload.noteId ? { ...note, category: payload.categoryId } : note ), }), - addNote: (state, { payload }: PayloadAction) => ({ - ...state, - notes: [...state.notes, payload], - }), deleteNotes: (state, { payload }: PayloadAction) => ({ ...state, notes: state.notes.filter((note) => !payload.includes(note.id)), diff --git a/src/client/slices/settings.ts b/src/client/slices/settings.ts index 2968bd5c..d0ec697d 100644 --- a/src/client/slices/settings.ts +++ b/src/client/slices/settings.ts @@ -27,49 +27,33 @@ const settingsSlice = createSlice({ name: 'settings', initialState, reducers: { - toggleSettingsModal: (state) => ({ - ...state, - isOpen: !state.isOpen, - }), - updateCodeMirrorOption: ( - state, - { payload }: PayloadAction<{ key: string; value: string }> - ) => ({ - ...state, - codeMirrorOptions: { - ...state.codeMirrorOptions, - [payload.key]: payload.value, - }, - }), - togglePreviewMarkdown: (state) => ({ - ...state, - previewMarkdown: !state.previewMarkdown, - }), - toggleDarkTheme: (state) => ({ - ...state, - darkTheme: !state.darkTheme, - }), - toggleSidebarVisibility: (state) => ({ - ...state, - sidebarVisible: !state.sidebarVisible, - }), - updateNotesSortStrategy: (state, { payload }: PayloadAction) => ({ - ...state, - notesSortKey: payload, - }), - loadSettings: (state) => ({ - ...state, - loading: true, - }), - loadSettingsError: (state) => ({ - ...state, - loading: false, - }), - loadSettingsSuccess: (state, { payload }: PayloadAction) => ({ - ...payload, - isOpen: false, - loading: false, - }), + toggleSettingsModal: (state) => { + state.isOpen = !state.isOpen + }, + updateCodeMirrorOption: (state, { payload }: PayloadAction<{ key: string; value: string }>) => { + state.codeMirrorOptions[payload.key] = payload.value + }, + togglePreviewMarkdown: (state) => { + state.previewMarkdown = !state.previewMarkdown + }, + toggleDarkTheme: (state) => { + state.darkTheme = !state.darkTheme + }, + toggleSidebarVisibility: (state) => { + state.sidebarVisible = !state.sidebarVisible + }, + updateNotesSortStrategy: (state, { payload }: PayloadAction) => { + state.notesSortKey = payload + }, + loadSettings: (state) => { + state.loading = true + }, + loadSettingsError: (state) => { + state.loading = false + }, + loadSettingsSuccess: (state, { payload }: PayloadAction) => { + return { ...payload, loading: false } + }, }, }) diff --git a/src/client/slices/sync.ts b/src/client/slices/sync.ts index e0a39924..51e98c47 100644 --- a/src/client/slices/sync.ts +++ b/src/client/slices/sync.ts @@ -3,35 +3,31 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' import { SyncState, SyncStatePayload } from '@/types' const initialState: SyncState = { - error: '', syncing: false, - lastSynced: '', pendingSync: false, + lastSynced: '', + error: '', } const syncSlice = createSlice({ name: 'sync', initialState, reducers: { - setPendingSync: (state) => ({ - ...state, - pendingSync: true, - }), - syncState: (state, { payload }: PayloadAction) => ({ - ...state, - syncing: true, - }), - syncStateError: (state, { payload }: PayloadAction) => ({ - ...state, - error: payload, - syncing: false, - }), - syncStateSuccess: (state, { payload }: PayloadAction) => ({ - ...state, - lastSynced: payload, - syncing: false, - pendingSync: false, - }), + setPendingSync: (state) => { + state.pendingSync = true + }, + syncState: (state, { payload }: PayloadAction) => { + state.syncing = true + }, + syncStateError: (state, { payload }: PayloadAction) => { + state.syncing = false + state.error = payload + }, + syncStateSuccess: (state, { payload }: PayloadAction) => { + state.syncing = false + state.lastSynced = payload + state.pendingSync = false + }, }, }) diff --git a/src/client/utils/notesSortStrategies.ts b/src/client/utils/notesSortStrategies.ts index 1ec7ae20..5a375e5c 100644 --- a/src/client/utils/notesSortStrategies.ts +++ b/src/client/utils/notesSortStrategies.ts @@ -7,48 +7,50 @@ export interface NotesSortStrategy { sort: (a: NoteItem, b: NoteItem) => number } -const _favorites: NotesSortStrategy = { +const favorites: NotesSortStrategy = { sort: (a: NoteItem, b: NoteItem): number => { if (a.favorite && !b.favorite) return -1 if (!a.favorite && b.favorite) return 1 + return 0 }, } -const _createdDate: NotesSortStrategy = { +const createdDate: NotesSortStrategy = { sort: (a: NoteItem, b: NoteItem): number => { - let dateA = new Date(a.created) - let dateB = new Date(b.created) + const dateA = new Date(a.created) + const dateB = new Date(b.created) return dateA < dateB ? 1 : -1 }, } -const _lastUpdated: NotesSortStrategy = { +const lastUpdated: NotesSortStrategy = { sort: (a: NoteItem, b: NoteItem): number => { - let dateA = new Date(a.lastUpdated) - let dateB = new Date(b.lastUpdated) + const dateA = new Date(a.lastUpdated) + const dateB = new Date(b.lastUpdated) // the first note in the list should consistently sort after if it is created at the same time return dateA < dateB ? 1 : -1 }, } -const _title: NotesSortStrategy = { +const title: NotesSortStrategy = { sort: (a: NoteItem, b: NoteItem): number => { - let titleA = getNoteTitle(a.text) - let titleB = getNoteTitle(b.text) + const titleA = getNoteTitle(a.text) + const titleB = getNoteTitle(b.text) if (titleA === titleB) return 0 + return titleA > titleB ? 1 : -1 }, } -export const _sortStrategyMap: { [key in NotesSortKey]: NotesSortStrategy } = { - [NotesSortKey.LAST_UPDATED]: _lastUpdated, - [NotesSortKey.FAVORITES]: _favorites, - [NotesSortKey.TITLE]: _title, - [NotesSortKey.CREATED_DATE]: _createdDate, +export const sortStrategyMap: { [key in NotesSortKey]: NotesSortStrategy } = { + [NotesSortKey.LAST_UPDATED]: lastUpdated, + [NotesSortKey.FAVORITES]: favorites, + [NotesSortKey.TITLE]: title, + [NotesSortKey.CREATED_DATE]: createdDate, } -export const getNotesSorter = (notesSortKey: NotesSortKey) => _sortStrategyMap[notesSortKey].sort +export const getNotesSorter = (notesSortKey: NotesSortKey) => sortStrategyMap[notesSortKey].sort From ebf6836bb312cbaf0034857cc2cdeabf645a8658 Mon Sep 17 00:00:00 2001 From: Tania Rascia Date: Tue, 6 Oct 2020 21:56:36 -0500 Subject: [PATCH 2/3] Refactor --- src/client/api/index.ts | 4 +- src/client/containers/AppSidebar.tsx | 26 +- src/client/containers/ContextMenuOptions.tsx | 12 +- src/client/containers/KeyboardShortcuts.tsx | 14 +- src/client/containers/NoteList.tsx | 6 +- src/client/containers/TakeNoteApp.tsx | 8 +- src/client/sagas/index.ts | 12 +- src/client/slices/auth.ts | 6 +- src/client/slices/category.ts | 23 +- src/client/slices/note.ts | 303 ++++++++++--------- src/client/slices/settings.ts | 12 +- src/client/slices/sync.ts | 12 +- src/client/types/index.ts | 10 +- 13 files changed, 238 insertions(+), 210 deletions(-) diff --git a/src/client/api/index.ts b/src/client/api/index.ts index 9198d514..9a08be89 100644 --- a/src/client/api/index.ts +++ b/src/client/api/index.ts @@ -1,4 +1,4 @@ -import { NoteItem, SyncStatePayload, SettingsState } from '../types' +import { NoteItem, SyncPayload, SettingsState } from '../types' import { welcomeNote } from '@/api/welcomeNote' import { scratchpadNote } from '@/api/scratchpadNote' @@ -53,7 +53,7 @@ export const requestCategories = () => new Promise(getLocalStorage('categories') export const requestSettings = () => new Promise(getLocalStorage('settings', 'Could not load settings')) -export const saveState = ({ categories, notes }: SyncStatePayload) => +export const saveState = ({ categories, notes }: SyncPayload) => new Promise((resolve) => { localStorage.setItem('categories', JSON.stringify(categories)) localStorage.setItem('notes', JSON.stringify(notes)) diff --git a/src/client/containers/AppSidebar.tsx b/src/client/containers/AppSidebar.tsx index bd250f04..3156a6f4 100644 --- a/src/client/containers/AppSidebar.tsx +++ b/src/client/containers/AppSidebar.tsx @@ -15,13 +15,13 @@ import { addNote, swapFolder, updateActiveNote, - addFavoriteNote, - addTrashedNote, + assignFavoriteToNotes, + assignTrashToNotes, updateSelectedNotes, - restoreTrashedNote, + unassignTrashFromNotes, } from '@/slices/note' import { toggleSettingsModal, togglePreviewMarkdown } from '@/slices/settings' -import { syncState } from '@/slices/sync' +import { sync } from '@/slices/sync' import { getSettings, getNotes, getCategories, getSync } from '@/selectors' import { CategoryItem, NoteItem } from '@/types' import { newNoteHandlerHelper, getActiveNote } from '@/utils/helpers' @@ -50,13 +50,13 @@ export const AppSidebar: React.FC = () => { const _updateSelectedNotes = (noteId: string, multiSelect: boolean) => dispatch(updateSelectedNotes({ noteId, multiSelect })) const _swapFolder = (folder: Folder) => dispatch(swapFolder(folder)) - const _syncState = (notes: NoteItem[], categories: CategoryItem[]) => - dispatch(syncState({ notes, categories })) + const _sync = (notes: NoteItem[], categories: CategoryItem[]) => + dispatch(sync({ notes, categories })) const _toggleSettingsModal = () => dispatch(toggleSettingsModal()) const _togglePreviewMarkdown = () => dispatch(togglePreviewMarkdown()) - const _addTrashedNote = (noteId: string) => dispatch(addTrashedNote(noteId)) - const _restoreTrashedNote = (noteId: string) => dispatch(restoreTrashedNote(noteId)) - const _addFavoriteNote = (noteId: string) => dispatch(addFavoriteNote(noteId)) + const _assignTrashToNotes = (noteId: string) => dispatch(assignTrashToNotes(noteId)) + const _unassignTrashFromNotes = (noteId: string) => dispatch(unassignTrashFromNotes(noteId)) + const _assignFavoriteToNotes = (noteId: string) => dispatch(assignFavoriteToNotes(noteId)) // =========================================================================== // Handlers @@ -75,7 +75,7 @@ export const AppSidebar: React.FC = () => { _updateSelectedNotes ) - const syncNotesHandler = () => _syncState(notes, categories) + const syncNotesHandler = () => _sync(notes, categories) const settingsHandler = () => _toggleSettingsModal() return ( @@ -109,7 +109,7 @@ export const AppSidebar: React.FC = () => { text={LabelText.NOTES} dataTestID={TestID.FOLDER_NOTES} folder={Folder.ALL} - addNoteType={_restoreTrashedNote} + addNoteType={_unassignTrashFromNotes} /> { dataTestID={TestID.FOLDER_FAVORITES} folder={Folder.FAVORITES} swapFolder={_swapFolder} - addNoteType={_addFavoriteNote} + addNoteType={_assignFavoriteToNotes} /> { dataTestID={TestID.FOLDER_TRASH} folder={Folder.TRASH} swapFolder={_swapFolder} - addNoteType={_addTrashedNote} + addNoteType={_assignTrashToNotes} />

Categories

diff --git a/src/client/containers/ContextMenuOptions.tsx b/src/client/containers/ContextMenuOptions.tsx index bd433c80..304a478c 100644 --- a/src/client/containers/ContextMenuOptions.tsx +++ b/src/client/containers/ContextMenuOptions.tsx @@ -9,8 +9,8 @@ import { ContextMenuOption } from '@/components/NoteList/ContextMenuOption' import { downloadNotes } from '@/utils/helpers' import { deleteNotes, - toggleFavoriteNote, - toggleTrashedNote, + toggleFavoriteNotes, + toggleTrashNotes, addCategoryToNote, updateActiveCategoryId, updateActiveNote, @@ -108,8 +108,8 @@ const NotesOptions: React.FC = ({ clickedNote }) => { const dispatch = useDispatch() const _deleteNotes = (noteIds: string[]) => dispatch(deleteNotes(noteIds)) - const _toggleTrashedNote = (noteId: string) => dispatch(toggleTrashedNote(noteId)) - const _toggleFavoriteNote = (noteId: string) => dispatch(toggleFavoriteNote(noteId)) + const _toggleTrashNotes = (noteId: string) => dispatch(toggleTrashNotes(noteId)) + const _toggleFavoriteNotes = (noteId: string) => dispatch(toggleFavoriteNotes(noteId)) const _addCategoryToNote = (categoryId: string, noteId: string) => dispatch(addCategoryToNote({ categoryId, noteId })) const _updateActiveNote = (noteId: string, multiSelect: boolean) => @@ -129,8 +129,8 @@ const NotesOptions: React.FC = ({ clickedNote }) => { : [clickedNote], categories ) - const favoriteNoteHandler = () => _toggleFavoriteNote(clickedNote.id) - const trashNoteHandler = () => _toggleTrashedNote(clickedNote.id) + const favoriteNoteHandler = () => _toggleFavoriteNotes(clickedNote.id) + const trashNoteHandler = () => _toggleTrashNotes(clickedNote.id) const removeCategoryFromNoteHandler = () => { _addCategoryToNote('', clickedNote.id) _updateActiveNote(clickedNote.id, false) diff --git a/src/client/containers/KeyboardShortcuts.tsx b/src/client/containers/KeyboardShortcuts.tsx index d601c161..e2bcfb19 100644 --- a/src/client/containers/KeyboardShortcuts.tsx +++ b/src/client/containers/KeyboardShortcuts.tsx @@ -14,12 +14,12 @@ import { useKey } from '@/utils/hooks' import { addNote, swapFolder, - toggleTrashedNote, + toggleTrashNotes, updateActiveNote, updateSelectedNotes, updateNote, } from '@/slices/note' -import { syncState } from '@/slices/sync' +import { sync } from '@/slices/sync' import { getCategories, getNotes, getSettings } from '@/selectors' import { CategoryItem, NoteItem } from '@/types' import { toggleDarkTheme, togglePreviewMarkdown, updateCodeMirrorOption } from '@/slices/settings' @@ -49,9 +49,9 @@ export const KeyboardShortcuts: React.FC = () => { const _updateSelectedNotes = (noteId: string, multiSelect: boolean) => dispatch(updateSelectedNotes({ noteId, multiSelect })) const _swapFolder = (folder: Folder) => dispatch(swapFolder(folder)) - const _toggleTrashedNote = (noteId: string) => dispatch(toggleTrashedNote(noteId)) - const _syncState = (notes: NoteItem[], categories: CategoryItem[]) => - dispatch(syncState({ notes, categories })) + const _toggleTrashNotes = (noteId: string) => dispatch(toggleTrashNotes(noteId)) + const _sync = (notes: NoteItem[], categories: CategoryItem[]) => + dispatch(sync({ notes, categories })) const _togglePreviewMarkdown = () => dispatch(togglePreviewMarkdown()) const _toggleDarkTheme = () => dispatch(toggleDarkTheme()) const _updateCodeMirrorOption = (key: string, value: string) => @@ -80,8 +80,8 @@ export const KeyboardShortcuts: React.FC = () => { _updateSelectedNotes ) const newTempCategoryHandler = () => !addingTempCategory && setAddingTempCategory(true) - const trashNoteHandler = () => _toggleTrashedNote(activeNote!.id) - const syncNotesHandler = () => _syncState(notes, categories) + const trashNoteHandler = () => _toggleTrashNotes(activeNote!.id) + const syncNotesHandler = () => _sync(notes, categories) const downloadNotesHandler = () => downloadNotes( selectedNotesIds.includes(activeNote!.id) diff --git a/src/client/containers/NoteList.tsx b/src/client/containers/NoteList.tsx index 870e4a51..bd273c4e 100644 --- a/src/client/containers/NoteList.tsx +++ b/src/client/containers/NoteList.tsx @@ -11,7 +11,7 @@ import { ContextMenu } from '@/containers/ContextMenu' import { getNoteTitle, shouldOpenContextMenu, debounceEvent } from '@/utils/helpers' import { useKey } from '@/utils/hooks' import { - emptyTrash, + permanentlyEmptyTrash, pruneNotes, updateActiveNote, searchNotes, @@ -41,7 +41,7 @@ export const NoteList: React.FC = () => { const _updateSelectedNotes = (noteId: string, multiSelect: boolean) => dispatch(updateSelectedNotes({ noteId, multiSelect })) - const _emptyTrash = () => dispatch(emptyTrash()) + const _permanentlyEmptyTrash = () => dispatch(permanentlyEmptyTrash()) const _toggleSidebarVisibility = () => dispatch(toggleSidebarVisibility()) const _pruneNotes = () => dispatch(pruneNotes()) const _updateActiveNote = (noteId: string, multiSelect: boolean) => @@ -171,7 +171,7 @@ export const NoteList: React.FC = () => { _emptyTrash()} + handler={() => _permanentlyEmptyTrash()} > Empty Trash diff --git a/src/client/containers/TakeNoteApp.tsx b/src/client/containers/TakeNoteApp.tsx index f8c5c7ee..8bd731f2 100644 --- a/src/client/containers/TakeNoteApp.tsx +++ b/src/client/containers/TakeNoteApp.tsx @@ -13,7 +13,7 @@ import { useInterval, useBeforeUnload } from '@/utils/hooks' import { getWebsiteTitle, determineAppClass, getActiveCategory } from '@/utils/helpers' import { loadCategories, swapCategories } from '@/slices/category' import { loadNotes } from '@/slices/note' -import { syncState } from '@/slices/sync' +import { sync } from '@/slices/sync' import { loadSettings } from '@/slices/settings' import { NoteItem, CategoryItem } from '@/types' import { getSettings, getNotes, getCategories, getSync } from '@/selectors' @@ -41,8 +41,8 @@ export const TakeNoteApp: React.FC = () => { const _loadSettings = () => dispatch(loadSettings()) const _swapCategories = (categoryId: number, destinationId: number) => dispatch(swapCategories({ categoryId, destinationId })) - const _syncState = (notes: NoteItem[], categories: CategoryItem[]) => - dispatch(syncState({ notes, categories })) + const _sync = (notes: NoteItem[], categories: CategoryItem[]) => + dispatch(sync({ notes, categories })) // =========================================================================== // Handlers @@ -71,7 +71,7 @@ export const TakeNoteApp: React.FC = () => { }, []) useInterval(() => { - _syncState(notes, categories) + _sync(notes, categories) }, 20000) useBeforeUnload((event: BeforeUnloadEvent) => (pendingSync ? event.preventDefault() : null)) diff --git a/src/client/sagas/index.ts b/src/client/sagas/index.ts index 8b4a9de4..5deefb0c 100644 --- a/src/client/sagas/index.ts +++ b/src/client/sagas/index.ts @@ -6,7 +6,7 @@ import axios from 'axios' import { requestCategories, requestNotes, requestSettings, saveState, saveSettings } from '@/api' import { loadCategories, loadCategoriesError, loadCategoriesSuccess } from '@/slices/category' import { loadNotes, loadNotesError, loadNotesSuccess } from '@/slices/note' -import { syncState, syncStateError, syncStateSuccess } from '@/slices/sync' +import { sync, syncError, syncSuccess } from '@/slices/sync' import { login, loginSuccess, loginError, logout, logoutSuccess } from '@/slices/auth' import { updateCodeMirrorOption, @@ -18,7 +18,7 @@ import { toggleSettingsModal, updateNotesSortStrategy, } from '@/slices/settings' -import { SyncStateAction } from '@/types' +import { SyncAction } from '@/types' import { getSettings } from '@/selectors' /** @@ -92,12 +92,12 @@ function* fetchSettings() { } } -function* postState({ payload }: SyncStateAction) { +function* syncData({ payload }: SyncAction) { try { yield saveState(payload) - yield put(syncStateSuccess(dayjs().format())) + yield put(syncSuccess(dayjs().format())) } catch (error) { - yield put(syncStateError(error.message)) + yield put(syncError(error.message)) } } @@ -117,7 +117,7 @@ function* rootSaga() { takeLatest(loadNotes.type, fetchNotes), takeLatest(loadCategories.type, fetchCategories), takeLatest(loadSettings.type, fetchSettings), - takeLatest(syncState.type, postState), + takeLatest(sync.type, syncData), takeLatest( [ toggleDarkTheme.type, diff --git a/src/client/slices/auth.ts b/src/client/slices/auth.ts index 71ba31d6..c1bc649d 100644 --- a/src/client/slices/auth.ts +++ b/src/client/slices/auth.ts @@ -3,10 +3,10 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' import { AuthState } from '@/types' const initialState: AuthState = { - loading: true, currentUser: {}, isAuthenticated: false, error: '', + loading: true, } const authSlice = createSlice({ @@ -16,19 +16,23 @@ const authSlice = createSlice({ login: (state) => { state.loading = true }, + loginSuccess: (state, { payload }: PayloadAction) => { state.currentUser = payload state.isAuthenticated = true state.loading = false }, + loginError: (state, { payload }: PayloadAction) => { state.error = payload state.isAuthenticated = false state.loading = false }, + logout: (state) => { state.loading = true }, + logoutSuccess: (state) => { state.isAuthenticated = false state.currentUser = {} diff --git a/src/client/slices/category.ts b/src/client/slices/category.ts index 8075ec8c..d546cf9b 100644 --- a/src/client/slices/category.ts +++ b/src/client/slices/category.ts @@ -12,12 +12,12 @@ const _swapCategories = (categories: CategoryItem[], categoryId: number, destina const initialState: CategoryState = { categories: [], - error: '', - loading: true, editingCategory: { id: '', tempName: '', }, + error: '', + loading: true, } const categorySlice = createSlice({ @@ -27,22 +27,30 @@ const categorySlice = createSlice({ addCategory: (state, { payload }: PayloadAction) => { state.categories.push(payload) }, + updateCategory: (state, { payload }: PayloadAction) => ({ ...state, categories: state.categories.map((category) => category.id === payload.id ? { ...category, name: payload.name } : category ), }), + + deleteCategory: (state, { payload }: PayloadAction) => { + state.categories = state.categories.filter((category) => category.id !== payload) + }, + categoryDragEnter: (state, { payload }: PayloadAction) => { state.categories = state.categories.map((category) => category.id === payload.id ? { ...category, draggedOver: true } : category ) }, + categoryDragLeave: (state, { payload }: PayloadAction) => { state.categories = state.categories.map((category) => category.id === payload.id ? { ...category, draggedOver: false } : category ) }, + swapCategories: ( state, { payload }: PayloadAction<{ categoryId: number; destinationId: number }> @@ -53,17 +61,20 @@ const categorySlice = createSlice({ payload.destinationId ) }, - deleteCategory: (state, { payload }: PayloadAction) => { - state.categories = state.categories.filter((category) => category.id !== payload) - }, + setCategoryEdit: (state, { payload }: PayloadAction<{ id: string; tempName: string }>) => { state.editingCategory = payload }, - loadCategories: () => initialState, + + loadCategories: (state) => { + state.loading = true + }, + loadCategoriesError: (state, { payload }: PayloadAction) => { state.loading = false state.error = payload }, + loadCategoriesSuccess: (state, { payload }: PayloadAction) => { state.categories = payload state.loading = false diff --git a/src/client/slices/note.ts b/src/client/slices/note.ts index 6a851dfa..650548d0 100644 --- a/src/client/slices/note.ts +++ b/src/client/slices/note.ts @@ -36,14 +36,14 @@ export const getFirstNoteId = (folder: Folder, notes: NoteItem[], categoryId?: s } const initialState: NoteState = { + notes: [], activeCategoryId: '', activeFolder: Folder.ALL, activeNoteId: '', selectedNotesIds: [], + searchValue: '', error: '', loading: true, - notes: [], - searchValue: '', } const noteSlice = createSlice({ @@ -53,210 +53,215 @@ const noteSlice = createSlice({ addNote: (state, { payload }: PayloadAction) => { state.notes.push(payload) }, - addCategoryToNote: ( - state, - { payload }: PayloadAction<{ categoryId: string; noteId: string }> - ) => ({ - ...state, - notes: state.selectedNotesIds.includes(payload.noteId) - ? state.notes.map((note) => - state.selectedNotesIds.includes(note.id) - ? { ...note, category: payload.categoryId } - : note - ) - : state.notes.map((note) => - note.id === payload.noteId ? { ...note, category: payload.categoryId } : note - ), - }), - deleteNotes: (state, { payload }: PayloadAction) => ({ - ...state, - notes: state.notes.filter((note) => !payload.includes(note.id)), - activeNoteId: getNewActiveNoteId( + + updateNote: (state, { payload }: PayloadAction) => { + state.notes = state.notes.map((note) => + note.id === payload.id + ? { ...note, text: payload.text, lastUpdated: payload.lastUpdated } + : note + ) + }, + + deleteNotes: (state, { payload }: PayloadAction) => { + state.notes = state.notes.filter((note) => !payload.includes(note.id)) + state.activeNoteId = getNewActiveNoteId( state.notes, state.activeNoteId, state.activeCategoryId, state.activeFolder - ), - selectedNotesIds: [ + ) + state.selectedNotesIds = [ getNewActiveNoteId( state.notes, state.activeNoteId, state.activeCategoryId, state.activeFolder ), - ], - }), - emptyTrash: (state) => ({ - ...state, - notes: state.notes.filter((note) => !note.trash), - }), - loadNotes: () => initialState, - loadNotesError: (state, { payload }: PayloadAction) => ({ - ...state, - loading: false, - error: payload, - }), - loadNotesSuccess: (state, { payload }: PayloadAction) => ({ - ...state, - notes: payload, - activeNoteId: getFirstNoteId(Folder.ALL, payload), - selectedNotesIds: [getFirstNoteId(Folder.ALL, payload)], - loading: false, - }), - pruneNotes: (state) => ({ - ...state, - notes: state.notes.filter( - (note) => note.text !== '' || state.selectedNotesIds.includes(note.id) - ), - }), - searchNotes: (state, { payload }: PayloadAction) => ({ - ...state, - searchValue: payload, - }), - updateActiveCategoryId: (state, { payload }: PayloadAction) => ({ - ...state, - activeCategoryId: payload, - activeFolder: Folder.CATEGORY, - activeNoteId: getFirstNoteId(Folder.CATEGORY, state.notes, payload), - selectedNotesIds: [getFirstNoteId(Folder.CATEGORY, state.notes, payload)], - }), - swapFolder: (state, { payload }: PayloadAction) => ({ - ...state, - activeFolder: payload, - activeCategoryId: '', - activeNoteId: getFirstNoteId(payload, state.notes), - selectedNotesIds: [getFirstNoteId(payload, state.notes)], - }), + ] + }, + + addCategoryToNote: ( + state, + { payload }: PayloadAction<{ categoryId: string; noteId: string }> + ) => { + state.notes = state.selectedNotesIds.includes(payload.noteId) + ? // Multi + state.notes.map((note) => + state.selectedNotesIds.includes(note.id) + ? { ...note, category: payload.categoryId } + : note + ) + : // Single + state.notes.map((note) => + note.id === payload.noteId ? { ...note, category: payload.categoryId } : note + ) + }, + updateActiveNote: ( state, { payload }: PayloadAction<{ noteId?: string; multiSelect: boolean }> - ) => ({ - ...state, - activeNoteId: payload.multiSelect + ) => { + state.activeNoteId = payload.multiSelect ? state.notes.filter(({ id }) => state.selectedNotesIds.includes(id)).slice(-1)[0].id - : payload.noteId!, - }), - toggleFavoriteNote: (state, { payload }: PayloadAction) => ({ - ...state, - notes: state.selectedNotesIds.includes(payload) + : payload.noteId! + }, + + updateActiveCategoryId: (state, { payload }: PayloadAction) => { + state.activeCategoryId = payload + state.activeFolder = Folder.CATEGORY + state.activeNoteId = getFirstNoteId(Folder.CATEGORY, state.notes, payload) + state.selectedNotesIds = [getFirstNoteId(Folder.CATEGORY, state.notes, payload)] + }, + + swapFolder: (state, { payload }: PayloadAction) => { + state.activeFolder = payload + state.activeCategoryId = '' + state.activeNoteId = getFirstNoteId(payload, state.notes) + state.selectedNotesIds = [getFirstNoteId(payload, state.notes)] + }, + + assignFavoriteToNotes: (state, { payload }: PayloadAction) => { + state.notes = state.notes.map((note) => { + if (state.selectedNotesIds.includes(payload)) { + return state.selectedNotesIds.includes(note.id) ? { ...note, favorite: true } : note + } + if (note.id === payload) { + return { ...note, favorite: true } + } + + return note + }) + }, + + toggleFavoriteNotes: (state, { payload }: PayloadAction) => { + state.notes = state.selectedNotesIds.includes(payload) ? state.notes.map((note) => state.selectedNotesIds.includes(note.id) ? { ...note, favorite: !note.favorite } : note ) : state.notes.map((note) => note.id === payload ? { ...note, favorite: !note.favorite } : note - ), - }), - restoreTrashedNote: (state, { payload }: PayloadAction) => ({ - ...state, - notes: state.notes.map((note) => { + ) + }, + + assignTrashToNotes: (state, { payload }: PayloadAction) => { + state.notes = state.notes.map((note) => { if (state.selectedNotesIds.includes(payload)) { - return state.selectedNotesIds.includes(note.id) && note.trash - ? { ...note, trash: false } - : note + return state.selectedNotesIds.includes(note.id) ? { ...note, trash: true } : note } if (note.id === payload) { - return { ...note, trash: false } + return { ...note, trash: true } } return note - }), - }), - toggleTrashedNote: (state, { payload }: PayloadAction) => ({ - ...state, - notes: state.selectedNotesIds.includes(payload) + }) + state.activeNoteId = getNewActiveNoteId( + state.notes, + payload, + state.activeCategoryId, + state.activeFolder + ) + state.selectedNotesIds = [ + getNewActiveNoteId(state.notes, payload, state.activeCategoryId, state.activeFolder), + ] + }, + + toggleTrashNotes: (state, { payload }: PayloadAction) => { + state.notes = state.selectedNotesIds.includes(payload) ? state.notes.map((note) => state.selectedNotesIds.includes(note.id) ? { ...note, trash: !note.trash } : note ) - : state.notes.map((note) => (note.id === payload ? { ...note, trash: !note.trash } : note)), - activeNoteId: getNewActiveNoteId( + : state.notes.map((note) => (note.id === payload ? { ...note, trash: !note.trash } : note)) + state.activeNoteId = getNewActiveNoteId( state.notes, payload, state.activeCategoryId, state.activeFolder - ), - selectedNotesIds: [ + ) + state.selectedNotesIds = [ getNewActiveNoteId(state.notes, payload, state.activeCategoryId, state.activeFolder), - ], - }), - addFavoriteNote: (state, { payload }: PayloadAction) => ({ - ...state, - notes: state.notes.map((note) => { - if (state.selectedNotesIds.includes(payload)) { - return state.selectedNotesIds.includes(note.id) ? { ...note, favorite: true } : note - } - if (note.id === payload) { - return { ...note, favorite: true } - } + ] + }, - return note - }), - }), - addTrashedNote: (state, { payload }: PayloadAction) => ({ - ...state, - notes: state.notes.map((note) => { + unassignTrashFromNotes: (state, { payload }: PayloadAction) => { + state.notes = state.notes.map((note) => { if (state.selectedNotesIds.includes(payload)) { - return state.selectedNotesIds.includes(note.id) ? { ...note, trash: true } : note + return state.selectedNotesIds.includes(note.id) && note.trash + ? { ...note, trash: false } + : note } if (note.id === payload) { - return { ...note, trash: true } + return { ...note, trash: false } } return note - }), - activeNoteId: getNewActiveNoteId( - state.notes, - payload, - state.activeCategoryId, - state.activeFolder - ), - selectedNotesIds: [ - getNewActiveNoteId(state.notes, payload, state.activeCategoryId, state.activeFolder), - ], - }), - updateNote: (state, { payload }: PayloadAction) => ({ - ...state, - notes: state.notes.map((note) => - note.id === payload.id - ? { ...note, text: payload.text, lastUpdated: payload.lastUpdated } - : note - ), - }), + }) + }, + updateSelectedNotes: ( state, { payload: { noteId, multiSelect } }: PayloadAction<{ noteId: string; multiSelect: boolean }> - ) => ({ - ...state, - selectedNotesIds: multiSelect + ) => { + state.selectedNotesIds = multiSelect ? state.selectedNotesIds.length === 1 && state.selectedNotesIds[0] === noteId ? state.selectedNotesIds : state.selectedNotesIds.includes(noteId) ? state.selectedNotesIds.filter((selectedNoteId) => selectedNoteId !== noteId) : [...state.selectedNotesIds, noteId] - : [noteId], - }), + : [noteId] + }, + + permanentlyEmptyTrash: (state) => { + state.notes = state.notes.filter((note) => !note.trash) + }, + + pruneNotes: (state) => { + state.notes = state.notes.filter( + (note) => note.text !== '' || state.selectedNotesIds.includes(note.id) + ) + }, + + searchNotes: (state, { payload }: PayloadAction) => { + state.searchValue = payload + }, + + loadNotes: (state) => { + state.loading = true + }, + + loadNotesError: (state, { payload }: PayloadAction) => { + state.loading = false + state.error = payload + }, + + loadNotesSuccess: (state, { payload }: PayloadAction) => { + state.notes = payload + state.activeNoteId = getFirstNoteId(Folder.ALL, payload) + state.selectedNotesIds = [getFirstNoteId(Folder.ALL, payload)] + state.loading = false + }, }, }) export const { - addCategoryToNote, addNote, + updateNote, deleteNotes, - emptyTrash, - loadNotes, - loadNotesError, - loadNotesSuccess, - pruneNotes, - searchNotes, + addCategoryToNote, + updateActiveNote, updateActiveCategoryId, swapFolder, - updateActiveNote, - toggleFavoriteNote, - toggleTrashedNote, - addFavoriteNote, - addTrashedNote, - updateNote, + assignFavoriteToNotes, + toggleFavoriteNotes, + assignTrashToNotes, + toggleTrashNotes, + unassignTrashFromNotes, updateSelectedNotes, - restoreTrashedNote, + permanentlyEmptyTrash, + pruneNotes, + searchNotes, + loadNotes, + loadNotesError, + loadNotesSuccess, } = noteSlice.actions export default noteSlice.reducer diff --git a/src/client/slices/settings.ts b/src/client/slices/settings.ts index d0ec697d..734de1f4 100644 --- a/src/client/slices/settings.ts +++ b/src/client/slices/settings.ts @@ -4,8 +4,6 @@ import { SettingsState } from '@/types' import { NotesSortKey, DirectionText } from '@/utils/enums' export const initialState: SettingsState = { - isOpen: false, - loading: false, previewMarkdown: false, darkTheme: false, sidebarVisible: true, @@ -21,6 +19,8 @@ export const initialState: SettingsState = { dragDrop: false, direction: DirectionText.LEFT_TO_RIGHT, }, + isOpen: false, + loading: false, } const settingsSlice = createSlice({ @@ -30,27 +30,35 @@ const settingsSlice = createSlice({ toggleSettingsModal: (state) => { state.isOpen = !state.isOpen }, + updateCodeMirrorOption: (state, { payload }: PayloadAction<{ key: string; value: string }>) => { state.codeMirrorOptions[payload.key] = payload.value }, + togglePreviewMarkdown: (state) => { state.previewMarkdown = !state.previewMarkdown }, + toggleDarkTheme: (state) => { state.darkTheme = !state.darkTheme }, + toggleSidebarVisibility: (state) => { state.sidebarVisible = !state.sidebarVisible }, + updateNotesSortStrategy: (state, { payload }: PayloadAction) => { state.notesSortKey = payload }, + loadSettings: (state) => { state.loading = true }, + loadSettingsError: (state) => { state.loading = false }, + loadSettingsSuccess: (state, { payload }: PayloadAction) => { return { ...payload, loading: false } }, diff --git a/src/client/slices/sync.ts b/src/client/slices/sync.ts index 51e98c47..7f0c27dc 100644 --- a/src/client/slices/sync.ts +++ b/src/client/slices/sync.ts @@ -1,12 +1,12 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' -import { SyncState, SyncStatePayload } from '@/types' +import { SyncState, SyncPayload } from '@/types' const initialState: SyncState = { - syncing: false, pendingSync: false, lastSynced: '', error: '', + syncing: false, } const syncSlice = createSlice({ @@ -16,14 +16,14 @@ const syncSlice = createSlice({ setPendingSync: (state) => { state.pendingSync = true }, - syncState: (state, { payload }: PayloadAction) => { + sync: (state, { payload }: PayloadAction) => { state.syncing = true }, - syncStateError: (state, { payload }: PayloadAction) => { + syncError: (state, { payload }: PayloadAction) => { state.syncing = false state.error = payload }, - syncStateSuccess: (state, { payload }: PayloadAction) => { + syncSuccess: (state, { payload }: PayloadAction) => { state.syncing = false state.lastSynced = payload state.pendingSync = false @@ -31,6 +31,6 @@ const syncSlice = createSlice({ }, }) -export const { syncState, syncStateError, syncStateSuccess, setPendingSync } = syncSlice.actions +export const { sync, syncError, syncSuccess, setPendingSync } = syncSlice.actions export default syncSlice.reducer diff --git a/src/client/types/index.ts b/src/client/types/index.ts index 8d90f5ff..ee3434bf 100644 --- a/src/client/types/index.ts +++ b/src/client/types/index.ts @@ -1,7 +1,7 @@ import React from 'react' import { Folder, NotesSortKey } from '@/utils/enums' -import { syncState } from '@/slices/sync' +import { sync } from '@/slices/sync' //============================================================================== // Items @@ -92,14 +92,14 @@ export interface RootState { // API //============================================================================== -export interface SyncStatePayload { +export interface SyncPayload { categories: CategoryItem[] notes: NoteItem[] } -export interface SyncStateAction { - type: typeof syncState.type - payload: SyncStatePayload +export interface SyncAction { + type: typeof sync.type + payload: SyncPayload } //============================================================================== From 900a2760b347ef353adb29506fd6f3ca1e69c3a0 Mon Sep 17 00:00:00 2001 From: Tania Rascia Date: Tue, 6 Oct 2020 22:01:51 -0500 Subject: [PATCH 3/3] Update --- src/client/slices/sync.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/client/slices/sync.ts b/src/client/slices/sync.ts index 7f0c27dc..c61fd9b2 100644 --- a/src/client/slices/sync.ts +++ b/src/client/slices/sync.ts @@ -16,13 +16,16 @@ const syncSlice = createSlice({ setPendingSync: (state) => { state.pendingSync = true }, + sync: (state, { payload }: PayloadAction) => { state.syncing = true }, + syncError: (state, { payload }: PayloadAction) => { state.syncing = false state.error = payload }, + syncSuccess: (state, { payload }: PayloadAction) => { state.syncing = false state.lastSynced = payload