Take into consideration exclñudeBots from query on short URLs row

This commit is contained in:
Alejandro Celaya
2022-12-23 20:00:59 +01:00
parent 80cea91339
commit 1d6f4bf5db
7 changed files with 99 additions and 22 deletions

View File

@@ -80,3 +80,7 @@ export interface ExportableShortUrl {
tags: string;
visits: number;
}
export interface ShortUrlsFilter {
excludeBots?: boolean;
}

View 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>
);
};

View File

@@ -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}

View File

@@ -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}`;