ducky/web

Paddy 2015-05-31 Parent:b9d0efb44eaa Child:3bdc03963abe

4:bd64a7d043d0 Go to Latest

ducky/web/package.json

Start tracking server errors. We've been storing client-side errors for a while now, so we can say "hey that input you entered is really screwed up, please don't even bother submitting the form." But once we pass that hurdle, it's still possible that the server will say "I don't care what the client-side validation said, this input is still wrong." To achieve this, we needed to start tracking server errors and client errors _separately_. The plan, originally, was just to put them in a single array, all mixed together--and, of course, that's what our ValidationError component requires--but there's a usability problem with this. The server error could be "you don't have an internet connection" (using 'server-error' loosely...) or "hey, the server had a problem handling your request, try again." The problem with putting everything together is that all these "try again" errors should get displayed to the user, but anything displayed to the user causes the Register button to be disabled. Meaning they can't try again until they (unintuitively) change pretty much any field in the form. The answer was to separate the two types of errors into their own arrays, and disable the button based on the client-side error array. When displaying errors, we concatenate the arrays. This means server-side errors only get displayed, but do not disable the button. Of course, we can have server errors that can mean "your input is bad and you should feel bad", which are decidedly different from "try again later" errors. These "your input is bad" errors hypothetically _should_ keep the form from being submitted until the value is changed to a valid input. Unfortunately, if we get to the point where a server error is returned, we've already proven the client is incapable of determining between invalid and valid inputs for that specific condition. If the client were capable of knowing, the input never would have reached the server in the first place. So considering the point of disabling the form input is to prevent unnecessary requests to the server, we should never disable the form based on a server error, because (by definition) those requests _must_ be necessary, or the client-side validation would have caught them. TL;DR: disabling a form because of server-side errors is silly. We also fixed a bug in the ValidationError component that would cause any error without a field, param, or header value set (e.g., an error that only contains the error field) would be considered a match for _every_ input, which is not what we want. We still need to decide on logic for displaying global errors. On the naive level, it's easy: match '/' or '' as the field. But that ignores any error responses that we are not specifically looking for. I'd much rather have a catch-all ValidationError handler that will catch any error not already handled by the other ValidationError instances. Unfortunately, I can't wrap my head around a good way to denote that a ValidationError instance has handled a specific error. The best I've got is to do an InverseValidationError that tracks a list of fields, params, and headers (the inputs available for ValidationError) and handles any error that _doesn't_ match them. Unfortunately, for complex forms, this would involve quite a bit of manual bookkeeping, updating ValidationError and InverseValidationError components in sync and never forgetting to update one or the other.

History
paddy@0 1 {
paddy@0 2 "name": "ducky",
paddy@0 3 "version": "0.0.1",
paddy@0 4 "author": "Second Bit",
paddy@0 5 "license": "MIT",
paddy@0 6 "dependencies": {
paddy@0 7 "ampersand-app": "^1.0.4",
paddy@0 8 "ampersand-collection": "^1.4.5",
paddy@0 9 "ampersand-model": "^5.0.3",
paddy@0 10 "ampersand-react-mixin": "^0.1.2",
paddy@0 11 "ampersand-router": "^3.0.2",
paddy@0 12 "ampersand-sync": "^3.0.7",
paddy@0 13 "babel": "^5.1.13",
paddy@0 14 "babel-loader": "^5.0.0",
paddy@0 15 "css-loader": "^0.12.0",
paddy@0 16 "extract-text-webpack-plugin": "^0.7.0",
paddy@0 17 "file-loader": "^0.8.1",
paddy@0 18 "find-root": "^0.1.1",
paddy@2 19 "jwt-decode": "^1.1.0",
paddy@0 20 "ladda": "^0.9.8",
paddy@0 21 "local-links": "^1.4.0",
paddy@2 22 "lodash.debounce": "^3.0.3",
paddy@0 23 "lodash.isobject": "^3.0.1",
paddy@0 24 "minimist": "^1.1.1",
paddy@0 25 "node-bourbon": "^4.2.1-beta1",
paddy@0 26 "node-neat": "^1.7.1-beta1",
paddy@0 27 "node-sass": "^2.1.1",
paddy@0 28 "normalize.css": "^3.0.3",
paddy@0 29 "qs": "^2.4.1",
paddy@0 30 "react": "^0.13.2",
paddy@2 31 "react-ladda": "^2.0.4",
paddy@2 32 "react-script-loader": "0.0.1",
paddy@0 33 "sass-loader": "0.4.2",
paddy@0 34 "style-loader": "^0.12.0",
paddy@0 35 "url-loader": "^0.5.5",
paddy@1 36 "webpack": "1.8.9"
paddy@0 37 },
paddy@0 38 "devDependencies": {
paddy@0 39 "react-hot-loader": "^1.2.5",
paddy@0 40 "webpack-dev-server": "^1.8.2"
paddy@0 41 },
paddy@0 42 "scripts": {
paddy@0 43 "build": "NODE_ENV=production webpack",
paddy@2 44 "start": "bin/dev-server",
paddy@2 45 "deploy": "surge ./build/"
paddy@0 46 }
paddy@0 47 }