Created Overview page as default page after connecting to a server

This commit is contained in:
Alejandro Celaya 2020-12-06 18:32:24 +01:00
parent 920effb4c6
commit dba0ac6442
13 changed files with 73 additions and 6 deletions

View file

@ -3,6 +3,7 @@ import {
faLink as createIcon,
faTags as tagsIcon,
faPen as editIcon,
faHome as overviewIcon,
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { FC } from 'react';
@ -48,6 +49,10 @@ const AsideMenu = (DeleteServerButton: FC<DeleteServerButtonProps>) => (
return (
<aside className={asideClass}>
<nav className="nav flex-column aside-menu__nav">
<AsideMenuItem to={buildPath('/overview')}>
<FontAwesomeIcon icon={overviewIcon} />
<span className="aside-menu__item-text">Overview</span>
</AsideMenuItem>
<AsideMenuItem to={buildPath('/list-short-urls/1')} isActive={shortUrlsIsActive}>
<FontAwesomeIcon icon={listIcon} />
<span className="aside-menu__item-text">List short URLs</span>

View file

@ -20,6 +20,7 @@ const MenuLayout = (
ShortUrlVisits: FC,
TagVisits: FC,
ServerError: FC,
Overview: FC,
) => withSelectedServer(({ location, selectedServer }) => {
const [ sidebarVisible, toggleSidebar, showSidebar, hideSidebar ] = useToggle();
@ -60,6 +61,7 @@ const MenuLayout = (
<div className="col-lg-10 offset-lg-2 col-md-9 offset-md-3" onClick={() => hideSidebar()}>
<div className="menu-layout__container">
<Switch>
<Route exact path="/server/:serverId/overview" component={Overview} />
<Route exact path="/server/:serverId/list-short-urls/:page" component={ShortUrls} />
<Route exact path="/server/:serverId/create-short-url" component={CreateShortUrl} />
<Route exact path="/server/:serverId/short-code/:shortCode/visits" component={ShortUrlVisits} />

View file

@ -33,6 +33,7 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator, withRouter:
'ShortUrlVisits',
'TagVisits',
'ServerError',
'Overview',
);
bottle.decorator('MenuLayout', connect([ 'selectedServer', 'shortUrlsListParams' ], [ 'selectServer' ]));
bottle.decorator('MenuLayout', withRouter);

View file

@ -39,7 +39,7 @@ const CreateServer = (ImportServersBtn: FC<ImportServersBtnProps>, useStateFlagT
const id = uuid();
createServer({ ...serverData, id });
push(`/server/${id}/list-short-urls/1`);
push(`/server/${id}/overview`);
};
return (

View file

@ -26,7 +26,7 @@ const DeleteServerModal = ({ server, toggle, isOpen, deleteServer, history }: De
<p>Are you sure you want to remove <b>{server ? server.name : ''}</b>?</p>
<p>
<i>
No data will be deleted, only the access to this server will be removed from this host.
No data will be deleted, only the access to this server will be removed from this device.
You can create it again at any moment.
</i>
</p>

View file

@ -18,7 +18,7 @@ export const EditServer = (ServerError: FC) => withSelectedServer<EditServerProp
const handleSubmit = (serverData: ServerData) => {
editServer(selectedServer.id, serverData);
push(`/server/${selectedServer.id}/list-short-urls/1`);
push(`/server/${selectedServer.id}/overview`);
};
return (

50
src/servers/Overview.tsx Normal file
View file

@ -0,0 +1,50 @@
import { useEffect } from 'react';
import { Card, CardText, CardTitle } from 'reactstrap';
import { ShortUrlsListParams } from '../short-urls/reducers/shortUrlsListParams';
import { ShortUrlsList as ShortUrlsListState } from '../short-urls/reducers/shortUrlsList';
import { prettify } from '../utils/helpers/numbers';
import { TagsList } from '../tags/reducers/tagsList';
interface OverviewConnectProps {
shortUrlsList: ShortUrlsListState;
listShortUrls: (params: ShortUrlsListParams) => void;
listTags: Function;
tagsList: TagsList;
}
export const Overview = ({ shortUrlsList, listShortUrls, listTags, tagsList }: OverviewConnectProps) => {
const { loading, error, shortUrls } = shortUrlsList;
const { loading: loadingTags } = tagsList;
useEffect(() => {
listShortUrls({ itemsPerPage: 5 });
listTags();
}, []);
return (
<div className="row">
<div className="col-sm-4">
<Card className="text-center mb-2 mb-sm-0" body>
<CardTitle tag="h5">Visits</CardTitle>
<CardText tag="h2">?</CardText>
</Card>
</div>
<div className="col-sm-4">
<Card className="text-center mb-2 mb-sm-0" body>
<CardTitle tag="h5">Short URLs</CardTitle>
<CardText tag="h2">
{loading && !error && 'Loading...'}
{error && !loading && 'Failed :('}
{!error && !loading && prettify(shortUrls?.pagination.totalItems ?? 0)}
</CardText>
</Card>
</div>
<div className="col-sm-4">
<Card className="text-center" body>
<CardTitle tag="h5">Tags</CardTitle>
<CardText tag="h2">{loadingTags ? 'Loading... ' : prettify(tagsList.tags.length)}</CardText>
</Card>
</div>
</div>
);
};

View file

@ -23,7 +23,7 @@ const ServersDropdown = (serversExporter: ServersExporter) => ({ servers, select
<DropdownItem
key={id}
tag={Link}
to={`/server/${id}/list-short-urls/1`}
to={`/server/${id}/overview`}
active={isServerWithId(selectedServer) && selectedServer.id === id}
>
{name}

View file

@ -11,7 +11,7 @@ interface ServersListGroup {
}
const ServerListItem = ({ id, name }: { id: string; name: string }) => (
<ListGroupItem tag={Link} to={`/server/${id}/list-short-urls/1`} className="servers-list__server-item">
<ListGroupItem tag={Link} to={`/server/${id}/overview`} className="servers-list__server-item">
{name}
<FontAwesomeIcon icon={chevronIcon} className="servers-list__server-item-icon" />
</ListGroupItem>

View file

@ -13,6 +13,7 @@ import ForServerVersion from '../helpers/ForServerVersion';
import { ServerError } from '../helpers/ServerError';
import { ConnectDecorator } from '../../container/types';
import { withoutSelectedServer } from '../helpers/withoutSelectedServer';
import { Overview } from '../Overview';
import ServersImporter from './ServersImporter';
import ServersExporter from './ServersExporter';
@ -43,6 +44,12 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator, withRouter:
bottle.serviceFactory('ServerError', ServerError, 'DeleteServerButton');
bottle.decorator('ServerError', connect([ 'servers', 'selectedServer' ]));
bottle.serviceFactory('Overview', () => Overview);
bottle.decorator('Overview', connect(
[ 'shortUrlsList', 'tagsList' ],
[ 'listShortUrls', 'listTags' ],
));
// Services
bottle.constant('csvjson', csvjson);
bottle.constant('fileReaderFactory', () => new FileReader());

View file

@ -15,6 +15,7 @@ export type OrderableFields = keyof typeof SORTABLE_FIELDS;
export interface ShortUrlsListParams {
page?: string;
itemsPerPage?: number;
tags?: string[];
searchTerm?: string;
startDate?: string;

View file

@ -36,6 +36,7 @@ export interface ShlinkTagsResponse {
export interface ShlinkPaginator {
currentPage: number;
pagesCount: number;
totalItems: number;
}
export interface ShlinkVisits {

View file

@ -17,7 +17,7 @@ describe('<AsideMenu />', () => {
it('contains links to different sections', () => {
const links = wrapped.find('[to]');
expect(links).toHaveLength(4);
expect(links).toHaveLength(5);
links.forEach((link) => expect(link.prop('to')).toContain('abc123'));
});