Added links to delete and edit the server when a server could not be reached

This commit is contained in:
Alejandro Celaya 2020-03-15 09:17:33 +01:00
parent dab75ab6a9
commit f44ec42f51
10 changed files with 75 additions and 49 deletions

14
package-lock.json generated
View file

@ -5340,7 +5340,7 @@
}, },
"discontinuous-range": { "discontinuous-range": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", "resolved": "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
"integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=",
"dev": true "dev": true
}, },
@ -9346,7 +9346,7 @@
}, },
"is-subset": { "is-subset": {
"version": "0.1.1", "version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", "resolved": "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz",
"integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=",
"dev": true "dev": true
}, },
@ -10557,13 +10557,13 @@
}, },
"lodash.escape": { "lodash.escape": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", "resolved": "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz",
"integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=",
"dev": true "dev": true
}, },
"lodash.flattendeep": { "lodash.flattendeep": {
"version": "4.4.0", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", "resolved": "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
"integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
"dev": true "dev": true
}, },
@ -10575,7 +10575,7 @@
}, },
"lodash.isequal": { "lodash.isequal": {
"version": "4.5.0", "version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "resolved": "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
"dev": true "dev": true
}, },
@ -13817,7 +13817,7 @@
}, },
"railroad-diagrams": { "railroad-diagrams": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", "resolved": "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
"integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=",
"dev": true "dev": true
}, },
@ -14977,7 +14977,7 @@
}, },
"rst-selector-parser": { "rst-selector-parser": {
"version": "2.2.3", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", "resolved": "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz",
"integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=", "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=",
"dev": true, "dev": true,
"requires": { "requires": {

View file

@ -9,8 +9,9 @@ const App = (MainHeader, Home, MenuLayout, CreateServer) => () => (
<div className="app"> <div className="app">
<Switch> <Switch>
<Route exact path="/server/create" component={CreateServer} />
<Route exact path="/" component={Home} /> <Route exact path="/" component={Home} />
<Route exact path="/server/create" component={CreateServer} />
<Route exact path="/server/:serverId/edit" component={CreateServer} />
<Route path="/server/:serverId" component={MenuLayout} /> <Route path="/server/:serverId" component={MenuLayout} />
<Route component={NotFound} /> <Route component={NotFound} />
</Switch> </Switch>

View file

@ -49,7 +49,11 @@ const AsideMenu = (DeleteServerButton) => {
<span className="aside-menu__item-text">Manage tags</span> <span className="aside-menu__item-text">Manage tags</span>
</AsideMenuItem> </AsideMenuItem>
<DeleteServerButton className="aside-menu__item aside-menu__item--danger" server={selectedServer} /> <DeleteServerButton
className="aside-menu__item aside-menu__item--danger"
textClassName="aside-menu__item-text"
server={selectedServer}
/>
</nav> </nav>
</aside> </aside>
); );

View file

@ -7,25 +7,22 @@ import { serverType } from './prop-types';
const propTypes = { const propTypes = {
server: serverType, server: serverType,
className: PropTypes.string, className: PropTypes.string,
textClassName: PropTypes.string,
children: PropTypes.node,
}; };
const DeleteServerButton = (DeleteServerModal) => { const DeleteServerButton = (DeleteServerModal) => {
const DeleteServerButtonComp = ({ server, className }) => { const DeleteServerButtonComp = ({ server, className, children, textClassName }) => {
const [ isModalOpen, setModalOpen ] = useState(false); const [ isModalOpen, setModalOpen ] = useState(false);
return ( return (
<React.Fragment> <React.Fragment>
<span className={className} key="deleteServerBtn" onClick={() => setModalOpen(true)}> <span className={className} onClick={() => setModalOpen(true)}>
<FontAwesomeIcon icon={deleteIcon} /> {!children && <FontAwesomeIcon icon={deleteIcon} />}
<span className="aside-menu__item-text">Remove this server</span> <span className={textClassName}>{children || 'Remove this server'}</span>
</span> </span>
<DeleteServerModal <DeleteServerModal server={server} isOpen={isModalOpen} toggle={() => setModalOpen(!isModalOpen)} />
isOpen={isModalOpen}
toggle={() => setModalOpen(!isModalOpen)}
server={server}
key="deleteServerModal"
/>
</React.Fragment> </React.Fragment>
); );
}; };

View file

@ -26,7 +26,9 @@ ServerListItem.propTypes = {
const ServersListGroup = ({ servers, children }) => ( const ServersListGroup = ({ servers, children }) => (
<React.Fragment> <React.Fragment>
<h5>{children}</h5> <div className="container">
<h5>{children}</h5>
</div>
{servers.length > 0 && ( {servers.length > 0 && (
<ListGroup className="servers-list__list-group mt-md-3"> <ListGroup className="servers-list__list-group mt-md-3">
{servers.map(({ id, name }) => <ServerListItem key={id} id={id} name={name} />)} {servers.map(({ id, name }) => <ServerListItem key={id} id={id} name={name} />)}

View file

@ -3,31 +3,48 @@ import PropTypes from 'prop-types';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import Message from '../../utils/Message'; import Message from '../../utils/Message';
import ServersListGroup from '../ServersListGroup'; import ServersListGroup from '../ServersListGroup';
import { serverType } from '../prop-types';
import './ServerError.scss'; import './ServerError.scss';
const propTypes = { const propTypes = {
servers: PropTypes.object, servers: PropTypes.object,
selectedServer: serverType,
type: PropTypes.oneOf([ 'not-found', 'not-reachable' ]).isRequired, type: PropTypes.oneOf([ 'not-found', 'not-reachable' ]).isRequired,
}; };
export const ServerError = ({ type, servers: { list } }) => ( export const ServerError = (DeleteServerButton) => {
<div className="server-error-container flex-column"> const ServerErrorComp = ({ type, servers: { list }, selectedServer }) => (
<div className="row w-100 mb-3 mb-md-5"> <div className="server-error__container flex-column">
<Message type="error"> <div className="row w-100 mb-3 mb-md-5">
{type === 'not-found' && 'Could not find this Shlink server.'} <Message type="error">
{type === 'not-reachable' && ( {type === 'not-found' && 'Could not find this Shlink server.'}
<React.Fragment> {type === 'not-reachable' && (
<p>Oops! Could not connect to this Shlink server.</p> <React.Fragment>
Make sure you have internet connection, and the server is properly configured and on-line. <p>Oops! Could not connect to this Shlink server.</p>
</React.Fragment> Make sure you have internet connection, and the server is properly configured and on-line.
)} </React.Fragment>
</Message> )}
</div> </Message>
<ServersListGroup servers={Object.values(list)}> </div>
These are the {type === 'not-reachable' ? 'other' : ''} Shlink servers currently configured. Choose one of
them or <Link to="/server/create">add a new one</Link>.
</ServersListGroup>
</div>
);
ServerError.propTypes = propTypes; <ServersListGroup servers={Object.values(list)}>
These are the Shlink servers currently configured. Choose one of
them or <Link to="/server/create">add a new one</Link>.
</ServersListGroup>
{type === 'not-reachable' && (
<div className="container mt-3 mt-md-5">
<h5>
Alternatively, if you think you may have miss-configured this server, you
can <DeleteServerButton server={selectedServer} className="server-error__delete-btn">remove it</DeleteServerButton> or&nbsp;
<Link to={`/server/${selectedServer.id}/edit`}>edit it</Link>.
</h5>
</div>
)}
</div>
);
ServerErrorComp.propTypes = propTypes;
return ServerErrorComp;
};

View file

@ -1,6 +1,15 @@
.server-error-container { .server-error__container {
text-align: center; text-align: center;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.server-error__delete-btn {
color: #dc3545;
cursor: pointer;
}
.server-error__delete-btn:hover {
text-decoration: underline;
}

View file

@ -7,18 +7,14 @@ const regularServerType = PropTypes.shape({
apiKey: PropTypes.string, apiKey: PropTypes.string,
version: PropTypes.string, version: PropTypes.string,
printableVersion: PropTypes.string, printableVersion: PropTypes.string,
serverNotReachable: PropTypes.bool,
}); });
const notFoundServerType = PropTypes.shape({ const notFoundServerType = PropTypes.shape({
serverNotFound: PropTypes.bool.isRequired, serverNotFound: PropTypes.bool.isRequired,
}); });
const notReachableServerType = PropTypes.shape({
serverNotReachable: PropTypes.bool.isRequired,
});
export const serverType = PropTypes.oneOfType([ export const serverType = PropTypes.oneOfType([
regularServerType, regularServerType,
notFoundServerType, notFoundServerType,
notReachableServerType,
]); ]);

View file

@ -49,7 +49,7 @@ export const selectServer = ({ findServerById }, buildShlinkApiClient) => (serve
} catch (e) { } catch (e) {
dispatch({ dispatch({
type: SELECT_SERVER, type: SELECT_SERVER,
selectedServer: { serverNotReachable: true }, selectedServer: { ...selectedServer, serverNotReachable: true },
}); });
} }
}; };

View file

@ -33,8 +33,8 @@ const provideServices = (bottle, connect, withRouter) => {
bottle.serviceFactory('ForServerVersion', () => ForServerVersion); bottle.serviceFactory('ForServerVersion', () => ForServerVersion);
bottle.decorator('ForServerVersion', connect([ 'selectedServer' ])); bottle.decorator('ForServerVersion', connect([ 'selectedServer' ]));
bottle.serviceFactory('ServerError', () => ServerError); bottle.serviceFactory('ServerError', ServerError, 'DeleteServerButton');
bottle.decorator('ServerError', connect([ 'servers' ])); bottle.decorator('ServerError', connect([ 'servers', 'selectedServer' ]));
// Services // Services
bottle.constant('csvjson', csvjson); bottle.constant('csvjson', csvjson);