Repository: shlinkio/shlink-web-client (ts)

Issue:
Allow providing "validateUrl" flag while creating a new short URL
<!--
Before opening an issue, just take into account that this is a completely free of charge and open source project.
I'm always happy to help and provide support, but some understanding will be expected.
I do this in my own free time, so expect some delays when implementing new features and fixing bugs, and don't take it personal if an issue gets eventually closed.
You may also be asked to provide tests or ways to reproduce reported bugs.
Try to be polite, and understand it is impossible for an OSS project to cover all use cases.

With that said, please fill in the information requested next. More information might be requested once the issue is open.
-->

#### Summary

Display the option only for Shlink >=2.4.0


Pull request description:
Feature/validate flag
Closes #315 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ce3226f..a2f46e32 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 ## [Unreleased]
 ### Added
 * [#309](https://github.com/shlinkio/shlink-web-client/issues/309) Added new domain selector component in create URL form which allows selecting from previously used domains or set a new one.
+* [#315](https://github.com/shlinkio/shlink-web-client/issues/315) Now you can tell if you want to validate the long URL when using Shlink >=2.4.
 
 ### Changed
 * *Nothing*
diff --git a/src/domains/DomainSelector.tsx b/src/domains/DomainSelector.tsx
index ec53331e..510b39f9 100644
--- a/src/domains/DomainSelector.tsx
+++ b/src/domains/DomainSelector.tsx
@@ -8,9 +8,9 @@ import {
   Input,
   InputGroup,
   InputGroupAddon,
-  InputProps,
   UncontrolledTooltip,
 } from 'reactstrap';
+import { InputProps } from 'reactstrap/lib/Input';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { faUndo } from '@fortawesome/free-solid-svg-icons';
 import { isEmpty, pipe } from 'ramda';
diff --git a/src/short-urls/CreateShortUrl.tsx b/src/short-urls/CreateShortUrl.tsx
index da07dffa..442ddd87 100644
--- a/src/short-urls/CreateShortUrl.tsx
+++ b/src/short-urls/CreateShortUrl.tsx
@@ -38,6 +38,7 @@ const initialState: ShortUrlData = {
   validUntil: undefined,
   maxVisits: undefined,
   findIfExists: false,
+  validateUrl: true,
 };
 
 type NonDateFields = 'longUrl' | 'customSlug' | 'shortCodeLength' | 'domain' | 'maxVisits';
@@ -154,16 +155,29 @@ const CreateShortUrl = (
         </div>
 
         <ForServerVersion minVersion="1.16.0">
-          <div className="mb-4 text-right">
-            <Checkbox
-              inline
-              className="mr-2"
-              checked={shortUrlCreation.findIfExists}
-              onChange={(findIfExists) => setShortUrlCreation({ ...shortUrlCreation, findIfExists })}
-            >
-              Use existing URL if found
-            </Checkbox>
-            <UseExistingIfFoundInfoIcon />
+          <div className="mb-4 row">
+            <div className="col-sm-6 text-center text-sm-left mb-2 mb-sm-0">
+              <ForServerVersion minVersion="2.4.0">
+                <Checkbox
+                  inline
+                  checked={shortUrlCreation.validateUrl}
+                  onChange={(validateUrl) => setShortUrlCreation({ ...shortUrlCreation, validateUrl })}
+                >
+                  Validate URL
+                </Checkbox>
+              </ForServerVersion>
+            </div>
+            <div className="col-sm-6 text-center text-sm-right">
+              <Checkbox
+                inline
+                className="mr-2"
+                checked={shortUrlCreation.findIfExists}
+                onChange={(findIfExists) => setShortUrlCreation({ ...shortUrlCreation, findIfExists })}
+              >
+                Use existing URL if found
+              </Checkbox>
+              <UseExistingIfFoundInfoIcon />
+            </div>
           </div>
         </ForServerVersion>
       </Collapse>
diff --git a/src/short-urls/data/index.ts b/src/short-urls/data/index.ts
index ba7d7c6e..237c6b6a 100644
--- a/src/short-urls/data/index.ts
+++ b/src/short-urls/data/index.ts
@@ -11,6 +11,7 @@ export interface ShortUrlData {
   validUntil?: m.Moment | string;
   maxVisits?: number;
   findIfExists?: boolean;
+  validateUrl?: boolean;
 }
 
 export interface ShortUrl {
diff --git a/src/utils/BooleanControl.tsx b/src/utils/BooleanControl.tsx
index 72f7056e..0b642dd0 100644
--- a/src/utils/BooleanControl.tsx
+++ b/src/utils/BooleanControl.tsx
@@ -1,4 +1,4 @@
-import { ChangeEvent, FC } from 'react';
+import { ChangeEvent, FC, useRef } from 'react';
 import classNames from 'classnames';
 import { v4 as uuid } from 'uuid';
 import { identity } from 'ramda';
@@ -17,7 +17,7 @@ interface BooleanControlWithTypeProps extends BooleanControlProps {
 const BooleanControl: FC<BooleanControlWithTypeProps> = (
   { checked = false, onChange = identity, className, children, type, inline = false },
 ) => {
-  const id = uuid();
+  const { current: id } = useRef(uuid());
   const onChecked = (e: ChangeEvent<HTMLInputElement>) => onChange(e.target.checked, e);
   const typeClasses = {
     'custom-switch': type === 'switch',


Test patch:
diff --git a/test/short-urls/CreateShortUrl.test.tsx b/test/short-urls/CreateShortUrl.test.tsx
index 4aeb72bb..797b2169 100644
--- a/test/short-urls/CreateShortUrl.test.tsx
+++ b/test/short-urls/CreateShortUrl.test.tsx
@@ -52,6 +52,7 @@ describe('<CreateShortUrl />', () => {
       maxVisits: '20',
       findIfExists: false,
       shortCodeLength: 15,
+      validateUrl: true,
     });
   });
 });