mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-22 17:10:26 +03:00
Updated list servers action so that it tries to fetch servers from the servers.json file when no local servers are found
This commit is contained in:
parent
502c8a7e02
commit
20820c47d4
9 changed files with 74 additions and 48 deletions
|
@ -3,7 +3,7 @@
|
|||
"description": "A React-based progressive web application for shlink",
|
||||
"version": "1.0.0",
|
||||
"private": false,
|
||||
"homepage": "https://shlink.io",
|
||||
"homepage": "",
|
||||
"scripts": {
|
||||
"lint": "npm run lint:js && npm run lint:css",
|
||||
"lint:js": "eslint src test scripts config",
|
||||
|
|
|
@ -18,18 +18,20 @@ export default class Home extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const servers = values(this.props.servers);
|
||||
const { servers: { list, loading } } = this.props;
|
||||
const servers = values(list);
|
||||
const hasServers = !isEmpty(servers);
|
||||
|
||||
return (
|
||||
<div className="home">
|
||||
<h1 className="home__title">Welcome to Shlink</h1>
|
||||
<h5 className="home__intro">
|
||||
{hasServers && <span>Please, select a server.</span>}
|
||||
{!hasServers && <span>Please, <Link to="/server/create">add a server</Link>.</span>}
|
||||
{!loading && hasServers && <span>Please, select a server.</span>}
|
||||
{!loading && !hasServers && <span>Please, <Link to="/server/create">add a server</Link>.</span>}
|
||||
{loading && <span>Trying to load servers....</span>}
|
||||
</h5>
|
||||
|
||||
{hasServers && (
|
||||
{!loading && hasServers && (
|
||||
<ListGroup className="home__servers-list">
|
||||
{servers.map(({ name, id }) => (
|
||||
<ListGroupItem
|
||||
|
|
|
@ -14,7 +14,12 @@ const ServersDropdown = (serversExporter) => class ServersDropdown extends React
|
|||
};
|
||||
|
||||
renderServers = () => {
|
||||
const { servers, selectedServer, selectServer } = this.props;
|
||||
const { servers: { list, loading }, selectedServer, selectServer } = this.props;
|
||||
const servers = values(list);
|
||||
|
||||
if (loading) {
|
||||
return <DropdownItem disabled><i>Trying to load servers...</i></DropdownItem>;
|
||||
}
|
||||
|
||||
if (isEmpty(servers)) {
|
||||
return <DropdownItem disabled><i>Add a server first...</i></DropdownItem>;
|
||||
|
@ -22,7 +27,7 @@ const ServersDropdown = (serversExporter) => class ServersDropdown extends React
|
|||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{values(servers).map(({ name, id }) => (
|
||||
{servers.map(({ name, id }) => (
|
||||
<DropdownItem
|
||||
key={id}
|
||||
tag={Link}
|
||||
|
@ -46,18 +51,14 @@ const ServersDropdown = (serversExporter) => class ServersDropdown extends React
|
|||
);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.props.listServers();
|
||||
}
|
||||
componentDidMount = this.props.listServers;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<UncontrolledDropdown nav inNavbar>
|
||||
<DropdownToggle nav caret>Servers</DropdownToggle>
|
||||
<DropdownMenu right>{this.renderServers()}</DropdownMenu>
|
||||
</UncontrolledDropdown>
|
||||
);
|
||||
}
|
||||
render = () => (
|
||||
<UncontrolledDropdown nav inNavbar>
|
||||
<DropdownToggle nav caret>Servers</DropdownToggle>
|
||||
<DropdownMenu right>{this.renderServers()}</DropdownMenu>
|
||||
</UncontrolledDropdown>
|
||||
);
|
||||
};
|
||||
|
||||
export default ServersDropdown;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import React from 'react';
|
||||
import { UncontrolledTooltip } from 'reactstrap';
|
||||
import { assoc, map } from 'ramda';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const ImportServersBtn = (serversImporter) => class ImportServersBtn extends React.Component {
|
||||
|
@ -22,10 +20,8 @@ const ImportServersBtn = (serversImporter) => class ImportServersBtn extends Rea
|
|||
render() {
|
||||
const { importServersFromFile } = serversImporter;
|
||||
const { onImport, createServers } = this.props;
|
||||
const assocId = (server) => assoc('id', uuid(), server);
|
||||
const onChange = ({ target }) =>
|
||||
importServersFromFile(target.files[0])
|
||||
.then(map(assocId))
|
||||
.then(createServers)
|
||||
.then(onImport)
|
||||
.then(() => {
|
||||
|
|
|
@ -10,10 +10,10 @@ const initialState = null;
|
|||
|
||||
export const resetSelectedServer = createAction(RESET_SELECTED_SERVER);
|
||||
|
||||
export const selectServer = (serversService) => (serverId) => (dispatch) => {
|
||||
export const selectServer = ({ findServerById }) => (serverId) => (dispatch) => {
|
||||
dispatch(resetShortUrlParams());
|
||||
|
||||
const selectedServer = serversService.findServerById(serverId);
|
||||
const selectedServer = findServerById(serverId);
|
||||
|
||||
dispatch({
|
||||
type: SELECT_SERVER,
|
||||
|
|
|
@ -1,16 +1,51 @@
|
|||
import { createAction, handleActions } from 'redux-actions';
|
||||
import { pipe } from 'ramda';
|
||||
import { handleActions } from 'redux-actions';
|
||||
import { pipe, isEmpty, assoc, map } from 'ramda';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { homepage } from '../../../package.json';
|
||||
|
||||
/* eslint-disable padding-line-between-statements */
|
||||
export const FETCH_SERVERS_START = 'shlink/servers/FETCH_SERVERS_START';
|
||||
export const FETCH_SERVERS = 'shlink/servers/FETCH_SERVERS';
|
||||
/* eslint-enable padding-line-between-statements */
|
||||
|
||||
export const listServers = ({ listServers }) => createAction(FETCH_SERVERS, () => listServers());
|
||||
const initialState = {
|
||||
list: {},
|
||||
loading: false,
|
||||
};
|
||||
|
||||
export const createServer = ({ createServer }, listServers) => pipe(createServer, listServers);
|
||||
|
||||
export const deleteServer = ({ deleteServer }, listServers) => pipe(deleteServer, listServers);
|
||||
|
||||
export const createServers = ({ createServers }, listServers) => pipe(createServers, listServers);
|
||||
const assocId = (server) => assoc('id', uuid(), server);
|
||||
|
||||
export default handleActions({
|
||||
[FETCH_SERVERS]: (state, { payload }) => payload,
|
||||
}, {});
|
||||
[FETCH_SERVERS_START]: (state) => ({ ...state, loading: true }),
|
||||
[FETCH_SERVERS]: (state, { list }) => ({ list, loading: false }),
|
||||
}, initialState);
|
||||
|
||||
export const listServers = ({ listServers, createServers }, { get }) => () => async (dispatch) => {
|
||||
dispatch({ type: FETCH_SERVERS_START });
|
||||
|
||||
// Fetch list from local storage.
|
||||
const localList = listServers();
|
||||
|
||||
if (!isEmpty(localList)) {
|
||||
dispatch({ type: FETCH_SERVERS, list: localList });
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If local list is empty, try to fetch it remotely, calculate IDs for every server, and use it
|
||||
const { data: remoteList } = await get(`${homepage}/servers.json`);
|
||||
const listWithIds = map(assocId, remoteList);
|
||||
|
||||
createServers(listWithIds);
|
||||
dispatch({ type: FETCH_SERVERS, list: listWithIds });
|
||||
};
|
||||
|
||||
export const createServer = ({ createServer }, listServersAction) => pipe(createServer, listServersAction);
|
||||
|
||||
export const deleteServer = ({ deleteServer }, listServersAction) => pipe(deleteServer, listServersAction);
|
||||
|
||||
export const createServers = ({ createServers }, listServersAction) => pipe(
|
||||
map(assocId),
|
||||
createServers,
|
||||
listServersAction
|
||||
);
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
export const serversImporterType = PropTypes.shape({
|
||||
importServersFromFile: PropTypes.func,
|
||||
});
|
||||
|
||||
export default class ServersImporter {
|
||||
constructor(csvjson) {
|
||||
this.csvjson = csvjson;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { assoc, dissoc, reduce } from 'ramda';
|
||||
import { assoc, curry, dissoc, reduce } from 'ramda';
|
||||
|
||||
const SERVERS_STORAGE_KEY = 'servers';
|
||||
|
||||
export default class ServersService {
|
||||
constructor(storage) {
|
||||
this.storage = storage;
|
||||
this.setServers = curry(this.storage.set)(SERVERS_STORAGE_KEY);
|
||||
}
|
||||
|
||||
listServers = () => this.storage.get(SERVERS_STORAGE_KEY) || {};
|
||||
|
@ -20,12 +21,9 @@ export default class ServersService {
|
|||
servers
|
||||
);
|
||||
|
||||
this.storage.set(SERVERS_STORAGE_KEY, allServers);
|
||||
this.setServers(allServers);
|
||||
};
|
||||
|
||||
deleteServer = (server) =>
|
||||
this.storage.set(
|
||||
SERVERS_STORAGE_KEY,
|
||||
dissoc(server.id, this.listServers())
|
||||
);
|
||||
deleteServer = ({ id }) =>
|
||||
this.setServers(dissoc(id, this.listServers()));
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ const provideServices = (bottle, connect, withRouter) => {
|
|||
bottle.serviceFactory('createServer', createServer, 'ServersService', 'listServers');
|
||||
bottle.serviceFactory('createServers', createServers, 'ServersService', 'listServers');
|
||||
bottle.serviceFactory('deleteServer', deleteServer, 'ServersService', 'listServers');
|
||||
bottle.serviceFactory('listServers', listServers, 'ServersService');
|
||||
bottle.serviceFactory('listServers', listServers, 'ServersService', 'axios');
|
||||
|
||||
bottle.serviceFactory('resetSelectedServer', () => resetSelectedServer);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue