Skip to content

Commit

Permalink
feat: make auto-generated datasetname valid, better errors
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswhong committed Sep 26, 2019
1 parent 10cc573 commit 839b432
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 14 deletions.
15 changes: 13 additions & 2 deletions app/components/modals/CreateDataset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react'
import path from 'path'
import { Action } from 'redux'
import { remote } from 'electron'
import changeCase from 'change-case'

import Modal from './Modal'
import ExternalLink from '../ExternalLink'
Expand Down Expand Up @@ -41,7 +42,7 @@ const CreateDataset: React.FunctionComponent<CreateDatasetProps> = (props) => {
datasetNameValidationError ? setDatasetNameError(datasetNameValidationError) : setDatasetNameError('')

// only ready when all three fields are not invalid
const ready = datasetDirPath !== '' && filePath !== '' && !datasetNameValidationError
const ready = datasetDirPath !== '' && filePath !== '' && datasetName !== '' && !datasetNameValidationError
setButtonDisabled(!ready)
}, [datasetName, datasetDirPath, filePath])

Expand Down Expand Up @@ -77,6 +78,16 @@ const CreateDataset: React.FunctionComponent<CreateDatasetProps> = (props) => {
}
}

const tryToSetValidName = (name: string) => {
// cast name to meet our specification
// make lower case, snakecase, and remove invalid characters
let coercedName = changeCase.lowerCase(name)
coercedName = changeCase.snakeCase(name)
coercedName = coercedName.replace(/^[^a-z0-9_]+$/g, '')

setDatasetName(coercedName)
}

