diff --git a/src/common/MenuLayout.tsx b/src/common/MenuLayout.tsx index b8205b2f..15c372d5 100644 --- a/src/common/MenuLayout.tsx +++ b/src/common/MenuLayout.tsx @@ -5,7 +5,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import classNames from 'classnames'; import { withSelectedServer } from '../servers/helpers/withSelectedServer'; import { useSwipeable, useToggle } from '../utils/helpers/hooks'; -import { supportsDomainRedirects, supportsOrphanVisits } from '../utils/helpers/features'; +import { supportsDomainRedirects, supportsNonOrphanVisits, supportsOrphanVisits } from '../utils/helpers/features'; import { isReachableServer } from '../servers/data'; import NotFound from './NotFound'; import { AsideMenuProps } from './AsideMenu'; @@ -33,6 +33,7 @@ const MenuLayout = ( } const addOrphanVisitsRoute = supportsOrphanVisits(selectedServer); + const addNonOrphanVisitsRoute = supportsNonOrphanVisits(selectedServer); const addManageDomainsRoute = supportsDomainRedirects(selectedServer); const burgerClasses = classNames('menu-layout__burger-icon', { 'menu-layout__burger-icon--active': sidebarVisible }); const swipeableProps = useSwipeable(showSidebar, hideSidebar); @@ -55,6 +56,7 @@ const MenuLayout = ( {addOrphanVisitsRoute && } + {addNonOrphanVisitsRoute && 'Non orphan'} />} {addManageDomainsRoute && } { @@ -52,40 +55,36 @@ export const Overview = ( return ( <> -
- - Visits - {loadingVisits ? 'Loading...' : prettify(visitsCount)} - +
+ + {loadingVisits ? 'Loading...' : prettify(visitsCount)} +
-
- - Orphan visits - - - {loadingVisits ? 'Loading...' : prettify(orphanVisitsCount ?? 0)} - - - Shlink 2.6 is needed - - - +
+ + + {loadingVisits ? 'Loading...' : prettify(orphanVisitsCount ?? 0)} + + + Shlink 2.6 is needed + +
-
- - Short URLs - - {loading ? 'Loading...' : prettify(shortUrls?.pagination.totalItems ?? 0)} - - +
+ + {loading ? 'Loading...' : prettify(shortUrls?.pagination.totalItems ?? 0)} +
-
- - Tags - {loadingTags ? 'Loading...' : prettify(tagsList.tags.length)} - +
+ + {loadingTags ? 'Loading...' : prettify(tagsList.tags.length)} +
+ Create a short URL diff --git a/src/servers/Overview.scss b/src/servers/helpers/HighlightCard.scss similarity index 66% rename from src/servers/Overview.scss rename to src/servers/helpers/HighlightCard.scss index 9f939a2f..ddb11b6b 100644 --- a/src/servers/Overview.scss +++ b/src/servers/helpers/HighlightCard.scss @@ -1,13 +1,13 @@ -@import '../utils/base'; +@import '../../utils/base'; -.overview__card.overview__card { +.highlight-card.highlight-card { text-align: center; border-top: 3px solid var(--brand-color); color: inherit; text-decoration: none; } -.overview__card-title { +.highlight-card__title { text-transform: uppercase; color: $textPlaceholder; } diff --git a/src/servers/helpers/HighlightCard.tsx b/src/servers/helpers/HighlightCard.tsx new file mode 100644 index 00000000..85988a7f --- /dev/null +++ b/src/servers/helpers/HighlightCard.tsx @@ -0,0 +1,16 @@ +import { FC } from 'react'; +import { Card, CardText, CardTitle } from 'reactstrap'; +import { Link } from 'react-router-dom'; +import './HighlightCard.scss'; + +export interface HighlightCardProps { + title: string; + link?: string; +} + +export const HighlightCard: FC = ({ children, title, link }) => ( + + {title} + {children} + +); diff --git a/src/utils/helpers/features.ts b/src/utils/helpers/features.ts index 8706a0eb..151fa409 100644 --- a/src/utils/helpers/features.ts +++ b/src/utils/helpers/features.ts @@ -25,3 +25,5 @@ export const supportsDomainRedirects = supportsQrErrorCorrection; export const supportsForwardQuery = serverMatchesVersions({ minVersion: '2.9.0' }); export const supportsDefaultDomainRedirectsEdition = serverMatchesVersions({ minVersion: '2.10.0' }); + +export const supportsNonOrphanVisits = serverMatchesVersions({ minVersion: '3.0.0' }); diff --git a/test/servers/helpers/HighlightCard.test.tsx b/test/servers/helpers/HighlightCard.test.tsx new file mode 100644 index 00000000..b166c1de --- /dev/null +++ b/test/servers/helpers/HighlightCard.test.tsx @@ -0,0 +1,59 @@ +import { shallow, ShallowWrapper } from 'enzyme'; +import { ReactNode } from 'react'; +import { Card, CardText, CardTitle } from 'reactstrap'; +import { Link } from 'react-router-dom'; +import { HighlightCard, HighlightCardProps } from '../../../src/servers/helpers/HighlightCard'; + +describe('', () => { + let wrapper: ShallowWrapper; + const createWrapper = (props: HighlightCardProps & { children?: ReactNode }) => { + wrapper = shallow(); + + return wrapper; + }; + + afterEach(() => wrapper?.unmount()); + + it('renders expected components', () => { + const wrapper = createWrapper({ title: 'foo' }); + + expect(wrapper.find(Card)).toHaveLength(1); + expect(wrapper.find(CardTitle)).toHaveLength(1); + expect(wrapper.find(CardText)).toHaveLength(1); + expect(wrapper.prop('tag')).not.toEqual(Link); + expect(wrapper.prop('to')).not.toBeDefined(); + }); + + it.each([ + [ 'foo' ], + [ 'bar' ], + [ 'baz' ], + ])('renders provided title', (title) => { + const wrapper = createWrapper({ title }); + const cardTitle = wrapper.find(CardTitle); + + expect(cardTitle.html()).toContain(`>${title}<`); + }); + + it.each([ + [ 'foo' ], + [ 'bar' ], + [ 'baz' ], + ])('renders provided children', (children) => { + const wrapper = createWrapper({ title: 'foo', children }); + const cardText = wrapper.find(CardText); + + expect(cardText.html()).toContain(`>${children}<`); + }); + + it.each([ + [ 'foo' ], + [ 'bar' ], + [ 'baz' ], + ])('adds extra props when a link is provided', (link) => { + const wrapper = createWrapper({ title: 'foo', link }); + + expect(wrapper.prop('tag')).toEqual(Link); + expect(wrapper.prop('to')).toEqual(link); + }); +});