diff --git a/src/common/AsideMenu.js b/src/common/AsideMenu.js
index 5a84719d..847d5cac 100644
--- a/src/common/AsideMenu.js
+++ b/src/common/AsideMenu.js
@@ -1,45 +1,49 @@
-import React from 'react';
-import { NavLink } from 'react-router-dom';
import listIcon from '@fortawesome/fontawesome-free-solid/faBars';
import createIcon from '@fortawesome/fontawesome-free-solid/faPlus';
-import deleteIcon from '@fortawesome/fontawesome-free-solid/faMinusCircle';
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
+import React from 'react';
+import { NavLink } from 'react-router-dom';
+import DeleteServerButton from '../servers/DeleteServerButton';
import './AsideMenu.scss';
-export default function AsideMenu({ selectedServer }) {
- const serverId = selectedServer ? selectedServer.id : '';
- const isListShortUrlsActive = (match, { pathname }) => {
- // FIXME. Should use the 'match' params, but they are not being properly resolved. Investigate
- const serverIdFromPathname = pathname.split('/')[2];
- return serverIdFromPathname === serverId && pathname.indexOf('list-short-urls') !== -1;
- };
+export default class AsideMenu extends React.Component {
+ render() {
+ const { selectedServer, history } = this.props;
+ const serverId = selectedServer ? selectedServer.id : '';
+ const isListShortUrlsActive = (match, { pathname }) => {
+ // FIXME. Should use the 'match' params, but they are not being properly resolved. Investigate
+ const serverIdFromPathname = pathname.split('/')[2];
+ return serverIdFromPathname === serverId && pathname.indexOf('list-short-urls') !== -1;
+ };
- return (
-
- );
+ return (
+
+ );
+ }
}
diff --git a/src/common/AsideMenu.scss b/src/common/AsideMenu.scss
index 6ce257ae..69b1ffde 100644
--- a/src/common/AsideMenu.scss
+++ b/src/common/AsideMenu.scss
@@ -1,4 +1,5 @@
@import "../utils/base";
+@import "../utils/mixins/border-radius";
.aside-menu {
position: fixed !important;
@@ -44,6 +45,8 @@
.aside-menu__item--danger {
color: $dangerColor;
+ margin: 0;
+ @include border-radius(4px);
}
.aside-menu__item--danger:hover {
color: #fff;
diff --git a/src/servers/DeleteServerButton.js b/src/servers/DeleteServerButton.js
new file mode 100644
index 00000000..982dff82
--- /dev/null
+++ b/src/servers/DeleteServerButton.js
@@ -0,0 +1,32 @@
+import deleteIcon from '@fortawesome/fontawesome-free-solid/faMinusCircle';
+import FontAwesomeIcon from '@fortawesome/react-fontawesome';
+import React from 'react';
+import DeleteServerModal from './DeleteServerModal';
+
+export default class DeleteServerButton extends React.Component {
+ state = { isModalOpen: false };
+
+ render() {
+ const { history, server } = this.props;
+
+ return [
+ (
+ this.setState({ isModalOpen: true })}
+ >
+
+ Delete this server
+
+ ),
+ (
+ this.setState({ isModalOpen: !this.state.isModalOpen })}
+ history={history}
+ server={server}
+ />
+ )
+ ];
+ }
+}
diff --git a/src/servers/DeleteServerModal.js b/src/servers/DeleteServerModal.js
new file mode 100644
index 00000000..eb0cedb5
--- /dev/null
+++ b/src/servers/DeleteServerModal.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
+import { deleteServer } from './reducers/server';
+
+export const DeleteServerModal = ({ server, deleteServer, toggle, history, isOpen }) => {
+ const closeModal = () => {
+ deleteServer(server);
+ toggle();
+ history.push('/');
+ };
+
+ return (
+
+ Delete server
+ Are you sure you want to delete server {server ? server.name : ''}.
+
+
+
+
+
+ );
+};
+
+export default connect(null, { deleteServer })(DeleteServerModal);
diff --git a/src/servers/reducers/server.js b/src/servers/reducers/server.js
index d93e4d99..e459300c 100644
--- a/src/servers/reducers/server.js
+++ b/src/servers/reducers/server.js
@@ -2,10 +2,12 @@ import ServersService from '../services';
const FETCH_SERVERS = 'shlink/servers/FETCH_SERVERS';
const CREATE_SERVER = 'shlink/servers/CREATE_SERVER';
+const DELETE_SERVER = 'shlink/servers/DELETE_SERVER';
export default function reducer(state = {}, action) {
switch (action.type) {
case FETCH_SERVERS:
+ case DELETE_SERVER:
return action.servers;
case CREATE_SERVER:
const server = action.server;
@@ -26,3 +28,8 @@ export const createServer = server => {
ServersService.createServer(server);
return listServers();
};
+
+export const deleteServer = server => {
+ ServersService.deleteServer(server);
+ return listServers();
+};
diff --git a/src/servers/services/index.js b/src/servers/services/index.js
index 6f70558d..fdd97a19 100644
--- a/src/servers/services/index.js
+++ b/src/servers/services/index.js
@@ -1,4 +1,5 @@
import Storage from '../../utils/Storage';
+import { dissoc } from 'ramda';
const SERVERS_STORAGE_KEY = 'servers';
@@ -21,6 +22,11 @@ export class ServersService {
servers[server.id] = server;
this.storage.set(SERVERS_STORAGE_KEY, servers);
};
+
+ deleteServer = server => {
+ const servers = dissoc(server.id, this.listServers());
+ this.storage.set(SERVERS_STORAGE_KEY, servers);
+ };
}
export default new ServersService(Storage);
diff --git a/src/utils/mixins/border-radius.scss b/src/utils/mixins/border-radius.scss
new file mode 100644
index 00000000..3c034fee
--- /dev/null
+++ b/src/utils/mixins/border-radius.scss
@@ -0,0 +1,5 @@
+@mixin border-radius($radius) {
+ border-radius: $radius;
+ -webkit-border-radius: $radius;
+ -moz-border-radius: $radius;
+}