mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 09:30:31 +03:00
Minor refactorings and function extractions
This commit is contained in:
parent
a3f5095dce
commit
165afa436d
6 changed files with 26 additions and 25 deletions
|
@ -1,6 +1,5 @@
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { isEmpty, pipe } from 'ramda';
|
import { isEmpty, pipe } from 'ramda';
|
||||||
import { parseISO } from 'date-fns';
|
|
||||||
import { Button, InputGroup, Row, UncontrolledTooltip } from 'reactstrap';
|
import { Button, InputGroup, Row, UncontrolledTooltip } from 'reactstrap';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faTag, faTags } from '@fortawesome/free-solid-svg-icons';
|
import { faTag, faTags } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
@ -8,7 +7,7 @@ import classNames from 'classnames';
|
||||||
import { SearchField } from '../utils/SearchField';
|
import { SearchField } from '../utils/SearchField';
|
||||||
import { DateRangeSelector } from '../utils/dates/DateRangeSelector';
|
import { DateRangeSelector } from '../utils/dates/DateRangeSelector';
|
||||||
import { formatIsoDate } from '../utils/helpers/date';
|
import { formatIsoDate } from '../utils/helpers/date';
|
||||||
import { DateRange } from '../utils/dates/types';
|
import { DateRange, datesToDateRange } from '../utils/dates/types';
|
||||||
import { supportsAllTagsFiltering } from '../utils/helpers/features';
|
import { supportsAllTagsFiltering } from '../utils/helpers/features';
|
||||||
import { SelectedServer } from '../servers/data';
|
import { SelectedServer } from '../servers/data';
|
||||||
import { OrderDir } from '../utils/helpers/ordering';
|
import { OrderDir } from '../utils/helpers/ordering';
|
||||||
|
@ -27,8 +26,6 @@ export interface ShortUrlsFilteringProps {
|
||||||
shortUrlsAmount?: number;
|
shortUrlsAmount?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dateOrNull = (date?: string) => (date ? parseISO(date) : null);
|
|
||||||
|
|
||||||
export const ShortUrlsFilteringBar = (
|
export const ShortUrlsFilteringBar = (
|
||||||
ExportShortUrlsBtn: FC<ExportShortUrlsBtnProps>,
|
ExportShortUrlsBtn: FC<ExportShortUrlsBtnProps>,
|
||||||
TagsSelector: FC<TagsSelectorProps>,
|
TagsSelector: FC<TagsSelectorProps>,
|
||||||
|
@ -74,10 +71,7 @@ export const ShortUrlsFilteringBar = (
|
||||||
<div className="col-lg-8 col-xl-6 mt-3">
|
<div className="col-lg-8 col-xl-6 mt-3">
|
||||||
<DateRangeSelector
|
<DateRangeSelector
|
||||||
defaultText="All short URLs"
|
defaultText="All short URLs"
|
||||||
initialDateRange={{
|
initialDateRange={datesToDateRange(startDate, endDate)}
|
||||||
startDate: dateOrNull(startDate),
|
|
||||||
endDate: dateOrNull(endDate),
|
|
||||||
}}
|
|
||||||
onDatesChange={setDates}
|
onDatesChange={setDates}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,8 +6,6 @@ import { ShortUrlsOrder, ShortUrlsOrderableFields } from '../data';
|
||||||
import { orderToString, stringToOrder } from '../../utils/helpers/ordering';
|
import { orderToString, stringToOrder } from '../../utils/helpers/ordering';
|
||||||
import { TagsFilteringMode } from '../../api/types';
|
import { TagsFilteringMode } from '../../api/types';
|
||||||
|
|
||||||
type ToFirstPage = (extra: Partial<ShortUrlsFiltering>) => void;
|
|
||||||
|
|
||||||
interface ShortUrlsQueryCommon {
|
interface ShortUrlsQueryCommon {
|
||||||
search?: string;
|
search?: string;
|
||||||
startDate?: string;
|
startDate?: string;
|
||||||
|
@ -25,14 +23,16 @@ interface ShortUrlsFiltering extends ShortUrlsQueryCommon {
|
||||||
tags: string[];
|
tags: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ToFirstPage = (extra: Partial<ShortUrlsFiltering>) => void;
|
||||||
|
|
||||||
export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => {
|
export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const { search } = useLocation();
|
||||||
const params = useParams<{ serverId: string }>();
|
const { serverId = '' } = useParams<{ serverId: string }>();
|
||||||
|
|
||||||
const query = useMemo(
|
const filtering = useMemo(
|
||||||
pipe(
|
pipe(
|
||||||
() => parseQuery<ShortUrlsQuery>(location.search),
|
() => parseQuery<ShortUrlsQuery>(search),
|
||||||
({ orderBy, tags, ...rest }: ShortUrlsQuery): ShortUrlsFiltering => {
|
({ orderBy, tags, ...rest }: ShortUrlsQuery): ShortUrlsFiltering => {
|
||||||
const parsedOrderBy = orderBy ? stringToOrder<ShortUrlsOrderableFields>(orderBy) : undefined;
|
const parsedOrderBy = orderBy ? stringToOrder<ShortUrlsOrderableFields>(orderBy) : undefined;
|
||||||
const parsedTags = tags?.split(',') ?? [];
|
const parsedTags = tags?.split(',') ?? [];
|
||||||
|
@ -40,20 +40,20 @@ export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => {
|
||||||
return { ...rest, orderBy: parsedOrderBy, tags: parsedTags };
|
return { ...rest, orderBy: parsedOrderBy, tags: parsedTags };
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
[location.search],
|
[search],
|
||||||
);
|
);
|
||||||
const toFirstPageWithExtra = (extra: Partial<ShortUrlsFiltering>) => {
|
const toFirstPageWithExtra = (extra: Partial<ShortUrlsFiltering>) => {
|
||||||
const { orderBy, tags, ...mergedQuery } = { ...query, ...extra };
|
const { orderBy, tags, ...mergedFiltering } = { ...filtering, ...extra };
|
||||||
const normalizedQuery: ShortUrlsQuery = {
|
const query: ShortUrlsQuery = {
|
||||||
...mergedQuery,
|
...mergedFiltering,
|
||||||
orderBy: orderBy && orderToString(orderBy),
|
orderBy: orderBy && orderToString(orderBy),
|
||||||
tags: tags.length > 0 ? tags.join(',') : undefined,
|
tags: tags.length > 0 ? tags.join(',') : undefined,
|
||||||
};
|
};
|
||||||
const evolvedQuery = stringifyQuery(normalizedQuery);
|
const stringifiedQuery = stringifyQuery(query);
|
||||||
const queryString = isEmpty(evolvedQuery) ? '' : `?${evolvedQuery}`;
|
const queryString = isEmpty(stringifiedQuery) ? '' : `?${stringifiedQuery}`;
|
||||||
|
|
||||||
navigate(`/server/${params.serverId ?? ''}/list-short-urls/1${queryString}`);
|
navigate(`/server/${serverId}/list-short-urls/1${queryString}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
return [query, toFirstPageWithExtra];
|
return [filtering, toFirstPageWithExtra];
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { subDays, startOfDay, endOfDay } from 'date-fns';
|
import { subDays, startOfDay, endOfDay } from 'date-fns';
|
||||||
import { cond, filter, isEmpty, T } from 'ramda';
|
import { cond, filter, isEmpty, T } from 'ramda';
|
||||||
import { DateOrString, formatInternational, isBeforeOrEqual, parseISO } from '../../helpers/date';
|
import { dateOrNull, DateOrString, formatInternational, isBeforeOrEqual, parseISO } from '../../helpers/date';
|
||||||
|
|
||||||
export interface DateRange {
|
export interface DateRange {
|
||||||
startDate?: Date | null;
|
startDate?: Date | null;
|
||||||
|
@ -28,6 +28,11 @@ const INTERVAL_TO_STRING_MAP: Record<DateInterval, string | undefined> = {
|
||||||
|
|
||||||
export const DATE_INTERVALS = Object.keys(INTERVAL_TO_STRING_MAP).filter((value) => value !== 'all') as DateInterval[];
|
export const DATE_INTERVALS = Object.keys(INTERVAL_TO_STRING_MAP).filter((value) => value !== 'all') as DateInterval[];
|
||||||
|
|
||||||
|
export const datesToDateRange = (startDate?: string, endDate?: string): DateRange => ({
|
||||||
|
startDate: dateOrNull(startDate),
|
||||||
|
endDate: dateOrNull(endDate),
|
||||||
|
});
|
||||||
|
|
||||||
const dateRangeToString = (range?: DateRange): string | undefined => {
|
const dateRangeToString = (range?: DateRange): string | undefined => {
|
||||||
if (!range || dateRangeIsEmpty(range)) {
|
if (!range || dateRangeIsEmpty(range)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
@ -32,6 +32,8 @@ export const parseDate = (date: string, theFormat: string) => parse(date, theFor
|
||||||
|
|
||||||
export const parseISO = (date: DateOrString): Date => (isDateObject(date) ? date : stdParseISO(date));
|
export const parseISO = (date: DateOrString): Date => (isDateObject(date) ? date : stdParseISO(date));
|
||||||
|
|
||||||
|
export const dateOrNull = (date?: string): Date | null => (date ? parseISO(date) : null);
|
||||||
|
|
||||||
export const isBetween = (date: DateOrString, start?: DateOrString, end?: DateOrString): boolean => {
|
export const isBetween = (date: DateOrString, start?: DateOrString, end?: DateOrString): boolean => {
|
||||||
try {
|
try {
|
||||||
return isWithinInterval(parseISO(date), { start: parseISO(start ?? date), end: parseISO(end ?? date) });
|
return isWithinInterval(parseISO(date), { start: parseISO(start ?? date), end: parseISO(end ?? date) });
|
||||||
|
|
|
@ -36,6 +36,6 @@ export const orderToString = <T>(order: Order<T>): string | undefined => (
|
||||||
);
|
);
|
||||||
|
|
||||||
export const stringToOrder = <T>(order: string): Order<T> => {
|
export const stringToOrder = <T>(order: string): Order<T> => {
|
||||||
const [field, dir] = order.split('-') as [ T | undefined, OrderDir | undefined ];
|
const [field, dir] = order.split('-') as [T | undefined, OrderDir | undefined];
|
||||||
return { field, dir };
|
return { field, dir };
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,9 +72,9 @@ export const VisitsStats: FC<VisitsStatsProps> = ({
|
||||||
fallbackInterval ?? settings.visits?.defaultInterval ?? 'last30Days',
|
fallbackInterval ?? settings.visits?.defaultInterval ?? 'last30Days',
|
||||||
);
|
);
|
||||||
const [dateRange, setDateRange] = useState<DateRange>(intervalToDateRange(initialInterval));
|
const [dateRange, setDateRange] = useState<DateRange>(intervalToDateRange(initialInterval));
|
||||||
|
const [visitsFilter, setVisitsFilter] = useState<VisitsFilter>({});
|
||||||
const [highlightedVisits, setHighlightedVisits] = useState<NormalizedVisit[]>([]);
|
const [highlightedVisits, setHighlightedVisits] = useState<NormalizedVisit[]>([]);
|
||||||
const [highlightedLabel, setHighlightedLabel] = useState<string | undefined>();
|
const [highlightedLabel, setHighlightedLabel] = useState<string | undefined>();
|
||||||
const [visitsFilter, setVisitsFilter] = useState<VisitsFilter>({});
|
|
||||||
const botsSupported = supportsBotVisits(selectedServer);
|
const botsSupported = supportsBotVisits(selectedServer);
|
||||||
const isFirstLoad = useRef(true);
|
const isFirstLoad = useRef(true);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue