Created new component to handle buttons displaying a dropdown menu

This commit is contained in:
Alejandro Celaya
2021-09-24 19:10:03 +02:00
parent 691dabcfbc
commit 304a7431ad
8 changed files with 54 additions and 41 deletions

View File

@@ -52,29 +52,29 @@ const AsideMenu = (DeleteServerButton: FC<DeleteServerButtonProps>) => (
<aside className={asideClass}> <aside className={asideClass}>
<nav className="nav flex-column aside-menu__nav"> <nav className="nav flex-column aside-menu__nav">
<AsideMenuItem to={buildPath('/overview')}> <AsideMenuItem to={buildPath('/overview')}>
<FontAwesomeIcon icon={overviewIcon} /> <FontAwesomeIcon fixedWidth icon={overviewIcon} />
<span className="aside-menu__item-text">Overview</span> <span className="aside-menu__item-text">Overview</span>
</AsideMenuItem> </AsideMenuItem>
<AsideMenuItem to={buildPath('/list-short-urls/1')} isActive={shortUrlsIsActive}> <AsideMenuItem to={buildPath('/list-short-urls/1')} isActive={shortUrlsIsActive}>
<FontAwesomeIcon icon={listIcon} /> <FontAwesomeIcon fixedWidth icon={listIcon} />
<span className="aside-menu__item-text">List short URLs</span> <span className="aside-menu__item-text">List short URLs</span>
</AsideMenuItem> </AsideMenuItem>
<AsideMenuItem to={buildPath('/create-short-url')}> <AsideMenuItem to={buildPath('/create-short-url')}>
<FontAwesomeIcon icon={createIcon} flip="horizontal" /> <FontAwesomeIcon fixedWidth icon={createIcon} flip="horizontal" />
<span className="aside-menu__item-text">Create short URL</span> <span className="aside-menu__item-text">Create short URL</span>
</AsideMenuItem> </AsideMenuItem>
<AsideMenuItem to={buildPath('/manage-tags')}> <AsideMenuItem to={buildPath('/manage-tags')}>
<FontAwesomeIcon icon={tagsIcon} /> <FontAwesomeIcon fixedWidth icon={tagsIcon} />
<span className="aside-menu__item-text">Manage tags</span> <span className="aside-menu__item-text">Manage tags</span>
</AsideMenuItem> </AsideMenuItem>
{addManageDomainsLink && ( {addManageDomainsLink && (
<AsideMenuItem to={buildPath('/manage-domains')}> <AsideMenuItem to={buildPath('/manage-domains')}>
<FontAwesomeIcon icon={domainsIcon} /> <FontAwesomeIcon fixedWidth icon={domainsIcon} />
<span className="aside-menu__item-text">Manage domains</span> <span className="aside-menu__item-text">Manage domains</span>
</AsideMenuItem> </AsideMenuItem>
)} )}
<AsideMenuItem to={buildPath('/edit')} className="aside-menu__item--push"> <AsideMenuItem to={buildPath('/edit')} className="aside-menu__item--push">
<FontAwesomeIcon icon={editIcon} /> <FontAwesomeIcon fixedWidth icon={editIcon} />
<span className="aside-menu__item-text">Edit this server</span> <span className="aside-menu__item-text">Edit this server</span>
</AsideMenuItem> </AsideMenuItem>
{isServerWithId(selectedServer) && ( {isServerWithId(selectedServer) && (

View File

@@ -19,7 +19,7 @@ const DeleteServerButton = (DeleteServerModal: FC<DeleteServerModalProps>): FC<D
return ( return (
<> <>
<span className={className} onClick={showModal}> <span className={className} onClick={showModal}>
{!children && <FontAwesomeIcon icon={deleteIcon} />} {!children && <FontAwesomeIcon fixedWidth icon={deleteIcon} />}
<span className={textClassName}>{children ?? 'Remove this server'}</span> <span className={textClassName}>{children ?? 'Remove this server'}</span>
</span> </span>

View File

@@ -40,3 +40,5 @@ export const isReachableServer = (server: SelectedServer): server is ReachableSe
export const isNotFoundServer = (server: SelectedServer): server is NotFoundServer => export const isNotFoundServer = (server: SelectedServer): server is NotFoundServer =>
!!server?.hasOwnProperty('serverNotFound'); !!server?.hasOwnProperty('serverNotFound');
export const getServerId = (server: SelectedServer) => isServerWithId(server) ? server.id : '';

View File

@@ -1,13 +1,5 @@
@import '../../utils/base'; @import '../../utils/base';
.short-urls-row-menu__dropdown-toggle:after {
display: none !important;
}
.short-urls-row-menu__dropdown-toggle--hidden {
visibility: hidden;
}
.short-urls-row-menu__dropdown-item--danger.short-urls-row-menu__dropdown-item--danger { .short-urls-row-menu__dropdown-item--danger.short-urls-row-menu__dropdown-item--danger {
color: $dangerColor; color: $dangerColor;

View File

@@ -1,16 +1,16 @@
import { import {
faChartPie as pieChartIcon, faChartPie as pieChartIcon,
faEllipsisV as menuIcon,
faQrcode as qrIcon, faQrcode as qrIcon,
faMinusCircle as deleteIcon, faMinusCircle as deleteIcon,
faEdit as editIcon, faEdit as editIcon,
} from '@fortawesome/free-solid-svg-icons'; } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { FC } from 'react'; import { FC } from 'react';
import { ButtonDropdown, DropdownItem, DropdownMenu, DropdownToggle } from 'reactstrap'; import { DropdownItem } from 'reactstrap';
import { useToggle } from '../../utils/helpers/hooks'; import { useToggle } from '../../utils/helpers/hooks';
import { ShortUrl, ShortUrlModalProps } from '../data'; import { ShortUrl, ShortUrlModalProps } from '../data';
import { SelectedServer } from '../../servers/data'; import { SelectedServer } from '../../servers/data';
import { DropdownBtnMenu } from '../../utils/DropdownBtnMenu';
import ShortUrlDetailLink from './ShortUrlDetailLink'; import ShortUrlDetailLink from './ShortUrlDetailLink';
import './ShortUrlsRowMenu.scss'; import './ShortUrlsRowMenu.scss';
@@ -29,32 +29,27 @@ const ShortUrlsRowMenu = (
const [ isDeleteModalOpen, toggleDelete ] = useToggle(); const [ isDeleteModalOpen, toggleDelete ] = useToggle();
return ( return (
<ButtonDropdown toggle={toggle} isOpen={isOpen}> <DropdownBtnMenu toggle={toggle} isOpen={isOpen}>
<DropdownToggle size="sm" caret outline className="short-urls-row-menu__dropdown-toggle"> <DropdownItem tag={ShortUrlDetailLink} selectedServer={selectedServer} shortUrl={shortUrl} suffix="visits">
&nbsp;<FontAwesomeIcon icon={menuIcon} />&nbsp; <FontAwesomeIcon icon={pieChartIcon} fixedWidth /> Visit stats
</DropdownToggle> </DropdownItem>
<DropdownMenu right>
<DropdownItem tag={ShortUrlDetailLink} selectedServer={selectedServer} shortUrl={shortUrl} suffix="visits">
<FontAwesomeIcon icon={pieChartIcon} fixedWidth /> Visit stats
</DropdownItem>
<DropdownItem tag={ShortUrlDetailLink} selectedServer={selectedServer} shortUrl={shortUrl} suffix="edit"> <DropdownItem tag={ShortUrlDetailLink} selectedServer={selectedServer} shortUrl={shortUrl} suffix="edit">
<FontAwesomeIcon icon={editIcon} fixedWidth /> Edit short URL <FontAwesomeIcon icon={editIcon} fixedWidth /> Edit short URL
</DropdownItem> </DropdownItem>
<DropdownItem onClick={toggleQrCode}> <DropdownItem onClick={toggleQrCode}>
<FontAwesomeIcon icon={qrIcon} fixedWidth /> QR code <FontAwesomeIcon icon={qrIcon} fixedWidth /> QR code
</DropdownItem> </DropdownItem>
<QrCodeModal shortUrl={shortUrl} isOpen={isQrModalOpen} toggle={toggleQrCode} /> <QrCodeModal shortUrl={shortUrl} isOpen={isQrModalOpen} toggle={toggleQrCode} />
<DropdownItem divider /> <DropdownItem divider />
<DropdownItem className="short-urls-row-menu__dropdown-item--danger" onClick={toggleDelete}> <DropdownItem className="short-urls-row-menu__dropdown-item--danger" onClick={toggleDelete}>
<FontAwesomeIcon icon={deleteIcon} fixedWidth /> Delete short URL <FontAwesomeIcon icon={deleteIcon} fixedWidth /> Delete short URL
</DropdownItem> </DropdownItem>
<DeleteShortUrlModal shortUrl={shortUrl} isOpen={isDeleteModalOpen} toggle={toggleDelete} /> <DeleteShortUrlModal shortUrl={shortUrl} isOpen={isDeleteModalOpen} toggle={toggleDelete} />
</DropdownMenu> </DropdownBtnMenu>
</ButtonDropdown>
); );
}; };

View File

@@ -0,0 +1,3 @@
.dropdown-btn-menu__dropdown-toggle:after {
display: none !important;
}

View File

@@ -0,0 +1,20 @@
import { FC } from 'react';
import { ButtonDropdown, DropdownMenu, DropdownToggle } from 'reactstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faEllipsisV as menuIcon } from '@fortawesome/free-solid-svg-icons';
import './DropdownBtnMenu.scss';
interface DropdownBtnMenuProps {
isOpen: boolean;
toggle: () => void;
right?: boolean;
}
export const DropdownBtnMenu: FC<DropdownBtnMenuProps> = ({ isOpen, toggle, children, right = true }) => (
<ButtonDropdown toggle={toggle} isOpen={isOpen}>
<DropdownToggle size="sm" caret outline className="dropdown-btn-menu__dropdown-toggle">
&nbsp;<FontAwesomeIcon icon={menuIcon} />&nbsp;
</DropdownToggle>
<DropdownMenu right={right}>{children}</DropdownMenu>
</ButtonDropdown>
);

View File

@@ -1,9 +1,10 @@
import { shallow, ShallowWrapper } from 'enzyme'; import { shallow, ShallowWrapper } from 'enzyme';
import { ButtonDropdown, DropdownItem } from 'reactstrap'; import { DropdownItem } from 'reactstrap';
import { Mock } from 'ts-mockery'; import { Mock } from 'ts-mockery';
import createShortUrlsRowMenu from '../../../src/short-urls/helpers/ShortUrlsRowMenu'; import createShortUrlsRowMenu from '../../../src/short-urls/helpers/ShortUrlsRowMenu';
import { ReachableServer } from '../../../src/servers/data'; import { ReachableServer } from '../../../src/servers/data';
import { ShortUrl } from '../../../src/short-urls/data'; import { ShortUrl } from '../../../src/short-urls/data';
import { DropdownBtnMenu } from '../../../src/utils/DropdownBtnMenu';
describe('<ShortUrlsRowMenu />', () => { describe('<ShortUrlsRowMenu />', () => {
let wrapper: ShallowWrapper; let wrapper: ShallowWrapper;
@@ -52,6 +53,6 @@ describe('<ShortUrlsRowMenu />', () => {
it('DeleteShortUrlModal', () => assert(DeleteShortUrlModal)); it('DeleteShortUrlModal', () => assert(DeleteShortUrlModal));
it('QrCodeModal', () => assert(QrCodeModal)); it('QrCodeModal', () => assert(QrCodeModal));
it('ShortUrlRowMenu', () => assert(ButtonDropdown)); it('ShortUrlRowMenu', () => assert(DropdownBtnMenu));
}); });
}); });