diff --git a/src/short-urls/ShortUrlsList.js b/src/short-urls/ShortUrlsList.js
index 11822c3a..09746f36 100644
--- a/src/short-urls/ShortUrlsList.js
+++ b/src/short-urls/ShortUrlsList.js
@@ -18,6 +18,7 @@ export const SORTABLE_FIELDS = {
visits: 'Visits',
};
+// FIXME Replace with typescript: (ShortUrlsRow component)
const ShortUrlsList = (ShortUrlsRow) => class ShortUrlsList extends React.Component {
static propTypes = {
listShortUrls: PropTypes.func,
diff --git a/src/short-urls/helpers/ShortUrlsRow.js b/src/short-urls/helpers/ShortUrlsRow.js
index a22f9ba2..f117c67a 100644
--- a/src/short-urls/helpers/ShortUrlsRow.js
+++ b/src/short-urls/helpers/ShortUrlsRow.js
@@ -2,6 +2,9 @@ import { isEmpty } from 'ramda';
import React from 'react';
import Moment from 'react-moment';
import PropTypes from 'prop-types';
+import { UncontrolledTooltip } from 'reactstrap';
+import { faInfoCircle as infoIcon } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { shortUrlsListParamsType } from '../reducers/shortUrlsListParams';
import { serverType } from '../../servers/prop-types';
import ExternalLink from '../../utils/ExternalLink';
@@ -9,6 +12,32 @@ import { shortUrlType } from '../reducers/shortUrlsList';
import Tag from '../../tags/helpers/Tag';
import './ShortUrlsRow.scss';
+const renderVisitsCount = (shortUrl) => {
+ const { visitsCount, meta } = shortUrl;
+ const maxVisits = meta && meta.maxVisits;
+
+ if (!maxVisits) {
+ return {visitsCount};
+ }
+
+ return (
+
+
+ {visitsCount}
+
+ {' '}/ {maxVisits}{' '}
+
+
+
+
+
+
+ This short URL will not accept more than {maxVisits} visits.
+
+
+ );
+};
+
const ShortUrlsRow = (
ShortUrlsRowMenu,
colorGenerator,
@@ -56,7 +85,9 @@ const ShortUrlsRow = (
{this.renderTags(shortUrl.tags)} |
- {shortUrl.visitsCount} |
+
+ {renderVisitsCount(shortUrl)}
+ |
', () => {
tags: [ 'nodejs', 'reactjs' ],
visitsCount: 45,
};
-
- beforeEach(() => {
- const ShortUrlsRow = createShortUrlsRow(ShortUrlsRowMenu, colorGenerator, stateFlagTimeout);
-
+ const ShortUrlsRow = createShortUrlsRow(ShortUrlsRowMenu, colorGenerator, stateFlagTimeout);
+ const createWrapper = (meta) => {
wrapper = shallow(
-
+
);
- });
- afterEach(() => wrapper.unmount());
+
+ return wrapper;
+ };
+
+ afterEach(() => wrapper && wrapper.unmount());
it('renders date in first column', () => {
+ const wrapper = createWrapper();
const col = wrapper.find('td').first();
const moment = col.find(Moment);
@@ -45,6 +53,7 @@ describe('', () => {
});
it('renders short URL in second row', () => {
+ const wrapper = createWrapper();
const col = wrapper.find('td').at(1);
const link = col.find(ExternalLink);
@@ -52,6 +61,7 @@ describe('', () => {
});
it('renders long URL in third row', () => {
+ const wrapper = createWrapper();
const col = wrapper.find('td').at(2);
const link = col.find(ExternalLink);
@@ -60,6 +70,7 @@ describe('', () => {
describe('renders list of tags in fourth row', () => {
it('with tags', () => {
+ const wrapper = createWrapper();
const col = wrapper.find('td').at(3);
const tags = col.find(Tag);
@@ -72,6 +83,8 @@ describe('', () => {
});
it('without tags', () => {
+ const wrapper = createWrapper();
+
wrapper.setProps({ shortUrl: assoc('tags', [], shortUrl) });
const col = wrapper.find('td').at(3);
@@ -81,12 +94,26 @@ describe('', () => {
});
it('renders visits count in fifth row', () => {
+ const wrapper = createWrapper();
const col = wrapper.find('td').at(4);
+ const maxVisitsHelper = wrapper.find('.short-urls-row__max-visits-control');
expect(col.text()).toEqual(toString(shortUrl.visitsCount));
+ expect(maxVisitsHelper).toHaveLength(0);
+ });
+
+ it('renders visits count with helper control displaying the maximum amount of visits', () => {
+ const maxVisits = 40;
+ const wrapper = createWrapper({ maxVisits });
+ const maxVisitsHelper = wrapper.find('.short-urls-row__max-visits-control');
+ const maxVisitsTooltip = wrapper.find(UncontrolledTooltip);
+
+ expect(maxVisitsHelper).toHaveLength(1);
+ expect(maxVisitsTooltip).toHaveLength(1);
});
it('updates state when copied to clipboard', () => {
+ const wrapper = createWrapper();
const col = wrapper.find('td').at(5);
const menu = col.find(ShortUrlsRowMenu);
@@ -97,6 +124,7 @@ describe('', () => {
});
it('shows copy hint when state prop is true', () => {
+ const wrapper = createWrapper();
const isHidden = () => wrapper.find('td').at(5).find('.short-urls-row__copy-hint').prop('hidden');
expect(isHidden()).toEqual(true);
|