mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 09:30:31 +03:00
Abstracted logic to parse tags from string to array and back for the query
This commit is contained in:
parent
47d30aaa34
commit
e632c5b04f
3 changed files with 23 additions and 19 deletions
|
@ -34,7 +34,6 @@ const ShortUrlsFilteringBar = (colorGenerator: ColorGenerator): FC<ShortUrlsFilt
|
||||||
{ selectedServer, className, order, handleOrderBy },
|
{ selectedServer, className, order, handleOrderBy },
|
||||||
) => {
|
) => {
|
||||||
const [{ search, tags, startDate, endDate, tagsMode = 'any' }, toFirstPage ] = useShortUrlsQuery();
|
const [{ search, tags, startDate, endDate, tagsMode = 'any' }, toFirstPage ] = useShortUrlsQuery();
|
||||||
const selectedTags = tags?.split(',') ?? [];
|
|
||||||
const setDates = pipe(
|
const setDates = pipe(
|
||||||
({ startDate, endDate }: DateRange) => ({
|
({ startDate, endDate }: DateRange) => ({
|
||||||
startDate: formatIsoDate(startDate) ?? undefined,
|
startDate: formatIsoDate(startDate) ?? undefined,
|
||||||
|
@ -47,9 +46,8 @@ const ShortUrlsFilteringBar = (colorGenerator: ColorGenerator): FC<ShortUrlsFilt
|
||||||
(search) => toFirstPage({ search }),
|
(search) => toFirstPage({ search }),
|
||||||
);
|
);
|
||||||
const removeTag = pipe(
|
const removeTag = pipe(
|
||||||
(tag: string) => selectedTags.filter((selectedTag) => selectedTag !== tag),
|
(tag: string) => tags.filter((selectedTag) => selectedTag !== tag),
|
||||||
(tagsList) => tagsList.length === 0 ? undefined : tagsList.join(','),
|
(updateTags) => toFirstPage({ tags: updateTags }),
|
||||||
(tags) => toFirstPage({ tags }),
|
|
||||||
);
|
);
|
||||||
const canChangeTagsMode = supportsAllTagsFiltering(selectedServer);
|
const canChangeTagsMode = supportsAllTagsFiltering(selectedServer);
|
||||||
const toggleTagsMode = pipe(
|
const toggleTagsMode = pipe(
|
||||||
|
@ -80,9 +78,9 @@ const ShortUrlsFilteringBar = (colorGenerator: ColorGenerator): FC<ShortUrlsFilt
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
{selectedTags.length > 0 && (
|
{tags.length > 0 && (
|
||||||
<h4 className="mt-3">
|
<h4 className="mt-3">
|
||||||
{canChangeTagsMode && selectedTags.length > 1 && (
|
{canChangeTagsMode && tags.length > 1 && (
|
||||||
<div className="float-end ms-2 mt-1">
|
<div className="float-end ms-2 mt-1">
|
||||||
<TooltipToggleSwitch
|
<TooltipToggleSwitch
|
||||||
checked={tagsMode === 'all'}
|
checked={tagsMode === 'all'}
|
||||||
|
@ -94,7 +92,7 @@ const ShortUrlsFilteringBar = (colorGenerator: ColorGenerator): FC<ShortUrlsFilt
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<FontAwesomeIcon icon={tagsIcon} className="short-urls-filtering-bar__tags-icon me-1" />
|
<FontAwesomeIcon icon={tagsIcon} className="short-urls-filtering-bar__tags-icon me-1" />
|
||||||
{selectedTags.map((tag) =>
|
{tags.map((tag) =>
|
||||||
<Tag colorGenerator={colorGenerator} key={tag} text={tag} clearable onClose={() => removeTag(tag)} />)}
|
<Tag colorGenerator={colorGenerator} key={tag} text={tag} clearable onClose={() => removeTag(tag)} />)}
|
||||||
</h4>
|
</h4>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { pipe } from 'ramda';
|
import { pipe } from 'ramda';
|
||||||
import { FC, useEffect, useMemo, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { Card } from 'reactstrap';
|
import { Card } from 'reactstrap';
|
||||||
import { useLocation, useParams } from 'react-router-dom';
|
import { useLocation, useParams } from 'react-router-dom';
|
||||||
import { determineOrderDir, OrderDir } from '../utils/helpers/ordering';
|
import { determineOrderDir, OrderDir } from '../utils/helpers/ordering';
|
||||||
|
@ -35,7 +35,6 @@ const ShortUrlsList = (
|
||||||
// This separated state handling is needed to be able to fall back to settings value, but only once when loaded
|
// This separated state handling is needed to be able to fall back to settings value, but only once when loaded
|
||||||
orderBy ?? settings.shortUrlsList?.defaultOrdering ?? DEFAULT_SHORT_URLS_ORDERING,
|
orderBy ?? settings.shortUrlsList?.defaultOrdering ?? DEFAULT_SHORT_URLS_ORDERING,
|
||||||
);
|
);
|
||||||
const selectedTags = useMemo(() => tags?.split(',') ?? [], [ tags ]);
|
|
||||||
const { pagination } = shortUrlsList?.shortUrls ?? {};
|
const { pagination } = shortUrlsList?.shortUrls ?? {};
|
||||||
const handleOrderBy = (field?: ShortUrlsOrderableFields, dir?: OrderDir) => {
|
const handleOrderBy = (field?: ShortUrlsOrderableFields, dir?: OrderDir) => {
|
||||||
toFirstPage({ orderBy: { field, dir } });
|
toFirstPage({ orderBy: { field, dir } });
|
||||||
|
@ -46,21 +45,21 @@ const ShortUrlsList = (
|
||||||
const renderOrderIcon = (field: ShortUrlsOrderableFields) =>
|
const renderOrderIcon = (field: ShortUrlsOrderableFields) =>
|
||||||
<TableOrderIcon currentOrder={actualOrderBy} field={field} />;
|
<TableOrderIcon currentOrder={actualOrderBy} field={field} />;
|
||||||
const addTag = pipe(
|
const addTag = pipe(
|
||||||
(newTag: string) => [ ...new Set([ ...selectedTags, newTag ]) ].join(','),
|
(newTag: string) => [ ...new Set([ ...tags, newTag ]) ],
|
||||||
(tags) => toFirstPage({ tags }),
|
(updatedTags) => toFirstPage({ tags: updatedTags }),
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
listShortUrls({
|
listShortUrls({
|
||||||
page,
|
page,
|
||||||
searchTerm: search,
|
searchTerm: search,
|
||||||
tags: selectedTags,
|
tags,
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
orderBy: actualOrderBy,
|
orderBy: actualOrderBy,
|
||||||
tagsMode,
|
tagsMode,
|
||||||
});
|
});
|
||||||
}, [ page, search, selectedTags, startDate, endDate, actualOrderBy, tagsMode ]);
|
}, [ page, search, tags, startDate, endDate, actualOrderBy, tagsMode ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -14,7 +14,6 @@ export interface ShortUrlListRouteParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ShortUrlsQueryCommon {
|
interface ShortUrlsQueryCommon {
|
||||||
tags?: string;
|
|
||||||
search?: string;
|
search?: string;
|
||||||
startDate?: string;
|
startDate?: string;
|
||||||
endDate?: string;
|
endDate?: string;
|
||||||
|
@ -23,10 +22,12 @@ interface ShortUrlsQueryCommon {
|
||||||
|
|
||||||
interface ShortUrlsQuery extends ShortUrlsQueryCommon {
|
interface ShortUrlsQuery extends ShortUrlsQueryCommon {
|
||||||
orderBy?: string;
|
orderBy?: string;
|
||||||
|
tags?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ShortUrlsFiltering extends ShortUrlsQueryCommon {
|
interface ShortUrlsFiltering extends ShortUrlsQueryCommon {
|
||||||
orderBy?: ShortUrlsOrder;
|
orderBy?: ShortUrlsOrder;
|
||||||
|
tags: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => {
|
export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => {
|
||||||
|
@ -37,16 +38,22 @@ export const useShortUrlsQuery = (): [ShortUrlsFiltering, ToFirstPage] => {
|
||||||
const query = useMemo(
|
const query = useMemo(
|
||||||
pipe(
|
pipe(
|
||||||
() => parseQuery<ShortUrlsQuery>(location.search),
|
() => parseQuery<ShortUrlsQuery>(location.search),
|
||||||
({ orderBy, ...rest }: ShortUrlsQuery): ShortUrlsFiltering => !orderBy ? rest : {
|
({ orderBy, tags, ...rest }: ShortUrlsQuery): ShortUrlsFiltering => {
|
||||||
...rest,
|
const parsedOrderBy = orderBy ? stringToOrder<ShortUrlsOrderableFields>(orderBy) : undefined;
|
||||||
orderBy: stringToOrder<ShortUrlsOrderableFields>(orderBy),
|
const parsedTags = tags?.split(',') ?? [];
|
||||||
|
|
||||||
|
return { ...rest, orderBy: parsedOrderBy, tags: parsedTags };
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
[ location.search ],
|
[ location.search ],
|
||||||
);
|
);
|
||||||
const toFirstPageWithExtra = (extra: Partial<ShortUrlsFiltering>) => {
|
const toFirstPageWithExtra = (extra: Partial<ShortUrlsFiltering>) => {
|
||||||
const { orderBy, ...mergedQuery } = { ...query, ...extra };
|
const { orderBy, tags, ...mergedQuery } = { ...query, ...extra };
|
||||||
const normalizedQuery: ShortUrlsQuery = { ...mergedQuery, orderBy: orderBy && orderToString(orderBy) };
|
const normalizedQuery: ShortUrlsQuery = {
|
||||||
|
...mergedQuery,
|
||||||
|
orderBy: orderBy && orderToString(orderBy),
|
||||||
|
tags: tags.length > 0 ? tags.join(',') : undefined,
|
||||||
|
};
|
||||||
const evolvedQuery = stringifyQuery(normalizedQuery);
|
const evolvedQuery = stringifyQuery(normalizedQuery);
|
||||||
const queryString = isEmpty(evolvedQuery) ? '' : `?${evolvedQuery}`;
|
const queryString = isEmpty(evolvedQuery) ? '' : `?${evolvedQuery}`;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue