diff --git a/src/short-urls/helpers/DisabledLabel.tsx b/src/short-urls/helpers/DisabledLabel.tsx new file mode 100644 index 00000000..90f42597 --- /dev/null +++ b/src/short-urls/helpers/DisabledLabel.tsx @@ -0,0 +1,21 @@ +import { FC, useRef } from 'react'; +import { UncontrolledTooltip } from 'reactstrap'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faLinkSlash } from '@fortawesome/free-solid-svg-icons'; +import { mutableRefToElementRef } from '../../utils/helpers/components'; + +export const DisabledLabel: FC = () => { + const tooltipRef = useRef(); + + return ( + <> + + + Disabled + + tooltipRef.current) as any} placement="left"> + This short URL cannot be currently visited because of some of its limits. + + + ); +}; diff --git a/src/short-urls/helpers/ShortUrlVisitsCount.scss b/src/short-urls/helpers/ShortUrlVisitsCount.scss index 2910381a..7ae9b852 100644 --- a/src/short-urls/helpers/ShortUrlVisitsCount.scss +++ b/src/short-urls/helpers/ShortUrlVisitsCount.scss @@ -10,3 +10,7 @@ .short-url-visits-count__amount--big { transform: scale(1.5); } + +.short-url-visits-count__tooltip-list-item:not(:last-child) { + margin-bottom: .5rem; +} diff --git a/src/short-urls/helpers/ShortUrlVisitsCount.tsx b/src/short-urls/helpers/ShortUrlVisitsCount.tsx index 3b76bda4..dfa0acf3 100644 --- a/src/short-urls/helpers/ShortUrlVisitsCount.tsx +++ b/src/short-urls/helpers/ShortUrlVisitsCount.tsx @@ -7,8 +7,9 @@ import { prettify } from '../../utils/helpers/numbers'; import { ShortUrl } from '../data'; import { SelectedServer } from '../../servers/data'; import { ShortUrlDetailLink } from './ShortUrlDetailLink'; -import './ShortUrlVisitsCount.scss'; import { mutableRefToElementRef } from '../../utils/helpers/components'; +import { formatHumanFriendly, parseISO } from '../../utils/helpers/date'; +import './ShortUrlVisitsCount.scss'; interface ShortUrlVisitsCountProps { shortUrl?: ShortUrl | null; @@ -20,7 +21,8 @@ interface ShortUrlVisitsCountProps { export const ShortUrlVisitsCount = ( { visitsCount, shortUrl, selectedServer, active = false }: ShortUrlVisitsCountProps, ) => { - const maxVisits = shortUrl?.meta?.maxVisits; + const { maxVisits, validSince, validUntil } = shortUrl?.meta ?? {}; + const hasLimit = !!maxVisits || !!validSince || !!validUntil; const visitsLink = ( ); - if (!maxVisits) { + if (!hasLimit) { return visitsLink; } - const prettifiedMaxVisits = prettify(maxVisits); const tooltipRef = useRef(); return ( <> {visitsLink} - - {' '}/ {prettifiedMaxVisits}{' '} - + + {maxVisits && <> / {prettify(maxVisits)}} + tooltipRef.current) as any} placement="bottom"> - This short URL will not accept more than {prettifiedMaxVisits} visits. +
    + {maxVisits && ( +
  • + This short URL will not accept more than {prettify(maxVisits)} visit{maxVisits === 1 ? '' : 's'}. +
  • + )} + {validSince && ( +
  • + This short URL will not accept visits + before {formatHumanFriendly(parseISO(validSince))}. +
  • + )} + {validUntil && ( +
  • + This short URL will not accept visits + after {formatHumanFriendly(parseISO(validUntil))}. +
  • + )} +
); diff --git a/src/short-urls/helpers/ShortUrlsRow.scss b/src/short-urls/helpers/ShortUrlsRow.scss index 4666be1a..64af7818 100644 --- a/src/short-urls/helpers/ShortUrlsRow.scss +++ b/src/short-urls/helpers/ShortUrlsRow.scss @@ -10,10 +10,6 @@ word-break: break-all; } -.short-urls-row__cell--relative { - position: relative; -} - .short-urls-row__cell--indivisible { @media (min-width: $lgMin) { white-space: nowrap; diff --git a/src/short-urls/helpers/ShortUrlsRow.tsx b/src/short-urls/helpers/ShortUrlsRow.tsx index 159c2b24..10f3e1a4 100644 --- a/src/short-urls/helpers/ShortUrlsRow.tsx +++ b/src/short-urls/helpers/ShortUrlsRow.tsx @@ -1,15 +1,16 @@ -import { FC, useEffect, useRef } from 'react'; -import { isEmpty } from 'ramda'; +import { useEffect, useRef } from 'react'; import { ExternalLink } from 'react-external-link'; import { ColorGenerator } from '../../utils/services/ColorGenerator'; import { TimeoutToggle } from '../../utils/helpers/hooks'; -import { Tag } from '../../tags/helpers/Tag'; import { SelectedServer } from '../../servers/data'; import { CopyToClipboardIcon } from '../../utils/CopyToClipboardIcon'; import { ShortUrl } from '../data'; import { Time } from '../../utils/dates/Time'; import { ShortUrlVisitsCount } from './ShortUrlVisitsCount'; -import { ShortUrlsRowMenuProps } from './ShortUrlsRowMenu'; +import { ShortUrlsRowMenuType } from './ShortUrlsRowMenu'; +import { Tags } from './Tags'; +import { shortUrlIsDisabled } from './index'; +import { DisabledLabel } from './DisabledLabel'; import './ShortUrlsRow.scss'; interface ShortUrlsRowProps { @@ -19,28 +20,14 @@ interface ShortUrlsRowProps { } export const ShortUrlsRow = ( - ShortUrlsRowMenu: FC, + ShortUrlsRowMenu: ShortUrlsRowMenuType, colorGenerator: ColorGenerator, useTimeoutToggle: TimeoutToggle, ) => ({ shortUrl, selectedServer, onTagClick }: ShortUrlsRowProps) => { const [copiedToClipboard, setCopiedToClipboard] = useTimeoutToggle(); const [active, setActive] = useTimeoutToggle(false, 500); const isFirstRun = useRef(true); - - const renderTags = (tags: string[]) => { - if (isEmpty(tags)) { - return No tags; - } - - return tags.map((tag) => ( - onTagClick?.(tag)} - /> - )); - }; + const isDisabled = shortUrlIsDisabled(shortUrl); useEffect(() => { !isFirstRun.current && setActive(); @@ -53,7 +40,7 @@ export const ShortUrlsRow = (