From e75d586c0f414fcece33231e47fece0a96f64ea0 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Tue, 5 Dec 2017 16:13:47 +0000 Subject: [PATCH] Move journal fetching to redux. --- src/JournalList.tsx | 70 +++++++++++++++++++++++++++++++-------------- src/store.tsx | 60 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 21 deletions(-) diff --git a/src/JournalList.tsx b/src/JournalList.tsx index fd982f1..8beaca8 100644 --- a/src/JournalList.tsx +++ b/src/JournalList.tsx @@ -1,4 +1,6 @@ import * as React from 'react'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router'; import { Link } from 'react-router-dom'; import { List, ListItem } from 'material-ui/List'; @@ -8,40 +10,56 @@ import { EteSyncContextType } from './EteSyncContext'; import * as EteSync from './api/EteSync'; import { routeResolver } from './App'; +import * as store from './store'; -export class JournalList extends React.Component { - props: { - etesync: EteSyncContextType - }; +interface PropsType { + etesync: EteSyncContextType; +} + +interface PropsTypeInner extends PropsType { + journals: store.JournalsType; +} + +function fetchJournals(etesync: EteSyncContextType) { + const credentials = etesync.credentials; + const apiBase = etesync.serviceApiUrl; + + return (dispatch: any) => { + dispatch(store.journalsRequest()); - state: { - journals: Array, + let journalManager = new EteSync.JournalManager(credentials, apiBase); + journalManager.list().then( + (journals) => { + dispatch(store.journalsSuccess(journals)); + }, + (error) => { + dispatch(store.journalsFailure(error)); + } + ); }; +} + +class JournalListInner extends React.Component { + props: PropsTypeInner; constructor(props: any) { super(props); - this.state = { - journals: [], - }; } componentDidMount() { - const credentials = this.props.etesync.credentials; - const apiBase = this.props.etesync.serviceApiUrl; - - let journalManager = new EteSync.JournalManager(credentials, apiBase); - journalManager.list().then((journals) => { - journals = journals.filter((x) => ( - // Skip shared journals for now. - !x.key - )); - this.setState({ journals }); - }); + store.store.dispatch(fetchJournals(this.props.etesync)); } render() { + if (this.props.journals.value === null) { + return (
); + } + const derived = this.props.etesync.encryptionKey; - const journalMap = this.state.journals.reduce( + const journalMap = this.props.journals.value.filter((x) => ( + // Skip shared journals for now. + !x.key + )).reduce( (ret, journal) => { let cryptoManager = new EteSync.CryptoManager(derived, journal.uid, journal.version); let info = journal.getInfo(cryptoManager); @@ -90,3 +108,13 @@ export class JournalList extends React.Component { ); } } + +const mapStateToProps = (state: store.StoreState, props: PropsType) => { + return { + journals: state.cache.journals, + }; +}; + +export const JournalList = withRouter(connect( + mapStateToProps +)(JournalListInner)); diff --git a/src/store.tsx b/src/store.tsx index 7797a8e..77e0046 100644 --- a/src/store.tsx +++ b/src/store.tsx @@ -10,6 +10,7 @@ const loggerMiddleware = createLogger(); enum Actions { FETCH_CREDENTIALS = 'FETCH_CREDENTIALS', + FETCH_JOURNALS = 'FETCH_JOURNALS', } export enum FetchStatus { @@ -33,9 +34,16 @@ export interface CredentialsData { export type CredentialsType = FetchType; +export type JournalsData = Array; + +export type JournalsType = FetchType; + export interface StoreState { fetchCount: number; credentials: CredentialsType; + cache: { + journals: JournalsType; + }; } export function credentialsSuccess(creds: CredentialsData) { @@ -61,6 +69,29 @@ export function credentialsFailure(error: Error) { }; } +export function journalsSuccess(value: JournalsData) { + return { + type: Actions.FETCH_JOURNALS, + status: FetchStatus.Success, + journals: value, + }; +} + +export function journalsRequest() { + return { + type: Actions.FETCH_JOURNALS, + status: FetchStatus.Request, + }; +} + +export function journalsFailure(error: Error) { + return { + type: Actions.FETCH_JOURNALS, + status: FetchStatus.Failure, + error + }; +} + export function logout() { return { type: Actions.FETCH_CREDENTIALS, @@ -95,6 +126,32 @@ function credentials(state: CredentialsType = {status: FetchStatus.Initial, valu } } +function journals(state: JournalsType = {status: FetchStatus.Initial, value: null}, action: any) { + switch (action.type) { + case Actions.FETCH_JOURNALS: + switch (action.status) { + case FetchStatus.Success: + return { + status: action.status, + value: action.journals, + }; + case FetchStatus.Failure: + return { + status: action.status, + value: null, + error: action.error, + }; + default: + return { + status: action.status, + value: null, + }; + } + default: + return state; + } +} + function fetchCount(state: number = 0, action: any) { if ('status' in action) { switch (action.status) { @@ -122,6 +179,9 @@ const credentialsPersistConfig = { const reducers = combineReducers({ fetchCount, credentials: persistReducer(credentialsPersistConfig, credentials), + cache: combineReducers({ + journals + }) }); export const store = createStore(