mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 01:20:24 +03:00
Add Shlink prefix to api-contract models
This commit is contained in:
parent
47dd105cd6
commit
23daa2de72
35 changed files with 160 additions and 159 deletions
|
@ -1,4 +1,4 @@
|
||||||
import type { ShortUrl, ShortUrlData } from '../short-urls/data';
|
import type { ShlinkShortUrl, ShortUrlData } from '../short-urls/data';
|
||||||
import type {
|
import type {
|
||||||
ShlinkDomainRedirects,
|
ShlinkDomainRedirects,
|
||||||
ShlinkDomainsResponse,
|
ShlinkDomainsResponse,
|
||||||
|
@ -20,7 +20,7 @@ export type ShlinkApiClient = {
|
||||||
|
|
||||||
listShortUrls(params?: ShlinkShortUrlsListParams): Promise<ShlinkShortUrlsResponse>;
|
listShortUrls(params?: ShlinkShortUrlsListParams): Promise<ShlinkShortUrlsResponse>;
|
||||||
|
|
||||||
createShortUrl(options: ShortUrlData): Promise<ShortUrl>;
|
createShortUrl(options: ShortUrlData): Promise<ShlinkShortUrl>;
|
||||||
|
|
||||||
getShortUrlVisits(shortCode: string, query?: ShlinkVisitsParams): Promise<ShlinkVisits>;
|
getShortUrlVisits(shortCode: string, query?: ShlinkVisitsParams): Promise<ShlinkVisits>;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ export type ShlinkApiClient = {
|
||||||
|
|
||||||
getVisitsOverview(): Promise<ShlinkVisitsOverview>;
|
getVisitsOverview(): Promise<ShlinkVisitsOverview>;
|
||||||
|
|
||||||
getShortUrl(shortCode: string, domain?: string | null): Promise<ShortUrl>;
|
getShortUrl(shortCode: string, domain?: string | null): Promise<ShlinkShortUrl>;
|
||||||
|
|
||||||
deleteShortUrl(shortCode: string, domain?: string | null): Promise<void>;
|
deleteShortUrl(shortCode: string, domain?: string | null): Promise<void>;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ export type ShlinkApiClient = {
|
||||||
shortCode: string,
|
shortCode: string,
|
||||||
domain: string | null | undefined,
|
domain: string | null | undefined,
|
||||||
body: ShlinkShortUrlData,
|
body: ShlinkShortUrlData,
|
||||||
): Promise<ShortUrl>;
|
): Promise<ShlinkShortUrl>;
|
||||||
|
|
||||||
listTags(): Promise<ShlinkTags>;
|
listTags(): Promise<ShlinkTags>;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import type { Order } from '@shlinkio/shlink-frontend-kit';
|
import type { Order } from '@shlinkio/shlink-frontend-kit';
|
||||||
import type { ShortUrl, ShortUrlMeta } from '../short-urls/data';
|
import type { ShlinkDeviceLongUrls, ShlinkShortUrl } from '../short-urls/data';
|
||||||
import type { Visit } from '../visits/types';
|
import type { Visit } from '../visits/types';
|
||||||
|
|
||||||
export interface ShlinkShortUrlsResponse {
|
export interface ShlinkShortUrlsResponse {
|
||||||
data: ShortUrl[];
|
data: ShlinkShortUrl[];
|
||||||
pagination: ShlinkPaginator;
|
pagination: ShlinkPaginator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,11 +77,18 @@ export interface ShlinkVisitsParams {
|
||||||
excludeBots?: boolean;
|
excludeBots?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShlinkShortUrlData extends ShortUrlMeta {
|
export interface ShlinkShortUrlData {
|
||||||
longUrl?: string;
|
longUrl?: string;
|
||||||
title?: string;
|
title?: string | null;
|
||||||
|
/** @deprecated */
|
||||||
validateUrl?: boolean;
|
validateUrl?: boolean;
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
|
deviceLongUrls?: ShlinkDeviceLongUrls;
|
||||||
|
crawlable?: boolean;
|
||||||
|
forwardQuery?: boolean;
|
||||||
|
validSince?: string | null;
|
||||||
|
validUntil?: string | null;
|
||||||
|
maxVisits?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShlinkDomainRedirects {
|
export interface ShlinkDomainRedirects {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { DateTimeInput } from '../utils/dates/DateTimeInput';
|
||||||
import { formatIsoDate } from '../utils/dates/helpers/date';
|
import { formatIsoDate } from '../utils/dates/helpers/date';
|
||||||
import { useFeature } from '../utils/features';
|
import { useFeature } from '../utils/features';
|
||||||
import { handleEventPreventingDefault, hasValue } from '../utils/helpers';
|
import { handleEventPreventingDefault, hasValue } from '../utils/helpers';
|
||||||
import type { DeviceLongUrls, ShortUrlData } from './data';
|
import type { ShlinkDeviceLongUrls, ShortUrlData } from './data';
|
||||||
import { ShortUrlFormCheckboxGroup } from './helpers/ShortUrlFormCheckboxGroup';
|
import { ShortUrlFormCheckboxGroup } from './helpers/ShortUrlFormCheckboxGroup';
|
||||||
import { UseExistingIfFoundInfoIcon } from './UseExistingIfFoundInfoIcon';
|
import { UseExistingIfFoundInfoIcon } from './UseExistingIfFoundInfoIcon';
|
||||||
import './ShortUrlForm.scss';
|
import './ShortUrlForm.scss';
|
||||||
|
@ -87,7 +87,7 @@ export const ShortUrlForm = (
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
);
|
);
|
||||||
const renderDeviceLongUrlInput = (id: keyof DeviceLongUrls, placeholder: string, icon: IconProp) => (
|
const renderDeviceLongUrlInput = (id: keyof ShlinkDeviceLongUrls, placeholder: string, icon: IconProp) => (
|
||||||
<IconInput
|
<IconInput
|
||||||
icon={icon}
|
icon={icon}
|
||||||
id={id}
|
id={id}
|
||||||
|
|
|
@ -1,49 +1,36 @@
|
||||||
import type { Order } from '@shlinkio/shlink-frontend-kit';
|
import type { Order } from '@shlinkio/shlink-frontend-kit';
|
||||||
import type { ShlinkVisitsSummary } from '../../api-contract';
|
import type { ShlinkShortUrlData, ShlinkVisitsSummary } from '../../api-contract';
|
||||||
import type { Nullable, OptionalString } from '../../utils/helpers';
|
import type { Nullable, OptionalString } from '../../utils/helpers';
|
||||||
|
|
||||||
export interface DeviceLongUrls {
|
export interface ShortUrlData extends Omit<ShlinkShortUrlData, 'deviceLongUrls'> {
|
||||||
android?: OptionalString;
|
|
||||||
ios?: OptionalString;
|
|
||||||
desktop?: OptionalString;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EditShortUrlData {
|
|
||||||
longUrl?: string;
|
|
||||||
deviceLongUrls?: DeviceLongUrls;
|
|
||||||
tags?: string[];
|
|
||||||
title?: string | null;
|
|
||||||
validSince?: Date | string | null;
|
|
||||||
validUntil?: Date | string | null;
|
|
||||||
maxVisits?: number | null;
|
|
||||||
validateUrl?: boolean;
|
|
||||||
crawlable?: boolean;
|
|
||||||
forwardQuery?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ShortUrlData extends EditShortUrlData {
|
|
||||||
longUrl: string;
|
longUrl: string;
|
||||||
customSlug?: string;
|
customSlug?: string;
|
||||||
shortCodeLength?: number;
|
shortCodeLength?: number;
|
||||||
domain?: string;
|
domain?: string;
|
||||||
findIfExists?: boolean;
|
findIfExists?: boolean;
|
||||||
|
deviceLongUrls?: {
|
||||||
|
android?: string;
|
||||||
|
ios?: string;
|
||||||
|
desktop?: string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShortUrlIdentifier {
|
export interface ShlinkDeviceLongUrls {
|
||||||
shortCode: string;
|
android?: OptionalString;
|
||||||
domain?: OptionalString;
|
ios?: OptionalString;
|
||||||
|
desktop?: OptionalString;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShortUrl {
|
export interface ShlinkShortUrl {
|
||||||
shortCode: string;
|
shortCode: string;
|
||||||
shortUrl: string;
|
shortUrl: string;
|
||||||
longUrl: string;
|
longUrl: string;
|
||||||
deviceLongUrls?: Required<DeviceLongUrls>, // Optional only before Shlink 3.5.0
|
deviceLongUrls?: Required<ShlinkDeviceLongUrls>, // Optional only before Shlink 3.5.0
|
||||||
dateCreated: string;
|
dateCreated: string;
|
||||||
/** @deprecated */
|
/** @deprecated */
|
||||||
visitsCount: number; // Deprecated since Shlink 3.4.0
|
visitsCount: number; // Deprecated since Shlink 3.4.0
|
||||||
visitsSummary?: ShlinkVisitsSummary; // Optional only before Shlink 3.4.0
|
visitsSummary?: ShlinkVisitsSummary; // Optional only before Shlink 3.4.0
|
||||||
meta: Required<Nullable<ShortUrlMeta>>;
|
meta: Required<Nullable<ShlinkShortUrlMeta>>;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
domain: string | null;
|
domain: string | null;
|
||||||
title?: string | null;
|
title?: string | null;
|
||||||
|
@ -51,14 +38,19 @@ export interface ShortUrl {
|
||||||
forwardQuery?: boolean;
|
forwardQuery?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShortUrlMeta {
|
export interface ShlinkShortUrlMeta {
|
||||||
validSince?: string;
|
validSince?: string;
|
||||||
validUntil?: string;
|
validUntil?: string;
|
||||||
maxVisits?: number;
|
maxVisits?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ShortUrlIdentifier {
|
||||||
|
shortCode: string;
|
||||||
|
domain?: OptionalString;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ShortUrlModalProps {
|
export interface ShortUrlModalProps {
|
||||||
shortUrl: ShortUrl;
|
shortUrl: ShlinkShortUrl;
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
toggle: () => void;
|
toggle: () => void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { useCallback } from 'react';
|
||||||
import type { ShlinkApiClient } from '../../api-contract';
|
import type { ShlinkApiClient } from '../../api-contract';
|
||||||
import { ExportBtn } from '../../utils/components/ExportBtn';
|
import { ExportBtn } from '../../utils/components/ExportBtn';
|
||||||
import type { ReportExporter } from '../../utils/services/ReportExporter';
|
import type { ReportExporter } from '../../utils/services/ReportExporter';
|
||||||
import type { ShortUrl } from '../data';
|
import type { ShlinkShortUrl } from '../data';
|
||||||
import { useShortUrlsQuery } from './hooks';
|
import { useShortUrlsQuery } from './hooks';
|
||||||
|
|
||||||
export interface ExportShortUrlsBtnProps {
|
export interface ExportShortUrlsBtnProps {
|
||||||
|
@ -21,7 +21,7 @@ export const ExportShortUrlsBtn = (
|
||||||
const [loading,, startLoading, stopLoading] = useToggle();
|
const [loading,, startLoading, stopLoading] = useToggle();
|
||||||
const exportAllUrls = useCallback(async () => {
|
const exportAllUrls = useCallback(async () => {
|
||||||
const totalPages = amount / itemsPerPage;
|
const totalPages = amount / itemsPerPage;
|
||||||
const loadAllUrls = async (page = 1): Promise<ShortUrl[]> => {
|
const loadAllUrls = async (page = 1): Promise<ShlinkShortUrl[]> => {
|
||||||
const { data } = await apiClientFactory().listShortUrls(
|
const { data } = await apiClientFactory().listShortUrls(
|
||||||
{ page: `${page}`, tags, searchTerm: search, startDate, endDate, orderBy, tagsMode, itemsPerPage },
|
{ page: `${page}`, tags, searchTerm: search, startDate, endDate, orderBy, tagsMode, itemsPerPage },
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { useRoutesPrefix } from '../../utils/routesPrefix';
|
import { useRoutesPrefix } from '../../utils/routesPrefix';
|
||||||
import type { ShortUrl } from '../data';
|
import type { ShlinkShortUrl } from '../data';
|
||||||
import { urlEncodeShortCode } from './index';
|
import { urlEncodeShortCode } from './index';
|
||||||
|
|
||||||
export type LinkSuffix = 'visits' | 'edit';
|
export type LinkSuffix = 'visits' | 'edit';
|
||||||
|
|
||||||
export interface ShortUrlDetailLinkProps {
|
export interface ShortUrlDetailLinkProps {
|
||||||
shortUrl?: ShortUrl | null;
|
shortUrl?: ShlinkShortUrl | null;
|
||||||
suffix: LinkSuffix;
|
suffix: LinkSuffix;
|
||||||
asLink?: boolean;
|
asLink?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildUrl = (routePrefix: string, { shortCode, domain }: ShortUrl, suffix: LinkSuffix) => {
|
const buildUrl = (routePrefix: string, { shortCode, domain }: ShlinkShortUrl, suffix: LinkSuffix) => {
|
||||||
const query = domain ? `?domain=${domain}` : '';
|
const query = domain ? `?domain=${domain}` : '';
|
||||||
return `${routePrefix}/short-code/${urlEncodeShortCode(shortCode)}/${suffix}${query}`;
|
return `${routePrefix}/short-code/${urlEncodeShortCode(shortCode)}/${suffix}${query}`;
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,10 +6,10 @@ import { isBefore } from 'date-fns';
|
||||||
import type { FC, ReactNode } from 'react';
|
import type { FC, ReactNode } from 'react';
|
||||||
import { UncontrolledTooltip } from 'reactstrap';
|
import { UncontrolledTooltip } from 'reactstrap';
|
||||||
import { formatHumanFriendly, now, parseISO } from '../../utils/dates/helpers/date';
|
import { formatHumanFriendly, now, parseISO } from '../../utils/dates/helpers/date';
|
||||||
import type { ShortUrl } from '../data';
|
import type { ShlinkShortUrl } from '../data';
|
||||||
|
|
||||||
interface ShortUrlStatusProps {
|
interface ShortUrlStatusProps {
|
||||||
shortUrl: ShortUrl;
|
shortUrl: ShlinkShortUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StatusResult {
|
interface StatusResult {
|
||||||
|
@ -18,7 +18,7 @@ interface StatusResult {
|
||||||
description: ReactNode;
|
description: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolveShortUrlStatus = (shortUrl: ShortUrl): StatusResult => {
|
const resolveShortUrlStatus = (shortUrl: ShlinkShortUrl): StatusResult => {
|
||||||
const { meta, visitsCount, visitsSummary } = shortUrl;
|
const { meta, visitsCount, visitsSummary } = shortUrl;
|
||||||
const { maxVisits, validSince, validUntil } = meta;
|
const { maxVisits, validSince, validUntil } = meta;
|
||||||
const totalVisits = visitsSummary?.total ?? visitsCount;
|
const totalVisits = visitsSummary?.total ?? visitsCount;
|
||||||
|
|
|
@ -5,12 +5,12 @@ import classNames from 'classnames';
|
||||||
import { UncontrolledTooltip } from 'reactstrap';
|
import { UncontrolledTooltip } from 'reactstrap';
|
||||||
import { formatHumanFriendly, parseISO } from '../../utils/dates/helpers/date';
|
import { formatHumanFriendly, parseISO } from '../../utils/dates/helpers/date';
|
||||||
import { prettify } from '../../utils/helpers/numbers';
|
import { prettify } from '../../utils/helpers/numbers';
|
||||||
import type { ShortUrl } from '../data';
|
import type { ShlinkShortUrl } from '../data';
|
||||||
import { ShortUrlDetailLink } from './ShortUrlDetailLink';
|
import { ShortUrlDetailLink } from './ShortUrlDetailLink';
|
||||||
import './ShortUrlVisitsCount.scss';
|
import './ShortUrlVisitsCount.scss';
|
||||||
|
|
||||||
interface ShortUrlVisitsCountProps {
|
interface ShortUrlVisitsCountProps {
|
||||||
shortUrl?: ShortUrl | null;
|
shortUrl?: ShlinkShortUrl | null;
|
||||||
visitsCount: number;
|
visitsCount: number;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
asLink?: boolean;
|
asLink?: boolean;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { Time } from '../../utils/dates/Time';
|
||||||
import type { TimeoutToggle } from '../../utils/helpers/hooks';
|
import type { TimeoutToggle } from '../../utils/helpers/hooks';
|
||||||
import type { ColorGenerator } from '../../utils/services/ColorGenerator';
|
import type { ColorGenerator } from '../../utils/services/ColorGenerator';
|
||||||
import { useSetting } from '../../utils/settings';
|
import { useSetting } from '../../utils/settings';
|
||||||
import type { ShortUrl } from '../data';
|
import type { ShlinkShortUrl } from '../data';
|
||||||
import { useShortUrlsQuery } from './hooks';
|
import { useShortUrlsQuery } from './hooks';
|
||||||
import type { ShortUrlsRowMenuType } from './ShortUrlsRowMenu';
|
import type { ShortUrlsRowMenuType } from './ShortUrlsRowMenu';
|
||||||
import { ShortUrlStatus } from './ShortUrlStatus';
|
import { ShortUrlStatus } from './ShortUrlStatus';
|
||||||
|
@ -16,7 +16,7 @@ import './ShortUrlsRow.scss';
|
||||||
|
|
||||||
interface ShortUrlsRowProps {
|
interface ShortUrlsRowProps {
|
||||||
onTagClick?: (tag: string) => void;
|
onTagClick?: (tag: string) => void;
|
||||||
shortUrl: ShortUrl;
|
shortUrl: ShlinkShortUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ShortUrlsRowType = FC<ShortUrlsRowProps>;
|
export type ShortUrlsRowType = FC<ShortUrlsRowProps>;
|
||||||
|
|
|
@ -8,11 +8,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { RowDropdownBtn, useToggle } from '@shlinkio/shlink-frontend-kit';
|
import { RowDropdownBtn, useToggle } from '@shlinkio/shlink-frontend-kit';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { DropdownItem } from 'reactstrap';
|
import { DropdownItem } from 'reactstrap';
|
||||||
import type { ShortUrl, ShortUrlModalProps } from '../data';
|
import type { ShlinkShortUrl, ShortUrlModalProps } from '../data';
|
||||||
import { ShortUrlDetailLink } from './ShortUrlDetailLink';
|
import { ShortUrlDetailLink } from './ShortUrlDetailLink';
|
||||||
|
|
||||||
interface ShortUrlsRowMenuProps {
|
interface ShortUrlsRowMenuProps {
|
||||||
shortUrl: ShortUrl;
|
shortUrl: ShlinkShortUrl;
|
||||||
}
|
}
|
||||||
type ShortUrlModal = FC<ShortUrlModalProps>;
|
type ShortUrlModal = FC<ShortUrlModalProps>;
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@ import { isNil } from 'ramda';
|
||||||
import type { OptionalString } from '../../utils/helpers';
|
import type { OptionalString } from '../../utils/helpers';
|
||||||
import type { ShortUrlCreationSettings } from '../../utils/settings';
|
import type { ShortUrlCreationSettings } from '../../utils/settings';
|
||||||
import { DEFAULT_DOMAIN } from '../../visits/reducers/domainVisits';
|
import { DEFAULT_DOMAIN } from '../../visits/reducers/domainVisits';
|
||||||
import type { ShortUrl, ShortUrlData } from '../data';
|
import type { ShlinkShortUrl, ShortUrlData } from '../data';
|
||||||
|
|
||||||
export const shortUrlMatches = (shortUrl: ShortUrl, shortCode: string, domain: OptionalString): boolean => {
|
export const shortUrlMatches = (shortUrl: ShlinkShortUrl, shortCode: string, domain: OptionalString): boolean => {
|
||||||
if (isNil(domain)) {
|
if (isNil(domain)) {
|
||||||
return shortUrl.shortCode === shortCode && !shortUrl.domain;
|
return shortUrl.shortCode === shortCode && !shortUrl.domain;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ export const shortUrlMatches = (shortUrl: ShortUrl, shortCode: string, domain: O
|
||||||
return shortUrl.shortCode === shortCode && shortUrl.domain === domain;
|
return shortUrl.shortCode === shortCode && shortUrl.domain === domain;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const domainMatches = (shortUrl: ShortUrl, domain: string): boolean => {
|
export const domainMatches = (shortUrl: ShlinkShortUrl, domain: string): boolean => {
|
||||||
if (!shortUrl.domain && domain === DEFAULT_DOMAIN) {
|
if (!shortUrl.domain && domain === DEFAULT_DOMAIN) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ export const domainMatches = (shortUrl: ShortUrl, domain: string): boolean => {
|
||||||
return shortUrl.domain === domain;
|
return shortUrl.domain === domain;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const shortUrlDataFromShortUrl = (shortUrl?: ShortUrl, settings?: ShortUrlCreationSettings): ShortUrlData => {
|
export const shortUrlDataFromShortUrl = (shortUrl?: ShlinkShortUrl, settings?: ShortUrlCreationSettings): ShortUrlData => {
|
||||||
const validateUrl = settings?.validateUrls ?? false;
|
const validateUrl = settings?.validateUrls ?? false;
|
||||||
|
|
||||||
if (!shortUrl) {
|
if (!shortUrl) {
|
||||||
|
@ -37,7 +37,11 @@ export const shortUrlDataFromShortUrl = (shortUrl?: ShortUrl, settings?: ShortUr
|
||||||
maxVisits: shortUrl.meta.maxVisits ?? undefined,
|
maxVisits: shortUrl.meta.maxVisits ?? undefined,
|
||||||
crawlable: shortUrl.crawlable,
|
crawlable: shortUrl.crawlable,
|
||||||
forwardQuery: shortUrl.forwardQuery,
|
forwardQuery: shortUrl.forwardQuery,
|
||||||
deviceLongUrls: shortUrl.deviceLongUrls,
|
deviceLongUrls: shortUrl.deviceLongUrls && {
|
||||||
|
android: shortUrl.deviceLongUrls.android ?? undefined,
|
||||||
|
ios: shortUrl.deviceLongUrls.ios ?? undefined,
|
||||||
|
desktop: shortUrl.deviceLongUrls.desktop ?? undefined,
|
||||||
|
},
|
||||||
validateUrl,
|
validateUrl,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { createSlice } from '@reduxjs/toolkit';
|
||||||
import type { ProblemDetailsError, ShlinkApiClient } from '../../api-contract';
|
import type { ProblemDetailsError, ShlinkApiClient } from '../../api-contract';
|
||||||
import { parseApiError } from '../../api-contract/utils';
|
import { parseApiError } from '../../api-contract/utils';
|
||||||
import { createAsyncThunk } from '../../utils/redux';
|
import { createAsyncThunk } from '../../utils/redux';
|
||||||
import type { ShortUrl, ShortUrlData } from '../data';
|
import type { ShlinkShortUrl, ShortUrlData } from '../data';
|
||||||
|
|
||||||
const REDUCER_PREFIX = 'shlink/shortUrlCreation';
|
const REDUCER_PREFIX = 'shlink/shortUrlCreation';
|
||||||
|
|
||||||
|
@ -21,13 +21,13 @@ export type ShortUrlCreation = {
|
||||||
error: true;
|
error: true;
|
||||||
errorData?: ProblemDetailsError;
|
errorData?: ProblemDetailsError;
|
||||||
} | {
|
} | {
|
||||||
result: ShortUrl;
|
result: ShlinkShortUrl;
|
||||||
saving: false;
|
saving: false;
|
||||||
saved: true;
|
saved: true;
|
||||||
error: false;
|
error: false;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateShortUrlAction = PayloadAction<ShortUrl>;
|
export type CreateShortUrlAction = PayloadAction<ShlinkShortUrl>;
|
||||||
|
|
||||||
const initialState: ShortUrlCreation = {
|
const initialState: ShortUrlCreation = {
|
||||||
saving: false,
|
saving: false,
|
||||||
|
@ -37,7 +37,7 @@ const initialState: ShortUrlCreation = {
|
||||||
|
|
||||||
export const createShortUrl = (apiClientFactory: () => ShlinkApiClient) => createAsyncThunk(
|
export const createShortUrl = (apiClientFactory: () => ShlinkApiClient) => createAsyncThunk(
|
||||||
`${REDUCER_PREFIX}/createShortUrl`,
|
`${REDUCER_PREFIX}/createShortUrl`,
|
||||||
(data: ShortUrlData): Promise<ShortUrl> => apiClientFactory().createShortUrl(data),
|
(data: ShortUrlData): Promise<ShlinkShortUrl> => apiClientFactory().createShortUrl(data),
|
||||||
);
|
);
|
||||||
|
|
||||||
export const shortUrlCreationReducerCreator = (createShortUrlThunk: ReturnType<typeof createShortUrl>) => {
|
export const shortUrlCreationReducerCreator = (createShortUrlThunk: ReturnType<typeof createShortUrl>) => {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { createAction, createSlice } from '@reduxjs/toolkit';
|
||||||
import type { ProblemDetailsError, ShlinkApiClient } from '../../api-contract';
|
import type { ProblemDetailsError, ShlinkApiClient } from '../../api-contract';
|
||||||
import { parseApiError } from '../../api-contract/utils';
|
import { parseApiError } from '../../api-contract/utils';
|
||||||
import { createAsyncThunk } from '../../utils/redux';
|
import { createAsyncThunk } from '../../utils/redux';
|
||||||
import type { ShortUrl, ShortUrlIdentifier } from '../data';
|
import type { ShlinkShortUrl, ShortUrlIdentifier } from '../data';
|
||||||
|
|
||||||
const REDUCER_PREFIX = 'shlink/shortUrlDeletion';
|
const REDUCER_PREFIX = 'shlink/shortUrlDeletion';
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ export const deleteShortUrl = (apiClientFactory: () => ShlinkApiClient) => creat
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export const shortUrlDeleted = createAction<ShortUrl>(`${REDUCER_PREFIX}/shortUrlDeleted`);
|
export const shortUrlDeleted = createAction<ShlinkShortUrl>(`${REDUCER_PREFIX}/shortUrlDeleted`);
|
||||||
|
|
||||||
export const shortUrlDeletionReducerCreator = (deleteShortUrlThunk: ReturnType<typeof deleteShortUrl>) => {
|
export const shortUrlDeletionReducerCreator = (deleteShortUrlThunk: ReturnType<typeof deleteShortUrl>) => {
|
||||||
const { actions, reducer } = createSlice({
|
const { actions, reducer } = createSlice({
|
||||||
|
|
|
@ -3,19 +3,19 @@ import { createSlice } from '@reduxjs/toolkit';
|
||||||
import type { ProblemDetailsError, ShlinkApiClient } from '../../api-contract';
|
import type { ProblemDetailsError, ShlinkApiClient } from '../../api-contract';
|
||||||
import { parseApiError } from '../../api-contract/utils';
|
import { parseApiError } from '../../api-contract/utils';
|
||||||
import { createAsyncThunk } from '../../utils/redux';
|
import { createAsyncThunk } from '../../utils/redux';
|
||||||
import type { ShortUrl, ShortUrlIdentifier } from '../data';
|
import type { ShlinkShortUrl, ShortUrlIdentifier } from '../data';
|
||||||
import { shortUrlMatches } from '../helpers';
|
import { shortUrlMatches } from '../helpers';
|
||||||
|
|
||||||
const REDUCER_PREFIX = 'shlink/shortUrlDetail';
|
const REDUCER_PREFIX = 'shlink/shortUrlDetail';
|
||||||
|
|
||||||
export interface ShortUrlDetail {
|
export interface ShortUrlDetail {
|
||||||
shortUrl?: ShortUrl;
|
shortUrl?: ShlinkShortUrl;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
error: boolean;
|
error: boolean;
|
||||||
errorData?: ProblemDetailsError;
|
errorData?: ProblemDetailsError;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ShortUrlDetailAction = PayloadAction<ShortUrl>;
|
export type ShortUrlDetailAction = PayloadAction<ShlinkShortUrl>;
|
||||||
|
|
||||||
const initialState: ShortUrlDetail = {
|
const initialState: ShortUrlDetail = {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@ -25,7 +25,7 @@ const initialState: ShortUrlDetail = {
|
||||||
export const shortUrlDetailReducerCreator = (apiClientFactory: () => ShlinkApiClient) => {
|
export const shortUrlDetailReducerCreator = (apiClientFactory: () => ShlinkApiClient) => {
|
||||||
const getShortUrlDetail = createAsyncThunk(
|
const getShortUrlDetail = createAsyncThunk(
|
||||||
`${REDUCER_PREFIX}/getShortUrlDetail`,
|
`${REDUCER_PREFIX}/getShortUrlDetail`,
|
||||||
async ({ shortCode, domain }: ShortUrlIdentifier, { getState }): Promise<ShortUrl> => {
|
async ({ shortCode, domain }: ShortUrlIdentifier, { getState }): Promise<ShlinkShortUrl> => {
|
||||||
const { shortUrlsList } = getState();
|
const { shortUrlsList } = getState();
|
||||||
const alreadyLoaded = shortUrlsList?.shortUrls?.data.find((url) => shortUrlMatches(url, shortCode, domain));
|
const alreadyLoaded = shortUrlsList?.shortUrls?.data.find((url) => shortUrlMatches(url, shortCode, domain));
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
|
||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
import type { ProblemDetailsError, ShlinkApiClient } from '../../api-contract';
|
import type { ProblemDetailsError, ShlinkApiClient, ShlinkShortUrlData } from '../../api-contract';
|
||||||
import { parseApiError } from '../../api-contract/utils';
|
import { parseApiError } from '../../api-contract/utils';
|
||||||
import { createAsyncThunk } from '../../utils/redux';
|
import { createAsyncThunk } from '../../utils/redux';
|
||||||
import type { EditShortUrlData, ShortUrl, ShortUrlIdentifier } from '../data';
|
import type { ShlinkShortUrl, ShortUrlIdentifier } from '../data';
|
||||||
|
|
||||||
const REDUCER_PREFIX = 'shlink/shortUrlEdition';
|
const REDUCER_PREFIX = 'shlink/shortUrlEdition';
|
||||||
|
|
||||||
export interface ShortUrlEdition {
|
export interface ShortUrlEdition {
|
||||||
shortUrl?: ShortUrl;
|
shortUrl?: ShlinkShortUrl;
|
||||||
saving: boolean;
|
saving: boolean;
|
||||||
saved: boolean;
|
saved: boolean;
|
||||||
error: boolean;
|
error: boolean;
|
||||||
|
@ -16,11 +15,9 @@ export interface ShortUrlEdition {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EditShortUrl extends ShortUrlIdentifier {
|
export interface EditShortUrl extends ShortUrlIdentifier {
|
||||||
data: EditShortUrlData;
|
data: ShlinkShortUrlData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ShortUrlEditedAction = PayloadAction<ShortUrl>;
|
|
||||||
|
|
||||||
const initialState: ShortUrlEdition = {
|
const initialState: ShortUrlEdition = {
|
||||||
saving: false,
|
saving: false,
|
||||||
saved: false,
|
saved: false,
|
||||||
|
@ -29,7 +26,7 @@ const initialState: ShortUrlEdition = {
|
||||||
|
|
||||||
export const editShortUrl = (apiClientFactory: () => ShlinkApiClient) => createAsyncThunk(
|
export const editShortUrl = (apiClientFactory: () => ShlinkApiClient) => createAsyncThunk(
|
||||||
`${REDUCER_PREFIX}/editShortUrl`,
|
`${REDUCER_PREFIX}/editShortUrl`,
|
||||||
({ shortCode, domain, data }: EditShortUrl): Promise<ShortUrl> =>
|
({ shortCode, domain, data }: EditShortUrl): Promise<ShlinkShortUrl> =>
|
||||||
apiClientFactory().updateShortUrl(shortCode, domain, data as any) // TODO parse dates
|
apiClientFactory().updateShortUrl(shortCode, domain, data as any) // TODO parse dates
|
||||||
,
|
,
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { assocPath, last, pipe, reject } from 'ramda';
|
||||||
import type { ShlinkApiClient, ShlinkShortUrlsListParams, ShlinkShortUrlsResponse } from '../../api-contract';
|
import type { ShlinkApiClient, ShlinkShortUrlsListParams, ShlinkShortUrlsResponse } from '../../api-contract';
|
||||||
import { createAsyncThunk } from '../../utils/redux';
|
import { createAsyncThunk } from '../../utils/redux';
|
||||||
import { createNewVisits } from '../../visits/reducers/visitCreation';
|
import { createNewVisits } from '../../visits/reducers/visitCreation';
|
||||||
import type { ShortUrl } from '../data';
|
import type { ShlinkShortUrl } from '../data';
|
||||||
import { shortUrlMatches } from '../helpers';
|
import { shortUrlMatches } from '../helpers';
|
||||||
import type { createShortUrl } from './shortUrlCreation';
|
import type { createShortUrl } from './shortUrlCreation';
|
||||||
import { shortUrlDeleted } from './shortUrlDeletion';
|
import { shortUrlDeleted } from './shortUrlDeletion';
|
||||||
|
@ -82,7 +82,7 @@ export const shortUrlsListReducerCreator = (
|
||||||
pipe(
|
pipe(
|
||||||
(state, { payload }) => (!state.shortUrls ? state : assocPath(
|
(state, { payload }) => (!state.shortUrls ? state : assocPath(
|
||||||
['shortUrls', 'data'],
|
['shortUrls', 'data'],
|
||||||
reject<ShortUrl, ShortUrl[]>((shortUrl) =>
|
reject<ShlinkShortUrl, ShlinkShortUrl[]>((shortUrl) =>
|
||||||
shortUrlMatches(shortUrl, payload.shortCode, payload.domain), state.shortUrls.data),
|
shortUrlMatches(shortUrl, payload.shortCode, payload.domain), state.shortUrls.data),
|
||||||
state,
|
state,
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { faArrowLeft } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import type { FC, PropsWithChildren, ReactNode } from 'react';
|
import type { FC, PropsWithChildren, ReactNode } from 'react';
|
||||||
import { Button, Card } from 'reactstrap';
|
import { Button, Card } from 'reactstrap';
|
||||||
import type { ShortUrl } from '../short-urls/data';
|
import type { ShlinkShortUrl } from '../short-urls/data';
|
||||||
import { ShortUrlVisitsCount } from '../short-urls/helpers/ShortUrlVisitsCount';
|
import { ShortUrlVisitsCount } from '../short-urls/helpers/ShortUrlVisitsCount';
|
||||||
import type { Visit } from './types';
|
import type { Visit } from './types';
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ type VisitsHeaderProps = PropsWithChildren<{
|
||||||
visits: Visit[];
|
visits: Visit[];
|
||||||
goBack: () => void;
|
goBack: () => void;
|
||||||
title: ReactNode;
|
title: ReactNode;
|
||||||
shortUrl?: ShortUrl;
|
shortUrl?: ShlinkShortUrl;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export const VisitsHeader: FC<VisitsHeaderProps> = ({ visits, goBack, shortUrl, children, title }) => (
|
export const VisitsHeader: FC<VisitsHeaderProps> = ({ visits, goBack, shortUrl, children, title }) => (
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { ShortUrl } from '../../short-urls/data';
|
import type { ShlinkShortUrl } from '../../short-urls/data';
|
||||||
import type { DateRange } from '../../utils/dates/helpers/dateIntervals';
|
import type { DateRange } from '../../utils/dates/helpers/dateIntervals';
|
||||||
|
|
||||||
export type OrphanVisitType = 'base_url' | 'invalid_short_url' | 'regular_404';
|
export type OrphanVisitType = 'base_url' | 'invalid_short_url' | 'regular_404';
|
||||||
|
@ -52,7 +52,7 @@ export interface NormalizedOrphanVisit extends NormalizedRegularVisit {
|
||||||
export type NormalizedVisit = NormalizedRegularVisit | NormalizedOrphanVisit;
|
export type NormalizedVisit = NormalizedRegularVisit | NormalizedOrphanVisit;
|
||||||
|
|
||||||
export interface CreateVisit {
|
export interface CreateVisit {
|
||||||
shortUrl?: ShortUrl;
|
shortUrl?: ShlinkShortUrl;
|
||||||
visit: Visit;
|
visit: Visit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,14 @@ import { screen, waitFor } from '@testing-library/react';
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { InvalidShortUrlDeletion } from '../../../src/api-contract';
|
import type { InvalidShortUrlDeletion } from '../../../src/api-contract';
|
||||||
import { ErrorTypeV2, ErrorTypeV3 } from '../../../src/api-contract';
|
import { ErrorTypeV2, ErrorTypeV3 } from '../../../src/api-contract';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { DeleteShortUrlModal } from '../../../src/short-urls/helpers/DeleteShortUrlModal';
|
import { DeleteShortUrlModal } from '../../../src/short-urls/helpers/DeleteShortUrlModal';
|
||||||
import type { ShortUrlDeletion } from '../../../src/short-urls/reducers/shortUrlDeletion';
|
import type { ShortUrlDeletion } from '../../../src/short-urls/reducers/shortUrlDeletion';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
import { TestModalWrapper } from '../../__helpers__/TestModalWrapper';
|
import { TestModalWrapper } from '../../__helpers__/TestModalWrapper';
|
||||||
|
|
||||||
describe('<DeleteShortUrlModal />', () => {
|
describe('<DeleteShortUrlModal />', () => {
|
||||||
const shortUrl = fromPartial<ShortUrl>({
|
const shortUrl = fromPartial<ShlinkShortUrl>({
|
||||||
tags: [],
|
tags: [],
|
||||||
shortCode: 'abc123',
|
shortCode: 'abc123',
|
||||||
longUrl: 'https://long-domain.com/foo/bar',
|
longUrl: 'https://long-domain.com/foo/bar',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { ExportShortUrlsBtn as createExportShortUrlsBtn } from '../../../src/short-urls/helpers/ExportShortUrlsBtn';
|
import { ExportShortUrlsBtn as createExportShortUrlsBtn } from '../../../src/short-urls/helpers/ExportShortUrlsBtn';
|
||||||
import type { ReportExporter } from '../../../src/utils/services/ReportExporter';
|
import type { ReportExporter } from '../../../src/utils/services/ReportExporter';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
@ -46,7 +46,7 @@ describe('<ExportShortUrlsBtn />', () => {
|
||||||
|
|
||||||
it('maps short URLs for exporting', async () => {
|
it('maps short URLs for exporting', async () => {
|
||||||
listShortUrls.mockResolvedValue({
|
listShortUrls.mockResolvedValue({
|
||||||
data: [fromPartial<ShortUrl>({
|
data: [fromPartial<ShlinkShortUrl>({
|
||||||
shortUrl: 'https://s.test/short-code',
|
shortUrl: 'https://s.test/short-code',
|
||||||
tags: [],
|
tags: [],
|
||||||
})],
|
})],
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import type { LinkSuffix } from '../../../src/short-urls/helpers/ShortUrlDetailLink';
|
import type { LinkSuffix } from '../../../src/short-urls/helpers/ShortUrlDetailLink';
|
||||||
import { ShortUrlDetailLink } from '../../../src/short-urls/helpers/ShortUrlDetailLink';
|
import { ShortUrlDetailLink } from '../../../src/short-urls/helpers/ShortUrlDetailLink';
|
||||||
import { RoutesPrefixProvider } from '../../../src/utils/routesPrefix';
|
import { RoutesPrefixProvider } from '../../../src/utils/routesPrefix';
|
||||||
|
@ -12,8 +12,8 @@ describe('<ShortUrlDetailLink />', () => {
|
||||||
[false, null],
|
[false, null],
|
||||||
[true, null],
|
[true, null],
|
||||||
[true, undefined],
|
[true, undefined],
|
||||||
[false, fromPartial<ShortUrl>({})],
|
[false, fromPartial<ShlinkShortUrl>({})],
|
||||||
[false, fromPartial<ShortUrl>({})],
|
[false, fromPartial<ShlinkShortUrl>({})],
|
||||||
])('only renders a plain span when either server or short URL are not set', (asLink, shortUrl) => {
|
])('only renders a plain span when either server or short URL are not set', (asLink, shortUrl) => {
|
||||||
render(
|
render(
|
||||||
<ShortUrlDetailLink shortUrl={shortUrl} asLink={asLink} suffix="visits">
|
<ShortUrlDetailLink shortUrl={shortUrl} asLink={asLink} suffix="visits">
|
||||||
|
@ -28,25 +28,25 @@ describe('<ShortUrlDetailLink />', () => {
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
'/server/1',
|
'/server/1',
|
||||||
fromPartial<ShortUrl>({ shortCode: 'abc123' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'abc123' }),
|
||||||
'visits' as LinkSuffix,
|
'visits' as LinkSuffix,
|
||||||
'/server/1/short-code/abc123/visits',
|
'/server/1/short-code/abc123/visits',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'/foobar',
|
'/foobar',
|
||||||
fromPartial<ShortUrl>({ shortCode: 'def456', domain: 'example.com' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'def456', domain: 'example.com' }),
|
||||||
'visits' as LinkSuffix,
|
'visits' as LinkSuffix,
|
||||||
'/foobar/short-code/def456/visits?domain=example.com',
|
'/foobar/short-code/def456/visits?domain=example.com',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'/server/1',
|
'/server/1',
|
||||||
fromPartial<ShortUrl>({ shortCode: 'abc123' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'abc123' }),
|
||||||
'edit' as LinkSuffix,
|
'edit' as LinkSuffix,
|
||||||
'/server/1/short-code/abc123/edit',
|
'/server/1/short-code/abc123/edit',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'/server/3',
|
'/server/3',
|
||||||
fromPartial<ShortUrl>({ shortCode: 'def456', domain: 'example.com' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'def456', domain: 'example.com' }),
|
||||||
'edit' as LinkSuffix,
|
'edit' as LinkSuffix,
|
||||||
'/server/3/short-code/def456/edit?domain=example.com',
|
'/server/3/short-code/def456/edit?domain=example.com',
|
||||||
],
|
],
|
||||||
|
|
|
@ -2,41 +2,41 @@ import { render, screen, waitFor } from '@testing-library/react';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkVisitsSummary } from '../../../src/api-contract';
|
import type { ShlinkVisitsSummary } from '../../../src/api-contract';
|
||||||
import type { ShortUrl, ShortUrlMeta } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrlMeta, ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { ShortUrlStatus } from '../../../src/short-urls/helpers/ShortUrlStatus';
|
import { ShortUrlStatus } from '../../../src/short-urls/helpers/ShortUrlStatus';
|
||||||
|
|
||||||
describe('<ShortUrlStatus />', () => {
|
describe('<ShortUrlStatus />', () => {
|
||||||
const setUp = (shortUrl: ShortUrl) => ({
|
const setUp = (shortUrl: ShlinkShortUrl) => ({
|
||||||
user: userEvent.setup(),
|
user: userEvent.setup(),
|
||||||
...render(<ShortUrlStatus shortUrl={shortUrl} />),
|
...render(<ShortUrlStatus shortUrl={shortUrl} />),
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
fromPartial<ShortUrlMeta>({ validSince: '2099-01-01T10:30:15' }),
|
fromPartial<ShlinkShortUrlMeta>({ validSince: '2099-01-01T10:30:15' }),
|
||||||
{},
|
{},
|
||||||
'This short URL will start working on 2099-01-01 10:30.',
|
'This short URL will start working on 2099-01-01 10:30.',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
fromPartial<ShortUrlMeta>({ validUntil: '2020-01-01T10:30:15' }),
|
fromPartial<ShlinkShortUrlMeta>({ validUntil: '2020-01-01T10:30:15' }),
|
||||||
{},
|
{},
|
||||||
'This short URL cannot be visited since 2020-01-01 10:30.',
|
'This short URL cannot be visited since 2020-01-01 10:30.',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
fromPartial<ShortUrlMeta>({ maxVisits: 10 }),
|
fromPartial<ShlinkShortUrlMeta>({ maxVisits: 10 }),
|
||||||
fromPartial<ShlinkVisitsSummary>({ total: 10 }),
|
fromPartial<ShlinkVisitsSummary>({ total: 10 }),
|
||||||
'This short URL cannot be currently visited because it has reached the maximum amount of 10 visits.',
|
'This short URL cannot be currently visited because it has reached the maximum amount of 10 visits.',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
fromPartial<ShortUrlMeta>({ maxVisits: 1 }),
|
fromPartial<ShlinkShortUrlMeta>({ maxVisits: 1 }),
|
||||||
fromPartial<ShlinkVisitsSummary>({ total: 1 }),
|
fromPartial<ShlinkVisitsSummary>({ total: 1 }),
|
||||||
'This short URL cannot be currently visited because it has reached the maximum amount of 1 visit.',
|
'This short URL cannot be currently visited because it has reached the maximum amount of 1 visit.',
|
||||||
],
|
],
|
||||||
[{}, {}, 'This short URL can be visited normally.'],
|
[{}, {}, 'This short URL can be visited normally.'],
|
||||||
[fromPartial<ShortUrlMeta>({ validUntil: '2099-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'],
|
[fromPartial<ShlinkShortUrlMeta>({ validUntil: '2099-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'],
|
||||||
[fromPartial<ShortUrlMeta>({ validSince: '2020-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'],
|
[fromPartial<ShlinkShortUrlMeta>({ validSince: '2020-01-01T10:30:15' }), {}, 'This short URL can be visited normally.'],
|
||||||
[
|
[
|
||||||
fromPartial<ShortUrlMeta>({ maxVisits: 10 }),
|
fromPartial<ShlinkShortUrlMeta>({ maxVisits: 10 }),
|
||||||
fromPartial<ShlinkVisitsSummary>({ total: 1 }),
|
fromPartial<ShlinkVisitsSummary>({ total: 1 }),
|
||||||
'This short URL can be visited normally.',
|
'This short URL can be visited normally.',
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { render, screen, waitFor } from '@testing-library/react';
|
import { render, screen, waitFor } from '@testing-library/react';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { ShortUrlVisitsCount } from '../../../src/short-urls/helpers/ShortUrlVisitsCount';
|
import { ShortUrlVisitsCount } from '../../../src/short-urls/helpers/ShortUrlVisitsCount';
|
||||||
|
|
||||||
describe('<ShortUrlVisitsCount />', () => {
|
describe('<ShortUrlVisitsCount />', () => {
|
||||||
const setUp = (visitsCount: number, shortUrl: ShortUrl) => ({
|
const setUp = (visitsCount: number, shortUrl: ShlinkShortUrl) => ({
|
||||||
user: userEvent.setup(),
|
user: userEvent.setup(),
|
||||||
...render(
|
...render(
|
||||||
<ShortUrlVisitsCount visitsCount={visitsCount} shortUrl={shortUrl} />,
|
<ShortUrlVisitsCount visitsCount={visitsCount} shortUrl={shortUrl} />,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { addDays, formatISO, subDays } from 'date-fns';
|
||||||
import { last } from 'ramda';
|
import { last } from 'ramda';
|
||||||
import { MemoryRouter, useLocation } from 'react-router-dom';
|
import { MemoryRouter, useLocation } from 'react-router-dom';
|
||||||
import type { Settings } from '../../../src';
|
import type { Settings } from '../../../src';
|
||||||
import type { ShortUrl, ShortUrlMeta } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrlMeta, ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { ShortUrlsRow as createShortUrlsRow } from '../../../src/short-urls/helpers/ShortUrlsRow';
|
import { ShortUrlsRow as createShortUrlsRow } from '../../../src/short-urls/helpers/ShortUrlsRow';
|
||||||
import { now, parseDate } from '../../../src/utils/dates/helpers/date';
|
import { now, parseDate } from '../../../src/utils/dates/helpers/date';
|
||||||
import type { TimeoutToggle } from '../../../src/utils/helpers/hooks';
|
import type { TimeoutToggle } from '../../../src/utils/helpers/hooks';
|
||||||
|
@ -15,7 +15,7 @@ import { colorGeneratorMock } from '../../utils/services/__mocks__/ColorGenerato
|
||||||
interface SetUpOptions {
|
interface SetUpOptions {
|
||||||
title?: string | null;
|
title?: string | null;
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
meta?: ShortUrlMeta;
|
meta?: ShlinkShortUrlMeta;
|
||||||
settings?: Partial<Settings>;
|
settings?: Partial<Settings>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ vi.mock('react-router-dom', async () => ({
|
||||||
describe('<ShortUrlsRow />', () => {
|
describe('<ShortUrlsRow />', () => {
|
||||||
const timeoutToggle = vi.fn(() => true);
|
const timeoutToggle = vi.fn(() => true);
|
||||||
const useTimeoutToggle = vi.fn(() => [false, timeoutToggle]) as TimeoutToggle;
|
const useTimeoutToggle = vi.fn(() => [false, timeoutToggle]) as TimeoutToggle;
|
||||||
const shortUrl: ShortUrl = {
|
const shortUrl: ShlinkShortUrl = {
|
||||||
shortCode: 'abc123',
|
shortCode: 'abc123',
|
||||||
shortUrl: 'https://s.test/abc123',
|
shortUrl: 'https://s.test/abc123',
|
||||||
longUrl: 'https://foo.com/bar',
|
longUrl: 'https://foo.com/bar',
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { ShortUrlsRowMenu as createShortUrlsRowMenu } from '../../../src/short-urls/helpers/ShortUrlsRowMenu';
|
import { ShortUrlsRowMenu as createShortUrlsRowMenu } from '../../../src/short-urls/helpers/ShortUrlsRowMenu';
|
||||||
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
import { renderWithEvents } from '../../__helpers__/setUpTest';
|
||||||
|
|
||||||
describe('<ShortUrlsRowMenu />', () => {
|
describe('<ShortUrlsRowMenu />', () => {
|
||||||
const ShortUrlsRowMenu = createShortUrlsRowMenu(() => <i>DeleteShortUrlModal</i>, () => <i>QrCodeModal</i>);
|
const ShortUrlsRowMenu = createShortUrlsRowMenu(() => <i>DeleteShortUrlModal</i>, () => <i>QrCodeModal</i>);
|
||||||
const shortUrl = fromPartial<ShortUrl>({
|
const shortUrl = fromPartial<ShlinkShortUrl>({
|
||||||
shortCode: 'abc123',
|
shortCode: 'abc123',
|
||||||
shortUrl: 'https://s.test/abc123',
|
shortUrl: 'https://s.test/abc123',
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { shortUrlDataFromShortUrl, urlDecodeShortCode, urlEncodeShortCode } from '../../../src/short-urls/helpers';
|
import { shortUrlDataFromShortUrl, urlDecodeShortCode, urlEncodeShortCode } from '../../../src/short-urls/helpers';
|
||||||
|
|
||||||
describe('helpers', () => {
|
describe('helpers', () => {
|
||||||
|
@ -8,7 +8,7 @@ describe('helpers', () => {
|
||||||
[undefined, { validateUrls: true }, { longUrl: '', validateUrl: true }],
|
[undefined, { validateUrls: true }, { longUrl: '', validateUrl: true }],
|
||||||
[undefined, undefined, { longUrl: '', validateUrl: false }],
|
[undefined, undefined, { longUrl: '', validateUrl: false }],
|
||||||
[
|
[
|
||||||
fromPartial<ShortUrl>({ meta: {} }),
|
fromPartial<ShlinkShortUrl>({ meta: {} }),
|
||||||
{ validateUrls: false },
|
{ validateUrls: false },
|
||||||
{
|
{
|
||||||
longUrl: undefined,
|
longUrl: undefined,
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient } from '../../../src/api-contract';
|
import type { ShlinkApiClient } from '../../../src/api-contract';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import {
|
import {
|
||||||
createShortUrl as createShortUrlCreator,
|
createShortUrl as createShortUrlCreator,
|
||||||
shortUrlCreationReducerCreator,
|
shortUrlCreationReducerCreator,
|
||||||
} from '../../../src/short-urls/reducers/shortUrlCreation';
|
} from '../../../src/short-urls/reducers/shortUrlCreation';
|
||||||
|
|
||||||
describe('shortUrlCreationReducer', () => {
|
describe('shortUrlCreationReducer', () => {
|
||||||
const shortUrl = fromPartial<ShortUrl>({});
|
const shortUrl = fromPartial<ShlinkShortUrl>({});
|
||||||
const createShortUrlCall = vi.fn();
|
const createShortUrlCall = vi.fn();
|
||||||
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ createShortUrl: createShortUrlCall });
|
const buildShlinkApiClient = () => fromPartial<ShlinkApiClient>({ createShortUrl: createShortUrlCall });
|
||||||
const createShortUrl = createShortUrlCreator(buildShlinkApiClient);
|
const createShortUrl = createShortUrlCreator(buildShlinkApiClient);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient } from '../../../src/api-contract';
|
import type { ShlinkApiClient } from '../../../src/api-contract';
|
||||||
import type { RootState } from '../../../src/container/store';
|
import type { RootState } from '../../../src/container/store';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { shortUrlDetailReducerCreator } from '../../../src/short-urls/reducers/shortUrlDetail';
|
import { shortUrlDetailReducerCreator } from '../../../src/short-urls/reducers/shortUrlDetail';
|
||||||
import type { ShortUrlsList } from '../../../src/short-urls/reducers/shortUrlsList';
|
import type { ShortUrlsList } from '../../../src/short-urls/reducers/shortUrlsList';
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ describe('shortUrlDetailReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return short URL on GET_SHORT_URL_DETAIL', () => {
|
it('return short URL on GET_SHORT_URL_DETAIL', () => {
|
||||||
const actionShortUrl = fromPartial<ShortUrl>({ longUrl: 'foo', shortCode: 'bar' });
|
const actionShortUrl = fromPartial<ShlinkShortUrl>({ longUrl: 'foo', shortCode: 'bar' });
|
||||||
const state = reducer(
|
const state = reducer(
|
||||||
{ loading: true, error: false },
|
{ loading: true, error: false },
|
||||||
getShortUrlDetail.fulfilled(actionShortUrl, '', { shortCode: '' }),
|
getShortUrlDetail.fulfilled(actionShortUrl, '', { shortCode: '' }),
|
||||||
|
@ -58,7 +58,7 @@ describe('shortUrlDetailReducer', () => {
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
])('performs API call when short URL is not found in local state', async (shortUrlsList?: ShortUrlsList) => {
|
])('performs API call when short URL is not found in local state', async (shortUrlsList?: ShortUrlsList) => {
|
||||||
const resolvedShortUrl = fromPartial<ShortUrl>({ longUrl: 'foo', shortCode: 'abc123' });
|
const resolvedShortUrl = fromPartial<ShlinkShortUrl>({ longUrl: 'foo', shortCode: 'abc123' });
|
||||||
getShortUrlCall.mockResolvedValue(resolvedShortUrl);
|
getShortUrlCall.mockResolvedValue(resolvedShortUrl);
|
||||||
|
|
||||||
await getShortUrlDetail({ shortCode: 'abc123', domain: '' })(dispatchMock, buildGetState(shortUrlsList), {});
|
await getShortUrlDetail({ shortCode: 'abc123', domain: '' })(dispatchMock, buildGetState(shortUrlsList), {});
|
||||||
|
@ -69,8 +69,8 @@ describe('shortUrlDetailReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('avoids API calls when short URL is found in local state', async () => {
|
it('avoids API calls when short URL is found in local state', async () => {
|
||||||
const foundShortUrl = fromPartial<ShortUrl>({ longUrl: 'foo', shortCode: 'abc123' });
|
const foundShortUrl = fromPartial<ShlinkShortUrl>({ longUrl: 'foo', shortCode: 'abc123' });
|
||||||
getShortUrlCall.mockResolvedValue(fromPartial<ShortUrl>({}));
|
getShortUrlCall.mockResolvedValue(fromPartial<ShlinkShortUrl>({}));
|
||||||
|
|
||||||
await getShortUrlDetail(foundShortUrl)(
|
await getShortUrlDetail(foundShortUrl)(
|
||||||
dispatchMock,
|
dispatchMock,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import {
|
import {
|
||||||
editShortUrl as editShortUrlCreator,
|
editShortUrl as editShortUrlCreator,
|
||||||
shortUrlEditionReducerCreator,
|
shortUrlEditionReducerCreator,
|
||||||
|
@ -8,7 +8,7 @@ import {
|
||||||
describe('shortUrlEditionReducer', () => {
|
describe('shortUrlEditionReducer', () => {
|
||||||
const longUrl = 'https://shlink.io';
|
const longUrl = 'https://shlink.io';
|
||||||
const shortCode = 'abc123';
|
const shortCode = 'abc123';
|
||||||
const shortUrl = fromPartial<ShortUrl>({ longUrl, shortCode });
|
const shortUrl = fromPartial<ShlinkShortUrl>({ longUrl, shortCode });
|
||||||
const updateShortUrl = vi.fn().mockResolvedValue(shortUrl);
|
const updateShortUrl = vi.fn().mockResolvedValue(shortUrl);
|
||||||
const buildShlinkApiClient = vi.fn().mockReturnValue({ updateShortUrl });
|
const buildShlinkApiClient = vi.fn().mockReturnValue({ updateShortUrl });
|
||||||
const editShortUrl = editShortUrlCreator(buildShlinkApiClient);
|
const editShortUrl = editShortUrlCreator(buildShlinkApiClient);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShlinkApiClient, ShlinkShortUrlsResponse } from '../../../src/api-contract';
|
import type { ShlinkApiClient, ShlinkShortUrlsResponse } from '../../../src/api-contract';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation';
|
import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation';
|
||||||
import { shortUrlDeleted } from '../../../src/short-urls/reducers/shortUrlDeletion';
|
import { shortUrlDeleted } from '../../../src/short-urls/reducers/shortUrlDeletion';
|
||||||
import { editShortUrl as editShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlEdition';
|
import { editShortUrl as editShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlEdition';
|
||||||
|
@ -102,36 +102,36 @@ describe('shortUrlsListReducer', () => {
|
||||||
it.each([
|
it.each([
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
fromPartial<ShortUrl>({ shortCode }),
|
fromPartial<ShlinkShortUrl>({ shortCode }),
|
||||||
fromPartial<ShortUrl>({ shortCode, domain: 'example.com' }),
|
fromPartial<ShlinkShortUrl>({ shortCode, domain: 'example.com' }),
|
||||||
fromPartial<ShortUrl>({ shortCode: 'foo' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'foo' }),
|
||||||
],
|
],
|
||||||
[{ shortCode: 'newOne' }, { shortCode }, { shortCode, domain: 'example.com' }, { shortCode: 'foo' }],
|
[{ shortCode: 'newOne' }, { shortCode }, { shortCode, domain: 'example.com' }, { shortCode: 'foo' }],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
fromPartial<ShortUrl>({ shortCode }),
|
fromPartial<ShlinkShortUrl>({ shortCode }),
|
||||||
fromPartial<ShortUrl>({ shortCode: 'code' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'code' }),
|
||||||
fromPartial<ShortUrl>({ shortCode: 'foo' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'foo' }),
|
||||||
fromPartial<ShortUrl>({ shortCode: 'bar' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'bar' }),
|
||||||
fromPartial<ShortUrl>({ shortCode: 'baz' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'baz' }),
|
||||||
],
|
],
|
||||||
[{ shortCode: 'newOne' }, { shortCode }, { shortCode: 'code' }, { shortCode: 'foo' }, { shortCode: 'bar' }],
|
[{ shortCode: 'newOne' }, { shortCode }, { shortCode: 'code' }, { shortCode: 'foo' }, { shortCode: 'bar' }],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
fromPartial<ShortUrl>({ shortCode }),
|
fromPartial<ShlinkShortUrl>({ shortCode }),
|
||||||
fromPartial<ShortUrl>({ shortCode: 'code' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'code' }),
|
||||||
fromPartial<ShortUrl>({ shortCode: 'foo' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'foo' }),
|
||||||
fromPartial<ShortUrl>({ shortCode: 'bar' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'bar' }),
|
||||||
fromPartial<ShortUrl>({ shortCode: 'baz1' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'baz1' }),
|
||||||
fromPartial<ShortUrl>({ shortCode: 'baz2' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'baz2' }),
|
||||||
fromPartial<ShortUrl>({ shortCode: 'baz3' }),
|
fromPartial<ShlinkShortUrl>({ shortCode: 'baz3' }),
|
||||||
],
|
],
|
||||||
[{ shortCode: 'newOne' }, { shortCode }, { shortCode: 'code' }, { shortCode: 'foo' }, { shortCode: 'bar' }],
|
[{ shortCode: 'newOne' }, { shortCode }, { shortCode: 'code' }, { shortCode: 'foo' }, { shortCode: 'bar' }],
|
||||||
],
|
],
|
||||||
])('prepends new short URL and increases total on CREATE_SHORT_URL', (data, expectedData) => {
|
])('prepends new short URL and increases total on CREATE_SHORT_URL', (data, expectedData) => {
|
||||||
const newShortUrl = fromPartial<ShortUrl>({ shortCode: 'newOne' });
|
const newShortUrl = fromPartial<ShlinkShortUrl>({ shortCode: 'newOne' });
|
||||||
const state = {
|
const state = {
|
||||||
shortUrls: fromPartial<ShlinkShortUrlsResponse>({
|
shortUrls: fromPartial<ShlinkShortUrlsResponse>({
|
||||||
data,
|
data,
|
||||||
|
@ -152,15 +152,15 @@ describe('shortUrlsListReducer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
((): [ShortUrl, ShortUrl[], ShortUrl[]] => {
|
((): [ShlinkShortUrl, ShlinkShortUrl[], ShlinkShortUrl[]] => {
|
||||||
const editedShortUrl = fromPartial<ShortUrl>({ shortCode: 'notMatching' });
|
const editedShortUrl = fromPartial<ShlinkShortUrl>({ shortCode: 'notMatching' });
|
||||||
const list: ShortUrl[] = [fromPartial({ shortCode: 'foo' }), fromPartial({ shortCode: 'bar' })];
|
const list: ShlinkShortUrl[] = [fromPartial({ shortCode: 'foo' }), fromPartial({ shortCode: 'bar' })];
|
||||||
|
|
||||||
return [editedShortUrl, list, list];
|
return [editedShortUrl, list, list];
|
||||||
})(),
|
})(),
|
||||||
((): [ShortUrl, ShortUrl[], ShortUrl[]] => {
|
((): [ShlinkShortUrl, ShlinkShortUrl[], ShlinkShortUrl[]] => {
|
||||||
const editedShortUrl = fromPartial<ShortUrl>({ shortCode: 'matching', longUrl: 'new_one' });
|
const editedShortUrl = fromPartial<ShlinkShortUrl>({ shortCode: 'matching', longUrl: 'new_one' });
|
||||||
const list: ShortUrl[] = [
|
const list: ShlinkShortUrl[] = [
|
||||||
fromPartial({ shortCode: 'matching', longUrl: 'old_one' }),
|
fromPartial({ shortCode: 'matching', longUrl: 'old_one' }),
|
||||||
fromPartial({ shortCode: 'bar' }),
|
fromPartial({ shortCode: 'bar' }),
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { RootState } from '../../../src/container/store';
|
import type { RootState } from '../../../src/container/store';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation';
|
import { createShortUrl as createShortUrlCreator } from '../../../src/short-urls/reducers/shortUrlCreation';
|
||||||
import { tagDeleted } from '../../../src/tags/reducers/tagDelete';
|
import { tagDeleted } from '../../../src/tags/reducers/tagDelete';
|
||||||
import { tagEdited } from '../../../src/tags/reducers/tagEdit';
|
import { tagEdited } from '../../../src/tags/reducers/tagEdit';
|
||||||
|
@ -112,7 +112,7 @@ describe('tagsListReducer', () => {
|
||||||
[['new', 'tag'], ['foo', 'bar', 'baz', 'foo2', 'fo', 'new', 'tag']],
|
[['new', 'tag'], ['foo', 'bar', 'baz', 'foo2', 'fo', 'new', 'tag']],
|
||||||
])('appends new short URL\'s tags to the list of tags on CREATE_SHORT_URL', (shortUrlTags, expectedTags) => {
|
])('appends new short URL\'s tags to the list of tags on CREATE_SHORT_URL', (shortUrlTags, expectedTags) => {
|
||||||
const tags = ['foo', 'bar', 'baz', 'foo2', 'fo'];
|
const tags = ['foo', 'bar', 'baz', 'foo2', 'fo'];
|
||||||
const payload = fromPartial<ShortUrl>({ tags: shortUrlTags });
|
const payload = fromPartial<ShlinkShortUrl>({ tags: shortUrlTags });
|
||||||
|
|
||||||
expect(reducer(state({ tags }), createShortUrl.fulfilled(payload, '', fromPartial({})))).toEqual({
|
expect(reducer(state({ tags }), createShortUrl.fulfilled(payload, '', fromPartial({})))).toEqual({
|
||||||
tags: expectedTags,
|
tags: expectedTags,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { addDays, formatISO, subDays } from 'date-fns';
|
import { addDays, formatISO, subDays } from 'date-fns';
|
||||||
import type { ShlinkApiClient, ShlinkVisits } from '../../../src/api-contract';
|
import type { ShlinkApiClient, ShlinkVisits } from '../../../src/api-contract';
|
||||||
import type { RootState } from '../../../src/container/store';
|
import type { RootState } from '../../../src/container/store';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { formatIsoDate } from '../../../src/utils/dates/helpers/date';
|
import { formatIsoDate } from '../../../src/utils/dates/helpers/date';
|
||||||
import type { DateInterval } from '../../../src/utils/dates/helpers/dateIntervals';
|
import type { DateInterval } from '../../../src/utils/dates/helpers/dateIntervals';
|
||||||
import { rangeOf } from '../../../src/utils/helpers';
|
import { rangeOf } from '../../../src/utils/helpers';
|
||||||
|
@ -124,7 +124,7 @@ describe('domainVisitsReducer', () => {
|
||||||
visitsMocks.length,
|
visitsMocks.length,
|
||||||
],
|
],
|
||||||
])('prepends new visits on CREATE_VISIT', (state, shortUrlDomain, expectedVisits) => {
|
])('prepends new visits on CREATE_VISIT', (state, shortUrlDomain, expectedVisits) => {
|
||||||
const shortUrl = fromPartial<ShortUrl>({ domain: shortUrlDomain });
|
const shortUrl = fromPartial<ShlinkShortUrl>({ domain: shortUrlDomain });
|
||||||
const { visits } = reducer(buildState({ ...state, visits: visitsMocks }), createNewVisits([
|
const { visits } = reducer(buildState({ ...state, visits: visitsMocks }), createNewVisits([
|
||||||
fromPartial({ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }),
|
fromPartial({ shortUrl, visit: { date: formatIsoDate(now) ?? undefined } }),
|
||||||
]));
|
]));
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShortUrl } from '../../../src/short-urls/data';
|
import type { ShlinkShortUrl } from '../../../src/short-urls/data';
|
||||||
import { createNewVisits } from '../../../src/visits/reducers/visitCreation';
|
import { createNewVisits } from '../../../src/visits/reducers/visitCreation';
|
||||||
import type { Visit } from '../../../src/visits/types';
|
import type { Visit } from '../../../src/visits/types';
|
||||||
|
|
||||||
describe('visitCreationReducer', () => {
|
describe('visitCreationReducer', () => {
|
||||||
describe('createNewVisits', () => {
|
describe('createNewVisits', () => {
|
||||||
const shortUrl = fromPartial<ShortUrl>({});
|
const shortUrl = fromPartial<ShlinkShortUrl>({});
|
||||||
const visit = fromPartial<Visit>({});
|
const visit = fromPartial<Visit>({});
|
||||||
|
|
||||||
it('just returns the action with proper type', () => {
|
it('just returns the action with proper type', () => {
|
||||||
|
|
|
@ -16,13 +16,14 @@ import type {
|
||||||
ShlinkTagsStatsResponse,
|
ShlinkTagsStatsResponse,
|
||||||
ShlinkVisits,
|
ShlinkVisits,
|
||||||
ShlinkVisitsOverview,
|
ShlinkVisitsOverview,
|
||||||
ShlinkVisitsParams } from '@shlinkio/shlink-web-component/api-contract';
|
ShlinkVisitsParams,
|
||||||
|
} from '@shlinkio/shlink-web-component/api-contract';
|
||||||
import {
|
import {
|
||||||
ErrorTypeV2,
|
ErrorTypeV2,
|
||||||
ErrorTypeV3,
|
ErrorTypeV3,
|
||||||
} from '@shlinkio/shlink-web-component/api-contract';
|
} from '@shlinkio/shlink-web-component/api-contract';
|
||||||
import { isEmpty, isNil, reject } from 'ramda';
|
import { isEmpty, isNil, reject } from 'ramda';
|
||||||
import type { ShortUrl, ShortUrlData } from '../../../shlink-web-component/src/short-urls/data';
|
import type { ShlinkShortUrl, ShortUrlData } from '../../../shlink-web-component/src/short-urls/data';
|
||||||
import type { HttpClient } from '../../common/services/HttpClient';
|
import type { HttpClient } from '../../common/services/HttpClient';
|
||||||
import { replaceAuthorityFromUri } from '../../utils/helpers/uri';
|
import { replaceAuthorityFromUri } from '../../utils/helpers/uri';
|
||||||
import type { OptionalString } from '../../utils/utils';
|
import type { OptionalString } from '../../utils/utils';
|
||||||
|
@ -71,9 +72,9 @@ export class ShlinkApiClient implements BaseShlinkApiClient {
|
||||||
{ url: '/short-urls', query: normalizeListParams(params) },
|
{ url: '/short-urls', query: normalizeListParams(params) },
|
||||||
).then(({ shortUrls }) => shortUrls);
|
).then(({ shortUrls }) => shortUrls);
|
||||||
|
|
||||||
public readonly createShortUrl = async (options: ShortUrlData): Promise<ShortUrl> => {
|
public readonly createShortUrl = async (options: ShortUrlData): Promise<ShlinkShortUrl> => {
|
||||||
const body = reject((value) => isEmpty(value) || isNil(value), options as any);
|
const body = reject((value) => isEmpty(value) || isNil(value), options as any);
|
||||||
return this.performRequest<ShortUrl>({ url: '/short-urls', method: 'POST', body });
|
return this.performRequest<ShlinkShortUrl>({ url: '/short-urls', method: 'POST', body });
|
||||||
};
|
};
|
||||||
|
|
||||||
public readonly getShortUrlVisits = async (shortCode: string, query?: ShlinkVisitsParams): Promise<ShlinkVisits> =>
|
public readonly getShortUrlVisits = async (shortCode: string, query?: ShlinkVisitsParams): Promise<ShlinkVisits> =>
|
||||||
|
@ -95,8 +96,8 @@ export class ShlinkApiClient implements BaseShlinkApiClient {
|
||||||
public readonly getVisitsOverview = async (): Promise<ShlinkVisitsOverview> =>
|
public readonly getVisitsOverview = async (): Promise<ShlinkVisitsOverview> =>
|
||||||
this.performRequest<{ visits: ShlinkVisitsOverview }>({ url: '/visits' }).then(({ visits }) => visits);
|
this.performRequest<{ visits: ShlinkVisitsOverview }>({ url: '/visits' }).then(({ visits }) => visits);
|
||||||
|
|
||||||
public readonly getShortUrl = async (shortCode: string, domain?: OptionalString): Promise<ShortUrl> =>
|
public readonly getShortUrl = async (shortCode: string, domain?: OptionalString): Promise<ShlinkShortUrl> =>
|
||||||
this.performRequest<ShortUrl>({ url: `/short-urls/${shortCode}`, query: { domain } });
|
this.performRequest<ShlinkShortUrl>({ url: `/short-urls/${shortCode}`, query: { domain } });
|
||||||
|
|
||||||
public readonly deleteShortUrl = async (shortCode: string, domain?: OptionalString): Promise<void> =>
|
public readonly deleteShortUrl = async (shortCode: string, domain?: OptionalString): Promise<void> =>
|
||||||
this.performEmptyRequest({ url: `/short-urls/${shortCode}`, method: 'DELETE', query: { domain } });
|
this.performEmptyRequest({ url: `/short-urls/${shortCode}`, method: 'DELETE', query: { domain } });
|
||||||
|
@ -105,8 +106,8 @@ export class ShlinkApiClient implements BaseShlinkApiClient {
|
||||||
shortCode: string,
|
shortCode: string,
|
||||||
domain: OptionalString,
|
domain: OptionalString,
|
||||||
body: ShlinkShortUrlData,
|
body: ShlinkShortUrlData,
|
||||||
): Promise<ShortUrl> =>
|
): Promise<ShlinkShortUrl> =>
|
||||||
this.performRequest<ShortUrl>({ url: `/short-urls/${shortCode}`, method: 'PATCH', query: { domain }, body });
|
this.performRequest<ShlinkShortUrl>({ url: `/short-urls/${shortCode}`, method: 'PATCH', query: { domain }, body });
|
||||||
|
|
||||||
public readonly listTags = async (): Promise<ShlinkTags> =>
|
public readonly listTags = async (): Promise<ShlinkTags> =>
|
||||||
this.performRequest<{ tags: ShlinkTagsResponse }>({ url: '/tags', query: { withStats: 'true' } })
|
this.performRequest<{ tags: ShlinkTagsResponse }>({ url: '/tags', query: { withStats: 'true' } })
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { ShlinkDomain, ShlinkVisits, ShlinkVisitsOverview } from '@shlinkio/shlink-web-component/api-contract';
|
import type { ShlinkDomain, ShlinkVisits, ShlinkVisitsOverview } from '@shlinkio/shlink-web-component/api-contract';
|
||||||
import { ErrorTypeV2, ErrorTypeV3 } from '@shlinkio/shlink-web-component/api-contract';
|
import { ErrorTypeV2, ErrorTypeV3 } from '@shlinkio/shlink-web-component/api-contract';
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import type { ShortUrl, ShortUrlsOrder } from '../../../shlink-web-component/src/short-urls/data';
|
import type { ShlinkShortUrl, ShortUrlsOrder } from '../../../shlink-web-component/src/short-urls/data';
|
||||||
import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
|
||||||
import type { HttpClient } from '../../../src/common/services/HttpClient';
|
import type { HttpClient } from '../../../src/common/services/HttpClient';
|
||||||
import type { OptionalString } from '../../../src/utils/utils';
|
import type { OptionalString } from '../../../src/utils/utils';
|
||||||
|
@ -175,7 +175,7 @@ describe('ShlinkApiClient', () => {
|
||||||
maxVisits: 50,
|
maxVisits: 50,
|
||||||
validSince: '2025-01-01T10:00:00+01:00',
|
validSince: '2025-01-01T10:00:00+01:00',
|
||||||
};
|
};
|
||||||
const expectedResp = fromPartial<ShortUrl>({});
|
const expectedResp = fromPartial<ShlinkShortUrl>({});
|
||||||
fetchJson.mockResolvedValue(expectedResp);
|
fetchJson.mockResolvedValue(expectedResp);
|
||||||
const { updateShortUrl } = buildApiClient();
|
const { updateShortUrl } = buildApiClient();
|
||||||
const expectedQuery = domain ? `?domain=${domain}` : '';
|
const expectedQuery = domain ? `?domain=${domain}` : '';
|
||||||
|
|
Loading…
Reference in a new issue