const showFilePicker = () => {
const window = remote.getCurrentWindow()
const filePath: string[] | undefined = remote.dialog.showOpenDialog(window, {
Expand All @@ -91,7 +102,7 @@ const CreateDataset: React.FunctionComponent<CreateDatasetProps> = (props) => {
const basename = path.basename(selectedPath)
const name = basename.split('.')[0]

name && datasetName === '' && setDatasetName(name)
name && datasetName === '' && tryToSetValidName(name)

setFilePath(selectedPath)
const isDataset = isQriDataset(selectedPath)
Expand Down
4 changes: 2 additions & 2 deletions app/utils/formValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { DatasetStatus } from '../models/store'

type ValidationError = string | null

export const ERR_INVALID_USERNAME_CHARACTERS: ValidationError = 'Usernames may only include a-z, 0-9, _ , and -'
export const ERR_INVALID_USERNAME_CHARACTERS: ValidationError = 'Usernames may only include lowercase letters, numbers, underscores, and hyphens'
export const ERR_INVALID_USERNAME_LENGTH: ValidationError = 'Username must be 50 characters or fewer'

// validators return an error message or null
Expand Down Expand Up @@ -37,7 +37,7 @@ export const validatePassword = (password: string) => {
return null
}

export const ERR_INVALID_DATASETNAME_CHARACTERS: ValidationError = 'Dataset names may only include a-z, 0-9, and _'
export const ERR_INVALID_DATASETNAME_CHARACTERS: ValidationError = 'Dataset names may only include lowercase letters, numbers, and underscores'
export const ERR_INVALID_DATASETNAME_LENGTH: ValidationError = 'Username must be 100 characters or fewer'

export const validateDatasetName = (name: string): ValidationError => {
Expand Down
19 changes: 9 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@
"@types/redux-logger": "3.0.7",
"@types/redux-testkit": "1.0.3",
"@types/rimraf": "2.0.2",
"@types/shortid": "^0.0.29",
"@types/sinon": "7.0.13",
"@types/underscore": "1.9.2",
"@typescript-eslint/eslint-plugin": "1.11.0",
Expand Down Expand Up @@ -165,7 +164,7 @@
"eslint-plugin-standard": "4.0.0",
"express": "4.17.1",
"file-loader": "4.0.0",
"fork-ts-checker-webpack-plugin": "^1.5.0",
"fork-ts-checker-webpack-plugin": "1.5.0",
"identity-obj-proxy": "3.0.0",
"jest": "24.8.0",
"json-loader": "0.5.7",
Expand Down Expand Up @@ -193,19 +192,20 @@
"webpack-merge": "4.2.1"
},
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-decorators": "^7.6.0",
"@babel/preset-env": "^7.6.0",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.6.0",
"@babel/plugin-proposal-class-properties": "7.5.5",
"@babel/plugin-proposal-decorators": "7.6.0",
"@babel/preset-env": "7.6.0",
"@babel/preset-react": "7.0.0",
"@babel/preset-typescript": "7.6.0",
"@fortawesome/fontawesome-svg-core": "1.2.22",
"@fortawesome/free-brands-svg-icons": "5.10.2",
"@fortawesome/free-regular-svg-icons": "5.10.2",
"@fortawesome/free-solid-svg-icons": "5.10.2",
"@fortawesome/react-fontawesome": "0.1.4",
"@handsontable/react": "3.0.0",
"@types/webpack-env": "^1.14.0",
"babel-loader": "^8.0.6",
"@types/webpack-env": "1.14.0",
"babel-loader": "8.0.6",
"change-case": "3.1.0",
"classnames": "2.2.6",
"deep-equal": "1.1.0",
"electron-debug": "3.0.1",
Expand All @@ -232,7 +232,6 @@
"react-transition-group": "4.2.1",
"redux": "4.0.4",
"redux-thunk": "2.3.0",
"shortid": "^2.2.15",
"source-map-support": "0.5.12",
"underscore": "1.9.1",
"use-debounce": "3.0.0"
Expand Down
153 changes: 153 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2632,6 +2632,14 @@ callsites@^3.0.0:
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==

camel-case@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=
dependencies:
no-case "^2.2.0"
upper-case "^1.1.1"

camelcase-keys@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
Expand Down Expand Up @@ -2692,6 +2700,30 @@ chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"

change-case@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.1.0.tgz#0e611b7edc9952df2e8513b27b42de72647dd17e"
integrity sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==
dependencies:
camel-case "^3.0.0"
constant-case "^2.0.0"
dot-case "^2.1.0"
header-case "^1.0.0"
is-lower-case "^1.1.0"
is-upper-case "^1.1.0"
lower-case "^1.1.1"
lower-case-first "^1.0.0"
no-case "^2.3.2"
param-case "^2.1.0"
pascal-case "^2.0.0"
path-case "^2.1.0"
sentence-case "^2.1.0"
snake-case "^2.1.0"
swap-case "^1.1.0"
title-case "^2.1.0"
upper-case "^1.1.1"
upper-case-first "^1.1.0"

chardet@^0.4.0:
version "0.4.2"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
Expand Down Expand Up @@ -2976,6 +3008,14 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0:
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=

constant-case@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-2.0.0.tgz#4175764d389d3fa9c8ecd29186ed6005243b6a46"
integrity sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=
dependencies:
snake-case "^2.1.0"
upper-case "^1.1.1"

constants-browserify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
Expand Down Expand Up @@ -3636,6 +3676,13 @@ domutils@^1.5.1:
dom-serializer "0"
domelementtype "1"

dot-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-2.1.1.tgz#34dcf37f50a8e93c2b3bca8bb7fb9155c7da3bee"
integrity sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4=
dependencies:
no-case "^2.2.0"

dot-prop@^4.1.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
Expand Down Expand Up @@ -5139,6 +5186,14 @@ hash.js@^1.0.0, hash.js@^1.0.3:
inherits "^2.0.3"
minimalistic-assert "^1.0.1"

header-case@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/header-case/-/header-case-1.0.1.tgz#9535973197c144b09613cd65d317ef19963bd02d"
integrity sha1-lTWXMZfBRLCWE81l0xfvGZY70C0=
dependencies:
no-case "^2.2.0"
upper-case "^1.1.3"

highlight.js@^9.3.0:
version "9.15.10"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.10.tgz#7b18ed75c90348c045eef9ed08ca1319a2219ad2"
Expand Down Expand Up @@ -5666,6 +5721,13 @@ is-installed-globally@^0.1.0:
global-dirs "^0.1.0"
is-path-inside "^1.0.0"

is-lower-case@^1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-1.1.3.tgz#7e147be4768dc466db3bfb21cc60b31e6ad69393"
integrity sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=
dependencies:
lower-case "^1.1.0"

is-npm@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-3.0.0.tgz#ec9147bfb629c43f494cf67936a961edec7e8053"
Expand Down Expand Up @@ -5751,6 +5813,13 @@ is-typedarray@~1.0.0:
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=

is-upper-case@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-1.1.2.tgz#8d0b1fa7e7933a1e58483600ec7d9661cbaf756f"
integrity sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=
dependencies:
upper-case "^1.1.0"

is-utf8@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
Expand Down Expand Up @@ -6627,6 +6696,18 @@ loud-rejection@^1.0.0:
currently-unhandled "^0.4.1"
signal-exit "^3.0.0"

lower-case-first@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-1.0.2.tgz#e5da7c26f29a7073be02d52bac9980e5922adfa1"
integrity sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=
dependencies:
lower-case "^1.1.2"

lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=

lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
Expand Down Expand Up @@ -7094,6 +7175,13 @@ nise@^1.4.10:
lolex "^4.1.0"
path-to-regexp "^1.7.0"

no-case@^2.2.0, no-case@^2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==
dependencies:
lower-case "^1.1.1"

node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
Expand Down Expand Up @@ -7625,6 +7713,13 @@ parallel-transform@^1.1.0:
inherits "^2.0.3"
readable-stream "^2.1.5"

param-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc=
dependencies:
no-case "^2.2.0"

parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
Expand Down Expand Up @@ -7688,6 +7783,14 @@ parseurl@~1.3.3:
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==

pascal-case@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-2.0.1.tgz#2d578d3455f660da65eca18ef95b4e0de912761e"
integrity sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=
dependencies:
camel-case "^3.0.0"
upper-case-first "^1.1.0"

pascalcase@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
Expand All @@ -7698,6 +7801,13 @@ path-browserify@0.0.1:
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a"
integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==

path-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/path-case/-/path-case-2.1.1.tgz#94b8037c372d3fe2906e465bb45e25d226e8eea5"
integrity sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=
dependencies:
no-case "^2.2.0"

path-dirname@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
Expand Down Expand Up @@ -9171,6 +9281,14 @@ send@0.17.1:
range-parser "~1.2.1"
statuses "~1.5.0"

sentence-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-2.1.1.tgz#1f6e2dda39c168bf92d13f86d4a918933f667ed4"
integrity sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ=
dependencies:
no-case "^2.2.0"
upper-case-first "^1.1.2"

serialize-javascript@^1.7.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb"
Expand Down Expand Up @@ -9301,6 +9419,13 @@ slice-ansi@^2.1.0:
astral-regex "^1.0.0"
is-fullwidth-code-point "^2.0.0"

snake-case@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-2.1.0.tgz#41bdb1b73f30ec66a04d4e2cad1b76387d4d6d9f"
integrity sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=
dependencies:
no-case "^2.2.0"

snapdragon-node@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
Expand Down Expand Up @@ -9738,6 +9863,14 @@ supports-color@~5.0.0:
dependencies:
has-flag "^2.0.0"

swap-case@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-1.1.2.tgz#c39203a4587385fad3c850a0bd1bcafa081974e3"
integrity sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=
dependencies:
lower-case "^1.1.1"
upper-case "^1.1.1"

symbol-observable@^1.0.3, symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
Expand Down Expand Up @@ -9909,6 +10042,14 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.2:
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==

title-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa"
integrity sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o=
dependencies:
no-case "^2.2.0"
upper-case "^1.0.3"

tmp-promise@^1.0.5:
version "1.1.0"
resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-1.1.0.tgz#bb924d239029157b9bc1d506a6aa341f8b13e64c"
Expand Down Expand Up @@ -10275,6 +10416,18 @@ update-notifier@^3.0.1:
semver-diff "^2.0.0"
xdg-basedir "^3.0.0"

upper-case-first@^1.1.0, upper-case-first@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-1.1.2.tgz#5d79bedcff14419518fd2edb0a0507c9b6859115"
integrity sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=
dependencies:
upper-case "^1.1.1"

upper-case@^1.0.3, upper-case@^1.1.0, upper-case@^1.1.1, upper-case@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=

uri-js@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
Expand Down

0 comments on commit 839b432

Please sign in to comment.