Moved logic to mark selected server to parent component in order to affect all children compo0nents on the same route

This commit is contained in:
Alejandro Celaya 2018-07-24 19:17:01 +02:00
parent 3eaa66435a
commit 78ba7c75ff
6 changed files with 72 additions and 41 deletions

View file

@ -16,7 +16,7 @@ export default class App extends React.Component {
<Switch> <Switch>
<Route exact path="/server/create" component={CreateServer} /> <Route exact path="/server/create" component={CreateServer} />
<Route exact path="/" component={Home} /> <Route exact path="/" component={Home} />
<Route component={MenuLayout} /> <Route path="/server/:serverId" component={MenuLayout} />
</Switch> </Switch>
</div> </div>
</div> </div>

View file

@ -1,33 +1,41 @@
import React from 'react'; import React from 'react';
import { Route, Switch } from 'react-router-dom'; import { Route, Switch } from 'react-router-dom';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectServer } from '../servers/reducers/selectedServer';
import CreateShortUrl from '../short-urls/CreateShortUrl'; import CreateShortUrl from '../short-urls/CreateShortUrl';
import ShortUrls from '../short-urls/ShortUrls'; import ShortUrls from '../short-urls/ShortUrls';
import AsideMenu from './AsideMenu'; import AsideMenu from './AsideMenu';
export function MenuLayout(props) { export class MenuLayout extends React.Component {
return ( componentDidMount() {
<div className="row"> const { serverId } = this.props.match.params;
<AsideMenu {...props} /> this.props.selectServer(serverId);
<div className="col-md-10 offset-md-2 col-sm-9 offset-sm-3"> }
<Switch>
<Route render() {
exact return (
path="/server/:serverId/list-short-urls/:page" <div className="row">
component={ShortUrls} <AsideMenu {...this.props} />
/> <div className="col-md-10 offset-md-2 col-sm-9 offset-sm-3">
<Route <Switch>
exact <Route
path="/server/:serverId/create-short-url" exact
component={CreateShortUrl} path="/server/:serverId/list-short-urls/:page"
/> component={ShortUrls}
</Switch> />
<Route
exact
path="/server/:serverId/create-short-url"
component={CreateShortUrl}
/>
</Switch>
</div>
</div> </div>
</div> );
); }
} }
export default connect(state => ({ export default connect(state => ({
selectedServer: state.selectedServer, selectedServer: state.selectedServer,
shortUrlsListParams: state.shortUrlsListParams, shortUrlsListParams: state.shortUrlsListParams,
}))(MenuLayout); }), { selectServer })(MenuLayout);

View file

