diff --git a/src/components/AddShortcut.js b/src/components/AddShortcut.js
index 070eecef..aff5b4b7 100644
--- a/src/components/AddShortcut.js
+++ b/src/components/AddShortcut.js
@@ -50,6 +50,14 @@ const addProtocolToURLIfNeeded = (url) => {
return url
}
+const isValidUrl = (urlString) => {
+ try {
+ return Boolean(new URL(urlString))
+ } catch (e) {
+ return false
+ }
+}
+
const AddShortcut = ({
onCancel,
onSave,
@@ -59,6 +67,8 @@ const AddShortcut = ({
}) => {
const [name, setName] = useState(existingName)
const [url, setUrl] = useState(existingUrl)
+ const [nameError, setNameError] = useState(null)
+ const [urlError, setUrlError] = useState(null)
useEffect(() => setName(existingName), [existingName])
useEffect(() => setUrl(existingUrl), [existingUrl])
const classes = useStyles()
@@ -67,17 +77,49 @@ const AddShortcut = ({
setUrl(existingUrl)
onCancel()
}
+ const validateName = (newName) => {
+ let newNameError
+ if (newName.length === 0) {
+ newNameError = 'Shortcut name cannot be empty.'
+ } else {
+ newNameError = null
+ }
+ setNameError(newNameError)
+ return newNameError
+ }
+ const validateUrl = (newUrl) => {
+ let newUrlError
+ if (newUrl.length === 0) {
+ newUrlError = 'URL cannot be empty.'
+ } else if (!isValidUrl(addProtocolToURLIfNeeded(newUrl))) {
+ newUrlError = 'URL is not valid.'
+ } else {
+ newUrlError = null
+ }
+ setUrlError(newUrlError)
+ return newUrlError
+ }
+ const validateForm = () => {
+ const newNameError = validateName(name)
+ const newUrlError = validateUrl(url)
+ return newNameError || newUrlError
+ }
const onSaveClick = () => {
const newUrl = addProtocolToURLIfNeeded(url)
+ if (validateForm()) {
+ return
+ }
onSave(existingId, name, newUrl)
setName(name)
setUrl(newUrl)
}
const changeName = (e) => {
setName(e.target.value)
+ validateName(e.target.value)
}
const changeUrl = (e) => {
setUrl(e.target.value)
+ validateUrl(e.target.value)
}
return (
@@ -130,8 +172,8 @@ const AddShortcut = ({
onClick={onSaveClick}
className={classes.yesButton}
variant="contained"
- disabled={name.length === 0 || url.length === 0}
disableElevation
+ disabled={!!(nameError || urlError)}
>
Save
diff --git a/src/components/FrontpageShortcutList.js b/src/components/FrontpageShortcutList.js
index 7d7ed935..ce327f7f 100644
--- a/src/components/FrontpageShortcutList.js
+++ b/src/components/FrontpageShortcutList.js
@@ -36,6 +36,7 @@ const useStyles = makeStyles((theme) => ({
flexDirection: 'row',
maxWidth: '550px',
flexWrap: 'wrap',
+ zIndex: 1.4e3,
},
addCircle: {
marginTop: '24px',
@@ -61,6 +62,7 @@ const useStyles = makeStyles((theme) => ({
},
addShortcutWrapper: {
width: '400px',
+ position: 'relative',
},
}))
const FrontpageShortcutList = ({ openHandler, user }) => {
diff --git a/src/pages/account.js b/src/pages/account.js
index b883ec35..e61e6fcf 100644
--- a/src/pages/account.js
+++ b/src/pages/account.js
@@ -376,7 +376,7 @@ const Account = ({ data: fallbackData }) => {
{localStorageFeaturesManager.getFeatureValue(LAUNCH_BOOKMARKS) !==
'false' && (
({
zIndex: 1e4, // must be higher than all content besides ads and modal
margin: theme.spacing(1),
},
- frontpageShortcutList: {
- zIndex: 1.4e3,
- },
logo: {
height: 50,
margin: theme.spacing(0.5),
@@ -1143,7 +1140,7 @@ const Index = ({ data: fallbackData, userAgent }) => {
{localStorageFeaturesManager.getFeatureValue(LAUNCH_BOOKMARKS) !==
'false' &&
bookmarkWidgetEnabled && (
-