diff --git a/src/short-urls/ShortUrlsFilteringBar.tsx b/src/short-urls/ShortUrlsFilteringBar.tsx index 205c62ef..00c3e164 100644 --- a/src/short-urls/ShortUrlsFilteringBar.tsx +++ b/src/short-urls/ShortUrlsFilteringBar.tsx @@ -1,6 +1,5 @@ import { FC } from 'react'; import { isEmpty, pipe } from 'ramda'; -import { parseISO } from 'date-fns'; import { Button, InputGroup, Row, UncontrolledTooltip } from 'reactstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTag, faTags } from '@fortawesome/free-solid-svg-icons'; @@ -8,7 +7,7 @@ import classNames from 'classnames'; import { SearchField } from '../utils/SearchField'; import { DateRangeSelector } from '../utils/dates/DateRangeSelector'; 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 { SelectedServer } from '../servers/data'; import { OrderDir } from '../utils/helpers/ordering'; @@ -27,8 +26,6 @@ export interface ShortUrlsFilteringProps { shortUrlsAmount?: number; } -const dateOrNull = (date?: string) => (date ? parseISO(date) : null); - export const ShortUrlsFilteringBar = ( ExportShortUrlsBtn: FC, TagsSelector: FC, @@ -74,10 +71,7 @@ export const ShortUrlsFilteringBar = (
diff --git a/src/short-urls/helpers/hooks.ts b/src/short-urls/helpers/hooks.ts index 3f1c165c..03b2323f 100644 --- a/src/short-urls/helpers/hooks.ts +++ b/src/short-urls/helpers/hooks.ts @@ -6,8 +6,6 @@ import { ShortUrlsOrder, ShortUrlsOrderableFields } from '../data'; import { orderToString, stringToOrder } from '../../utils/helpers/ordering'; import { TagsFilteringMode } from '../../api/types'; -type ToFirstPage = (extra: Partial) => void; - interface ShortUrlsQueryCommon { search?: string; startDate?: string; @@ -25,14 +23,16 @@ interface ShortUrlsFiltering extends ShortUrlsQueryCommon { tags: string[]; } +type ToFirstPage = (extra: Partial) => void; + export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => { const navigate = useNavigate(); - const location = useLocation(); - const params = useParams<{ serverId: string }>(); + const { search } = useLocation(); + const { serverId = '' } = useParams<{ serverId: string }>(); - const query = useMemo( + const filtering = useMemo( pipe( - () => parseQuery(location.search), + () => parseQuery(search), ({ orderBy, tags, ...rest }: ShortUrlsQuery): ShortUrlsFiltering => { const parsedOrderBy = orderBy ? stringToOrder(orderBy) : undefined; const parsedTags = tags?.split(',') ?? []; @@ -40,20 +40,20 @@ export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => { return { ...rest, orderBy: parsedOrderBy, tags: parsedTags }; }, ), - [location.search], + [search], ); const toFirstPageWithExtra = (extra: Partial) => { - const { orderBy, tags, ...mergedQuery } = { ...query, ...extra }; - const normalizedQuery: ShortUrlsQuery = { - ...mergedQuery, + const { orderBy, tags, ...mergedFiltering } = { ...filtering, ...extra }; + const query: ShortUrlsQuery = { + ...mergedFiltering, orderBy: orderBy && orderToString(orderBy), tags: tags.length > 0 ? tags.join(',') : undefined, }; - const evolvedQuery = stringifyQuery(normalizedQuery); - const queryString = isEmpty(evolvedQuery) ? '' : `?${evolvedQuery}`; + const stringifiedQuery = stringifyQuery(query); + 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]; }; diff --git a/src/utils/dates/types/index.ts b/src/utils/dates/types/index.ts index d7d81d78..04e4eef3 100644 --- a/src/utils/dates/types/index.ts +++ b/src/utils/dates/types/index.ts @@ -1,6 +1,6 @@ import { subDays, startOfDay, endOfDay } from 'date-fns'; 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 { startDate?: Date | null; @@ -28,6 +28,11 @@ const INTERVAL_TO_STRING_MAP: Record = { 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 => { if (!range || dateRangeIsEmpty(range)) { return undefined; diff --git a/src/utils/helpers/date.ts b/src/utils/helpers/date.ts index 9e0a73b5..e9489193 100644 --- a/src/utils/helpers/date.ts +++ b/src/utils/helpers/date.ts @@ -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 dateOrNull = (date?: string): Date | null => (date ? parseISO(date) : null); + export const isBetween = (date: DateOrString, start?: DateOrString, end?: DateOrString): boolean => { try { return isWithinInterval(parseISO(date), { start: parseISO(start ?? date), end: parseISO(end ?? date) }); diff --git a/src/utils/helpers/ordering.ts b/src/utils/helpers/ordering.ts index d79a9898..dafe7b69 100644 --- a/src/utils/helpers/ordering.ts +++ b/src/utils/helpers/ordering.ts @@ -36,6 +36,6 @@ export const orderToString = (order: Order): string | undefined => ( ); export const stringToOrder = (order: string): Order => { - const [field, dir] = order.split('-') as [ T | undefined, OrderDir | undefined ]; + const [field, dir] = order.split('-') as [T | undefined, OrderDir | undefined]; return { field, dir }; }; diff --git a/src/visits/VisitsStats.tsx b/src/visits/VisitsStats.tsx index 2f22f5e7..5976d223 100644 --- a/src/visits/VisitsStats.tsx +++ b/src/visits/VisitsStats.tsx @@ -72,9 +72,9 @@ export const VisitsStats: FC = ({ fallbackInterval ?? settings.visits?.defaultInterval ?? 'last30Days', ); const [dateRange, setDateRange] = useState(intervalToDateRange(initialInterval)); + const [visitsFilter, setVisitsFilter] = useState({}); const [highlightedVisits, setHighlightedVisits] = useState([]); const [highlightedLabel, setHighlightedLabel] = useState(); - const [visitsFilter, setVisitsFilter] = useState({}); const botsSupported = supportsBotVisits(selectedServer); const isFirstLoad = useRef(true);