From f2e7a2161d35d7beabb39040c43dcd5f23e5e7b9 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 4 Sep 2020 19:05:41 +0200 Subject: [PATCH] Removed duplicated code on mercure-bound components --- src/common/MainHeader.tsx | 4 +- src/common/ScrollToTop.tsx | 4 +- src/mercure/helpers/index.ts | 6 ++ src/servers/helpers/withSelectedServer.tsx | 8 +-- src/short-urls/ShortUrlsList.tsx | 12 ++-- src/tags/TagsList.tsx | 8 +-- src/visits/ShortUrlVisits.js | 68 ---------------------- src/visits/ShortUrlVisits.tsx | 49 ++++++++++++++++ test/common/ScrollToTop.test.tsx | 4 +- 9 files changed, 71 insertions(+), 92 deletions(-) delete mode 100644 src/visits/ShortUrlVisits.js create mode 100644 src/visits/ShortUrlVisits.tsx diff --git a/src/common/MainHeader.tsx b/src/common/MainHeader.tsx index e4a8c163..627aaa58 100644 --- a/src/common/MainHeader.tsx +++ b/src/common/MainHeader.tsx @@ -4,12 +4,12 @@ import React, { FC, useEffect } from 'react'; import { Link } from 'react-router-dom'; import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } from 'reactstrap'; import classNames from 'classnames'; -import { RouteChildrenProps } from 'react-router'; +import { RouteComponentProps } from 'react-router'; import { useToggle } from '../utils/helpers/hooks'; import shlinkLogo from './shlink-logo-white.png'; import './MainHeader.scss'; -const MainHeader = (ServersDropdown: FC) => ({ location }: RouteChildrenProps) => { +const MainHeader = (ServersDropdown: FC) => ({ location }: RouteComponentProps) => { const [ isOpen, toggleOpen, , close ] = useToggle(); const { pathname } = location; diff --git a/src/common/ScrollToTop.tsx b/src/common/ScrollToTop.tsx index 48bf2a04..f24a8b80 100644 --- a/src/common/ScrollToTop.tsx +++ b/src/common/ScrollToTop.tsx @@ -1,7 +1,7 @@ import React, { PropsWithChildren, useEffect } from 'react'; -import { RouteChildrenProps } from 'react-router'; +import { RouteComponentProps } from 'react-router'; -const ScrollToTop = () => ({ location, children }: PropsWithChildren) => { +const ScrollToTop = () => ({ location, children }: PropsWithChildren) => { useEffect(() => { scrollTo(0, 0); }, [ location ]); diff --git a/src/mercure/helpers/index.ts b/src/mercure/helpers/index.ts index 8f6eec78..4fa89f24 100644 --- a/src/mercure/helpers/index.ts +++ b/src/mercure/helpers/index.ts @@ -32,3 +32,9 @@ export const useMercureTopicBinding = ( ) => { useEffect(bindToMercureTopic(mercureInfo, topic, onMessage, onTokenExpired), [ mercureInfo ]); }; + +export interface MercureBoundProps { + createNewVisit: (message: any) => void; + loadMercureInfo: Function; + mercureInfo: MercureInfo; +} diff --git a/src/servers/helpers/withSelectedServer.tsx b/src/servers/helpers/withSelectedServer.tsx index 41f8a45c..0f602f6e 100644 --- a/src/servers/helpers/withSelectedServer.tsx +++ b/src/servers/helpers/withSelectedServer.tsx @@ -1,9 +1,9 @@ import React, { FC, useEffect } from 'react'; -import { RouteChildrenProps } from 'react-router'; +import { RouteComponentProps } from 'react-router'; import Message from '../../utils/Message'; import { isNotFoundServer, SelectedServer } from '../data'; -interface WithSelectedServerProps extends RouteChildrenProps<{ serverId: string }> { +interface WithSelectedServerProps extends RouteComponentProps<{ serverId: string }> { selectServer: (serverId: string) => void; selectedServer: SelectedServer; } @@ -13,8 +13,8 @@ export function withSelectedServer(WrappedComponent: FC { - match?.params?.serverId && selectServer(match?.params.serverId); - }, [ match?.params.serverId ]); + selectServer(match.params.serverId); + }, [ match.params.serverId ]); if (!selectedServer) { return ; diff --git a/src/short-urls/ShortUrlsList.tsx b/src/short-urls/ShortUrlsList.tsx index c045c892..ccab7bca 100644 --- a/src/short-urls/ShortUrlsList.tsx +++ b/src/short-urls/ShortUrlsList.tsx @@ -3,11 +3,10 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { head, isEmpty, keys, values } from 'ramda'; import React, { useState, useEffect, FC } from 'react'; import qs from 'qs'; -import { RouteChildrenProps } from 'react-router'; +import { RouteComponentProps } from 'react-router'; import SortingDropdown from '../utils/SortingDropdown'; import { determineOrderDir, OrderDir } from '../utils/utils'; -import { MercureInfo } from '../mercure/reducers/mercureInfo'; -import { useMercureTopicBinding } from '../mercure/helpers'; +import { MercureBoundProps, useMercureTopicBinding } from '../mercure/helpers'; import { SelectedServer } from '../servers/data'; import { ShortUrlsList as ShortUrlsListState } from './reducers/shortUrlsList'; import { ShortUrlsRowProps } from './helpers/ShortUrlsRow'; @@ -32,14 +31,11 @@ export interface WithList { shortUrlsList: ShortUrl[]; } -export interface ShortUrlsListProps extends ShortUrlsListState, RouteChildrenProps { +export interface ShortUrlsListProps extends ShortUrlsListState, RouteComponentProps, MercureBoundProps { selectedServer: SelectedServer; listShortUrls: (params: ShortUrlsListParams) => void; shortUrlsListParams: ShortUrlsListParams; resetShortUrlParams: () => void; - createNewVisit: (message: any) => void; - loadMercureInfo: Function; - mercureInfo: MercureInfo; } const ShortUrlsList = (ShortUrlsRow: FC) => ({ @@ -116,7 +112,7 @@ const ShortUrlsList = (ShortUrlsRow: FC) => ({ const query = qs.parse(location.search, { ignoreQueryPrefix: true }); const tags = query.tag ? [ query.tag as string ] : shortUrlsListParams.tags; - refreshList({ page: match?.params.page, tags }); + refreshList({ page: match.params.page, tags }); return resetShortUrlParams; }, []); diff --git a/src/tags/TagsList.tsx b/src/tags/TagsList.tsx index 0da20b1b..e73ee4da 100644 --- a/src/tags/TagsList.tsx +++ b/src/tags/TagsList.tsx @@ -2,8 +2,7 @@ import React, { FC, useEffect, useState } from 'react'; import { splitEvery } from 'ramda'; import Message from '../utils/Message'; import SearchField from '../utils/SearchField'; -import { MercureInfo } from '../mercure/reducers/mercureInfo'; -import { useMercureTopicBinding } from '../mercure/helpers'; +import { MercureBoundProps, useMercureTopicBinding } from '../mercure/helpers'; import { SelectedServer } from '../servers/data'; import { TagsList as TagsListState } from './reducers/tagsList'; import { TagCardProps } from './TagCard'; @@ -11,14 +10,11 @@ import { TagCardProps } from './TagCard'; const { ceil } = Math; const TAGS_GROUPS_AMOUNT = 4; -export interface TagsListProps { +export interface TagsListProps extends MercureBoundProps { filterTags: (searchTerm: string) => void; forceListTags: Function; tagsList: TagsListState; selectedServer: SelectedServer; - createNewVisit: () => void; - loadMercureInfo: Function; - mercureInfo: MercureInfo; } const TagsList = (TagCard: FC) => ( diff --git a/src/visits/ShortUrlVisits.js b/src/visits/ShortUrlVisits.js deleted file mode 100644 index 20e7aeea..00000000 --- a/src/visits/ShortUrlVisits.js +++ /dev/null @@ -1,68 +0,0 @@ -import React, { useEffect } from 'react'; -import PropTypes from 'prop-types'; -import qs from 'qs'; -import { MercureInfoType } from '../mercure/reducers/mercureInfo'; -import { useMercureTopicBinding } from '../mercure/helpers'; -import { shortUrlVisitsType } from './reducers/shortUrlVisits'; -import ShortUrlVisitsHeader from './ShortUrlVisitsHeader'; -import { shortUrlDetailType } from './reducers/shortUrlDetail'; - -const propTypes = { - history: PropTypes.shape({ - goBack: PropTypes.func, - }), - match: PropTypes.shape({ - params: PropTypes.object, - }), - location: PropTypes.shape({ - search: PropTypes.string, - }), - getShortUrlVisits: PropTypes.func, - shortUrlVisits: shortUrlVisitsType, - getShortUrlDetail: PropTypes.func, - shortUrlDetail: shortUrlDetailType, - cancelGetShortUrlVisits: PropTypes.func, - createNewVisit: PropTypes.func, - loadMercureInfo: PropTypes.func, - mercureInfo: MercureInfoType, -}; - -const ShortUrlVisits = (VisitsStats) => { - const ShortUrlVisitsComp = ({ - history, - match, - location, - shortUrlVisits, - shortUrlDetail, - getShortUrlVisits, - getShortUrlDetail, - cancelGetShortUrlVisits, - createNewVisit, - loadMercureInfo, - mercureInfo, - }) => { - const { params } = match; - const { shortCode } = params; - const { search } = location; - const { domain } = qs.parse(search, { ignoreQueryPrefix: true }); - - const loadVisits = (dates) => getShortUrlVisits(shortCode, { ...dates, domain }); - - useEffect(() => { - getShortUrlDetail(shortCode, domain); - }, []); - useMercureTopicBinding(mercureInfo, `https://shlink.io/new-visit/${shortCode}`, createNewVisit, loadMercureInfo); - - return ( - - - - ); - }; - - ShortUrlVisitsComp.propTypes = propTypes; - - return ShortUrlVisitsComp; -}; - -export default ShortUrlVisits; diff --git a/src/visits/ShortUrlVisits.tsx b/src/visits/ShortUrlVisits.tsx new file mode 100644 index 00000000..805f5524 --- /dev/null +++ b/src/visits/ShortUrlVisits.tsx @@ -0,0 +1,49 @@ +import React, { FC, useEffect } from 'react'; +import qs from 'qs'; +import { RouteComponentProps } from 'react-router'; +import { MercureBoundProps, useMercureTopicBinding } from '../mercure/helpers'; +import { ShlinkVisitsParams } from '../utils/services/types'; +import { ShortUrlVisits as ShortUrlVisitsState } from './reducers/shortUrlVisits'; +import ShortUrlVisitsHeader from './ShortUrlVisitsHeader'; +import { ShortUrlDetail } from './reducers/shortUrlDetail'; + +interface ShortUrlVisitsProps extends RouteComponentProps<{ shortCode: string }>, MercureBoundProps { + getShortUrlVisits: (shortCode: string, query?: ShlinkVisitsParams) => void; + shortUrlVisits: ShortUrlVisitsState; + getShortUrlDetail: Function; + shortUrlDetail: ShortUrlDetail; + cancelGetShortUrlVisits: Function; +} + +const ShortUrlVisits = (VisitsStats: FC) => ({ // TODO Use VisitsStatsProps once available + history: { goBack }, + match, + location: { search }, + shortUrlVisits, + shortUrlDetail, + getShortUrlVisits, + getShortUrlDetail, + cancelGetShortUrlVisits, + createNewVisit, + loadMercureInfo, + mercureInfo, +}: ShortUrlVisitsProps) => { + const { params } = match; + const { shortCode } = params; + const { domain } = qs.parse(search, { ignoreQueryPrefix: true }) as { domain?: string }; + + const loadVisits = (dates: Partial) => getShortUrlVisits(shortCode, { ...dates, domain }); + + useEffect(() => { + getShortUrlDetail(shortCode, domain); + }, []); + useMercureTopicBinding(mercureInfo, `https://shlink.io/new-visit/${shortCode}`, createNewVisit, loadMercureInfo); + + return ( + + + + ); +}; + +export default ShortUrlVisits; diff --git a/test/common/ScrollToTop.test.tsx b/test/common/ScrollToTop.test.tsx index ff925292..59918f1a 100644 --- a/test/common/ScrollToTop.test.tsx +++ b/test/common/ScrollToTop.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { shallow, ShallowWrapper } from 'enzyme'; import { Mock } from 'ts-mockery'; -import { RouteChildrenProps } from 'react-router'; +import { RouteComponentProps } from 'react-router'; import createScrollToTop from '../../src/common/ScrollToTop'; describe('', () => { @@ -10,7 +10,7 @@ describe('', () => { beforeEach(() => { const ScrollToTop = createScrollToTop(); - wrapper = shallow(()}>Foobar); + wrapper = shallow(()}>Foobar); }); afterEach(() => wrapper.unmount());