mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-03-13 19:13:46 +00:00
Take into consideration exclñudeBots from query on short URLs row
This commit is contained in:
@@ -80,3 +80,7 @@ export interface ExportableShortUrl {
|
||||
tags: string;
|
||||
visits: number;
|
||||
}
|
||||
|
||||
export interface ShortUrlsFilter {
|
||||
excludeBots?: boolean;
|
||||
}
|
||||
|
||||
38
src/short-urls/helpers/ShortUrlsFilterDropdown.tsx
Normal file
38
src/short-urls/helpers/ShortUrlsFilterDropdown.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import { DropdownItem } from 'reactstrap';
|
||||
import { DropdownBtn } from '../../utils/DropdownBtn';
|
||||
import { hasValue } from '../../utils/utils';
|
||||
import { ShortUrlsFilter } from '../data';
|
||||
|
||||
interface ShortUrlsFilterDropdownProps {
|
||||
onChange: (filters: ShortUrlsFilter) => void;
|
||||
selected?: ShortUrlsFilter;
|
||||
className?: string;
|
||||
botsSupported: boolean;
|
||||
}
|
||||
|
||||
export const ShortUrlsFilterDropdown = (
|
||||
{ onChange, selected = {}, className, botsSupported }: ShortUrlsFilterDropdownProps,
|
||||
) => {
|
||||
if (!botsSupported) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { excludeBots = false } = selected;
|
||||
const onBotsClick = () => onChange({ ...selected, excludeBots: !selected?.excludeBots });
|
||||
|
||||
return (
|
||||
<DropdownBtn text="Filters" dropdownClassName={className} className="me-3" right minWidth={250}>
|
||||
{botsSupported && (
|
||||
<>
|
||||
<DropdownItem header>Bots:</DropdownItem>
|
||||
<DropdownItem active={excludeBots} onClick={onBotsClick}>Exclude bots visits</DropdownItem>
|
||||
</>
|
||||
)}
|
||||
|
||||
<DropdownItem divider />
|
||||
<DropdownItem disabled={!hasValue(selected)} onClick={() => onChange({ excludeBots: false })}>
|
||||
<i>Clear filters</i>
|
||||
</DropdownItem>
|
||||
</DropdownBtn>
|
||||
);
|
||||
};
|
||||
@@ -11,6 +11,7 @@ import { ShortUrlVisitsCount } from './ShortUrlVisitsCount';
|
||||
import { ShortUrlsRowMenuType } from './ShortUrlsRowMenu';
|
||||
import { Tags } from './Tags';
|
||||
import { ShortUrlStatus } from './ShortUrlStatus';
|
||||
import { useShortUrlsQuery } from './hooks';
|
||||
import './ShortUrlsRow.scss';
|
||||
|
||||
interface ShortUrlsRowProps {
|
||||
@@ -33,7 +34,9 @@ export const ShortUrlsRow = (
|
||||
const [copiedToClipboard, setCopiedToClipboard] = useTimeoutToggle();
|
||||
const [active, setActive] = useTimeoutToggle(false, 500);
|
||||
const isFirstRun = useRef(true);
|
||||
const [{ excludeBots }] = useShortUrlsQuery();
|
||||
const { visits } = settings;
|
||||
const doExcludeBots = excludeBots ?? visits?.excludeBots;
|
||||
|
||||
useEffect(() => {
|
||||
!isFirstRun.current && setActive();
|
||||
@@ -73,7 +76,7 @@ export const ShortUrlsRow = (
|
||||
<td className="responsive-table__cell short-urls-row__cell text-lg-end" data-th="Visits">
|
||||
<ShortUrlVisitsCount
|
||||
visitsCount={(
|
||||
visits?.excludeBots ? shortUrl.visitsSummary?.nonBots : shortUrl.visitsSummary?.total
|
||||
doExcludeBots ? shortUrl.visitsSummary?.nonBots : shortUrl.visitsSummary?.total
|
||||
) ?? shortUrl.visitsCount}
|
||||
shortUrl={shortUrl}
|
||||
selectedServer={selectedServer}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { parseQuery, stringifyQuery } from '../../utils/helpers/query';
|
||||
import { ShortUrlsOrder, ShortUrlsOrderableFields } from '../data';
|
||||
import { orderToString, stringToOrder } from '../../utils/helpers/ordering';
|
||||
import { TagsFilteringMode } from '../../api/types';
|
||||
import { BooleanString, parseBooleanToString } from '../../utils/utils';
|
||||
|
||||
interface ShortUrlsQueryCommon {
|
||||
search?: string;
|
||||
@@ -16,11 +17,13 @@ interface ShortUrlsQueryCommon {
|
||||
interface ShortUrlsQuery extends ShortUrlsQueryCommon {
|
||||
orderBy?: string;
|
||||
tags?: string;
|
||||
excludeBots?: BooleanString;
|
||||
}
|
||||
|
||||
interface ShortUrlsFiltering extends ShortUrlsQueryCommon {
|
||||
orderBy?: ShortUrlsOrder;
|
||||
tags: string[];
|
||||
excludeBots?: boolean;
|
||||
}
|
||||
|
||||
type ToFirstPage = (extra: Partial<ShortUrlsFiltering>) => void;
|
||||
@@ -33,20 +36,26 @@ export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => {
|
||||
const filtering = useMemo(
|
||||
pipe(
|
||||
() => parseQuery<ShortUrlsQuery>(search),
|
||||
({ orderBy, tags, ...rest }: ShortUrlsQuery): ShortUrlsFiltering => {
|
||||
({ orderBy, tags, excludeBots, ...rest }: ShortUrlsQuery): ShortUrlsFiltering => {
|
||||
const parsedOrderBy = orderBy ? stringToOrder<ShortUrlsOrderableFields>(orderBy) : undefined;
|
||||
const parsedTags = tags?.split(',') ?? [];
|
||||
return { ...rest, orderBy: parsedOrderBy, tags: parsedTags };
|
||||
return {
|
||||
...rest,
|
||||
orderBy: parsedOrderBy,
|
||||
tags: parsedTags,
|
||||
excludeBots: excludeBots !== undefined ? excludeBots === 'true' : undefined,
|
||||
};
|
||||
},
|
||||
),
|
||||
[search],
|
||||
);
|
||||
const toFirstPageWithExtra = (extra: Partial<ShortUrlsFiltering>) => {
|
||||
const { orderBy, tags, ...mergedFiltering } = { ...filtering, ...extra };
|
||||
const { orderBy, tags, excludeBots, ...mergedFiltering } = { ...filtering, ...extra };
|
||||
const query: ShortUrlsQuery = {
|
||||
...mergedFiltering,
|
||||
orderBy: orderBy && orderToString(orderBy),
|
||||
tags: tags.length > 0 ? tags.join(',') : undefined,
|
||||
excludeBots: excludeBots === undefined ? undefined : parseBooleanToString(excludeBots),
|
||||
};
|
||||
const stringifiedQuery = stringifyQuery(query);
|
||||
const queryString = isEmpty(stringifiedQuery) ? '' : `?${stringifiedQuery}`;
|
||||
|
||||
Reference in New Issue
Block a user