@ -1,10 +1,12 @@
import { LIST_SHORT_URLS } from '../../short-urls/reducers/shortUrlsList'; import ShlinkApiClient from '../../api/ShlinkApiClient';
import ServersService from '../../servers/services';
const SELECT_SERVER = 'shlink/selectedServer/SELECT_SERVER';
const RESET_SELECTED_SERVER = 'shlink/selectedServer/RESET_SELECTED_SERVER'; const RESET_SELECTED_SERVER = 'shlink/selectedServer/RESET_SELECTED_SERVER';
export default function reducer(state = null, action) { export default function reducer(state = null, action) {
switch (action.type) { switch (action.type) {
case LIST_SHORT_URLS: case SELECT_SERVER:
return action.selectedServer; return action.selectedServer;
case RESET_SELECTED_SERVER: case RESET_SELECTED_SERVER:
return null; return null;
@ -14,3 +16,13 @@ export default function reducer(state = null, action) {
} }
export const resetSelectedServer = () => ({ type: RESET_SELECTED_SERVER }); export const resetSelectedServer = () => ({ type: RESET_SELECTED_SERVER });
export const selectServer = serverId => {
const selectedServer = ServersService.findServerById(serverId);
ShlinkApiClient.setConfig(selectedServer);
return {
type: SELECT_SERVER,
selectedServer
}
};

View file

@ -3,6 +3,7 @@ import { connect } from 'react-redux';
import Paginator from './Paginator'; import Paginator from './Paginator';
import SearchBar from './SearchBar'; import SearchBar from './SearchBar';
import ShortUrlsList from './ShortUrlsList'; import ShortUrlsList from './ShortUrlsList';
import { assoc } from 'ramda';
export function ShortUrls(props) { export function ShortUrls(props) {
const { match: { params } } = props; const { match: { params } } = props;
@ -18,7 +19,4 @@ export function ShortUrls(props) {
); );
} }
export default connect(state => ({ export default connect(state => assoc('shortUrlsList', state.shortUrlsList.shortUrls, state.shortUrlsList))(ShortUrls);
shortUrlsList: state.shortUrlsList.shortUrls,
loading: state.shortUrlsList.loading,
}))(ShortUrls);

View file

@ -102,7 +102,11 @@ export class ShortUrlsList extends React.Component {
} }
renderShortUrls() { renderShortUrls() {
const { shortUrlsList, selectedServer, loading } = this.props; const { shortUrlsList, selectedServer, loading, error } = this.props;
if (error) {
return <tr><td colSpan="6" className="text-center table-danger">Something went wrong while loading short URLs :(</td></tr>;
}
if (loading) { if (loading) {
return <tr><td colSpan="6" className="text-center">Loading...</td></tr>; return <tr><td colSpan="6" className="text-center">Loading...</td></tr>;
} }

View file

@ -1,9 +1,10 @@
import ServersService from '../../servers/services';
import ShlinkApiClient from '../../api/ShlinkApiClient'; import ShlinkApiClient from '../../api/ShlinkApiClient';
import ServersService from '../../servers/services';
export const LIST_SHORT_URLS_START = 'shlink/shortUrlsList/LIST_SHORT_URLS_START'; export const LIST_SHORT_URLS_START = 'shlink/shortUrlsList/LIST_SHORT_URLS_START';
export const LIST_SHORT_URLS_ERROR = 'shlink/shortUrlsList/LIST_SHORT_URLS_ERROR';
export const LIST_SHORT_URLS = 'shlink/shortUrlsList/LIST_SHORT_URLS'; export const LIST_SHORT_URLS = 'shlink/shortUrlsList/LIST_SHORT_URLS';
export const UPDATE_SHORT_URLS_LIST = 'shlink/shortUrlsList/UPDATE_SHORT_URLS_LIST'; export const UPDATE_SHORT_URLS_LIST = LIST_SHORT_URLS;
const initialState = { const initialState = {
shortUrls: [], shortUrls: [],
@ -13,34 +14,42 @@ const initialState = {
export default function reducer(state = initialState, action) { export default function reducer(state = initialState, action) {
switch (action.type) { switch (action.type) {
case LIST_SHORT_URLS_START: case LIST_SHORT_URLS_START:
return { ...state, loading: true }; return { ...state, loading: true, error: false };
case LIST_SHORT_URLS: case LIST_SHORT_URLS:
case UPDATE_SHORT_URLS_LIST:
return { return {
loading: false, loading: false,
error: false,
shortUrls: action.shortUrls shortUrls: action.shortUrls
}; };
case LIST_SHORT_URLS_ERROR:
return {
loading: false,
error: true,
shortUrls: []
};
default: default:
return state; return state;
} }
} }
export const listShortUrls = (serverId, params = {}) => { export const listShortUrls = (serverId, params = {}) => {
return async dispatch => { // FIXME There should be a way to not need this, however, the active server is set when any route is loaded, in an
dispatch({ type: LIST_SHORT_URLS_START }); // FIXME outer component's componentDidMount, which makes it be invoked after this action
const selectedServer = ServersService.findServerById(serverId); const selectedServer = ServersService.findServerById(serverId);
ShlinkApiClient.setConfig(selectedServer);
ShlinkApiClient.setConfig(selectedServer); return updateShortUrlsList(params);
const shortUrls = await ShlinkApiClient.listShortUrls(params);
dispatch({ type: LIST_SHORT_URLS, shortUrls, selectedServer, params });
};
}; };
export const updateShortUrlsList = (params = {}) => { export const updateShortUrlsList = (params = {}) => {
return async dispatch => { return async dispatch => {
dispatch({ type: LIST_SHORT_URLS_START }); dispatch({ type: LIST_SHORT_URLS_START });
const shortUrls = await ShlinkApiClient.listShortUrls(params); try {
dispatch({ type: UPDATE_SHORT_URLS_LIST, shortUrls, params }); const shortUrls = await ShlinkApiClient.listShortUrls(params);
dispatch({ type: LIST_SHORT_URLS, shortUrls, params });
} catch (e) {
dispatch({ type: LIST_SHORT_URLS_ERROR, params });
}
}; };
}; };