Skip to content

Commit

Permalink
Refactored data persistence
Browse files Browse the repository at this point in the history
  • Loading branch information
mannycolon committed Jun 30, 2021
1 parent 40f23a6 commit 9d32c2b
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 306 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"date-fns": "^2.16.1",
"deep-equal": "^2.0.3",
"deep-freeze": "0.0.1",
"file-saver": "^2.0.2",
"gitea-react-toolkit": "^1.6.0",
Expand Down
8 changes: 2 additions & 6 deletions src/components/WorkingArea/WorkingArea.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,8 @@ export default function WorkingArea({
setSavedBackup(true);
}

// This will get called when the table needs new data
const fetchData = useCallback(({ pageSize, pageIndex }) => {
// This will get called when the table needs new data
// You could fetch your data from literally anywhere,
// even a server. But for this example, we'll just fake it.

// Give this fetch an ID
const fetchId = ++fetchIdRef.current

Expand All @@ -121,8 +118,7 @@ export default function WorkingArea({
setTargetData(targetNotes.slice(startRow, endRow))

setPrecedingItemsCount(sourceNotes.slice(0, pageSize * pageIndex).length)
// Your server could send back total page count.
// For now we'll just fake it, too
// Set total page count.
setPageCount(Math.ceil(sourceNotes.length / pageSize))

setLoading(false)
Expand Down
8 changes: 3 additions & 5 deletions src/hooks/useLocalStorage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { useState } from 'react'

// based on example at https://usehooks.com/useLocalStorage/
import { useState, useCallback } from 'react'

export default function useLocalStorage(key, initialValue) {
// State to store our value
Expand Down Expand Up @@ -31,7 +29,7 @@ export default function useLocalStorage(key, initialValue) {

// Return a wrapped version of useState's setter function that ...
// ... persists the new value to localStorage.
const setValue = value => {
const setValue = useCallback(value => {
try {
// Allow value to be a function so we have same API as useState
const valueToStore =
Expand All @@ -45,7 +43,7 @@ export default function useLocalStorage(key, initialValue) {
// A more advanced implementation would handle the error case
console.log(`useLocalStorage.setValue(${key}) - error:'`, error)
}
}
}, [storedValue, key])

return [storedValue, setValue]
}
141 changes: 35 additions & 106 deletions src/state/contexts/TsvDataContextProvider.js
Original file line number Diff line number Diff line change
@@ -1,102 +1,21 @@
import React, { useState, useEffect, useReducer, useCallback } from 'react';
// import ric from 'ric-shim'
// import equal from 'deep-equal';
// import * as cacheLibrary from 'money-clip';
import React, { useState, useCallback } from 'react';
import { customAlphabet } from 'nanoid/non-secure'
import useDeepCompareEffect from 'use-deep-compare-effect'
import fetchEnglishTsvsAction from '../actions/fetchEnglishTsvsAction';
import fetchTnMarkdownAction from '../actions/fetchTnMarkdownAction';
import getGlTsvContent from '../../helpers/getGlTsvContent';
import generateTimestamp from '../../helpers/generateTimestamp';
import useLoading from '../../hooks/useLoading';
import populateHeaders from '../../helpers/populateHeaders';
import useLocalStorage from '../../hooks/useLocalStorage'

export const TsvDataContext = React.createContext({});

const reducerName = 'tsvDataReducer';
const initialState = {
targetNotes: {},
sourceNotes: {},
glTsvs: {},
bookId: null,
projects: [],
currentProject: null,
};

function tsvDataReducer(state, action) {
switch (action.type) {
case 'SET_BOOK_ID':
return {
...state,
bookId: action.bookId,
};
case 'SET_CURRENT_PROJECT':
const found = state.projects.find(project => project.name === action.project.name)
const projects = found ? state.projects : [...state.projects, action.project];
return {
...state,
projects,
currentProject: action.project,
};
case 'UPDATE_CURRENT_PROJECT':
const foundIndex = state.projects.findIndex(project => project.name === action.project.name)
const newProjects = state.projects.map((project, index) => {
if (foundIndex !== index) {
return project;
} else {
return action.project;
}
})

return {
...state,
projects: newProjects,
currentProject: action.project,
};
case 'REMOVE_CURRENT_PROJECT':
return {
...state,
currentProject: null,
};
case 'SET_PROJECTS':
return {
...state,
projects: action.projects,
};
case 'SET_CACHED_REDUCER':
return {
...initialState,
...action.payload,
};
default:
return state;
}
}

export default function TsvDataContextProvider(props) {
const [state, dispatch] = useReducer(tsvDataReducer, initialState);
const [projects, setProjects] = useLocalStorage('projects', [])
const [currentProject, setCurrentProject] = useLocalStorage('currentProject', null);
const { isLoading, setIsLoading, setIsError, setLoadingMessage, loadingMessage } = useLoading();
const [savedBackup, setSavedBackup] = useState(false);

// useEffect(() => {
// cacheLibrary.getAll().then(cacheData => {
// const payload = cacheData[reducerName];

// if (cacheData[reducerName]) {
// dispatch({
// type: 'SET_CACHED_REDUCER',
// payload,
// })
// }
// });
// }, []);

// useDeepCompareEffect(() => {
// if (!equal(state, initialState)) {
// ric(() => cacheLibrary.set(reducerName, state))
// }
// }, [state])

const fetchTnMarkdown = async (bookUrl, bookId, targetManifest, resourceId) => {
try {
removeProject()
Expand All @@ -122,54 +41,66 @@ export default function TsvDataContextProvider(props) {
timestamp: generateTimestamp(),
})

setBookId(bookId);
setIsLoading(false);
} catch (error) {
console.error(error)
}
}

const setBookId = (bookId) => dispatch({ type: 'SET_BOOK_ID', bookId })

const setProject = (project) => {
const setProject = useCallback((project) => {
setSavedBackup(false);
console.info('setProject()');

dispatch({ type: 'SET_CURRENT_PROJECT', project })
}
let newProjects = []
const foundIndex = projects.findIndex(p => p.name === project.name)

const updateProject = (project) => {
setSavedBackup(false);
if (foundIndex) {
newProjects = projects.map((p, index) => {
if (foundIndex !== index) {
return p;
} else {
return project;
}
})
} else {
newProjects = [...projects, project]
}

setProjects([...newProjects])
setCurrentProject(project)
// dispatch({ type: 'SET_CURRENT_PROJECT', project })
}, [setSavedBackup, projects, setProjects, setCurrentProject])

const updateProject = useCallback((project) => {
console.info('updateProject()');

dispatch({ type: 'UPDATE_CURRENT_PROJECT', project })
}
setProject(project)
}, [setProject])

const removeProject = () => dispatch({ type: 'REMOVE_CURRENT_PROJECT' })
const removeProject = () => setCurrentProject(null)

const saveProjectChanges = (targetRecords) => {
console.info('Saving Project Changes...');
const { currentProject } = state;
const updatedProject = Object.assign({}, currentProject);
updatedProject.targetNotes = targetRecords;
updatedProject.timestamp = generateTimestamp();

dispatch({ type: 'UPDATE_CURRENT_PROJECT', project: updatedProject })
setProject(updatedProject)
// dispatch({ type: 'UPDATE_CURRENT_PROJECT', project: updatedProject })
}

const deleteProject = (projectName) => {
const { projects } = state;
const foundIndex = projects.findIndex(project => project.name === projectName)
const newProjects = [...projects];
newProjects.splice(foundIndex, 1);

dispatch({ type: 'SET_PROJECTS', projects: newProjects })
setProjects([...newProjects])
// dispatch({ type: 'SET_PROJECTS', projects: newProjects })
}

const toggleRecordView = useCallback((e, index) => {
const nanoid = customAlphabet('123456789abcdefghijklmnopqrstuvwxyz', 4);
const currentProject = state.currentProject
const { targetNotes, sourceNotes, bookId } = currentProject
const { targetNotes, sourceNotes, bookId } = currentProject || {}
// Create a copy of the arrays to avoid mutation
const newTargetNotes = Object.assign([], targetNotes)
const newSourceNotes = Object.assign([], sourceNotes)
Expand Down Expand Up @@ -239,12 +170,9 @@ export default function TsvDataContextProvider(props) {
targetNotes: newTargetNotes,
timestamp: generateTimestamp(),
})
}, [state.currentProject])
}, [currentProject, updateProject])

const value = {
state,
dispatch,
setBookId,
setProject,
isLoading,
setIsError,
Expand All @@ -257,6 +185,7 @@ export default function TsvDataContextProvider(props) {
fetchTnMarkdown,
toggleRecordView,
saveProjectChanges,
state: { currentProject, projects, sourceNotes: {} },
}

return <TsvDataContext.Provider value={value}>{props.children}</TsvDataContext.Provider>;
Expand Down
Loading

0 comments on commit 9d32c2b

Please sign in to comment.