Added modal window for server deletion

This commit is contained in:
Alejandro Celaya 2018-07-20 22:14:17 +02:00
parent 0de191ac0b
commit 168b24344e
7 changed files with 120 additions and 38 deletions

View file

@ -1,45 +1,49 @@
import React from 'react';
import { NavLink } from 'react-router-dom';
import listIcon from '@fortawesome/fontawesome-free-solid/faBars'; import listIcon from '@fortawesome/fontawesome-free-solid/faBars';
import createIcon from '@fortawesome/fontawesome-free-solid/faPlus'; import createIcon from '@fortawesome/fontawesome-free-solid/faPlus';
import deleteIcon from '@fortawesome/fontawesome-free-solid/faMinusCircle';
import FontAwesomeIcon from '@fortawesome/react-fontawesome'; import FontAwesomeIcon from '@fortawesome/react-fontawesome';
import React from 'react';
import { NavLink } from 'react-router-dom';
import DeleteServerButton from '../servers/DeleteServerButton';
import './AsideMenu.scss'; import './AsideMenu.scss';
export default function AsideMenu({ selectedServer }) { export default class AsideMenu extends React.Component {
const serverId = selectedServer ? selectedServer.id : ''; render() {
const isListShortUrlsActive = (match, { pathname }) => { const { selectedServer, history } = this.props;
// FIXME. Should use the 'match' params, but they are not being properly resolved. Investigate const serverId = selectedServer ? selectedServer.id : '';
const serverIdFromPathname = pathname.split('/')[2]; const isListShortUrlsActive = (match, { pathname }) => {
return serverIdFromPathname === serverId && pathname.indexOf('list-short-urls') !== -1; // 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 (
<aside className="aside-menu col-md-2 col-sm-2"> <aside className="aside-menu col-md-2 col-sm-2">
<nav className="nav flex-column aside-menu__nav"> <nav className="nav flex-column aside-menu__nav">
<NavLink <NavLink
className="aside-menu__item" className="aside-menu__item"
activeClassName="aside-menu__item--selected" activeClassName="aside-menu__item--selected"
to={`/server/${serverId}/list-short-urls/1`} to={`/server/${serverId}/list-short-urls/1`}
isActive={isListShortUrlsActive} isActive={isListShortUrlsActive}
> >
<FontAwesomeIcon icon={listIcon} /> <FontAwesomeIcon icon={listIcon} />
<span className="aside-menu__item-text">List short URLs</span> <span className="aside-menu__item-text">List short URLs</span>
</NavLink> </NavLink>
<NavLink <NavLink
className="aside-menu__item" className="aside-menu__item"
activeClassName="aside-menu__item--selected" activeClassName="aside-menu__item--selected"
to={`/server/${serverId}/create-short-url`} to={`/server/${serverId}/create-short-url`}
> >
<FontAwesomeIcon icon={createIcon} /> <FontAwesomeIcon icon={createIcon} />
<span className="aside-menu__item-text">Create short code</span> <span className="aside-menu__item-text">Create short code</span>
</NavLink> </NavLink>
<span className="aside-menu__item--divider" /> <span className="aside-menu__item--divider" />
<span className="aside-menu__item aside-menu__item--danger"> <DeleteServerButton
<FontAwesomeIcon icon={deleteIcon} /> className="aside-menu__item aside-menu__item--danger"
<span className="aside-menu__item-text">Delete this server</span> history={history}
</span> server={selectedServer}
</nav> />
</aside> </nav>
); </aside>
);
}
} }

View file

@ -1,4 +1,5 @@
@import "../utils/base"; @import "../utils/base";
@import "../utils/mixins/border-radius";
.aside-menu { .aside-menu {
position: fixed !important; position: fixed !important;
@ -44,6 +45,8 @@
.aside-menu__item--danger { .aside-menu__item--danger {
color: $dangerColor; color: $dangerColor;
margin: 0;
@include border-radius(4px);
} }
.aside-menu__item--danger:hover { .aside-menu__item--danger:hover {
color: #fff; color: #fff;

View file

@ -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 [
(
<span
className={this.props.className}
onClick={() => this.setState({ isModalOpen: true })}
>
<FontAwesomeIcon icon={deleteIcon} />
<span className="aside-menu__item-text">Delete this server</span>
</span>
),
(
<DeleteServerModal
isOpen={this.state.isModalOpen}
toggle={() => this.setState({ isModalOpen: !this.state.isModalOpen })}
history={history}
server={server}
/>
)
];
}
}

View file

@ -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 (
<Modal isOpen={isOpen} toggle={toggle} centered={true}>
<ModalHeader toggle={toggle}>Delete server</ModalHeader>
<ModalBody>Are you sure you want to delete server <b>{server ? server.name : ''}</b>.</ModalBody>
<ModalFooter>
<button className="btn btn-link" onClick={toggle}>Cancel</button>
<button className="btn btn-danger" onClick={() => closeModal()}>Delete</button>
</ModalFooter>
</Modal>
);
};
export default connect(null, { deleteServer })(DeleteServerModal);

View file

@ -2,10 +2,12 @@ import ServersService from '../services';
const FETCH_SERVERS = 'shlink/servers/FETCH_SERVERS'; const FETCH_SERVERS = 'shlink/servers/FETCH_SERVERS';
const CREATE_SERVER = 'shlink/servers/CREATE_SERVER'; const CREATE_SERVER = 'shlink/servers/CREATE_SERVER';
const DELETE_SERVER = 'shlink/servers/DELETE_SERVER';
export default function reducer(state = {}, action) { export default function reducer(state = {}, action) {
switch (action.type) { switch (action.type) {
case FETCH_SERVERS: case FETCH_SERVERS:
case DELETE_SERVER:
return action.servers; return action.servers;
case CREATE_SERVER: case CREATE_SERVER:
const server = action.server; const server = action.server;
@ -26,3 +28,8 @@ export const createServer = server => {
ServersService.createServer(server); ServersService.createServer(server);
return listServers(); return listServers();
}; };
export const deleteServer = server => {
ServersService.deleteServer(server);
return listServers();
};

View file

@ -1,4 +1,5 @@
import Storage from '../../utils/Storage'; import Storage from '../../utils/Storage';
import { dissoc } from 'ramda';
const SERVERS_STORAGE_KEY = 'servers'; const SERVERS_STORAGE_KEY = 'servers';
@ -21,6 +22,11 @@ export class ServersService {
servers[server.id] = server; servers[server.id] = server;
this.storage.set(SERVERS_STORAGE_KEY, servers); 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); export default new ServersService(Storage);

View file

@ -0,0 +1,5 @@
@mixin border-radius($radius) {
border-radius: $radius;
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
}