diff --git a/src/mercure/reducers/mercureInfo.ts b/src/mercure/reducers/mercureInfo.ts index 768d8acf..5b08c364 100644 --- a/src/mercure/reducers/mercureInfo.ts +++ b/src/mercure/reducers/mercureInfo.ts @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import { Action, Dispatch } from 'redux'; import { ShlinkMercureInfo } from '../../utils/services/types'; import { GetState } from '../../container/types'; @@ -11,14 +10,6 @@ export const GET_MERCURE_INFO_ERROR = 'shlink/mercure/GET_MERCURE_INFO_ERROR'; export const GET_MERCURE_INFO = 'shlink/mercure/GET_MERCURE_INFO'; /* eslint-enable padding-line-between-statements */ -/** @deprecated Use MercureInfo interface */ -export const MercureInfoType = PropTypes.shape({ - token: PropTypes.string, - mercureHubUrl: PropTypes.string, - loading: PropTypes.bool, - error: PropTypes.bool, -}); - export interface MercureInfo { token?: string; mercureHubUrl?: string; diff --git a/src/short-urls/reducers/shortUrlMeta.ts b/src/short-urls/reducers/shortUrlMeta.ts index 71736ea0..8b4e8a51 100644 --- a/src/short-urls/reducers/shortUrlMeta.ts +++ b/src/short-urls/reducers/shortUrlMeta.ts @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import { Dispatch, Action } from 'redux'; import { ShortUrlIdentifier, ShortUrlMeta } from '../data'; import { GetState } from '../../container/types'; @@ -13,13 +12,6 @@ export const SHORT_URL_META_EDITED = 'shlink/shortUrlMeta/SHORT_URL_META_EDITED' export const RESET_EDIT_SHORT_URL_META = 'shlink/shortUrlMeta/RESET_EDIT_SHORT_URL_META'; /* eslint-enable padding-line-between-statements */ -/** @deprecated Use ShortUrlMeta interface instead */ -export const shortUrlMetaType = PropTypes.shape({ - validSince: PropTypes.string, - validUntil: PropTypes.string, - maxVisits: PropTypes.number, -}); - export interface ShortUrlMetaEdition { shortCode: string | null; meta: ShortUrlMeta; diff --git a/src/short-urls/reducers/shortUrlsList.ts b/src/short-urls/reducers/shortUrlsList.ts index 71a153e5..4370fb20 100644 --- a/src/short-urls/reducers/shortUrlsList.ts +++ b/src/short-urls/reducers/shortUrlsList.ts @@ -1,5 +1,4 @@ import { assoc, assocPath, reject } from 'ramda'; -import PropTypes from 'prop-types'; import { Action, Dispatch } from 'redux'; import { shortUrlMatches } from '../helpers'; import { CREATE_VISIT, CreateVisitAction } from '../../visits/reducers/visitCreation'; @@ -10,7 +9,7 @@ import { ShlinkApiClientBuilder } from '../../utils/services/ShlinkApiClientBuil import { ShlinkShortUrlsResponse } from '../../utils/services/types'; import { EditShortUrlTagsAction, SHORT_URL_TAGS_EDITED } from './shortUrlTags'; import { SHORT_URL_DELETED } from './shortUrlDeletion'; -import { SHORT_URL_META_EDITED, ShortUrlMetaEditedAction, shortUrlMetaType } from './shortUrlMeta'; +import { SHORT_URL_META_EDITED, ShortUrlMetaEditedAction } from './shortUrlMeta'; import { SHORT_URL_EDITED, ShortUrlEditedAction } from './shortUrlEdition'; import { ShortUrlsListParams } from './shortUrlsListParams'; @@ -20,17 +19,6 @@ export const LIST_SHORT_URLS_ERROR = 'shlink/shortUrlsList/LIST_SHORT_URLS_ERROR export const LIST_SHORT_URLS = 'shlink/shortUrlsList/LIST_SHORT_URLS'; /* eslint-enable padding-line-between-statements */ -/** @deprecated Use ShortUrl interface instead */ -export const shortUrlType = PropTypes.shape({ - shortCode: PropTypes.string, - shortUrl: PropTypes.string, - longUrl: PropTypes.string, - visitsCount: PropTypes.number, - meta: shortUrlMetaType, - tags: PropTypes.arrayOf(PropTypes.string), - domain: PropTypes.string, -}); - export interface ShortUrlsList { shortUrls?: ShlinkShortUrlsResponse; loading: boolean; diff --git a/src/utils/services/ColorGenerator.ts b/src/utils/services/ColorGenerator.ts index 5f79b0b8..7a9c8abd 100644 --- a/src/utils/services/ColorGenerator.ts +++ b/src/utils/services/ColorGenerator.ts @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import { rangeOf } from '../utils'; import LocalStorage from './LocalStorage'; @@ -36,9 +35,3 @@ export default class ColorGenerator { return color; }; } - -/** @deprecated Use ColorGenerator class instead */ -export const colorGeneratorType = PropTypes.shape({ - getColorForKey: PropTypes.func, - setColorForKey: PropTypes.func, -}); diff --git a/src/visits/ShortUrlVisits.tsx b/src/visits/ShortUrlVisits.tsx index 805f5524..e4f8a5c2 100644 --- a/src/visits/ShortUrlVisits.tsx +++ b/src/visits/ShortUrlVisits.tsx @@ -7,7 +7,7 @@ import { ShortUrlVisits as ShortUrlVisitsState } from './reducers/shortUrlVisits import ShortUrlVisitsHeader from './ShortUrlVisitsHeader'; import { ShortUrlDetail } from './reducers/shortUrlDetail'; -interface ShortUrlVisitsProps extends RouteComponentProps<{ shortCode: string }>, MercureBoundProps { +export interface ShortUrlVisitsProps extends RouteComponentProps<{ shortCode: string }>, MercureBoundProps { getShortUrlVisits: (shortCode: string, query?: ShlinkVisitsParams) => void; shortUrlVisits: ShortUrlVisitsState; getShortUrlDetail: Function; diff --git a/src/visits/ShortUrlVisitsHeader.js b/src/visits/ShortUrlVisitsHeader.tsx similarity index 71% rename from src/visits/ShortUrlVisitsHeader.js rename to src/visits/ShortUrlVisitsHeader.tsx index 1d901cbc..9704bcba 100644 --- a/src/visits/ShortUrlVisitsHeader.js +++ b/src/visits/ShortUrlVisitsHeader.tsx @@ -1,24 +1,23 @@ import { UncontrolledTooltip } from 'reactstrap'; import Moment from 'react-moment'; import React from 'react'; -import PropTypes from 'prop-types'; import { ExternalLink } from 'react-external-link'; -import { shortUrlDetailType } from './reducers/shortUrlDetail'; -import { shortUrlVisitsType } from './reducers/shortUrlVisits'; +import { ShortUrlDetail } from './reducers/shortUrlDetail'; +import { ShortUrlVisits } from './reducers/shortUrlVisits'; import VisitsHeader from './VisitsHeader'; import './ShortUrlVisitsHeader.scss'; -const propTypes = { - shortUrlDetail: shortUrlDetailType.isRequired, - shortUrlVisits: shortUrlVisitsType.isRequired, - goBack: PropTypes.func.isRequired, -}; +interface ShortUrlVisitsHeaderProps { + shortUrlDetail: ShortUrlDetail; + shortUrlVisits: ShortUrlVisits; + goBack: () => void; +} -const ShortUrlVisitsHeader = ({ shortUrlDetail, shortUrlVisits, goBack }) => { +const ShortUrlVisitsHeader = ({ shortUrlDetail, shortUrlVisits, goBack }: ShortUrlVisitsHeaderProps) => { const { shortUrl, loading } = shortUrlDetail; const { visits } = shortUrlVisits; - const shortLink = shortUrl && shortUrl.shortUrl ? shortUrl.shortUrl : ''; - const longLink = shortUrl && shortUrl.longUrl ? shortUrl.longUrl : ''; + const shortLink = shortUrl?.shortUrl ?? ''; + const longLink = shortUrl?.longUrl ?? ''; const renderDate = () => !shortUrl ? Loading... : ( @@ -49,6 +48,4 @@ const ShortUrlVisitsHeader = ({ shortUrlDetail, shortUrlVisits, goBack }) => { ); }; -ShortUrlVisitsHeader.propTypes = propTypes; - export default ShortUrlVisitsHeader; diff --git a/src/visits/TagVisits.js b/src/visits/TagVisits.js deleted file mode 100644 index 299e6e0c..00000000 --- a/src/visits/TagVisits.js +++ /dev/null @@ -1,52 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { MercureInfoType } from '../mercure/reducers/mercureInfo'; -import { useMercureTopicBinding } from '../mercure/helpers'; -import { TagVisitsType } from './reducers/tagVisits'; -import TagVisitsHeader from './TagVisitsHeader'; - -const propTypes = { - history: PropTypes.shape({ - goBack: PropTypes.func, - }), - match: PropTypes.shape({ - params: PropTypes.object, - }), - getTagVisits: PropTypes.func, - tagVisits: TagVisitsType, - cancelGetTagVisits: PropTypes.func, - createNewVisit: PropTypes.func, - loadMercureInfo: PropTypes.func, - mercureInfo: MercureInfoType, -}; - -const TagVisits = (VisitsStats, colorGenerator) => { - const TagVisitsComp = ({ - history, - match, - getTagVisits, - tagVisits, - cancelGetTagVisits, - createNewVisit, - loadMercureInfo, - mercureInfo, - }) => { - const { params } = match; - const { tag } = params; - const loadVisits = (dates) => getTagVisits(tag, dates); - - useMercureTopicBinding(mercureInfo, 'https://shlink.io/new-visit', createNewVisit, loadMercureInfo); - - return ( - - - - ); - }; - - TagVisitsComp.propTypes = propTypes; - - return TagVisitsComp; -}; - -export default TagVisits; diff --git a/src/visits/TagVisits.tsx b/src/visits/TagVisits.tsx new file mode 100644 index 00000000..2efd5c98 --- /dev/null +++ b/src/visits/TagVisits.tsx @@ -0,0 +1,37 @@ +import React, { FC } from 'react'; +import { RouteComponentProps } from 'react-router'; +import { MercureBoundProps, useMercureTopicBinding } from '../mercure/helpers'; +import ColorGenerator from '../utils/services/ColorGenerator'; +import { TagVisits as TagVisitsState } from './reducers/tagVisits'; +import TagVisitsHeader from './TagVisitsHeader'; + +export interface TagVisitsProps extends RouteComponentProps<{ tag: string }>, MercureBoundProps { + getTagVisits: (tag: string, query: any) => void; + tagVisits: TagVisitsState; + cancelGetTagVisits: Function; +} + +const TagVisits = (VisitsStats: FC, colorGenerator: ColorGenerator) => ({ // TODO Use VisitsStatsProps once available + history: { goBack }, + match, + getTagVisits, + tagVisits, + cancelGetTagVisits, + createNewVisit, + loadMercureInfo, + mercureInfo, +}: TagVisitsProps) => { + const { params } = match; + const { tag } = params; + const loadVisits = (dates: any) => getTagVisits(tag, dates); + + useMercureTopicBinding(mercureInfo, 'https://shlink.io/new-visit', createNewVisit, loadMercureInfo); + + return ( + + + + ); +}; + +export default TagVisits; diff --git a/src/visits/TagVisitsHeader.js b/src/visits/TagVisitsHeader.tsx similarity index 56% rename from src/visits/TagVisitsHeader.js rename to src/visits/TagVisitsHeader.tsx index 48c8bf3c..b27acc2b 100644 --- a/src/visits/TagVisitsHeader.js +++ b/src/visits/TagVisitsHeader.tsx @@ -1,18 +1,17 @@ import React from 'react'; -import PropTypes from 'prop-types'; import Tag from '../tags/helpers/Tag'; -import { colorGeneratorType } from '../utils/services/ColorGenerator'; +import ColorGenerator from '../utils/services/ColorGenerator'; import VisitsHeader from './VisitsHeader'; -import { TagVisitsType } from './reducers/tagVisits'; +import { TagVisits } from './reducers/tagVisits'; import './ShortUrlVisitsHeader.scss'; -const propTypes = { - tagVisits: TagVisitsType.isRequired, - goBack: PropTypes.func.isRequired, - colorGenerator: colorGeneratorType, -}; +interface TagVisitsHeader { + tagVisits: TagVisits; + goBack: () => void; + colorGenerator: ColorGenerator; +} -const TagVisitsHeader = ({ tagVisits, goBack, colorGenerator }) => { +const TagVisitsHeader = ({ tagVisits, goBack, colorGenerator }: TagVisitsHeader) => { const { visits, tag } = tagVisits; const visitsStatsTitle = ( @@ -25,6 +24,4 @@ const TagVisitsHeader = ({ tagVisits, goBack, colorGenerator }) => { return ; }; -TagVisitsHeader.propTypes = propTypes; - export default TagVisitsHeader; diff --git a/src/visits/VisitsHeader.js b/src/visits/VisitsHeader.tsx similarity index 68% rename from src/visits/VisitsHeader.js rename to src/visits/VisitsHeader.tsx index fa59beee..51ef2e22 100644 --- a/src/visits/VisitsHeader.js +++ b/src/visits/VisitsHeader.tsx @@ -1,21 +1,19 @@ import { Button, Card } from 'reactstrap'; -import React from 'react'; -import PropTypes from 'prop-types'; +import React, { FC, ReactNode } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faArrowLeft } from '@fortawesome/free-solid-svg-icons'; import ShortUrlVisitsCount from '../short-urls/helpers/ShortUrlVisitsCount'; -import { shortUrlType } from '../short-urls/reducers/shortUrlsList'; -import { VisitType } from './types'; +import { ShortUrl } from '../short-urls/data'; +import { Visit } from './types'; -const propTypes = { - visits: PropTypes.arrayOf(VisitType).isRequired, - goBack: PropTypes.func.isRequired, - title: PropTypes.node.isRequired, - children: PropTypes.node, - shortUrl: shortUrlType, -}; +interface VisitsHeaderProps { + visits: Visit[]; + goBack: () => void; + title: ReactNode; + shortUrl?: ShortUrl; +} -const VisitsHeader = ({ visits, goBack, shortUrl, children, title }) => ( +const VisitsHeader: FC = ({ visits, goBack, shortUrl, children, title }) => (

@@ -39,6 +37,4 @@ const VisitsHeader = ({ visits, goBack, shortUrl, children, title }) => (

); -VisitsHeader.propTypes = propTypes; - export default VisitsHeader; diff --git a/src/visits/reducers/shortUrlDetail.ts b/src/visits/reducers/shortUrlDetail.ts index 177380df..07e27711 100644 --- a/src/visits/reducers/shortUrlDetail.ts +++ b/src/visits/reducers/shortUrlDetail.ts @@ -1,6 +1,4 @@ -import PropTypes from 'prop-types'; import { Action, Dispatch } from 'redux'; -import { shortUrlType } from '../../short-urls/reducers/shortUrlsList'; import { ShortUrl } from '../../short-urls/data'; import { buildReducer } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../utils/services/ShlinkApiClientBuilder'; @@ -13,13 +11,6 @@ export const GET_SHORT_URL_DETAIL_ERROR = 'shlink/shortUrlDetail/GET_SHORT_URL_D export const GET_SHORT_URL_DETAIL = 'shlink/shortUrlDetail/GET_SHORT_URL_DETAIL'; /* eslint-enable padding-line-between-statements */ -/** @deprecated Use ShortUrlDetail interface instead */ -export const shortUrlDetailType = PropTypes.shape({ - shortUrl: shortUrlType, - loading: PropTypes.bool, - error: PropTypes.bool, -}); - export interface ShortUrlDetail { shortUrl?: ShortUrl; loading: boolean; diff --git a/src/visits/reducers/shortUrlVisits.ts b/src/visits/reducers/shortUrlVisits.ts index 6a1e837b..5f56121e 100644 --- a/src/visits/reducers/shortUrlVisits.ts +++ b/src/visits/reducers/shortUrlVisits.ts @@ -1,7 +1,6 @@ -import PropTypes from 'prop-types'; import { Action, Dispatch } from 'redux'; import { shortUrlMatches } from '../../short-urls/helpers'; -import { Visit, VisitsInfo, VisitsLoadProgressChangedAction, VisitType } from '../types'; +import { Visit, VisitsInfo, VisitsLoadProgressChangedAction } from '../types'; import { ShortUrlIdentifier } from '../../short-urls/data'; import { buildActionCreator, buildReducer } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../utils/services/ShlinkApiClientBuilder'; @@ -19,17 +18,6 @@ export const GET_SHORT_URL_VISITS_CANCEL = 'shlink/shortUrlVisits/GET_SHORT_URL_ export const GET_SHORT_URL_VISITS_PROGRESS_CHANGED = 'shlink/shortUrlVisits/GET_SHORT_URL_VISITS_PROGRESS_CHANGED'; /* eslint-enable padding-line-between-statements */ -/** @deprecated Use ShortUrlVisits interface instead */ -export const shortUrlVisitsType = PropTypes.shape({ - visits: PropTypes.arrayOf(VisitType), - shortCode: PropTypes.string, - domain: PropTypes.string, - loading: PropTypes.bool, - loadingLarge: PropTypes.bool, - error: PropTypes.bool, - progress: PropTypes.number, -}); - export interface ShortUrlVisits extends VisitsInfo, ShortUrlIdentifier {} interface ShortUrlVisitsAction extends Action, ShortUrlIdentifier { diff --git a/src/visits/reducers/tagVisits.ts b/src/visits/reducers/tagVisits.ts index b0f5746d..76491994 100644 --- a/src/visits/reducers/tagVisits.ts +++ b/src/visits/reducers/tagVisits.ts @@ -1,6 +1,5 @@ -import PropTypes from 'prop-types'; import { Action, Dispatch } from 'redux'; -import { Visit, VisitsInfo, VisitsLoadProgressChangedAction, VisitType } from '../types'; +import { Visit, VisitsInfo, VisitsLoadProgressChangedAction } from '../types'; import { buildActionCreator, buildReducer } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../utils/services/ShlinkApiClientBuilder'; import { GetState } from '../../container/types'; @@ -16,16 +15,6 @@ export const GET_TAG_VISITS_CANCEL = 'shlink/tagVisits/GET_TAG_VISITS_CANCEL'; export const GET_TAG_VISITS_PROGRESS_CHANGED = 'shlink/tagVisits/GET_TAG_VISITS_PROGRESS_CHANGED'; /* eslint-enable padding-line-between-statements */ -/** @deprecated Use TagVisits interface instead */ -export const TagVisitsType = PropTypes.shape({ - visits: PropTypes.arrayOf(VisitType), - tag: PropTypes.string, - loading: PropTypes.bool, - loadingLarge: PropTypes.bool, - error: PropTypes.bool, - progress: PropTypes.number, -}); - export interface TagVisits extends VisitsInfo { tag: string; } diff --git a/test/visits/ShortUrlVisits.test.js b/test/visits/ShortUrlVisits.test.tsx similarity index 53% rename from test/visits/ShortUrlVisits.test.js rename to test/visits/ShortUrlVisits.test.tsx index 89310a55..de93ea28 100644 --- a/test/visits/ShortUrlVisits.test.js +++ b/test/visits/ShortUrlVisits.test.tsx @@ -1,19 +1,24 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow, ShallowWrapper } from 'enzyme'; import { identity } from 'ramda'; -import createShortUrlVisits from '../../src/visits/ShortUrlVisits'; +import { Mock } from 'ts-mockery'; +import { History, Location } from 'history'; +import { match } from 'react-router'; // eslint-disable-line @typescript-eslint/no-unused-vars +import createShortUrlVisits, { ShortUrlVisitsProps } from '../../src/visits/ShortUrlVisits'; import ShortUrlVisitsHeader from '../../src/visits/ShortUrlVisitsHeader'; +import { ShortUrlVisits as ShortUrlVisitsState } from '../../src/visits/reducers/shortUrlVisits'; +import { ShortUrlDetail } from '../../src/visits/reducers/shortUrlDetail'; describe('', () => { - let wrapper; + let wrapper: ShallowWrapper; const getShortUrlVisitsMock = jest.fn(); - const match = { + const match = Mock.of>({ params: { shortCode: 'abc123' }, - }; - const location = { search: '' }; - const history = { + }); + const location = Mock.of({ search: '' }); + const history = Mock.of({ goBack: jest.fn(), - }; + }); const VisitsStats = jest.fn(); beforeEach(() => { @@ -21,15 +26,15 @@ describe('', () => { wrapper = shallow( ()} getShortUrlDetail={identity} getShortUrlVisits={getShortUrlVisitsMock} match={match} location={location} history={history} - shortUrlVisits={{ loading: true, visits: [] }} - shortUrlDetail={{}} + shortUrlVisits={Mock.of({ loading: true, visits: [] })} + shortUrlDetail={Mock.all()} cancelGetShortUrlVisits={identity} - matchMedia={() => ({ matches: false })} />, ); });