Remove feature flags for features introduced on Shlink <3.0

This commit is contained in:
Alejandro Celaya 2023-07-24 18:10:22 +02:00
parent 21525ef945
commit 768fb1992f
8 changed files with 25 additions and 55 deletions

View file

@ -28,7 +28,6 @@ export const Main = (
const [sidebarVisible, toggleSidebar, showSidebar, hideSidebar] = useToggle(); const [sidebarVisible, toggleSidebar, showSidebar, hideSidebar] = useToggle();
useEffect(() => hideSidebar(), [location]); useEffect(() => hideSidebar(), [location]);
const addNonOrphanVisitsRoute = useFeature('nonOrphanVisits');
const addDomainVisitsRoute = useFeature('domainVisits'); const addDomainVisitsRoute = useFeature('domainVisits');
const burgerClasses = classNames('menu-layout__burger-icon', { 'menu-layout__burger-icon--active': sidebarVisible }); const burgerClasses = classNames('menu-layout__burger-icon', { 'menu-layout__burger-icon--active': sidebarVisible });
const swipeableProps = useSwipeable(showSidebar, hideSidebar); const swipeableProps = useSwipeable(showSidebar, hideSidebar);
@ -54,7 +53,7 @@ export const Main = (
<Route path="/tag/:tag/visits/*" element={<TagVisits />} /> <Route path="/tag/:tag/visits/*" element={<TagVisits />} />
{addDomainVisitsRoute && <Route path="/domain/:domain/visits/*" element={<DomainVisits />} />} {addDomainVisitsRoute && <Route path="/domain/:domain/visits/*" element={<DomainVisits />} />}
<Route path="/orphan-visits/*" element={<OrphanVisits />} /> <Route path="/orphan-visits/*" element={<OrphanVisits />} />
{addNonOrphanVisitsRoute && <Route path="/non-orphan-visits/*" element={<NonOrphanVisits />} />} <Route path="/non-orphan-visits/*" element={<NonOrphanVisits />} />
<Route path="/manage-tags" element={<TagsList />} /> <Route path="/manage-tags" element={<TagsList />} />
<Route path="/manage-domains" element={<ManageDomains />} /> <Route path="/manage-domains" element={<ManageDomains />} />
<Route <Route

View file

@ -20,7 +20,7 @@ interface DomainDropdownProps {
export const DomainDropdown: FC<DomainDropdownProps> = ({ domain, editDomainRedirects }) => { export const DomainDropdown: FC<DomainDropdownProps> = ({ domain, editDomainRedirects }) => {
const [isModalOpen, toggleModal] = useToggle(); const [isModalOpen, toggleModal] = useToggle();
const { isDefault } = domain; const { isDefault } = domain;
const canBeEdited = !isDefault || useFeature('defaultDomainRedirectsEdition'); const canBeEdited = !isDefault;
const withVisits = useFeature('domainVisits'); const withVisits = useFeature('domainVisits');
const routesPrefix = useRoutesPrefix(); const routesPrefix = useRoutesPrefix();

View file

@ -11,7 +11,6 @@ import type { ShortUrlsList as ShortUrlsListState } from '../short-urls/reducers
import { ITEMS_IN_OVERVIEW_PAGE } from '../short-urls/reducers/shortUrlsList'; import { ITEMS_IN_OVERVIEW_PAGE } from '../short-urls/reducers/shortUrlsList';
import type { ShortUrlsTableType } from '../short-urls/ShortUrlsTable'; import type { ShortUrlsTableType } from '../short-urls/ShortUrlsTable';
import type { TagsList } from '../tags/reducers/tagsList'; import type { TagsList } from '../tags/reducers/tagsList';
import { useFeature } from '../utils/features';
import { useRoutesPrefix } from '../utils/routesPrefix'; import { useRoutesPrefix } from '../utils/routesPrefix';
import { useSetting } from '../utils/settings'; import { useSetting } from '../utils/settings';
import type { VisitsOverview } from '../visits/reducers/visitsOverview'; import type { VisitsOverview } from '../visits/reducers/visitsOverview';
@ -42,7 +41,6 @@ export const Overview = (
const { loading: loadingTags } = tagsList; const { loading: loadingTags } = tagsList;
const { loading: loadingVisits, nonOrphanVisits, orphanVisits } = visitsOverview; const { loading: loadingVisits, nonOrphanVisits, orphanVisits } = visitsOverview;
const routesPrefix = useRoutesPrefix(); const routesPrefix = useRoutesPrefix();
const linkToNonOrphanVisits = useFeature('nonOrphanVisits');
const navigate = useNavigate(); const navigate = useNavigate();
const visits = useSetting('visits'); const visits = useSetting('visits');
@ -58,7 +56,7 @@ export const Overview = (
<div className="col-lg-6 col-xl-3 mb-3"> <div className="col-lg-6 col-xl-3 mb-3">
<VisitsHighlightCard <VisitsHighlightCard
title="Visits" title="Visits"
link={linkToNonOrphanVisits ? `${routesPrefix}/non-orphan-visits` : undefined} link={`${routesPrefix}/non-orphan-visits`}
excludeBots={visits?.excludeBots ?? false} excludeBots={visits?.excludeBots ?? false}
loading={loadingVisits} loading={loadingVisits}
visitsSummary={nonOrphanVisits} visitsSummary={nonOrphanVisits}

View file

@ -8,11 +8,11 @@ import './HighlightCard.scss';
export type HighlightCardProps = PropsWithChildren<{ export type HighlightCardProps = PropsWithChildren<{
title: string; title: string;
link?: string; link: string;
tooltip?: ReactNode; tooltip?: ReactNode;
}>; }>;
const buildExtraProps = (link?: string) => (!link ? {} : { tag: Link, to: link }); const buildExtraProps = (link: string) => ({ tag: Link, to: link });
export const HighlightCard: FC<HighlightCardProps> = ({ children, title, link, tooltip }) => { export const HighlightCard: FC<HighlightCardProps> = ({ children, title, link, tooltip }) => {
const ref = useElementRef<HTMLElement>(); const ref = useElementRef<HTMLElement>();
@ -20,7 +20,7 @@ export const HighlightCard: FC<HighlightCardProps> = ({ children, title, link, t
return ( return (
<> <>
<Card innerRef={ref} className="highlight-card" body {...buildExtraProps(link)}> <Card innerRef={ref} className="highlight-card" body {...buildExtraProps(link)}>
{link && <FontAwesomeIcon size="3x" className="highlight-card__link-icon" icon={linkIcon} />} <FontAwesomeIcon size="3x" className="highlight-card__link-icon" icon={linkIcon} />
<CardTitle tag="h5" className="highlight-card__title">{title}</CardTitle> <CardTitle tag="h5" className="highlight-card__title">{title}</CardTitle>
<CardText tag="h2">{children}</CardText> <CardText tag="h2">{children}</CardText>
</Card> </Card>

View file

@ -134,8 +134,6 @@ export const ShortUrlForm = (
</> </>
); );
const showForwardQueryControl = useFeature('forwardQuery');
return ( return (
<form name="shortUrlForm" className="short-url-form" onSubmit={submit}> <form name="shortUrlForm" className="short-url-form" onSubmit={submit}>
{isBasicMode && basicComponents} {isBasicMode && basicComponents}
@ -242,15 +240,13 @@ export const ShortUrlForm = (
> >
Make it crawlable Make it crawlable
</ShortUrlFormCheckboxGroup> </ShortUrlFormCheckboxGroup>
{showForwardQueryControl && ( <ShortUrlFormCheckboxGroup
<ShortUrlFormCheckboxGroup infoTooltip="When this short URL is visited, any query params appended to it will be forwarded to the long URL."
infoTooltip="When this short URL is visited, any query params appended to it will be forwarded to the long URL." checked={shortUrlData.forwardQuery}
checked={shortUrlData.forwardQuery} onChange={(forwardQuery) => setShortUrlData({ ...shortUrlData, forwardQuery })}
onChange={(forwardQuery) => setShortUrlData({ ...shortUrlData, forwardQuery })} >
> Forward query params on redirect
Forward query params on redirect </ShortUrlFormCheckboxGroup>
</ShortUrlFormCheckboxGroup>
)}
</SimpleCard> </SimpleCard>
</div> </div>
</Row> </Row>

View file

@ -58,7 +58,6 @@ export const ShortUrlsFilteringBar = (
(searchTerm) => toFirstPage({ search: searchTerm }), (searchTerm) => toFirstPage({ search: searchTerm }),
); );
const changeTagSelection = (selectedTags: string[]) => toFirstPage({ tags: selectedTags }); const changeTagSelection = (selectedTags: string[]) => toFirstPage({ tags: selectedTags });
const canChangeTagsMode = useFeature('allTagsFiltering');
const toggleTagsMode = pipe( const toggleTagsMode = pipe(
() => (tagsMode === 'any' ? 'all' : 'any'), () => (tagsMode === 'any' ? 'all' : 'any'),
(mode) => toFirstPage({ tagsMode: mode }), (mode) => toFirstPage({ tagsMode: mode }),
@ -70,7 +69,7 @@ export const ShortUrlsFilteringBar = (
<InputGroup className="mt-3"> <InputGroup className="mt-3">
<TagsSelector allowNew={false} placeholder="With tags..." selectedTags={tags} onChange={changeTagSelection} /> <TagsSelector allowNew={false} placeholder="With tags..." selectedTags={tags} onChange={changeTagSelection} />
{canChangeTagsMode && tags.length > 1 && ( {tags.length > 1 && (
<> <>
<Button outline color="secondary" onClick={toggleTagsMode} id="tagsModeBtn" aria-label="Change tags mode"> <Button outline color="secondary" onClick={toggleTagsMode} id="tagsModeBtn" aria-label="Change tags mode">
<FontAwesomeIcon className="short-urls-filtering-bar__tags-icon" icon={tagsMode === 'all' ? faTags : faTag} /> <FontAwesomeIcon className="short-urls-filtering-bar__tags-icon" icon={tagsMode === 'all' ? faTags : faTag} />

View file

@ -7,7 +7,6 @@ import type { ImageDownloader } from '../../../common/services/ImageDownloader';
import { CopyToClipboardIcon } from '../../../utils/CopyToClipboardIcon'; import { CopyToClipboardIcon } from '../../../utils/CopyToClipboardIcon';
import type { QrCodeFormat, QrErrorCorrection } from '../../../utils/helpers/qrCodes'; import type { QrCodeFormat, QrErrorCorrection } from '../../../utils/helpers/qrCodes';
import { buildQrCodeUrl } from '../../../utils/helpers/qrCodes'; import { buildQrCodeUrl } from '../../../utils/helpers/qrCodes';
import { useFeature } from '../../utils/features';
import type { ShortUrlModalProps } from '../data'; import type { ShortUrlModalProps } from '../data';
import { QrErrorCorrectionDropdown } from './qr-codes/QrErrorCorrectionDropdown'; import { QrErrorCorrectionDropdown } from './qr-codes/QrErrorCorrectionDropdown';
import { QrFormatDropdown } from './qr-codes/QrFormatDropdown'; import { QrFormatDropdown } from './qr-codes/QrFormatDropdown';
@ -20,7 +19,6 @@ export const QrCodeModal = (imageDownloader: ImageDownloader) => (
const [margin, setMargin] = useState(0); const [margin, setMargin] = useState(0);
const [format, setFormat] = useState<QrCodeFormat>('png'); const [format, setFormat] = useState<QrCodeFormat>('png');
const [errorCorrection, setErrorCorrection] = useState<QrErrorCorrection>('L'); const [errorCorrection, setErrorCorrection] = useState<QrErrorCorrection>('L');
const displayDownloadBtn = useFeature('nonRestCors');
const qrCodeUrl = useMemo( const qrCodeUrl = useMemo(
() => buildQrCodeUrl(shortUrl, { size, format, margin, errorCorrection }), () => buildQrCodeUrl(shortUrl, { size, format, margin, errorCorrection }),
[shortUrl, size, format, margin, errorCorrection], [shortUrl, size, format, margin, errorCorrection],
@ -79,19 +77,17 @@ export const QrCodeModal = (imageDownloader: ImageDownloader) => (
<CopyToClipboardIcon text={qrCodeUrl} /> <CopyToClipboardIcon text={qrCodeUrl} />
</div> </div>
<img src={qrCodeUrl} className="qr-code-modal__img" alt="QR code" /> <img src={qrCodeUrl} className="qr-code-modal__img" alt="QR code" />
{displayDownloadBtn && ( <div className="mt-3">
<div className="mt-3"> <Button
<Button block
block color="primary"
color="primary" onClick={() => {
onClick={() => { imageDownloader.saveImage(qrCodeUrl, `${shortCode}-qr-code.${format}`).catch(() => {});
imageDownloader.saveImage(qrCodeUrl, `${shortCode}-qr-code.${format}`).catch(() => {}); }}
}} >
> Download <FontAwesomeIcon icon={downloadIcon} className="ms-1" />
Download <FontAwesomeIcon icon={downloadIcon} className="ms-1" /> </Button>
</Button> </div>
</div>
)}
</div> </div>
</ModalBody> </ModalBody>
</Modal> </Modal>

View file

@ -3,15 +3,6 @@ import type { SemVer } from '../../utils/helpers/version';
import { versionMatch } from '../../utils/helpers/version'; import { versionMatch } from '../../utils/helpers/version';
const supportedFeatures = { const supportedFeatures = {
// Deprecated
forwardQuery: '2.9.0',
nonRestCors: '2.9.0',
defaultDomainRedirectsEdition: '2.10.0',
nonOrphanVisits: '3.0.0',
allTagsFiltering: '3.0.0',
tagsStats: '3.0.0',
// End deprecated
domainVisits: '3.1.0', domainVisits: '3.1.0',
excludeBotsOnShortUrls: '3.4.0', excludeBotsOnShortUrls: '3.4.0',
filterDisabledUrls: '3.4.0', filterDisabledUrls: '3.4.0',
@ -26,15 +17,6 @@ export const isFeatureEnabledForVersion = (feature: Feature, serverVersion: SemV
versionMatch(serverVersion, { minVersion: supportedFeatures[feature] }); versionMatch(serverVersion, { minVersion: supportedFeatures[feature] });
const getFeaturesForVersion = (serverVersion: SemVer): Record<Feature, boolean> => ({ const getFeaturesForVersion = (serverVersion: SemVer): Record<Feature, boolean> => ({
// Deprecated
forwardQuery: isFeatureEnabledForVersion('forwardQuery', serverVersion),
nonRestCors: isFeatureEnabledForVersion('nonRestCors', serverVersion),
defaultDomainRedirectsEdition: isFeatureEnabledForVersion('defaultDomainRedirectsEdition', serverVersion),
nonOrphanVisits: isFeatureEnabledForVersion('nonOrphanVisits', serverVersion),
allTagsFiltering: isFeatureEnabledForVersion('allTagsFiltering', serverVersion),
tagsStats: isFeatureEnabledForVersion('tagsStats', serverVersion),
// End
domainVisits: isFeatureEnabledForVersion('domainVisits', serverVersion), domainVisits: isFeatureEnabledForVersion('domainVisits', serverVersion),
excludeBotsOnShortUrls: isFeatureEnabledForVersion('excludeBotsOnShortUrls', serverVersion), excludeBotsOnShortUrls: isFeatureEnabledForVersion('excludeBotsOnShortUrls', serverVersion),
filterDisabledUrls: isFeatureEnabledForVersion('filterDisabledUrls', serverVersion), filterDisabledUrls: isFeatureEnabledForVersion('filterDisabledUrls', serverVersion),