Exported some specific component types and improved spacing in short URLs list

This commit is contained in:
Alejandro Celaya 2022-12-18 10:12:34 +01:00
parent f4cf4850a3
commit 90837546ab
9 changed files with 33 additions and 22 deletions

View file

@ -4,7 +4,7 @@ import { Link, useNavigate } from 'react-router-dom';
import { ITEMS_IN_OVERVIEW_PAGE, ShortUrlsList as ShortUrlsListState } from '../short-urls/reducers/shortUrlsList'; import { ITEMS_IN_OVERVIEW_PAGE, ShortUrlsList as ShortUrlsListState } from '../short-urls/reducers/shortUrlsList';
import { prettify } from '../utils/helpers/numbers'; import { prettify } from '../utils/helpers/numbers';
import { TagsList } from '../tags/reducers/tagsList'; import { TagsList } from '../tags/reducers/tagsList';
import { ShortUrlsTableProps } from '../short-urls/ShortUrlsTable'; import { ShortUrlsTableType } from '../short-urls/ShortUrlsTable';
import { boundToMercureHub } from '../mercure/helpers/boundToMercureHub'; import { boundToMercureHub } from '../mercure/helpers/boundToMercureHub';
import { CreateShortUrlProps } from '../short-urls/CreateShortUrl'; import { CreateShortUrlProps } from '../short-urls/CreateShortUrl';
import { VisitsOverview } from '../visits/reducers/visitsOverview'; import { VisitsOverview } from '../visits/reducers/visitsOverview';
@ -25,7 +25,7 @@ interface OverviewConnectProps {
} }
export const Overview = ( export const Overview = (
ShortUrlsTable: FC<ShortUrlsTableProps>, ShortUrlsTable: ShortUrlsTableType,
CreateShortUrl: FC<CreateShortUrlProps>, CreateShortUrl: FC<CreateShortUrlProps>,
) => boundToMercureHub(({ ) => boundToMercureHub(({
shortUrlsList, shortUrlsList,

View file

@ -21,7 +21,7 @@ export const Paginator = ({ paginator, serverId, currentQueryString = '' }: Pagi
`/server/${serverId}/list-short-urls/${pageNumber}${currentQueryString}`; `/server/${serverId}/list-short-urls/${pageNumber}${currentQueryString}`;
if (pagesCount <= 1) { if (pagesCount <= 1) {
return null; return <div className="pb-3" />; // Return some space
} }
const renderPages = () => const renderPages = () =>
@ -38,7 +38,7 @@ export const Paginator = ({ paginator, serverId, currentQueryString = '' }: Pagi
)); ));
return ( return (
<Pagination className="sticky-card-paginator" listClassName="flex-wrap justify-content-center mb-0"> <Pagination className="sticky-card-paginator py-3" listClassName="flex-wrap justify-content-center mb-0">
<PaginationItem disabled={currentPage === 1}> <PaginationItem disabled={currentPage === 1}>
<PaginationLink previous tag={Link} to={urlForPage(currentPage - 1)} /> <PaginationLink previous tag={Link} to={urlForPage(currentPage - 1)} />
</PaginationItem> </PaginationItem>

View file

@ -18,7 +18,7 @@ import { ExportShortUrlsBtnProps } from './helpers/ExportShortUrlsBtn';
import { TagsSelectorProps } from '../tags/helpers/TagsSelector'; import { TagsSelectorProps } from '../tags/helpers/TagsSelector';
import './ShortUrlsFilteringBar.scss'; import './ShortUrlsFilteringBar.scss';
export interface ShortUrlsFilteringProps { interface ShortUrlsFilteringProps {
selectedServer: SelectedServer; selectedServer: SelectedServer;
order: ShortUrlsOrder; order: ShortUrlsOrder;
handleOrderBy: (orderField?: ShortUrlsOrderableFields, orderDir?: OrderDir) => void; handleOrderBy: (orderField?: ShortUrlsOrderableFields, orderDir?: OrderDir) => void;
@ -90,3 +90,5 @@ export const ShortUrlsFilteringBar = (
</div> </div>
); );
}; };
export type ShortUrlsFilteringBarType = ReturnType<typeof ShortUrlsFilteringBar>;

View file

@ -1,5 +1,5 @@
import { pipe } from 'ramda'; import { pipe } from 'ramda';
import { FC, useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Card } from 'reactstrap'; import { Card } from 'reactstrap';
import { useLocation, useParams } from 'react-router-dom'; import { useLocation, useParams } from 'react-router-dom';
import { determineOrderDir, OrderDir } from '../utils/helpers/ordering'; import { determineOrderDir, OrderDir } from '../utils/helpers/ordering';
@ -10,11 +10,11 @@ import { TableOrderIcon } from '../utils/table/TableOrderIcon';
import { ShlinkShortUrlsListParams } from '../api/types'; import { ShlinkShortUrlsListParams } from '../api/types';
import { DEFAULT_SHORT_URLS_ORDERING, Settings } from '../settings/reducers/settings'; import { DEFAULT_SHORT_URLS_ORDERING, Settings } from '../settings/reducers/settings';
import { ShortUrlsList as ShortUrlsListState } from './reducers/shortUrlsList'; import { ShortUrlsList as ShortUrlsListState } from './reducers/shortUrlsList';
import { ShortUrlsTableProps } from './ShortUrlsTable'; import { ShortUrlsTableType } from './ShortUrlsTable';
import { Paginator } from './Paginator'; import { Paginator } from './Paginator';
import { useShortUrlsQuery } from './helpers/hooks'; import { useShortUrlsQuery } from './helpers/hooks';
import { ShortUrlsOrderableFields } from './data'; import { ShortUrlsOrderableFields } from './data';
import { ShortUrlsFilteringProps } from './ShortUrlsFilteringBar'; import { ShortUrlsFilteringBarType } from './ShortUrlsFilteringBar';
interface ShortUrlsListProps { interface ShortUrlsListProps {
selectedServer: SelectedServer; selectedServer: SelectedServer;
@ -24,8 +24,8 @@ interface ShortUrlsListProps {
} }
export const ShortUrlsList = ( export const ShortUrlsList = (
ShortUrlsTable: FC<ShortUrlsTableProps>, ShortUrlsTable: ShortUrlsTableType,
ShortUrlsFilteringBar: FC<ShortUrlsFilteringProps>, ShortUrlsFilteringBar: ShortUrlsFilteringBarType,
) => boundToMercureHub(({ listShortUrls, shortUrlsList, selectedServer, settings }: ShortUrlsListProps) => { ) => boundToMercureHub(({ listShortUrls, shortUrlsList, selectedServer, settings }: ShortUrlsListProps) => {
const serverId = getServerId(selectedServer); const serverId = getServerId(selectedServer);
const { page } = useParams(); const { page } = useParams();
@ -70,7 +70,7 @@ export const ShortUrlsList = (
handleOrderBy={handleOrderBy} handleOrderBy={handleOrderBy}
className="mb-3" className="mb-3"
/> />
<Card body className="pb-1"> <Card body className="pb-0">
<ShortUrlsTable <ShortUrlsTable
selectedServer={selectedServer} selectedServer={selectedServer}
shortUrlsList={shortUrlsList} shortUrlsList={shortUrlsList}

View file

@ -1,3 +1,7 @@
.short-urls-table.short-urls-table {
margin-bottom: -1px;
}
.short-urls-table__header-cell--with-action { .short-urls-table__header-cell--with-action {
cursor: pointer; cursor: pointer;
} }

View file

@ -1,13 +1,13 @@
import { FC, ReactNode } from 'react'; import { ReactNode } from 'react';
import { isEmpty } from 'ramda'; import { isEmpty } from 'ramda';
import classNames from 'classnames'; import classNames from 'classnames';
import { SelectedServer } from '../servers/data'; import { SelectedServer } from '../servers/data';
import { ShortUrlsList as ShortUrlsListState } from './reducers/shortUrlsList'; import { ShortUrlsList as ShortUrlsListState } from './reducers/shortUrlsList';
import { ShortUrlsRowProps } from './helpers/ShortUrlsRow'; import { ShortUrlsRowType } from './helpers/ShortUrlsRow';
import { ShortUrlsOrderableFields } from './data'; import { ShortUrlsOrderableFields } from './data';
import './ShortUrlsTable.scss'; import './ShortUrlsTable.scss';
export interface ShortUrlsTableProps { interface ShortUrlsTableProps {
orderByColumn?: (column: ShortUrlsOrderableFields) => () => void; orderByColumn?: (column: ShortUrlsOrderableFields) => () => void;
renderOrderIcon?: (column: ShortUrlsOrderableFields) => ReactNode; renderOrderIcon?: (column: ShortUrlsOrderableFields) => ReactNode;
shortUrlsList: ShortUrlsListState; shortUrlsList: ShortUrlsListState;
@ -16,7 +16,7 @@ export interface ShortUrlsTableProps {
className?: string; className?: string;
} }
export const ShortUrlsTable = (ShortUrlsRow: FC<ShortUrlsRowProps>) => ({ export const ShortUrlsTable = (ShortUrlsRow: ShortUrlsRowType) => ({
orderByColumn, orderByColumn,
renderOrderIcon, renderOrderIcon,
shortUrlsList, shortUrlsList,
@ -27,7 +27,7 @@ export const ShortUrlsTable = (ShortUrlsRow: FC<ShortUrlsRowProps>) => ({
const { error, loading, shortUrls } = shortUrlsList; const { error, loading, shortUrls } = shortUrlsList;
const actionableFieldClasses = classNames({ 'short-urls-table__header-cell--with-action': !!orderByColumn }); const actionableFieldClasses = classNames({ 'short-urls-table__header-cell--with-action': !!orderByColumn });
const orderableColumnsClasses = classNames('short-urls-table__header-cell', actionableFieldClasses); const orderableColumnsClasses = classNames('short-urls-table__header-cell', actionableFieldClasses);
const tableClasses = classNames('table table-hover responsive-table', className); const tableClasses = classNames('table table-hover responsive-table short-urls-table', className);
const renderShortUrls = () => { const renderShortUrls = () => {
if (error) { if (error) {
@ -90,3 +90,5 @@ export const ShortUrlsTable = (ShortUrlsRow: FC<ShortUrlsRowProps>) => ({
</table> </table>
); );
}; };
export type ShortUrlsTableType = ReturnType<typeof ShortUrlsTable>;

View file

@ -12,7 +12,7 @@ import { ShortUrlVisitsCount } from './ShortUrlVisitsCount';
import { ShortUrlsRowMenuProps } from './ShortUrlsRowMenu'; import { ShortUrlsRowMenuProps } from './ShortUrlsRowMenu';
import './ShortUrlsRow.scss'; import './ShortUrlsRow.scss';
export interface ShortUrlsRowProps { interface ShortUrlsRowProps {
onTagClick?: (tag: string) => void; onTagClick?: (tag: string) => void;
selectedServer: SelectedServer; selectedServer: SelectedServer;
shortUrl: ShortUrl; shortUrl: ShortUrl;
@ -89,3 +89,5 @@ export const ShortUrlsRow = (
</tr> </tr>
); );
}; };
export type ShortUrlsRowType = ReturnType<typeof ShortUrlsRow>;

View file

@ -18,9 +18,11 @@ describe('<Paginator />', () => {
[buildPaginator()], [buildPaginator()],
[buildPaginator(0)], [buildPaginator(0)],
[buildPaginator(1)], [buildPaginator(1)],
])('renders nothing if the number of pages is below 2', (paginator) => { ])('renders an empty gap if the number of pages is below 2', (paginator) => {
const { container } = setUp(paginator); const { container } = setUp(paginator);
expect(container.firstChild).toBeNull();
expect(container.firstChild).toBeEmpty();
expect(container.firstChild).toHaveClass('pb-3');
}); });
it.each([ it.each([

View file

@ -1,5 +1,4 @@
import { screen } from '@testing-library/react'; import { screen } from '@testing-library/react';
import { FC } from 'react';
import { Mock } from 'ts-mockery'; import { Mock } from 'ts-mockery';
import { MemoryRouter, useNavigate } from 'react-router-dom'; import { MemoryRouter, useNavigate } from 'react-router-dom';
import { ShortUrlsList as createShortUrlsList } from '../../src/short-urls/ShortUrlsList'; import { ShortUrlsList as createShortUrlsList } from '../../src/short-urls/ShortUrlsList';
@ -8,7 +7,7 @@ import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
import { ShortUrlsList as ShortUrlsListModel } from '../../src/short-urls/reducers/shortUrlsList'; import { ShortUrlsList as ShortUrlsListModel } from '../../src/short-urls/reducers/shortUrlsList';
import { ReachableServer } from '../../src/servers/data'; import { ReachableServer } from '../../src/servers/data';
import { Settings } from '../../src/settings/reducers/settings'; import { Settings } from '../../src/settings/reducers/settings';
import { ShortUrlsTableProps } from '../../src/short-urls/ShortUrlsTable'; import { ShortUrlsTableType } from '../../src/short-urls/ShortUrlsTable';
import { renderWithEvents } from '../__helpers__/setUpTest'; import { renderWithEvents } from '../__helpers__/setUpTest';
jest.mock('react-router-dom', () => ({ jest.mock('react-router-dom', () => ({
@ -18,7 +17,7 @@ jest.mock('react-router-dom', () => ({
})); }));
describe('<ShortUrlsList />', () => { describe('<ShortUrlsList />', () => {
const ShortUrlsTable: FC<ShortUrlsTableProps> = ({ onTagClick }) => <span onClick={() => onTagClick?.('foo')}>ShortUrlsTable</span>; const ShortUrlsTable: ShortUrlsTableType = ({ onTagClick }) => <span onClick={() => onTagClick?.('foo')}>ShortUrlsTable</span>;
const ShortUrlsFilteringBar = () => <span>ShortUrlsFilteringBar</span>; const ShortUrlsFilteringBar = () => <span>ShortUrlsFilteringBar</span>;
const listShortUrlsMock = jest.fn(); const listShortUrlsMock = jest.fn();
const navigate = jest.fn(); const navigate = jest.fn();