mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 09:30:31 +03:00
Added links to delete and edit the server when a server could not be reached
This commit is contained in:
parent
dab75ab6a9
commit
f44ec42f51
10 changed files with 75 additions and 49 deletions
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -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": {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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} />)}
|
||||||
|
|
|
@ -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
|
||||||
|
<Link to={`/server/${selectedServer.id}/edit`}>edit it</Link>.
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
ServerErrorComp.propTypes = propTypes;
|
||||||
|
|
||||||
|
return ServerErrorComp;
|
||||||
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -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 },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue