Moved remote servers loading to separated action

This commit is contained in:
Alejandro Celaya
2020-04-27 12:54:52 +02:00
parent bdd7932e07
commit b08c6748c7
7 changed files with 114 additions and 132 deletions

View File

@@ -1,23 +1,40 @@
import React from 'react';
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { Route, Switch } from 'react-router-dom';
import NotFound from './common/NotFound';
import './App.scss';
const App = (MainHeader, Home, MenuLayout, CreateServer, EditServer, Settings) => () => (
<div className="container-fluid app-container">
<MainHeader />
const propTypes = {
fetchServers: PropTypes.func,
servers: PropTypes.object,
};
<div className="app">
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/settings" component={Settings} />
<Route exact path="/server/create" component={CreateServer} />
<Route exact path="/server/:serverId/edit" component={EditServer} />
<Route path="/server/:serverId" component={MenuLayout} />
<Route component={NotFound} />
</Switch>
const App = (MainHeader, Home, MenuLayout, CreateServer, EditServer, Settings) => ({ fetchServers, servers }) => {
// On first load, try to fetch the remote servers if the list is empty
useEffect(() => {
if (Object.keys(servers).length === 0) {
fetchServers();
}
}, []);
return (
<div className="container-fluid app-container">
<MainHeader />
<div className="app">
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/settings" component={Settings} />
<Route exact path="/server/create" component={CreateServer} />
<Route exact path="/server/:serverId/edit" component={EditServer} />
<Route path="/server/:serverId" component={MenuLayout} />
<Route component={NotFound} />
</Switch>
</div>
</div>
</div>
);
);
};
App.propTypes = propTypes;
export default App;

View File

@@ -29,6 +29,7 @@ const connect = (propsFromState, actionServiceNames = []) =>
);
bottle.serviceFactory('App', App, 'MainHeader', 'Home', 'MenuLayout', 'CreateServer', 'EditServer', 'Settings');
bottle.decorator('App', connect([ 'servers' ], [ 'fetchServers' ]));
provideCommonServices(bottle, connect, withRouter);
provideShortUrlsServices(bottle, connect);

View File

@@ -0,0 +1,22 @@
import { pipe, prop } from 'ramda';
import { homepage } from '../../../package.json';
import { createServers } from './servers';
const responseToServersList = pipe(
prop('data'),
(value) => {
if (!Array.isArray(value)) {
throw new Error('Value is not an array');
}
return value;
},
);
export const fetchServers = ({ get }) => () => async (dispatch) => {
const remoteList = await get(`${homepage}/servers.json`)
.then(responseToServersList)
.catch(() => []);
dispatch(createServers(remoteList));
};

View File

@@ -1,10 +1,8 @@
import { handleActions } from 'redux-actions';
import { pipe, isEmpty, assoc, map, prop, reduce, dissoc } from 'ramda';
import { pipe, assoc, map, reduce, dissoc } from 'ramda';
import { v4 as uuid } from 'uuid';
import { homepage } from '../../../package.json';
/* eslint-disable padding-line-between-statements */
export const LIST_SERVERS = 'shlink/servers/LIST_SERVERS';
export const EDIT_SERVER = 'shlink/servers/EDIT_SERVER';
export const DELETE_SERVER = 'shlink/servers/DELETE_SERVER';
export const CREATE_SERVERS = 'shlink/servers/CREATE_SERVERS';
@@ -15,7 +13,6 @@ const initialState = {};
const assocId = (server) => assoc('id', server.id || uuid(), server);
export default handleActions({
[LIST_SERVERS]: (state, { list }) => list,
[CREATE_SERVERS]: (state, { newServers }) => ({ ...state, ...newServers }),
[DELETE_SERVER]: (state, { serverId }) => dissoc(serverId, state),
[EDIT_SERVER]: (state, { serverId, serverData }) => !state[serverId]
@@ -23,35 +20,6 @@ export default handleActions({
: assoc(serverId, { ...state[serverId], ...serverData }, state),
}, initialState);
export const listServers = ({ listServers, createServers }, { get }) => () => async (dispatch) => {
const localList = listServers();
if (!isEmpty(localList)) {
dispatch({ type: LIST_SERVERS, list: localList });
return;
}
// If local list is empty, try to fetch it remotely (making sure it's an array) and calculate IDs for every server
const getDataAsArrayWithIds = pipe(
prop('data'),
(value) => {
if (!Array.isArray(value)) {
throw new Error('Value is not an array');
}
return value;
},
map(assocId),
);
const remoteList = await get(`${homepage}/servers.json`)
.then(getDataAsArrayWithIds)
.catch(() => []);
createServers(remoteList);
dispatch({ type: LIST_SERVERS, list: remoteList.reduce((map, server) => ({ ...map, [server.id]: server }), {}) });
};
export const createServer = (server) => createServers([ server ]);
const serversListToMap = reduce((acc, server) => assoc(server.id, server, acc), {});

View File

@@ -6,7 +6,8 @@ import DeleteServerButton from '../DeleteServerButton';
import { EditServer } from '../EditServer';
import ImportServersBtn from '../helpers/ImportServersBtn';
import { resetSelectedServer, selectServer } from '../reducers/selectedServer';
import { createServer, createServers, deleteServer, editServer, listServers } from '../reducers/servers';
import { createServer, createServers, deleteServer, editServer } from '../reducers/servers';
import { fetchServers } from '../reducers/remoteServers';
import ForServerVersion from '../helpers/ForServerVersion';
import { ServerError } from '../helpers/ServerError';
import ServersImporter from './ServersImporter';
@@ -52,7 +53,7 @@ const provideServices = (bottle, connect, withRouter) => {
bottle.serviceFactory('createServers', () => createServers);
bottle.serviceFactory('deleteServer', () => deleteServer);
bottle.serviceFactory('editServer', () => editServer);
bottle.serviceFactory('listServers', listServers, 'ServersService', 'axios');
bottle.serviceFactory('fetchServers', fetchServers, 'axios');
bottle.serviceFactory('resetSelectedServer', () => resetSelectedServer);
};