Change journals to also not be a complex fetch type.

master
Tom Hacohen 5 years ago
parent 23048cfa63
commit 2946be464c

@ -16,7 +16,7 @@ export default function Debug(props: PropsType) {
const [stateJournalUid, setJournalUid] = React.useState('');
const [entriesUids, setEntriesUids] = React.useState('');
const [result, setResult] = React.useState('');
const journals = useSelector((state: StoreState) => state.cache.journals.value)!;
const journals = useSelector((state: StoreState) => state.cache.journals!);
const journalEntries = useSelector((state: StoreState) => state.cache.entries);
function handleInputChange(func: (value: string) => void) {

@ -16,7 +16,7 @@ import logo from '../images/logo.svg';
import { routeResolver } from '../App';
import { store, JournalsType, UserInfoData, StoreState, CredentialsData } from '../store';
import { store, UserInfoData, StoreState, CredentialsData } from '../store';
import { logout } from '../store/actions';
import * as C from '../constants';
@ -27,7 +27,6 @@ interface PropsType {
}
type PropsTypeInner = RouteComponentProps<{}> & PropsType & {
journals: JournalsType;
userInfo: UserInfoData;
theme: Theme;
};
@ -114,7 +113,6 @@ class SideMenu extends React.PureComponent<PropsTypeInner> {
const mapStateToProps = (state: StoreState, _props: PropsType) => {
return {
journals: state.cache.journals,
userInfo: state.cache.userInfo,
};
};

@ -12,7 +12,6 @@ import { routeResolver } from './App';
import AppBarOverride from './widgets/AppBarOverride';
import LoadingIndicator from './widgets/LoadingIndicator';
import PrettyError from './widgets/PrettyError';
import Journals from './Journals';
import Settings from './Settings';
@ -22,7 +21,7 @@ import Pim from './Pim';
import * as EteSync from 'etesync';
import { CURRENT_VERSION } from 'etesync';
import { store, SettingsType, JournalsType, EntriesType, StoreState, CredentialsData, UserInfoData } from './store';
import { store, SettingsType, JournalsData, EntriesType, StoreState, CredentialsData, UserInfoData } from './store';
import { addJournal, fetchAll, fetchEntries, fetchUserInfo, createUserInfo } from './store/actions';
export interface SyncInfoJournal {
@ -40,7 +39,7 @@ interface PropsType {
type PropsTypeInner = RouteComponentProps<{}> & PropsType & {
settings: SettingsType;
journals: JournalsType;
journals: JournalsData;
entries: EntriesType;
userInfo: UserInfoData;
fetchCount: number;
@ -48,7 +47,7 @@ type PropsTypeInner = RouteComponentProps<{}> & PropsType & {
const syncInfoSelector = createSelector(
(props: PropsTypeInner) => props.etesync,
(props: PropsTypeInner) => props.journals.value!,
(props: PropsTypeInner) => props.journals!,
(props: PropsTypeInner) => props.entries,
(props: PropsTypeInner) => props.userInfo,
(etesync, journals, entries, userInfo) => {
@ -153,11 +152,9 @@ class SyncGate extends React.PureComponent<PropsTypeInner> {
public render() {
const entryArrays = this.props.entries;
const journals = this.props.journals.value;
const journals = this.props.journals;
if (this.props.journals.error) {
return <PrettyError error={this.props.journals.error} />;
} else {
{
const errors: Array<{journal: string, error: Error}> = [];
this.props.entries.forEach((entry, journal) => {
if (entry.error) {

@ -7,8 +7,8 @@ import { List, Map as ImmutableMap } from 'immutable';
import * as EteSync from 'etesync';
import {
JournalsData, FetchType, EntriesData, EntriesFetchRecord, UserInfoData, JournalsFetchRecord,
CredentialsDataRemote, JournalsType, EntriesType, SettingsType,
JournalsData, FetchType, EntriesData, EntriesFetchRecord, UserInfoData,
CredentialsDataRemote, EntriesType, SettingsType,
fetchCount, journals, entries, credentials, userInfo, settingsReducer, encryptionKeyReducer, errorsReducer,
} from './reducers';
@ -18,7 +18,7 @@ export interface StoreState {
settings: SettingsType;
encryptionKey: {key: string};
cache: {
journals: JournalsType;
journals: JournalsData;
entries: EntriesType;
userInfo: UserInfoData;
};
@ -49,19 +49,19 @@ const journalsSerialize = (state: JournalsData) => {
return state.map((x, _uid) => x.serialize()).toJS();
};
const journalsDeserialize = (state: {}) => {
const journalsDeserialize = (state: []) => {
if (state === null) {
return null;
}
const newState = new Map<string, EteSync.Journal>();
const newState = ImmutableMap<string, EteSync.Journal>().asMutable();
Object.keys(state).forEach((uid) => {
const x = state[uid];
const ret = new EteSync.Journal({ uid }, x.version);
ret.deserialize(x);
newState.set(uid, ret);
});
return ImmutableMap(newState);
return newState.asImmutable();
};
const entriesSerialize = (state: FetchType<EntriesData>) => {
@ -110,7 +110,7 @@ const cacheSerialize = (state: any, key: string) => {
});
return ret;
} else if (key === 'journals') {
return journalsSerialize(state.value);
return journalsSerialize(state);
} else if (key === 'userInfo') {
return userInfoSerialize(state);
}
@ -126,7 +126,7 @@ const cacheDeserialize = (state: any, key: string) => {
});
return ImmutableMap(ret);
} else if (key === 'journals') {
return new JournalsFetchRecord({ value: journalsDeserialize(state) });
return journalsDeserialize(state);
} else if (key === 'userInfo') {
return userInfoDeserialize(state);
}

@ -1,4 +1,4 @@
import { Action, ActionFunctionAny, combineActions, handleAction, handleActions } from 'redux-actions';
import { Action, ActionMeta, ActionFunctionAny, combineActions, handleAction, handleActions } from 'redux-actions';
import { shallowEqual } from 'react-redux';
import { List, Map as ImmutableMap, Record } from 'immutable';
@ -31,14 +31,7 @@ function fetchTypeRecord<T>() {
});
}
interface BaseModel {
uid: string;
}
export type JournalsData = ImmutableMap<string, EteSync.Journal>;
export const JournalsFetchRecord = fetchTypeRecord<JournalsData>();
export type JournalsType = FetchType<JournalsData>;
export type JournalsTypeImmutable = Record<JournalsType>;
export type EntriesData = List<EteSync.Entry>;
export const EntriesFetchRecord = fetchTypeRecord<EntriesData>();
@ -112,105 +105,100 @@ export const credentials = handleActions(
{} as CredentialsDataRemote
);
const setMapModelReducer = <T extends Record<any>, V extends BaseModel>(state: T, action: any) => {
const newState = fetchTypeIdentityReducer(state, action);
// Compare the states and see if they are really different
const newItems = newState.get('value', null);
function fetchCreateEntriesReducer(state: EntriesTypeImmutable, action: any) {
const prevState = state.get(action.meta.journal);
const extend = action.meta.prevUid != null;
return state.set(action.meta.journal,
fetchTypeIdentityReducer(prevState, action, extend));
}
if (!newItems) {
return newState;
export const entries = handleActions(
{
[actions.fetchEntries.toString()]: fetchCreateEntriesReducer,
[actions.addEntries.toString()]: fetchCreateEntriesReducer,
[actions.addJournal.toString()]: (state: EntriesTypeImmutable, action: any) => {
const journal = action.meta.item.uid;
const prevState = state.get(journal);
return state.set(journal,
fetchTypeIdentityReducer(prevState, { payload: [] }, false));
},
},
ImmutableMap({})
);
const setMapModelReducer = (state: JournalsData, action: Action<EteSync.Journal[]>) => {
if (action.error || !action.payload) {
return state;
}
const ret = new Map<string, V>();
state = state ?? ImmutableMap<string, EteSync.Journal>().asMutable();
const old = state.asMutable();
newItems.forEach((item: V) => {
return state.withMutations((ret) => {
const items = action.payload!;
for (const item of items) {
const current = old.get(item.uid);
if (!current || !shallowEqual(current.serialize(), item.serialize())) {
ret.set(item.uid, item);
});
}
return newState.set('value', ImmutableMap(ret));
if (current) {
old.delete(item.uid);
}
}
// Delete all the items that were deleted remotely (not handled above).
for (const uid of old.keys()) {
ret.delete(uid);
}
});
};
const addEditMapModelReducer = <T extends Record<any>, V extends BaseModel>(state: T, action: any) => {
const addEditMapModelReducer = (state: JournalsData, action: ActionMeta<EteSync.Journal, { item: EteSync.Journal }>) => {
if (action.error) {
return state.set('error', action.payload);
return state;
} else {
let payload = (action.payload === undefined) ? null : action.payload;
payload = (action.meta === undefined) ? payload : action.meta.item;
state = state.set('error', undefined);
if (action.payload === undefined) {
if (!payload) {
return state;
}
const item = payload as V;
let value = state.get('value', null)!;
value = value.set(item.uid, item);
return state.set('value', value);
const item = payload;
return state.set(item.uid, item);
}
};
const deleteMapModelReducer = <T extends Record<any>>(state: T, action: any) => {
const deleteMapModelReducer = (state: JournalsData, action: ActionMeta<EteSync.Journal, { item: EteSync.Journal }>) => {
if (action.error) {
return state.set('error', action.payload);
return state;
} else {
let payload = (action.payload === undefined) ? null : action.payload;
payload = (action.meta === undefined) ? payload : action.meta.item;
state = state.set('error', undefined);
if (action.payload === undefined) {
if (!payload) {
return state;
}
const uid = payload.uid;
let value = state.get('value', null)!;
value = value.delete(uid);
return state.set('value', value);
return state.delete(uid);
}
};
const mapReducerActionsMapCreator = <T extends Record<any>, V extends BaseModel>(actionName: string) => {
const setsReducer = (state: T, action: any) => setMapModelReducer<T, V>(state, action);
const addEditReducer = (state: T, action: any) => addEditMapModelReducer<T, V>(state, action);
const deleteReducer = (state: T, action: any) => deleteMapModelReducer<T>(state, action);
return {
[actions['fetchList' + actionName].toString() as string]: setsReducer,
[actions['add' + actionName].toString() as string]: addEditReducer,
[actions['update' + actionName].toString() as string]: addEditReducer,
[actions['delete' + actionName].toString() as string]: deleteReducer,
};
};
function fetchCreateEntriesReducer(state: EntriesTypeImmutable, action: any) {
const prevState = state.get(action.meta.journal);
const extend = action.meta.prevUid != null;
return state.set(action.meta.journal,
fetchTypeIdentityReducer(prevState, action, extend));
}
export const entries = handleActions(
export const journals = handleActions(
{
[actions.fetchEntries.toString()]: fetchCreateEntriesReducer,
[actions.addEntries.toString()]: fetchCreateEntriesReducer,
[actions.addJournal.toString()]: (state: EntriesTypeImmutable, action: any) => {
const journal = action.meta.item.uid;
const prevState = state.get(journal);
return state.set(journal,
fetchTypeIdentityReducer(prevState, { payload: [] }, false));
[actions.fetchListJournal.toString()]: setMapModelReducer as any,
[actions.addJournal.toString()]: addEditMapModelReducer,
[actions.updateJournal.toString()]: addEditMapModelReducer,
[actions.deleteJournal.toString()]: deleteMapModelReducer,
[actions.logout.toString()]: (state: JournalsData, _action: any) => {
return state.clear();
},
},
ImmutableMap({})
);
export const journals = handleActions(
{
...mapReducerActionsMapCreator<JournalsTypeImmutable, EteSync.Journal>('Journal'),
},
new JournalsFetchRecord()
);
export const userInfo = handleActions(
{
[combineActions(

@ -11,6 +11,7 @@
"allowJs": true,
"jsx": "preserve",
"rootDir": "src",
"downlevelIteration": true,
"forceConsistentCasingInFileNames": true,
"noUnusedLocals": true,
"moduleResolution": "node",

Loading…
Cancel
Save