mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 09:30:31 +03:00
Minor changes on tags filtering for short URLs
This commit is contained in:
parent
303900756d
commit
109baef828
12 changed files with 19 additions and 68 deletions
|
@ -13,7 +13,7 @@ import './MenuLayout.scss';
|
||||||
|
|
||||||
const MenuLayout = (
|
const MenuLayout = (
|
||||||
TagsList: FC,
|
TagsList: FC,
|
||||||
ShortUrls: FC,
|
ShortUrlsList: FC,
|
||||||
AsideMenu: FC<AsideMenuProps>,
|
AsideMenu: FC<AsideMenuProps>,
|
||||||
CreateShortUrl: FC,
|
CreateShortUrl: FC,
|
||||||
ShortUrlVisits: FC,
|
ShortUrlVisits: FC,
|
||||||
|
@ -49,7 +49,7 @@ const MenuLayout = (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Redirect exact from="/server/:serverId" to="/server/:serverId/overview" />
|
<Redirect exact from="/server/:serverId" to="/server/:serverId/overview" />
|
||||||
<Route exact path="/server/:serverId/overview" component={Overview} />
|
<Route exact path="/server/:serverId/overview" component={Overview} />
|
||||||
<Route exact path="/server/:serverId/list-short-urls/:page" component={ShortUrls} />
|
<Route exact path="/server/:serverId/list-short-urls/:page" component={ShortUrlsList} />
|
||||||
<Route exact path="/server/:serverId/create-short-url" component={CreateShortUrl} />
|
<Route exact path="/server/:serverId/create-short-url" component={CreateShortUrl} />
|
||||||
<Route path="/server/:serverId/short-code/:shortCode/visits" component={ShortUrlVisits} />
|
<Route path="/server/:serverId/short-code/:shortCode/visits" component={ShortUrlVisits} />
|
||||||
<Route path="/server/:serverId/short-code/:shortCode/edit" component={EditShortUrl} />
|
<Route path="/server/:serverId/short-code/:shortCode/edit" component={EditShortUrl} />
|
||||||
|
|
|
@ -35,7 +35,7 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator, withRouter:
|
||||||
'MenuLayout',
|
'MenuLayout',
|
||||||
MenuLayout,
|
MenuLayout,
|
||||||
'TagsList',
|
'TagsList',
|
||||||
'ShortUrls',
|
'ShortUrlsList',
|
||||||
'AsideMenu',
|
'AsideMenu',
|
||||||
'CreateShortUrl',
|
'CreateShortUrl',
|
||||||
'ShortUrlVisits',
|
'ShortUrlVisits',
|
||||||
|
|
|
@ -36,7 +36,7 @@ const connect: ConnectDecorator = (propsFromState: string[] | null, actionServic
|
||||||
provideAppServices(bottle, connect);
|
provideAppServices(bottle, connect);
|
||||||
provideCommonServices(bottle, connect, withRouter);
|
provideCommonServices(bottle, connect, withRouter);
|
||||||
provideApiServices(bottle);
|
provideApiServices(bottle);
|
||||||
provideShortUrlsServices(bottle, connect);
|
provideShortUrlsServices(bottle, connect, withRouter);
|
||||||
provideServersServices(bottle, connect, withRouter);
|
provideServersServices(bottle, connect, withRouter);
|
||||||
provideTagsServices(bottle, connect);
|
provideTagsServices(bottle, connect);
|
||||||
provideVisitsServices(bottle, connect);
|
provideVisitsServices(bottle, connect);
|
||||||
|
|
|
@ -107,7 +107,7 @@ export const Overview = (
|
||||||
shortUrlsList={shortUrlsList}
|
shortUrlsList={shortUrlsList}
|
||||||
selectedServer={selectedServer}
|
selectedServer={selectedServer}
|
||||||
className="mb-0"
|
className="mb-0"
|
||||||
onTagClick={(tag) => history.push(`/server/${serverId}/list-short-urls/1?tag=${tag}`)}
|
onTagClick={(tag) => history.push(`/server/${serverId}/list-short-urls/1?tags=${encodeURIComponent(tag)}`)}
|
||||||
/>
|
/>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
import { FC, useEffect, useState } from 'react';
|
|
||||||
import { ShortUrlsListProps } from './ShortUrlsList';
|
|
||||||
|
|
||||||
const ShortUrls = (SearchBar: FC, ShortUrlsList: FC<ShortUrlsListProps>) => (props: ShortUrlsListProps) => {
|
|
||||||
const { match } = props;
|
|
||||||
const { page = '1', serverId = '' } = match?.params ?? {};
|
|
||||||
const [ urlsListKey, setUrlsListKey ] = useState(`${serverId}_${page}`);
|
|
||||||
|
|
||||||
// Using a key on a component makes react to create a new instance every time the key changes
|
|
||||||
// Without it, pagination on the URL will not make the component to be refreshed
|
|
||||||
useEffect(() => {
|
|
||||||
setUrlsListKey(`${serverId}_${page}`);
|
|
||||||
}, [ serverId, page ]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="form-group"><SearchBar /></div>
|
|
||||||
<ShortUrlsList {...props} key={urlsListKey} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ShortUrls;
|
|
|
@ -1,5 +1,4 @@
|
||||||
import Bottle from 'bottlejs';
|
import Bottle, { Decorator } from 'bottlejs';
|
||||||
import ShortUrls from '../ShortUrls';
|
|
||||||
import SearchBar from '../SearchBar';
|
import SearchBar from '../SearchBar';
|
||||||
import ShortUrlsList from '../ShortUrlsList';
|
import ShortUrlsList from '../ShortUrlsList';
|
||||||
import ShortUrlsRow from '../helpers/ShortUrlsRow';
|
import ShortUrlsRow from '../helpers/ShortUrlsRow';
|
||||||
|
@ -19,14 +18,11 @@ import { ShortUrlForm } from '../ShortUrlForm';
|
||||||
import { EditShortUrl } from '../EditShortUrl';
|
import { EditShortUrl } from '../EditShortUrl';
|
||||||
import { getShortUrlDetail } from '../reducers/shortUrlDetail';
|
import { getShortUrlDetail } from '../reducers/shortUrlDetail';
|
||||||
|
|
||||||
const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
|
const provideServices = (bottle: Bottle, connect: ConnectDecorator, withRouter: Decorator) => {
|
||||||
// Components
|
// Components
|
||||||
bottle.serviceFactory('ShortUrls', ShortUrls, 'SearchBar', 'ShortUrlsList');
|
bottle.serviceFactory('ShortUrlsList', ShortUrlsList, 'ShortUrlsTable', 'SearchBar');
|
||||||
bottle.decorator('ShortUrls', connect([ 'shortUrlsList' ]));
|
|
||||||
|
|
||||||
bottle.serviceFactory('ShortUrlsList', ShortUrlsList, 'ShortUrlsTable');
|
|
||||||
bottle.decorator('ShortUrlsList', connect(
|
bottle.decorator('ShortUrlsList', connect(
|
||||||
[ 'selectedServer', 'shortUrlsListParams', 'mercureInfo' ],
|
[ 'selectedServer', 'shortUrlsListParams', 'mercureInfo', 'shortUrlsList' ],
|
||||||
[ 'listShortUrls', 'resetShortUrlParams', 'createNewVisits', 'loadMercureInfo' ],
|
[ 'listShortUrls', 'resetShortUrlParams', 'createNewVisits', 'loadMercureInfo' ],
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -57,6 +53,7 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
|
||||||
// Services
|
// Services
|
||||||
bottle.serviceFactory('SearchBar', SearchBar, 'ColorGenerator');
|
bottle.serviceFactory('SearchBar', SearchBar, 'ColorGenerator');
|
||||||
bottle.decorator('SearchBar', connect([ 'shortUrlsListParams' ], [ 'listShortUrls' ]));
|
bottle.decorator('SearchBar', connect([ 'shortUrlsListParams' ], [ 'listShortUrls' ]));
|
||||||
|
bottle.decorator('SearchBar', withRouter);
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
bottle.serviceFactory('listShortUrls', listShortUrls, 'buildShlinkApiClient');
|
bottle.serviceFactory('listShortUrls', listShortUrls, 'buildShlinkApiClient');
|
||||||
|
|
|
@ -61,7 +61,7 @@ const TagCard = (
|
||||||
<Collapse isOpen={displayed}>
|
<Collapse isOpen={displayed}>
|
||||||
<CardBody className="tag-card__body">
|
<CardBody className="tag-card__body">
|
||||||
<Link
|
<Link
|
||||||
to={`/server/${serverId}/list-short-urls/1?tag=${encodeURIComponent(tag.tag)}`}
|
to={`/server/${serverId}/list-short-urls/1?tags=${encodeURIComponent(tag.tag)}`}
|
||||||
className="btn btn-outline-secondary btn-block d-flex justify-content-between align-items-center mb-1"
|
className="btn btn-outline-secondary btn-block d-flex justify-content-between align-items-center mb-1"
|
||||||
>
|
>
|
||||||
<span className="text-ellipsis"><FontAwesomeIcon icon={faLink} className="mr-2" />Short URLs</span>
|
<span className="text-ellipsis"><FontAwesomeIcon icon={faLink} className="mr-2" />Short URLs</span>
|
||||||
|
|
|
@ -32,7 +32,7 @@ export const TagsTableRow = (
|
||||||
<TagBullet tag={tag.tag} colorGenerator={colorGenerator} /> {tag.tag}
|
<TagBullet tag={tag.tag} colorGenerator={colorGenerator} /> {tag.tag}
|
||||||
</th>
|
</th>
|
||||||
<td className="responsive-table__cell text-lg-right" data-th="Short URLs">
|
<td className="responsive-table__cell text-lg-right" data-th="Short URLs">
|
||||||
<Link to={`/server/${serverId}/list-short-urls/1?tag=${encodeURIComponent(tag.tag)}`}>
|
<Link to={`/server/${serverId}/list-short-urls/1?tags=${encodeURIComponent(tag.tag)}`}>
|
||||||
{prettify(tag.shortUrls)}
|
{prettify(tag.shortUrls)}
|
||||||
</Link>
|
</Link>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -12,10 +12,11 @@ interface SearchFieldProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
large?: boolean;
|
large?: boolean;
|
||||||
noBorder?: boolean;
|
noBorder?: boolean;
|
||||||
|
initialValue?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SearchField = ({ onChange, className, large = true, noBorder = false }: SearchFieldProps) => {
|
const SearchField = ({ onChange, className, large = true, noBorder = false, initialValue = '' }: SearchFieldProps) => {
|
||||||
const [ searchTerm, setSearchTerm ] = useState('');
|
const [ searchTerm, setSearchTerm ] = useState(initialValue);
|
||||||
|
|
||||||
const resetTimer = () => {
|
const resetTimer = () => {
|
||||||
timer && clearTimeout(timer);
|
timer && clearTimeout(timer);
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
import { shallow, ShallowWrapper } from 'enzyme';
|
|
||||||
import { Mock } from 'ts-mockery';
|
|
||||||
import shortUrlsCreator from '../../src/short-urls/ShortUrls';
|
|
||||||
import { ShortUrlsListProps } from '../../src/short-urls/ShortUrlsList';
|
|
||||||
|
|
||||||
describe('<ShortUrls />', () => {
|
|
||||||
let wrapper: ShallowWrapper;
|
|
||||||
const SearchBar = () => null;
|
|
||||||
const ShortUrlsList = () => null;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
const ShortUrls = shortUrlsCreator(SearchBar, ShortUrlsList);
|
|
||||||
|
|
||||||
wrapper = shallow(
|
|
||||||
<ShortUrls {...Mock.all<ShortUrlsListProps>()} />,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
afterEach(() => wrapper.unmount());
|
|
||||||
|
|
||||||
it('wraps a SearchBar and ShortUrlsList', () => {
|
|
||||||
expect(wrapper.find(SearchBar)).toHaveLength(1);
|
|
||||||
expect(wrapper.find(ShortUrlsList)).toHaveLength(1);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -30,8 +30,8 @@ describe('<TagCard />', () => {
|
||||||
afterEach(jest.resetAllMocks);
|
afterEach(jest.resetAllMocks);
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[ 'ssr', '/server/1/list-short-urls/1?tag=ssr' ],
|
[ 'ssr', '/server/1/list-short-urls/1?tags=ssr' ],
|
||||||
[ 'ssr-&-foo', '/server/1/list-short-urls/1?tag=ssr-%26-foo' ],
|
[ 'ssr-&-foo', '/server/1/list-short-urls/1?tags=ssr-%26-foo' ],
|
||||||
])('shows a TagBullet and a link to the list filtering by the tag', (tag, expectedLink) => {
|
])('shows a TagBullet and a link to the list filtering by the tag', (tag, expectedLink) => {
|
||||||
const wrapper = createWrapper(tag);
|
const wrapper = createWrapper(tag);
|
||||||
const links = wrapper.find(Link);
|
const links = wrapper.find(Link);
|
||||||
|
@ -61,7 +61,7 @@ describe('<TagCard />', () => {
|
||||||
const links = wrapper.find(Link);
|
const links = wrapper.find(Link);
|
||||||
|
|
||||||
expect(links).toHaveLength(2);
|
expect(links).toHaveLength(2);
|
||||||
expect(links.at(0).prop('to')).toEqual('/server/1/list-short-urls/1?tag=ssr');
|
expect(links.at(0).prop('to')).toEqual('/server/1/list-short-urls/1?tags=ssr');
|
||||||
expect(links.at(0).text()).toContain('48');
|
expect(links.at(0).text()).toContain('48');
|
||||||
expect(links.at(1).prop('to')).toEqual('/server/1/tag/ssr/visits');
|
expect(links.at(1).prop('to')).toEqual('/server/1/tag/ssr/visits');
|
||||||
expect(links.at(1).text()).toContain('23,257');
|
expect(links.at(1).text()).toContain('23,257');
|
||||||
|
|
|
@ -35,7 +35,7 @@ describe('<TagsTableRow />', () => {
|
||||||
const visitsLink = links.last();
|
const visitsLink = links.last();
|
||||||
|
|
||||||
expect(shortUrlsLink.prop('children')).toEqual(expectedShortUrls);
|
expect(shortUrlsLink.prop('children')).toEqual(expectedShortUrls);
|
||||||
expect(shortUrlsLink.prop('to')).toEqual(`/server/abc123/list-short-urls/1?tag=${encodeURIComponent('foo&bar')}`);
|
expect(shortUrlsLink.prop('to')).toEqual(`/server/abc123/list-short-urls/1?tags=${encodeURIComponent('foo&bar')}`);
|
||||||
expect(visitsLink.prop('children')).toEqual(expectedVisits);
|
expect(visitsLink.prop('children')).toEqual(expectedVisits);
|
||||||
expect(visitsLink.prop('to')).toEqual('/server/abc123/tag/foo&bar/visits');
|
expect(visitsLink.prop('to')).toEqual('/server/abc123/tag/foo&bar/visits');
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue