mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-10 18:27:25 +03:00
Ensured proper amount of visits is displayed on short URLs based on config
This commit is contained in:
parent
2859ba6cd2
commit
5942cd6fcf
3 changed files with 34 additions and 12 deletions
|
@ -1,4 +1,4 @@
|
||||||
import { useEffect, useRef } from 'react';
|
import { FC, useEffect, useRef } from 'react';
|
||||||
import { ExternalLink } from 'react-external-link';
|
import { ExternalLink } from 'react-external-link';
|
||||||
import { ColorGenerator } from '../../utils/services/ColorGenerator';
|
import { ColorGenerator } from '../../utils/services/ColorGenerator';
|
||||||
import { TimeoutToggle } from '../../utils/helpers/hooks';
|
import { TimeoutToggle } from '../../utils/helpers/hooks';
|
||||||
|
@ -6,6 +6,7 @@ import { SelectedServer } from '../../servers/data';
|
||||||
import { CopyToClipboardIcon } from '../../utils/CopyToClipboardIcon';
|
import { CopyToClipboardIcon } from '../../utils/CopyToClipboardIcon';
|
||||||
import { ShortUrl } from '../data';
|
import { ShortUrl } from '../data';
|
||||||
import { Time } from '../../utils/dates/Time';
|
import { Time } from '../../utils/dates/Time';
|
||||||
|
import { Settings } from '../../settings/reducers/settings';
|
||||||
import { ShortUrlVisitsCount } from './ShortUrlVisitsCount';
|
import { ShortUrlVisitsCount } from './ShortUrlVisitsCount';
|
||||||
import { ShortUrlsRowMenuType } from './ShortUrlsRowMenu';
|
import { ShortUrlsRowMenuType } from './ShortUrlsRowMenu';
|
||||||
import { Tags } from './Tags';
|
import { Tags } from './Tags';
|
||||||
|
@ -18,19 +19,26 @@ interface ShortUrlsRowProps {
|
||||||
shortUrl: ShortUrl;
|
shortUrl: ShortUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ShortUrlsRowConnectProps extends ShortUrlsRowProps {
|
||||||
|
settings: Settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ShortUrlsRowType = FC<ShortUrlsRowProps>;
|
||||||
|
|
||||||
export const ShortUrlsRow = (
|
export const ShortUrlsRow = (
|
||||||
ShortUrlsRowMenu: ShortUrlsRowMenuType,
|
ShortUrlsRowMenu: ShortUrlsRowMenuType,
|
||||||
colorGenerator: ColorGenerator,
|
colorGenerator: ColorGenerator,
|
||||||
useTimeoutToggle: TimeoutToggle,
|
useTimeoutToggle: TimeoutToggle,
|
||||||
) => ({ shortUrl, selectedServer, onTagClick }: ShortUrlsRowProps) => {
|
) => ({ shortUrl, selectedServer, onTagClick, settings }: ShortUrlsRowConnectProps) => {
|
||||||
const [copiedToClipboard, setCopiedToClipboard] = useTimeoutToggle();
|
const [copiedToClipboard, setCopiedToClipboard] = useTimeoutToggle();
|
||||||
const [active, setActive] = useTimeoutToggle(false, 500);
|
const [active, setActive] = useTimeoutToggle(false, 500);
|
||||||
const isFirstRun = useRef(true);
|
const isFirstRun = useRef(true);
|
||||||
|
const { visits } = settings;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
!isFirstRun.current && setActive();
|
!isFirstRun.current && setActive();
|
||||||
isFirstRun.current = false;
|
isFirstRun.current = false;
|
||||||
}, [shortUrl.visitsCount]);
|
}, [shortUrl.visitsSummary?.total, shortUrl.visitsSummary?.nonBots, shortUrl.visitsCount]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className="responsive-table__row">
|
<tr className="responsive-table__row">
|
||||||
|
@ -64,7 +72,9 @@ export const ShortUrlsRow = (
|
||||||
</td>
|
</td>
|
||||||
<td className="responsive-table__cell short-urls-row__cell text-lg-end" data-th="Visits">
|
<td className="responsive-table__cell short-urls-row__cell text-lg-end" data-th="Visits">
|
||||||
<ShortUrlVisitsCount
|
<ShortUrlVisitsCount
|
||||||
visitsCount={shortUrl.visitsSummary?.total ?? shortUrl.visitsCount}
|
visitsCount={(
|
||||||
|
visits?.excludeBots ? shortUrl.visitsSummary?.nonBots : shortUrl.visitsSummary?.total
|
||||||
|
) ?? shortUrl.visitsCount}
|
||||||
shortUrl={shortUrl}
|
shortUrl={shortUrl}
|
||||||
selectedServer={selectedServer}
|
selectedServer={selectedServer}
|
||||||
active={active}
|
active={active}
|
||||||
|
@ -79,5 +89,3 @@ export const ShortUrlsRow = (
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ShortUrlsRowType = ReturnType<typeof ShortUrlsRow>;
|
|
||||||
|
|
|
@ -28,7 +28,10 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
|
||||||
));
|
));
|
||||||
|
|
||||||
bottle.serviceFactory('ShortUrlsTable', ShortUrlsTable, 'ShortUrlsRow');
|
bottle.serviceFactory('ShortUrlsTable', ShortUrlsTable, 'ShortUrlsRow');
|
||||||
|
|
||||||
bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'ShortUrlsRowMenu', 'ColorGenerator', 'useTimeoutToggle');
|
bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'ShortUrlsRowMenu', 'ColorGenerator', 'useTimeoutToggle');
|
||||||
|
bottle.decorator('ShortUrlsRow', connect(['settings']));
|
||||||
|
|
||||||
bottle.serviceFactory('ShortUrlsRowMenu', ShortUrlsRowMenu, 'DeleteShortUrlModal', 'QrCodeModal');
|
bottle.serviceFactory('ShortUrlsRowMenu', ShortUrlsRowMenu, 'DeleteShortUrlModal', 'QrCodeModal');
|
||||||
bottle.serviceFactory('CreateShortUrlResult', CreateShortUrlResult, 'useTimeoutToggle');
|
bottle.serviceFactory('CreateShortUrlResult', CreateShortUrlResult, 'useTimeoutToggle');
|
||||||
bottle.serviceFactory('ShortUrlForm', ShortUrlForm, 'TagsSelector', 'DomainSelector');
|
bottle.serviceFactory('ShortUrlForm', ShortUrlForm, 'TagsSelector', 'DomainSelector');
|
||||||
|
|
|
@ -5,12 +5,20 @@ import { addDays, formatISO, subDays } from 'date-fns';
|
||||||
import { ShortUrlsRow as createShortUrlsRow } from '../../../src/short-urls/helpers/ShortUrlsRow';
|
import { ShortUrlsRow as createShortUrlsRow } from '../../../src/short-urls/helpers/ShortUrlsRow';
|
||||||
import { TimeoutToggle } from '../../../src/utils/helpers/hooks';
|
import { TimeoutToggle } from '../../../src/utils/helpers/hooks';
|
||||||
import { ShortUrl, ShortUrlMeta } from '../../../src/short-urls/data';
|
import { ShortUrl, ShortUrlMeta } from '../../../src/short-urls/data';
|
||||||
|
import { Settings } from '../../../src/settings/reducers/settings';
|
||||||
import { ReachableServer } from '../../../src/servers/data';
|
import { ReachableServer } from '../../../src/servers/data';
|
||||||
import { parseDate, now } from '../../../src/utils/helpers/date';
|
import { parseDate, now } from '../../../src/utils/helpers/date';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
import { OptionalString } from '../../../src/utils/utils';
|
import { OptionalString } from '../../../src/utils/utils';
|
||||||
import { colorGeneratorMock } from '../../utils/services/__mocks__/ColorGenerator.mock';
|
import { colorGeneratorMock } from '../../utils/services/__mocks__/ColorGenerator.mock';
|
||||||
|
|
||||||
|
interface SetUpOptions {
|
||||||
|
title?: OptionalString;
|
||||||
|
tags?: string[];
|
||||||
|
meta?: ShortUrlMeta;
|
||||||
|
settings?: Partial<Settings>;
|
||||||
|
}
|
||||||
|
|
||||||
describe('<ShortUrlsRow />', () => {
|
describe('<ShortUrlsRow />', () => {
|
||||||
const timeoutToggle = jest.fn(() => true);
|
const timeoutToggle = jest.fn(() => true);
|
||||||
const useTimeoutToggle = jest.fn(() => [false, timeoutToggle]) as TimeoutToggle;
|
const useTimeoutToggle = jest.fn(() => [false, timeoutToggle]) as TimeoutToggle;
|
||||||
|
@ -35,15 +43,14 @@ describe('<ShortUrlsRow />', () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const ShortUrlsRow = createShortUrlsRow(() => <span>ShortUrlsRowMenu</span>, colorGeneratorMock, useTimeoutToggle);
|
const ShortUrlsRow = createShortUrlsRow(() => <span>ShortUrlsRowMenu</span>, colorGeneratorMock, useTimeoutToggle);
|
||||||
const setUp = (
|
const setUp = ({ title, tags = [], meta = {}, settings = {} }: SetUpOptions = {}) => renderWithEvents(
|
||||||
{ title, tags = [], meta = {} }: { title?: OptionalString; tags?: string[]; meta?: ShortUrlMeta } = {},
|
|
||||||
) => renderWithEvents(
|
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<ShortUrlsRow
|
<ShortUrlsRow
|
||||||
selectedServer={server}
|
selectedServer={server}
|
||||||
shortUrl={{ ...shortUrl, title, tags, meta: { ...shortUrl.meta, ...meta } }}
|
shortUrl={{ ...shortUrl, title, tags, meta: { ...shortUrl.meta, ...meta } }}
|
||||||
onTagClick={() => null}
|
onTagClick={() => null}
|
||||||
|
settings={Mock.of<Settings>(settings)}
|
||||||
/>
|
/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>,
|
</table>,
|
||||||
|
@ -97,9 +104,13 @@ describe('<ShortUrlsRow />', () => {
|
||||||
expectedContents.forEach((content) => expect(cell).toHaveTextContent(content));
|
expectedContents.forEach((content) => expect(cell).toHaveTextContent(content));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders visits count in fifth row', () => {
|
it.each([
|
||||||
setUp();
|
[{}, shortUrl.visitsSummary?.total],
|
||||||
expect(screen.getAllByRole('cell')[4]).toHaveTextContent(`${shortUrl.visitsCount}`);
|
[Mock.of<Settings>({ visits: { excludeBots: false } }), shortUrl.visitsSummary?.total],
|
||||||
|
[Mock.of<Settings>({ visits: { excludeBots: true } }), shortUrl.visitsSummary?.nonBots],
|
||||||
|
])('renders visits count in fifth row', (settings, expectedAmount) => {
|
||||||
|
setUp({ settings });
|
||||||
|
expect(screen.getAllByRole('cell')[4]).toHaveTextContent(`${expectedAmount}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('updates state when copied to clipboard', async () => {
|
it('updates state when copied to clipboard', async () => {
|
||||||
|
|
Loading…
Reference in a new issue