diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..23fd35f0e0e708ef622c7d957b9c8bb60c7876eb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.formatOnSave": true +} \ No newline at end of file diff --git a/npm-debug.log b/npm-debug.log new file mode 100644 index 0000000000000000000000000000000000000000..a1e64b3b27ccf5944c7fbc885da5e86a4fe330d5 --- /dev/null +++ b/npm-debug.log @@ -0,0 +1,45 @@ +0 info it worked if it ends with ok +1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'start' ] +2 info using npm@3.5.2 +3 info using node@v8.10.0 +4 verbose run-script [ 'prestart', 'start', 'poststart' ] +5 info lifecycle my-app@0.1.0~prestart: my-app@0.1.0 +6 silly lifecycle my-app@0.1.0~prestart: no script for prestart, continuing +7 info lifecycle my-app@0.1.0~start: my-app@0.1.0 +8 verbose lifecycle my-app@0.1.0~start: unsafe-perm in lifecycle true +9 verbose lifecycle my-app@0.1.0~start: PATH: /usr/share/npm/bin/node-gyp-bin:/home/gabriel/Documents/c3sl/form-creator-ui/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/gabriel/.npm-packages/bin:/snap/bin:/home/gabriel/.npm-packages/bin:/snap/bin +10 verbose lifecycle my-app@0.1.0~start: CWD: /home/gabriel/Documents/c3sl/form-creator-ui +11 silly lifecycle my-app@0.1.0~start: Args: [ '-c', 'react-scripts start' ] +12 silly lifecycle my-app@0.1.0~start: Returned: code: 1 signal: null +13 info lifecycle my-app@0.1.0~start: Failed to exec start script +14 verbose stack Error: my-app@0.1.0 start: `react-scripts start` +14 verbose stack Exit status 1 +14 verbose stack at EventEmitter.<anonymous> (/usr/share/npm/lib/utils/lifecycle.js:232:16) +14 verbose stack at emitTwo (events.js:126:13) +14 verbose stack at EventEmitter.emit (events.js:214:7) +14 verbose stack at ChildProcess.<anonymous> (/usr/share/npm/lib/utils/spawn.js:24:14) +14 verbose stack at emitTwo (events.js:126:13) +14 verbose stack at ChildProcess.emit (events.js:214:7) +14 verbose stack at maybeClose (internal/child_process.js:925:16) +14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:209:5) +15 verbose pkgid my-app@0.1.0 +16 verbose cwd /home/gabriel/Documents/c3sl/form-creator-ui +17 error Linux 5.3.0-42-generic +18 error argv "/usr/bin/node" "/usr/bin/npm" "start" +19 error node v8.10.0 +20 error npm v3.5.2 +21 error code ELIFECYCLE +22 error my-app@0.1.0 start: `react-scripts start` +22 error Exit status 1 +23 error Failed at the my-app@0.1.0 start script 'react-scripts start'. +23 error Make sure you have the latest version of node.js and npm installed. +23 error If you do, this is most likely a problem with the my-app package, +23 error not with npm itself. +23 error Tell the author that this fails on your system: +23 error react-scripts start +23 error You can get information on how to open an issue for this project with: +23 error npm bugs my-app +23 error Or if that isn't available, you can get their info via: +23 error npm owner ls my-app +23 error There is likely additional logging output above. +24 verbose exit [ 1, true ] diff --git a/package-lock.json b/package-lock.json index 0e5b74dc58c1b546848a22b4d5f902f16a3638c7..4f2a33b51e0f606aa3bfba9ff05c49106b875b0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1044,9 +1044,9 @@ "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==" }, "@emotion/hash": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.7.4.tgz", - "integrity": "sha512-fxfMSBMX3tlIbKUdtGKxqB1fyrH6gVrX39Gsv3y8lRYKUqlgDt3UMqQyGnR1bQMa2B8aGnhLZokZgg8vT0Le+A==" + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" }, "@hapi/address": { "version": "2.1.4", @@ -1274,20 +1274,18 @@ } }, "@material-ui/core": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.8.3.tgz", - "integrity": "sha512-ZJbfJQmkuZCSQTf0nzpfZwizmDdCq8ruZxnPNFnhoKDqgJpMvV8TJRi8vdI9ls1tMuTqxlhyhw8556fxOpWpFQ==", + "version": "4.9.7", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.9.7.tgz", + "integrity": "sha512-RTRibZgq572GHEskMAG4sP+bt3P3XyIkv3pOTR8grZAW2rSUd6JoGZLRM4S2HkuO7wS7cAU5SpU2s1EsmTgWog==", "requires": { "@babel/runtime": "^7.4.4", - "@material-ui/styles": "^4.8.2", - "@material-ui/system": "^4.7.1", - "@material-ui/types": "^4.1.1", - "@material-ui/utils": "^4.7.1", + "@material-ui/styles": "^4.9.6", + "@material-ui/system": "^4.9.6", + "@material-ui/types": "^5.0.0", + "@material-ui/utils": "^4.9.6", "@types/react-transition-group": "^4.2.0", "clsx": "^1.0.2", - "convert-css-length": "^2.0.1", - "hoist-non-react-statics": "^3.2.1", - "normalize-scroll-left": "^0.2.0", + "hoist-non-react-statics": "^3.3.2", "popper.js": "^1.14.1", "prop-types": "^15.7.2", "react-is": "^16.8.0", @@ -1304,9 +1302,9 @@ } }, "hoist-non-react-statics": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", - "integrity": "sha512-wbg3bpgA/ZqWrZuMOeJi8+SKMhr7X9TesL/rXMjTzh0p0JUBo3II8DHboYbuIXWRlttrUFxwcu/5kygrCw8fJw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "requires": { "react-is": "^16.7.0" } @@ -1325,40 +1323,64 @@ } }, "@material-ui/icons": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.5.1.tgz", - "integrity": "sha512-YZ/BgJbXX4a0gOuKWb30mBaHaoXRqPanlePam83JQPZ/y4kl+3aW0Wv9tlR70hB5EGAkEJGW5m4ktJwMgxQAeA==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.9.1.tgz", + "integrity": "sha512-GBitL3oBWO0hzBhvA9KxqcowRUsA0qzwKkURyC8nppnC3fw54KPKZ+d4V1Eeg/UnDRSzDaI9nGCdel/eh9AQMg==", "requires": { "@babel/runtime": "^7.4.4" } }, + "@material-ui/lab": { + "version": "4.0.0-alpha.46", + "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.46.tgz", + "integrity": "sha512-JGgZmj1UNP8bbYNAGvndipjXRK3x2+9mFBzbX7MyCj+WpfnJbeqTmJK2No9MXvPj/EZJ1piaKif46FdDc4U93A==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.9.6", + "clsx": "^1.0.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0" + }, + "dependencies": { + "@material-ui/utils": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.9.6.tgz", + "integrity": "sha512-gqlBn0JPPTUZeAktn1rgMcy9Iczrr74ecx31tyZLVGdBGGzsxzM6PP6zeS7FuoLS6vG4hoZP7hWnOoHtkR0Kvw==", + "requires": { + "@babel/runtime": "^7.4.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0" + } + } + } + }, "@material-ui/styles": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.8.2.tgz", - "integrity": "sha512-r5U+93pkpwQOmHTmwyn2sqTio6PHd873xvSHiKP6fdybAXXX6CZgVvh3W8saZNbYr/QXsS8OHmFv7sYJLt5Yfg==", + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.9.6.tgz", + "integrity": "sha512-ijgwStEkw1OZ6gCz18hkjycpr/3lKs1hYPi88O/AUn4vMuuGEGAIrqKVFq/lADmZUNF3DOFIk8LDkp7zmjPxtA==", "requires": { "@babel/runtime": "^7.4.4", - "@emotion/hash": "^0.7.4", - "@material-ui/types": "^4.1.1", - "@material-ui/utils": "^4.7.1", + "@emotion/hash": "^0.8.0", + "@material-ui/types": "^5.0.0", + "@material-ui/utils": "^4.9.6", "clsx": "^1.0.2", "csstype": "^2.5.2", - "hoist-non-react-statics": "^3.2.1", - "jss": "^10.0.0", - "jss-plugin-camel-case": "^10.0.0", - "jss-plugin-default-unit": "^10.0.0", - "jss-plugin-global": "^10.0.0", - "jss-plugin-nested": "^10.0.0", - "jss-plugin-props-sort": "^10.0.0", - "jss-plugin-rule-value-function": "^10.0.0", - "jss-plugin-vendor-prefixer": "^10.0.0", + "hoist-non-react-statics": "^3.3.2", + "jss": "^10.0.3", + "jss-plugin-camel-case": "^10.0.3", + "jss-plugin-default-unit": "^10.0.3", + "jss-plugin-global": "^10.0.3", + "jss-plugin-nested": "^10.0.3", + "jss-plugin-props-sort": "^10.0.3", + "jss-plugin-rule-value-function": "^10.0.3", + "jss-plugin-vendor-prefixer": "^10.0.3", "prop-types": "^15.7.2" }, "dependencies": { "hoist-non-react-statics": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", - "integrity": "sha512-wbg3bpgA/ZqWrZuMOeJi8+SKMhr7X9TesL/rXMjTzh0p0JUBo3II8DHboYbuIXWRlttrUFxwcu/5kygrCw8fJw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "requires": { "react-is": "^16.7.0" } @@ -1366,27 +1388,24 @@ } }, "@material-ui/system": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.7.1.tgz", - "integrity": "sha512-zH02p+FOimXLSKOW/OT2laYkl9bB3dD1AvnZqsHYoseUaq0aVrpbl2BGjQi+vJ5lg8w73uYlt9zOWzb3+1UdMQ==", + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.9.6.tgz", + "integrity": "sha512-QtfoAePyqXoZ2HUVSwGb1Ro0kucMCvVjbI0CdYIR21t0Opgfm1Oer6ni9P5lfeXA39xSt0wCierw37j+YES48Q==", "requires": { "@babel/runtime": "^7.4.4", - "@material-ui/utils": "^4.7.1", + "@material-ui/utils": "^4.9.6", "prop-types": "^15.7.2" } }, "@material-ui/types": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-4.1.1.tgz", - "integrity": "sha512-AN+GZNXytX9yxGi0JOfxHrRTbhFybjUJ05rnsBVjcB+16e466Z0Xe5IxawuOayVZgTBNDxmPKo5j4V6OnMtaSQ==", - "requires": { - "@types/react": "*" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.0.0.tgz", + "integrity": "sha512-UeH2BuKkwDndtMSS0qgx1kCzSMw+ydtj0xx/XbFtxNSTlXydKwzs5gVW5ZKsFlAkwoOOQ9TIsyoCC8hq18tOwg==" }, "@material-ui/utils": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.7.1.tgz", - "integrity": "sha512-+ux0SlLdlehvzCk2zdQ3KiS3/ylWvuo/JwAGhvb8dFVvwR21K28z0PU9OQW2PGogrMEdvX3miEI5tGxTwwWiwQ==", + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.9.6.tgz", + "integrity": "sha512-gqlBn0JPPTUZeAktn1rgMcy9Iczrr74ecx31tyZLVGdBGGzsxzM6PP6zeS7FuoLS6vG4hoZP7hWnOoHtkR0Kvw==", "requires": { "@babel/runtime": "^7.4.4", "prop-types": "^15.7.2", @@ -1408,9 +1427,9 @@ "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==" }, "@sheerun/mutationobserver-shim": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz", - "integrity": "sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q==" + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz", + "integrity": "sha512-DetpxZw1fzPD5xUBrIAoplLChO2VB8DlL5Gg+I1IR9b2wPqYIca2WSUxL5g1vLeR4MsQq1NeWriXAVffV+U1Fw==" }, "@svgr/babel-plugin-add-jsx-attribute": { "version": "4.2.0", @@ -1522,16 +1541,115 @@ } }, "@testing-library/dom": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-6.11.0.tgz", - "integrity": "sha512-Pkx9LMIGshyNbfmecjt18rrAp/ayMqGH674jYER0SXj0iG9xZc+zWRjk2Pg9JgPBDvwI//xGrI/oOQkAi4YEew==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-6.16.0.tgz", + "integrity": "sha512-lBD88ssxqEfz0wFL6MeUyyWZfV/2cjEZZV3YRpb2IoJRej/4f1jB0TzqIOznTpfR1r34CNesrubxwIlAQ8zgPA==", "requires": { - "@babel/runtime": "^7.6.2", + "@babel/runtime": "^7.8.4", "@sheerun/mutationobserver-shim": "^0.3.2", - "@types/testing-library__dom": "^6.0.0", - "aria-query": "3.0.0", - "pretty-format": "^24.9.0", - "wait-for-expect": "^3.0.0" + "@types/testing-library__dom": "^6.12.1", + "aria-query": "^4.0.2", + "dom-accessibility-api": "^0.3.0", + "pretty-format": "^25.1.0", + "wait-for-expect": "^3.0.2" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@jest/types": { + "version": "25.2.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.2.3.tgz", + "integrity": "sha512-6oLQwO9mKif3Uph3RX5J1i3S7X7xtDHWBaaaoeKw8hOzV6YUd0qDcYcHZ6QXMHDIzSr7zzrEa51o2Ovlj6AtKQ==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "@types/yargs": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz", + "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "aria-query": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.0.2.tgz", + "integrity": "sha512-S1G1V790fTaigUSM/Gd0NngzEfiMy9uTUfMyHhKhVyy4cH5O/eTuR01ydhGL0z4Za1PXFTRGH3qL8VhUQuEO5w==", + "requires": { + "@babel/runtime": "^7.7.4", + "@babel/runtime-corejs3": "^7.7.4" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "pretty-format": { + "version": "25.2.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.2.3.tgz", + "integrity": "sha512-IP4+5UOAVGoyqC/DiomOeHBUKN6q00gfyT2qpAsRH64tgOKB2yF7FHJXC18OCiU0/YFierACup/zdCOWw0F/0w==", + "requires": { + "@jest/types": "^25.2.3", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } } }, "@testing-library/jest-dom": { @@ -1551,22 +1669,27 @@ } }, "@testing-library/react": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-9.4.0.tgz", - "integrity": "sha512-XdhDWkI4GktUPsz0AYyeQ8M9qS/JFie06kcSnUVcpgOwFjAu9vhwR83qBl+lw9yZWkbECjL8Hd+n5hH6C0oWqg==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-9.5.0.tgz", + "integrity": "sha512-di1b+D0p+rfeboHO5W7gTVeZDIK5+maEgstrZbWZSSvxDyfDRkkyBE1AJR5Psd6doNldluXlCWqXriUfqu/9Qg==", "requires": { - "@babel/runtime": "^7.7.6", - "@testing-library/dom": "^6.11.0", + "@babel/runtime": "^7.8.4", + "@testing-library/dom": "^6.15.0", "@types/testing-library__react": "^9.1.2" }, "dependencies": { "@babel/runtime": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.0.tgz", - "integrity": "sha512-Z7ti+HB0puCcLmFE3x90kzaVgbx6TRrYIReaygW6EkBEnJh1ajS4/inhF7CypzWeDV3NFl1AfWj0eMtdihojxw==", + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", "requires": { - "regenerator-runtime": "^0.13.2" + "regenerator-runtime": "^0.13.4" } + }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" } } }, @@ -1612,6 +1735,11 @@ "@babel/types": "^7.3.0" } }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -1685,26 +1813,26 @@ "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==" }, "@types/react": { - "version": "16.9.17", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.17.tgz", - "integrity": "sha512-UP27In4fp4sWF5JgyV6pwVPAQM83Fj76JOcg02X5BZcpSu5Wx+fP9RMqc2v0ssBoQIFvD5JdKY41gjJJKmw6Bg==", + "version": "16.9.26", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.26.tgz", + "integrity": "sha512-dGuSM+B0Pq1MKXYUMlUQWeS6Jj9IhSAUf9v8Ikaimj+YhkBcQrihWBkmyEhK/1fzkJTwZQkhZp5YhmWa2CH+Rw==", "requires": { "@types/prop-types": "*", "csstype": "^2.2.0" } }, "@types/react-dom": { - "version": "16.9.4", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.4.tgz", - "integrity": "sha512-fya9xteU/n90tda0s+FtN5Ym4tbgxpq/hb/Af24dvs6uYnYn+fspaxw5USlw0R8apDNwxsqumdRoCoKitckQqw==", + "version": "16.9.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.5.tgz", + "integrity": "sha512-BX6RQ8s9D+2/gDhxrj8OW+YD4R+8hj7FEM/OJHGNR0KipE1h1mSsf39YeyC81qafkq+N3rU3h3RFbLSwE5VqUg==", "requires": { "@types/react": "*" } }, "@types/react-transition-group": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.2.3.tgz", - "integrity": "sha512-Hk8jiuT7iLOHrcjKP/ZVSyCNXK73wJAUz60xm0mVhiRujrdiI++j4duLiL282VGxwAgxetHQFfqA29LgEeSkFA==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.2.4.tgz", + "integrity": "sha512-8DMUaDqh0S70TjkqU0DxOu80tFUiiaS9rxkWip/nb7gtvAsbqOXm02UCmR8zdcjWujgeYPiPNTVpVpKzUDotwA==", "requires": { "@types/react": "*" } @@ -1715,20 +1843,97 @@ "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==" }, "@types/testing-library__dom": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/@types/testing-library__dom/-/testing-library__dom-6.11.1.tgz", - "integrity": "sha512-ImChHtQqmjwraRLqBC2sgSQFtczeFvBmBcfhTYZn/3KwXbyD07LQykEQ0xJo7QHc1GbVvf7pRyGaIe6PkCdxEw==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/testing-library__dom/-/testing-library__dom-6.14.0.tgz", + "integrity": "sha512-sMl7OSv0AvMOqn1UJ6j1unPMIHRXen0Ita1ujnMX912rrOcawe4f7wu0Zt9GIQhBhJvH2BaibqFgQ3lP+Pj2hA==", "requires": { "pretty-format": "^24.3.0" } }, "@types/testing-library__react": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@types/testing-library__react/-/testing-library__react-9.1.2.tgz", - "integrity": "sha512-CYaMqrswQ+cJACy268jsLAw355DZtPZGt3Jwmmotlcu8O/tkoXBI6AeZ84oZBJsIsesozPKzWzmv/0TIU+1E9Q==", + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/@types/testing-library__react/-/testing-library__react-9.1.3.tgz", + "integrity": "sha512-iCdNPKU3IsYwRK9JieSYAiX0+aYDXOGAmrC/3/M7AqqSDKnWWVv07X+Zk1uFSL7cMTUYzv4lQRfohucEocn5/w==", "requires": { "@types/react-dom": "*", - "@types/testing-library__dom": "*" + "@types/testing-library__dom": "*", + "pretty-format": "^25.1.0" + }, + "dependencies": { + "@jest/types": { + "version": "25.2.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.2.3.tgz", + "integrity": "sha512-6oLQwO9mKif3Uph3RX5J1i3S7X7xtDHWBaaaoeKw8hOzV6YUd0qDcYcHZ6QXMHDIzSr7zzrEa51o2Ovlj6AtKQ==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "@types/yargs": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz", + "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "pretty-format": { + "version": "25.2.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.2.3.tgz", + "integrity": "sha512-IP4+5UOAVGoyqC/DiomOeHBUKN6q00gfyT2qpAsRH64tgOKB2yF7FHJXC18OCiU0/YFierACup/zdCOWw0F/0w==", + "requires": { + "@jest/types": "^25.2.3", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } } }, "@types/yargs": { @@ -4107,11 +4312,6 @@ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, - "convert-css-length": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/convert-css-length/-/convert-css-length-2.0.1.tgz", - "integrity": "sha512-iGpbcvhLPRKUbBc0Quxx7w/bV14AC3ItuBEGMahA5WTYqB8lq9jH0kTXFheCBASsYnqeMFZhiTruNxr1N59Axg==" - }, "convert-source-map": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", @@ -4287,6 +4487,14 @@ "postcss": "^7.0.5" } }, + "css-box-model": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.0.tgz", + "integrity": "sha512-lri0br+jSNV0kkkiGEp9y9y3Njq2PmpqbeGWRFQJuZteZzY9iC9GZhQ8Y4WpPwM/2YocjHePxy14igJY7YKzkA==", + "requires": { + "tiny-invariant": "^1.0.6" + } + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -4529,9 +4737,9 @@ } }, "csstype": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.8.tgz", - "integrity": "sha512-msVS9qTuMT5zwAGCVm4mxfrZ18BNc6Csd0oJAtiFMZ1FAx1CCvy2+5MDmYoix63LM/6NDbNtodCiGYGmFgO0dA==" + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.9.tgz", + "integrity": "sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==" }, "cyclist": { "version": "1.0.1", @@ -4618,6 +4826,11 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, + "deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==" + }, "default-gateway": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", @@ -4834,6 +5047,11 @@ "esutils": "^2.0.2" } }, + "dom-accessibility-api": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.3.0.tgz", + "integrity": "sha512-PzwHEmsRP3IGY4gv/Ug+rMeaTIyTJvadCb+ujYXYeIylbHJezIyNToe8KfEgHTCEYyC+/bUghYOGg8yMGlZ6vA==" + }, "dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", @@ -6180,6 +6398,11 @@ } } }, + "fn-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-3.0.0.tgz", + "integrity": "sha512-eNMNr5exLoavuAMhIUVsOKF79SWd/zG104ef6sxBTSw+cZc6BXdQXDvYcGvp0VbxVVSp1XDUNoz7mg1xMtSznA==" + }, "follow-redirects": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.9.0.tgz", @@ -6248,6 +6471,40 @@ "mime-types": "^2.1.12" } }, + "formik": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.1.4.tgz", + "integrity": "sha512-oKz8S+yQBzuQVSEoxkqqJrKQS5XJASWGVn6mrs+oTWrBoHgByVwwI1qHiVc9GKDpZBU9vAxXYAKz2BvujlwunA==", + "requires": { + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.14", + "lodash-es": "^4.17.14", + "react-fast-compare": "^2.0.1", + "scheduler": "^0.18.0", + "tiny-warning": "^1.0.2", + "tslib": "^1.10.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, + "scheduler": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", + "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -8523,9 +8780,9 @@ } }, "jss": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.3.tgz", - "integrity": "sha512-AcDvFdOk16If9qvC9KN3oFXsrkHWM9+TaPMpVB9orm3z+nq1Xw3ofHyflRe/mkSucRZnaQtlhZs1hdP3DR9uRw==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.1.1.tgz", + "integrity": "sha512-Xz3qgRUFlxbWk1czCZibUJqhVPObrZHxY3FPsjCXhDld4NOj1BgM14Ir5hVm+Qr6OLqVljjGvoMcCdXNOAbdkQ==", "requires": { "@babel/runtime": "^7.3.1", "csstype": "^2.6.5", @@ -8534,69 +8791,69 @@ } }, "jss-plugin-camel-case": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.0.3.tgz", - "integrity": "sha512-rild/oFKFkmRP7AoiX9D6bdDAUfmJv8c7sEBvFoi+JP31dn2W8nw4txMKGnV1LJKlFkYprdZt1X99Uvztl1hug==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.1.1.tgz", + "integrity": "sha512-MDIaw8FeD5uFz1seQBKz4pnvDLnj5vIKV5hXSVdMaAVq13xR6SVTVWkIV/keyTs5txxTvzGJ9hXoxgd1WTUlBw==", "requires": { "@babel/runtime": "^7.3.1", "hyphenate-style-name": "^1.0.3", - "jss": "^10.0.3" + "jss": "10.1.1" } }, "jss-plugin-default-unit": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.0.3.tgz", - "integrity": "sha512-n+XfVLPF9Qh7IOTdQ8M4oRpjpg6egjr/r0NNytubbCafMgCILJYIVrMTGgOTydH+uvak8onQY3f/F9hasPUx6g==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.1.1.tgz", + "integrity": "sha512-UkeVCA/b3QEA4k0nIKS4uWXDCNmV73WLHdh2oDGZZc3GsQtlOCuiH3EkB/qI60v2MiCq356/SYWsDXt21yjwdg==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "^10.0.3" + "jss": "10.1.1" } }, "jss-plugin-global": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.0.3.tgz", - "integrity": "sha512-kNotkAciJIXpIGYnmueaIifBne9rdq31O8Xq1nF7KMfKlskNRANTcEX5rVnsGKl2yubTMYfjKBFCeDgcQn6+gA==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.1.1.tgz", + "integrity": "sha512-VBG3wRyi3Z8S4kMhm8rZV6caYBegsk+QnQZSVmrWw6GVOT/Z4FA7eyMu5SdkorDlG/HVpHh91oFN56O4R9m2VA==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "^10.0.3" + "jss": "10.1.1" } }, "jss-plugin-nested": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.0.3.tgz", - "integrity": "sha512-OMucRs9YLvWlZ3Ew+VhdgNVMwSS2zZy/2vy+s/etvopnPUzDHgCnJwdY2Wx/SlhLGERJeKKufyih2seH+ui0iw==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.1.1.tgz", + "integrity": "sha512-ozEu7ZBSVrMYxSDplPX3H82XHNQk2DQEJ9TEyo7OVTPJ1hEieqjDFiOQOxXEj9z3PMqkylnUbvWIZRDKCFYw5Q==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "^10.0.3", + "jss": "10.1.1", "tiny-warning": "^1.0.2" } }, "jss-plugin-props-sort": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.0.3.tgz", - "integrity": "sha512-ufhvdCMnRcDa0tNHoZ12OcVNQQyE10yLMohxo/UIMarLV245rM6n9D19A12epjldRgyiS13SoSyLFCJEobprYg==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.1.1.tgz", + "integrity": "sha512-g/joK3eTDZB4pkqpZB38257yD4LXB0X15jxtZAGbUzcKAVUHPl9Jb47Y7lYmiGsShiV4YmQRqG1p2DHMYoK91g==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "^10.0.3" + "jss": "10.1.1" } }, "jss-plugin-rule-value-function": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.0.3.tgz", - "integrity": "sha512-RWwIT2UBAIwf3f6DQtt5gyjxHMRJoeO9TQku+ueR8dBMakqSSe8vFwQNfjXEoe0W+Tez5HZCTkZKNMulv3Z+9A==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.1.1.tgz", + "integrity": "sha512-ClV1lvJ3laU9la1CUzaDugEcwnpjPTuJ0yGy2YtcU+gG/w9HMInD5vEv7xKAz53Bk4WiJm5uLOElSEshHyhKNw==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "^10.0.3" + "jss": "10.1.1" } }, "jss-plugin-vendor-prefixer": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.0.3.tgz", - "integrity": "sha512-zVs6e5z4tFRK/fJ5kuTLzXlTFQbLeFTVwk7lTZiYNufmZwKT0kSmnOJDUukcSe7JLGSRztjWhnHB/6voP174gw==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.1.1.tgz", + "integrity": "sha512-09MZpQ6onQrhaVSF6GHC4iYifQ7+4YC/tAP6D4ZWeZotvCMq1mHLqNKRIaqQ2lkgANjlEot2JnVi1ktu4+L4pw==", "requires": { "@babel/runtime": "^7.3.1", "css-vendor": "^2.0.7", - "jss": "^10.0.3" + "jss": "10.1.1" } }, "jsx-ast-utils": { @@ -8781,6 +9038,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash-es": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz", + "integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==" + }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -8969,6 +9231,11 @@ "p-is-promise": "^2.0.0" } }, + "memoize-one": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz", + "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==" + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -9515,11 +9782,6 @@ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" }, - "normalize-scroll-left": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/normalize-scroll-left/-/normalize-scroll-left-0.2.0.tgz", - "integrity": "sha512-t5oCENZJl8TGusJKoCJm7+asaSsPuNmK6+iEjrZ5TyBj2f02brCRsd4c83hwtu+e5d4LCSBZ0uoDlMjBo+A8yA==" - }, "normalize-url": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", @@ -10118,9 +10380,9 @@ } }, "popper.js": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.0.tgz", - "integrity": "sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw==" + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" }, "portfinder": { "version": "1.0.25", @@ -11206,6 +11468,11 @@ "react-is": "^16.8.1" } }, + "property-expr": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.2.tgz", + "integrity": "sha512-bc/5ggaYZxNkFKj374aLbEDqVADdYaLcFo8XBkishUWbaAdjlphaBFns9TvRA2pUseVL/wMFmui9X3IdNDU37g==" + }, "proxy-addr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", @@ -11315,6 +11582,11 @@ "performance-now": "^2.1.0" } }, + "raf-schd": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.2.tgz", + "integrity": "sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -11356,9 +11628,9 @@ } }, "react": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz", - "integrity": "sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA==", + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", + "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -11378,6 +11650,35 @@ "whatwg-fetch": "^3.0.0" } }, + "react-beautiful-dnd": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz", + "integrity": "sha512-87It8sN0ineoC3nBW0SbQuTFXM6bUqM62uJGY4BtTf0yzPl8/3+bHMWkgIe0Z6m8e+gJgjWxefGRVfpE3VcdEg==", + "requires": { + "@babel/runtime": "^7.8.4", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.1.1", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" + } + } + }, "react-dev-utils": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-10.0.0.tgz", @@ -11527,14 +11828,14 @@ } }, "react-dom": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.12.0.tgz", - "integrity": "sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw==", + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz", + "integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "scheduler": "^0.18.0" + "scheduler": "^0.19.1" } }, "react-error-overlay": { @@ -11562,11 +11863,43 @@ } } }, + "react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" + }, "react-is": { "version": "16.12.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" }, + "react-os": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/react-os/-/react-os-0.0.9.tgz", + "integrity": "sha1-kM+AyDZntZVBCbh3f9iFXxtvdHY=" + }, + "react-redux": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", + "integrity": "sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==", + "requires": { + "@babel/runtime": "^7.5.5", + "hoist-non-react-statics": "^3.3.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.9.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + } + } + }, "react-router": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.1.2.tgz", @@ -11792,6 +12125,15 @@ "strip-indent": "^3.0.0" } }, + "redux": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", + "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + } + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -12286,9 +12628,9 @@ } }, "scheduler": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", - "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -13202,6 +13544,11 @@ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, + "synchronous-promise": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.10.tgz", + "integrity": "sha512-6PC+JRGmNjiG3kJ56ZMNWDPL8hjyghF5cMXIFOKg+NiwwEZZIvxTWd0pinWKyD227odg9ygF8xVhhz7gb8Uq7A==" + }, "table": { "version": "5.4.6", "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", @@ -13478,6 +13825,11 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" + }, "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", @@ -13764,6 +14116,11 @@ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, + "use-memo-one": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.1.tgz", + "integrity": "sha512-oFfsyun+bP7RX8X2AskHNTxu+R3QdE/RC5IefMbqptmACAA/gfol1KDD5KRzPsGMa62sWxGZw+Ui43u6x4ddoQ==" + }, "util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", @@ -13871,9 +14228,9 @@ } }, "wait-for-expect": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wait-for-expect/-/wait-for-expect-3.0.1.tgz", - "integrity": "sha512-3Ha7lu+zshEG/CeHdcpmQsZnnZpPj/UsG3DuKO8FskjuDbkx3jE3845H+CuwZjA2YWYDfKMU2KhnCaXMLd3wVw==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/wait-for-expect/-/wait-for-expect-3.0.2.tgz", + "integrity": "sha512-cfS1+DZxuav1aBYbaO/kE06EOS8yRw7qOFoD3XtjTkYvCvh3zUvNST8DXK/nPaeqIzIv3P3kL3lRJn8iwOiSag==" }, "walker": { "version": "1.0.7", @@ -14669,6 +15026,35 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "yup": { + "version": "0.28.3", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.28.3.tgz", + "integrity": "sha512-amVkCgFWe5bGjrrUiODkbIzrSwtB8JpZrQYSrfj2YsbRdrV+tn9LquWdZDlfOx2HXyfEA8FGnlwidE/bFDxO7Q==", + "requires": { + "@babel/runtime": "^7.8.7", + "fn-name": "~3.0.0", + "lodash": "^4.17.15", + "lodash-es": "^4.17.11", + "property-expr": "^2.0.0", + "synchronous-promise": "^2.0.10", + "toposort": "^2.0.2" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" + } + } } } } diff --git a/package.json b/package.json index ac7cf9b9ed60208e70dfe115bf781c71247df0bd..7e622c12bee3695fcec81dc85ab8ad3e473ab53b 100644 --- a/package.json +++ b/package.json @@ -3,17 +3,22 @@ "version": "0.1.0", "private": true, "dependencies": { - "@material-ui/core": "^4.8.3", - "@material-ui/icons": "^4.5.1", + "@material-ui/core": "^4.9.7", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "^4.0.0-alpha.46", "@testing-library/jest-dom": "^4.2.4", - "@testing-library/react": "^9.4.0", + "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", "axios": "^0.19.2", + "formik": "^2.1.4", "material-ui": "^0.20.2", - "react": "^16.12.0", - "react-dom": "^16.12.0", + "react": "^16.13.1", + "react-beautiful-dnd": "^13.0.0", + "react-dom": "^16.13.1", + "react-os": "0.0.9", "react-router-dom": "^5.1.2", - "react-scripts": "3.3.0" + "react-scripts": "3.3.0", + "yup": "^0.28.3" }, "scripts": { "start": "react-scripts start", diff --git a/src/components/fieldsAnswerForm/FormFieldCheckbox.js b/src/components/fieldsAnswerForm/FormFieldCheckbox.js index 7b4adf5bcee7769442b311a8b9243a0811b966eb..462b63f1bd60af6128e7340f95ea291d5c43c3c5 100644 --- a/src/components/fieldsAnswerForm/FormFieldCheckbox.js +++ b/src/components/fieldsAnswerForm/FormFieldCheckbox.js @@ -1,41 +1,42 @@ -import React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import Grid from '@material-ui/core/Grid'; -import Paper from '@material-ui/core/Paper'; -import TextField from '@material-ui/core/TextField'; -import DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined'; -import IconButton from '@material-ui/core/IconButton'; -import Select from '@material-ui/core/Select'; -import MenuItem from '@material-ui/core/MenuItem'; -import AddCircleIcon from '@material-ui/icons/AddCircle'; -import CloseIcon from '@material-ui/icons/Close'; -import Switch from '@material-ui/core/Switch'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; -import Typography from '@material-ui/core/Typography'; -import Checkbox from '@material-ui/core/Checkbox'; +import React from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import Grid from "@material-ui/core/Grid"; +import Paper from "@material-ui/core/Paper"; +import TextField from "@material-ui/core/TextField"; +import DeleteOutlinedIcon from "@material-ui/icons/DeleteOutlined"; +import IconButton from "@material-ui/core/IconButton"; +import Select from "@material-ui/core/Select"; +import MenuItem from "@material-ui/core/MenuItem"; +import AddCircleIcon from "@material-ui/icons/AddCircle"; +import CloseIcon from "@material-ui/icons/Close"; +import Switch from "@material-ui/core/Switch"; +import FormControlLabel from "@material-ui/core/FormControlLabel"; +import Typography from "@material-ui/core/Typography"; +import Checkbox from "@material-ui/core/Checkbox"; -import FieldFooterOptions from './FieldFooterOptions'; +import FieldFooterOptions from "./FieldFooterOptions"; - -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ paper: { padding: theme.spacing(3), width: theme.spacing(100), minheight: theme.spacing(16), - margin: theme.spacing(2) + margin: theme.spacing(2), }, questionsGrid: { - marginBottom: '20px' + marginBottom: "20px", }, })); - - function FormFieldCheckbox(props) { const classes = useStyles(); - const options = props.options.map(function(x) { - return <span>{x.value} <Checkbox /></span>; + const options = props.options.map(function (x) { + return ( + <span> + {x.value} <Checkbox /> + </span> + ); }); return ( @@ -46,17 +47,20 @@ function FormFieldCheckbox(props) { {props.question} </Typography> </Grid> - <Grid item container + <Grid + item + container direction="column" justify="flex-start" - alignItems="flex-start" xs={5} className={classes.questionsGrid} + alignItems="flex-start" + xs={5} + className={classes.questionsGrid} > {options} </Grid> </Grid> </Paper> ); - } -export default FormFieldCheckbox; \ No newline at end of file +export default FormFieldCheckbox; diff --git a/src/components/fieldsCreateForm/DefaultField.js b/src/components/fieldsCreateForm/DefaultField.js new file mode 100644 index 0000000000000000000000000000000000000000..258abf4d0c754e0a914de6c2fc6416b6a4705f89 --- /dev/null +++ b/src/components/fieldsCreateForm/DefaultField.js @@ -0,0 +1,48 @@ +import React from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import Grid from "@material-ui/core/Grid"; +import TextField from "@material-ui/core/TextField"; +const useStyles = makeStyles((theme) => ({ + questionsGrid: { + marginBottom: "20px", + }, + errorGrid: { + marginTop: "1%", + color: "#ff4646", + width: "40%", + fontSize: "13px", + }, + textFieldStyle: { + width: "80%", + }, +})); + +export default function DefaultField(props) { + const classes = useStyles(); + return ( + <> + <Grid item xs={12} sm={6} className={classes.questionsGrid}> + <TextField + value={props.question} + label="Pergunta" + className={classes.textFieldStyle} + onChange={(e) => props.setQuestionField(e.target.value, props.idq)} + /> + <Grid className={classes.errorGrid}> + {props.error.errorMsg.question} + </Grid> + </Grid> + <Grid item xs={12} sm={6} className={classes.questionsGrid}> + <TextField + value={props.description} + label="Descrição" + className={classes.textFieldStyle} + onChange={(e) => props.setDescriptionField(e.target.value, props.idq)} + /> + <Grid className={classes.errorGrid}> + {props.error.errorMsg.description} + </Grid> + </Grid> + </> + ); +} diff --git a/src/components/fieldsCreateForm/FieldFooterOptions.js b/src/components/fieldsCreateForm/FieldFooterOptions.js index f6446f0b9fbd69735a1c055d79c59f301da37250..88902677418219d9f54192f9b1139561b556ae56 100644 --- a/src/components/fieldsCreateForm/FieldFooterOptions.js +++ b/src/components/fieldsCreateForm/FieldFooterOptions.js @@ -1,40 +1,45 @@ -import React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import Grid from '@material-ui/core/Grid'; -import Paper from '@material-ui/core/Paper'; -import TextField from '@material-ui/core/TextField'; -import DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined'; -import IconButton from '@material-ui/core/IconButton'; -import Select from '@material-ui/core/Select'; -import MenuItem from '@material-ui/core/MenuItem'; -import AddCircleIcon from '@material-ui/icons/AddCircle'; -import CloseIcon from '@material-ui/icons/Close'; -import Switch from '@material-ui/core/Switch'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; +import React from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import Grid from "@material-ui/core/Grid"; +import DeleteOutlinedIcon from "@material-ui/icons/DeleteOutlined"; +import IconButton from "@material-ui/core/IconButton"; +import Switch from "@material-ui/core/Switch"; +import FormControlLabel from "@material-ui/core/FormControlLabel"; +import Tooltip from "@material-ui/core/Tooltip"; +/** Main function that return the component's 'footer' options, handling the required validation and deleting the field as necessary. */ function FieldFooterOptions(props) { - - return ( - <> - <FormControlLabel - control={ - <Switch - onChange={e => props.setRequiredField(props.idq) } - value="required" - color="primary" - checked={props.required} - /> - } - label="Obrigatória" - /> - <IconButton aria-label="delete" onClick={() => { props.deleteFromForm(props.idq) } }> - <DeleteOutlinedIcon /> - </IconButton> - </> - ); - - + return ( + <Grid> + <FormControlLabel + control={ + <Tooltip + title="Marcar como obrigatório" + aria-label="Marcar como obrigatório" + > + <Switch + onChange={(e) => props.setRequiredField(props.idq)} + value="required" + color="primary" + checked={props.required} + /> + </Tooltip> + } + style={{ size: "0px" }} + label="Obrigatória" + /> + <Tooltip title="Remover a pergunta" aria-label="Remover a pergunta"> + <IconButton + aria-label="Remover a pergunta" + onClick={() => { + props.deleteFromForm(props.idq); + }} + > + <DeleteOutlinedIcon /> + </IconButton> + </Tooltip> + </Grid> + ); } - -export default FieldFooterOptions; \ No newline at end of file +export default FieldFooterOptions; diff --git a/src/components/fieldsCreateForm/FormFieldCheckbox.js b/src/components/fieldsCreateForm/FormFieldCheckbox.js index c4f88cdb7b2f7fd0b3855755d220effae4145d65..fc8d1ba6336ab08b03437feb9fcc41f0f44f79b8 100644 --- a/src/components/fieldsCreateForm/FormFieldCheckbox.js +++ b/src/components/fieldsCreateForm/FormFieldCheckbox.js @@ -1,98 +1,194 @@ -import React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import Grid from '@material-ui/core/Grid'; -import Paper from '@material-ui/core/Paper'; -import TextField from '@material-ui/core/TextField'; -import DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined'; -import IconButton from '@material-ui/core/IconButton'; -import Select from '@material-ui/core/Select'; -import MenuItem from '@material-ui/core/MenuItem'; -import AddCircleIcon from '@material-ui/icons/AddCircle'; -import CloseIcon from '@material-ui/icons/Close'; -import Switch from '@material-ui/core/Switch'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; -import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'; +import React from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import Grid from "@material-ui/core/Grid"; +import Paper from "@material-ui/core/Paper"; +import TextField from "@material-ui/core/TextField"; +import IconButton from "@material-ui/core/IconButton"; +import AddCircleIcon from "@material-ui/icons/AddCircle"; +import CloseIcon from "@material-ui/icons/Close"; +import CheckBoxOutlineBlankIcon from "@material-ui/icons/CheckBoxOutlineBlank"; +import Tooltip from "@material-ui/core/Tooltip"; +import FieldFooterOptions from "./FieldFooterOptions"; +import { Draggable } from "react-beautiful-dnd"; +import DefaultField from "./DefaultField"; - -import FieldFooterOptions from './FieldFooterOptions'; - - -const useStyles = makeStyles(theme => ({ +/** CSS styles used on page components. */ +const useStyles = makeStyles((theme) => ({ paper: { padding: theme.spacing(3), width: theme.spacing(100), - minheight: theme.spacing(16), - margin: theme.spacing(2) + ["@media (max-width:1050px)"]: { + width: theme.spacing(63), + ["@media (max-width:849px)"]: { + width: "100%", + }, + }, + marginBottom: "2%", + ["@media (min-width:600px)"]: { + marginLeft: "4%", + }, }, questionsGrid: { - marginBottom: '20px' + marginBottom: "20px", + }, + errorGrid: { + marginTop: "1%", + color: "#ff4646", + width: "40%", + fontSize: "13px", + }, + textFieldStyle: { + width: "80%", + }, + iconAdjustment: { + marginTop: "17px", }, })); - - - +/** Main function that returns the 'checkbox' field. */ function FormFieldCheckbox(props) { const classes = useStyles(); return ( - <Paper className={classes.paper}> - <Grid container> - <Grid item xs={12} className={classes.questionsGrid}> - <TextField value={props.question} label="sua pergunta" - onChange={e => props.setQuestionField(e.target.value, props.idq)}/> - </Grid> - <Grid item container - direction="column" - justify="flex-start" - alignItems="flex-start" xs={5} className={classes.questionsGrid} - > - { - props.options.map((x, index) => { - return <Grid container> - <Grid item container - justify="center" - alignItems="center" - xs={1} - > - <CheckBoxOutlineBlankIcon/> - </Grid> - <Grid item xs={10}> - <TextField label={"opção "+index} value={x} fullWidth - onChange={e => props.setSelectOption(e.target.value, props.idq, index)} /> + <Draggable key={props.id} draggableId={props.id} index={props.idq}> + {(provided, snapshot) => { + return ( + <Paper + className={classes.paper} + ref={provided.innerRef} + {...provided.draggableProps} + {...provided.dragHandleProps} + > + <Grid container> + <DefaultField + question={props.question} + description={props.description} + idq={props.idq} + setQuestionField={props.setQuestionField} + setDescriptionField={props.setDescriptionField} + error={props.error} + /> + <Grid + item + container + direction="column" + justify="flex-start" + alignItems="flex-start" + xs={12} + sm={8} + className={classes.questionsGrid} + > + {props.options.map((x, index) => { + return ( + <Grid container> + <Grid + item + container + justify="center" + alignItems="center" + xs={1} + className={ + props.error.errorMsg.options[index] + ? null + : classes.iconAdjustment + } + > + <CheckBoxOutlineBlankIcon /> </Grid> - <Grid item xs={1}> - <IconButton aria-label="remove option" - onClick={() => { props.removeSelectOption(props.idq, index) } }> - <CloseIcon /> - </IconButton> + <Grid item xs={8}> + <TextField + label={"Opção " + index} + value={x} + className={classes.textFieldStyle} + onChange={(e) => + props.setSelectOption( + e.target.value, + props.idq, + index + ) + } + /> + <Grid + item + className={classes.errorGrid} + style={{ width: "100%" }} + > + {props.error.errorMsg.options[index]} + </Grid> + </Grid> + <Grid item xs={2}> + <Tooltip + title="Remover a opção" + aria-label="Remover a opção" + > + <IconButton + aria-label="remove option" + onClick={() => { + props.removeSelectOption(props.idq, index); + }} + > + <CloseIcon /> + </IconButton> + </Tooltip> </Grid> </Grid> - }) - } - </Grid> - <Grid item container - direction="column" - justify="flex-start" - alignItems="flex-start" - xs={4} - > - <IconButton aria-label="add option" onClick={() => { props.addSelectOption(props.idq) } }> - <AddCircleIcon /> - </IconButton> - </Grid> - <Grid item container - direction="row" - justify="flex-end" - alignItems="flex-end" - xs={3} - > - <FieldFooterOptions deleteFromForm={props.deleteFromForm} idq={props.idq} - setRequiredField={props.setRequiredField} required={props.required}/> - </Grid> - </Grid> - </Paper> + ); + })} + </Grid> + <Grid + item + className={classes.errorGrid} + container + direction="column" + justify="flex-start" + alignItems="flex-start" + sm={4} //antes era 3 + xs={12} + > + {props.error.errorMsg.optionsNumber} + </Grid> + <Grid + item + container + direction="column" + alignItems="center" + xs={6} + > + <Tooltip + title="Adicionar uma nova opção" + aria-label="Adicionar uma nova opção" + > + <IconButton + aria-label="add option" + onClick={() => { + props.addSelectOption(props.idq); + }} + > + <AddCircleIcon /> + </IconButton> + </Tooltip> + </Grid> + <Grid + item + container + direction="row" + justify="flex-end" + alignItems="flex-end" + sm={6} + xs={12} + > + <FieldFooterOptions + deleteFromForm={props.deleteFromForm} + idq={props.idq} + setRequiredField={props.setRequiredField} + required={props.validation[0].value} + /> + </Grid> + </Grid> + </Paper> + ); + }} + </Draggable> ); - } -export default FormFieldCheckbox; \ No newline at end of file +export default FormFieldCheckbox; diff --git a/src/components/fieldsCreateForm/FormFieldRadio.js b/src/components/fieldsCreateForm/FormFieldRadio.js index ce10709559547929e966015952f0e48e8dd03d4a..95185698c0a67bd31cddba665afdd2ab1a793301 100644 --- a/src/components/fieldsCreateForm/FormFieldRadio.js +++ b/src/components/fieldsCreateForm/FormFieldRadio.js @@ -1,97 +1,193 @@ -import React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import Grid from '@material-ui/core/Grid'; -import Paper from '@material-ui/core/Paper'; -import TextField from '@material-ui/core/TextField'; -import DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined'; -import IconButton from '@material-ui/core/IconButton'; -import Select from '@material-ui/core/Select'; -import MenuItem from '@material-ui/core/MenuItem'; -import AddCircleIcon from '@material-ui/icons/AddCircle'; -import CloseIcon from '@material-ui/icons/Close'; -import Switch from '@material-ui/core/Switch'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; -import RadioButtonUncheckedIcon from '@material-ui/icons/RadioButtonUnchecked'; +import React from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import Grid from "@material-ui/core/Grid"; +import Paper from "@material-ui/core/Paper"; +import TextField from "@material-ui/core/TextField"; +import IconButton from "@material-ui/core/IconButton"; +import AddCircleIcon from "@material-ui/icons/AddCircle"; +import CloseIcon from "@material-ui/icons/Close"; +import RadioButtonUncheckedIcon from "@material-ui/icons/RadioButtonUnchecked"; +import Tooltip from "@material-ui/core/Tooltip"; +import { Draggable } from "react-beautiful-dnd"; +import FieldFooterOptions from "./FieldFooterOptions"; +import DefaultField from "./DefaultField"; -import FieldFooterOptions from './FieldFooterOptions'; - - -const useStyles = makeStyles(theme => ({ +/** CSS styles used on page components. */ +const useStyles = makeStyles((theme) => ({ paper: { padding: theme.spacing(3), width: theme.spacing(100), - minheight: theme.spacing(16), - margin: theme.spacing(2) + ["@media (max-width:1050px)"]: { + width: theme.spacing(63), + ["@media (max-width:849px)"]: { + width: "100%", + }, + }, + marginBottom: "2%", + ["@media (min-width:600px)"]: { + marginLeft: "4%", + }, }, questionsGrid: { - marginBottom: '20px' + marginBottom: "20px", + }, + errorGrid: { + marginTop: "1%", + color: "#ff4646", + width: "40%", + fontSize: "13px", + }, + textFieldStyle: { + width: "80%", + }, + iconAdjustment: { + marginTop: "17px", }, })); - - - +/** Main function that returns the 'radio' field. */ function FormFieldRadio(props) { const classes = useStyles(); return ( - <Paper className={classes.paper}> - <Grid container> - <Grid item xs={12} className={classes.questionsGrid}> - <TextField value={props.question} label="sua pergunta" - onChange={e => props.setQuestionField(e.target.value, props.idq)}/> - </Grid> - <Grid item container - direction="column" - justify="flex-start" - alignItems="flex-start" xs={5} className={classes.questionsGrid} - > - { - props.options.map((x, index) => { - return <Grid container> - <Grid item container - justify="center" - alignItems="center" - xs={1} - > - <RadioButtonUncheckedIcon/> - </Grid> - <Grid item xs={10}> - <TextField label={"opção "+index} value={x} fullWidth - onChange={e => props.setSelectOption(e.target.value, props.idq, index)} /> + <Draggable key={props.id} draggableId={props.id} index={props.idq}> + {(provided, snapshot) => { + return ( + <Paper + className={classes.paper} + ref={provided.innerRef} + {...provided.draggableProps} + {...provided.dragHandleProps} + > + <Grid container> + <DefaultField + question={props.question} + description={props.description} + idq={props.idq} + setQuestionField={props.setQuestionField} + setDescriptionField={props.setDescriptionField} + error={props.error} + /> + <Grid + item + container + direction="column" + justify="flex-start" + alignItems="flex-start" + xs={12} + sm={8} + className={classes.questionsGrid} + > + {props.options.map((x, index) => { + return ( + <Grid container> + <Grid + item + container + justify="center" + alignItems="center" + xs={1} + className={ + props.error.errorMsg.options[index] + ? null + : classes.iconAdjustment + } + > + <RadioButtonUncheckedIcon /> </Grid> - <Grid item xs={1}> - <IconButton aria-label="remove option" - onClick={() => { props.removeSelectOption(props.idq, index) } }> - <CloseIcon /> - </IconButton> + <Grid item xs={8}> + <TextField + label={"Opção " + index} + value={x} + className={classes.textFieldStyle} + onChange={(e) => + props.setSelectOption( + e.target.value, + props.idq, + index + ) + } + /> + <Grid + item + className={classes.errorGrid} + style={{ width: "100%" }} + > + {props.error.errorMsg.options[index]} + </Grid> + </Grid> + <Grid item xs={2}> + <Tooltip + title="Remover a opção" + aria-label="Remover a opção" + > + <IconButton + onClick={() => { + props.removeSelectOption(props.idq, index); + }} + > + <CloseIcon /> + </IconButton> + </Tooltip> </Grid> </Grid> - }) - } - </Grid> - <Grid item container - direction="column" - justify="flex-start" - alignItems="flex-start" - xs={4} - > - <IconButton aria-label="add option" onClick={() => { props.addSelectOption(props.idq) } }> - <AddCircleIcon /> - </IconButton> - </Grid> - <Grid item container - direction="row" - justify="flex-end" - alignItems="flex-end" - xs={3} - > - <FieldFooterOptions deleteFromForm={props.deleteFromForm} idq={props.idq} - setRequiredField={props.setRequiredField} required={props.required} /> - </Grid> - </Grid> - </Paper> + ); + })} + </Grid> + <Grid + item + className={classes.errorGrid} + container + direction="column" + justify="flex-start" + alignItems="flex-start" + sm={4} + xs={12} + > + {props.error.errorMsg.optionsNumber} + </Grid> + <Grid + item + container + direction="column" + alignItems="center" + xs={6} + > + <Tooltip + title="Adicionar uma nova opção" + aria-label="Adicionar uma nova opção" + > + <IconButton + aria-label="adicionar opção" + onClick={() => { + props.addSelectOption(props.idq); + }} + > + <AddCircleIcon /> + </IconButton> + </Tooltip> + </Grid> + <Grid + item + container + direction="row" + justify="flex-end" + alignItems="flex-end" + xs={12} + sm={6} + > + <FieldFooterOptions + deleteFromForm={props.deleteFromForm} + idq={props.idq} + setRequiredField={props.setRequiredField} + required={props.validation[0].value} + /> + </Grid> + </Grid> + </Paper> + ); + }} + </Draggable> ); - } -export default FormFieldRadio; \ No newline at end of file +export default FormFieldRadio; diff --git a/src/components/fieldsCreateForm/FormFieldSelect.js b/src/components/fieldsCreateForm/FormFieldSelect.js index 3158b466acf45f9495309eade1ac2859283e6fb0..7555ef581b0f05d45f3de63a238616f2b06924e7 100644 --- a/src/components/fieldsCreateForm/FormFieldSelect.js +++ b/src/components/fieldsCreateForm/FormFieldSelect.js @@ -1,89 +1,179 @@ -import React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import Grid from '@material-ui/core/Grid'; -import Paper from '@material-ui/core/Paper'; -import TextField from '@material-ui/core/TextField'; -import DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined'; -import IconButton from '@material-ui/core/IconButton'; -import Select from '@material-ui/core/Select'; -import MenuItem from '@material-ui/core/MenuItem'; -import AddCircleIcon from '@material-ui/icons/AddCircle'; -import CloseIcon from '@material-ui/icons/Close'; -import Switch from '@material-ui/core/Switch'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; +import React from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import Grid from "@material-ui/core/Grid"; +import Paper from "@material-ui/core/Paper"; +import TextField from "@material-ui/core/TextField"; +import IconButton from "@material-ui/core/IconButton"; +import AddCircleIcon from "@material-ui/icons/AddCircle"; +import CloseIcon from "@material-ui/icons/Close"; +import Tooltip from "@material-ui/core/Tooltip"; +import FieldFooterOptions from "./FieldFooterOptions"; +import { Draggable } from "react-beautiful-dnd"; +import DefaultField from "./DefaultField"; -import FieldFooterOptions from './FieldFooterOptions'; - - -const useStyles = makeStyles(theme => ({ +/** CSS styles used on page components. */ +const useStyles = makeStyles((theme) => ({ paper: { padding: theme.spacing(3), width: theme.spacing(100), - minheight: theme.spacing(16), - margin: theme.spacing(2) + ["@media (max-width:1050px)"]: { + width: theme.spacing(63), + ["@media (max-width:849px)"]: { + width: "100%", + }, + }, + marginBottom: "2%", + ["@media (min-width:600px)"]: { + marginLeft: "4%", + }, }, questionsGrid: { - marginBottom: '20px' + marginBottom: "20px", + }, + errorGrid: { + marginTop: "1%", + color: "#ff4646", + width: "40%", + fontSize: "13px", + }, + errorGridOpts: { + marginTop: "1%", + color: "#ff4646", + width: "100%", + fontSize: "13px", + }, + textFieldStyle: { + width: "80%", }, })); - - - +/** Main function that returns the 'select' field. */ function FormFieldSelect(props) { + /** Style class. */ const classes = useStyles(); - return ( - <Paper className={classes.paper}> - <Grid container> - <Grid item xs={12} className={classes.questionsGrid}> - <TextField value={props.question} label="sua pergunta" - onChange={e => props.setQuestionField(e.target.value, props.idq)}/> - </Grid> - <Grid item container - direction="column" - justify="flex-start" - alignItems="flex-start" xs={5} className={classes.questionsGrid} - > - { - props.options.map((x, index) => { - return <Grid container> - <Grid item xs={11}> - <TextField label={"opção "+index} value={x} fullWidth - onChange={e => props.setSelectOption(e.target.value, props.idq, index)} /> + <Draggable key={props.id} draggableId={props.id} index={props.idq}> + {(provided, snapshot) => { + return ( + <Paper + className={classes.paper} + ref={provided.innerRef} + {...provided.draggableProps} + {...provided.dragHandleProps} + > + <Grid container> + <DefaultField + question={props.question} + description={props.description} + idq={props.idq} + setQuestionField={props.setQuestionField} + setDescriptionField={props.setDescriptionField} + error={props.error} + /> + <Grid + item + container + direction="column" + justify="flex-start" + alignItems="flex-start" + xs={12} + sm={8} + className={classes.questionsGrid} + > + {props.options.map((x, index) => { + return ( + <Grid container> + <Grid itemxs={1}></Grid> + <Grid item xs={10}> + <TextField + label={"Opção " + index} + value={x} + className={classes.textFieldStyle} + onChange={(e) => + props.setSelectOption( + e.target.value, + props.idq, + index + ) + } + /> + <Grid item className={classes.errorGridOpts}> + {props.error.errorMsg.options[index]} + </Grid> </Grid> <Grid item xs={1}> - <IconButton aria-label="remove option" - onClick={() => { props.removeSelectOption(props.idq, index) } }> - <CloseIcon /> - </IconButton> + <Tooltip + title="Remover a opção" + aria-label="Remover a opção" + > + <IconButton + aria-label="remove option" + onClick={() => { + props.removeSelectOption(props.idq, index); + }} + > + <CloseIcon /> + </IconButton> + </Tooltip> </Grid> </Grid> - }) - } - </Grid> - <Grid item container - direction="column" - justify="flex-start" - alignItems="flex-start" - xs={4} - > - <IconButton aria-label="add option" onClick={() => { props.addSelectOption(props.idq) } }> - <AddCircleIcon /> - </IconButton> - </Grid> - <Grid item container - direction="row" - justify="flex-end" - alignItems="flex-end" - xs={3} - > - <FieldFooterOptions deleteFromForm={props.deleteFromForm} idq={props.idq} - setRequiredField={props.setRequiredField} required={props.required} /> - </Grid> - </Grid> - </Paper> + ); + })} + </Grid> + <Grid + item + className={classes.errorGrid} + container + direction="column" + justify="flex-start" + alignItems="flex-start" + sm={4} + xs={12} + > + {props.error.errorMsg.optionsNumber} + </Grid> + <Grid + item + container + direction="column" + alignItems="center" + xs={6} + > + <Tooltip + title="Adicionar uma nova opção" + aria-label="Adicionar uma nova opção" + > + <IconButton + aria-label="add option" + onClick={() => { + props.addSelectOption(props.idq); + }} + > + <AddCircleIcon /> + </IconButton> + </Tooltip> + </Grid> + <Grid + item + container + direction="row" + justify="flex-end" + alignItems="flex-end" + sm={6} + xs={12} + > + <FieldFooterOptions + deleteFromForm={props.deleteFromForm} + idq={props.idq} + setRequiredField={props.setRequiredField} + required={props.validation[0].value} + /> + </Grid> + </Grid> + </Paper> + ); + }} + </Draggable> ); - } -export default FormFieldSelect; \ No newline at end of file +export default FormFieldSelect; diff --git a/src/components/fieldsCreateForm/FormFieldSubform.js b/src/components/fieldsCreateForm/FormFieldSubform.js new file mode 100644 index 0000000000000000000000000000000000000000..628b6b362ce977108f2a67f16c2807dd3f5765de --- /dev/null +++ b/src/components/fieldsCreateForm/FormFieldSubform.js @@ -0,0 +1,219 @@ +import React, { useEffect } from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import Grid from "@material-ui/core/Grid"; +import Paper from "@material-ui/core/Paper"; +import TextField from "@material-ui/core/TextField"; +import api from "../../api"; +import FieldFooterOptions from "./FieldFooterOptions"; +import Select from "@material-ui/core/Select"; +import MenuItem from "@material-ui/core/MenuItem"; +import FormControl from "@material-ui/core/FormControl"; +import InputLabel from "@material-ui/core/InputLabel"; +import InfoIcon from "@material-ui/icons/Info"; +import { Draggable } from "react-beautiful-dnd"; +import Tooltip from "@material-ui/core/Tooltip"; +import DefaultField from "./DefaultField"; + +/** CSS styles used on page components. */ +const useStyles = makeStyles((theme) => ({ + paper: { + padding: theme.spacing(3), + width: theme.spacing(100), + ["@media (max-width:1050px)"]: { + width: theme.spacing(63), + ["@media (max-width:849px)"]: { + width: "100%", + }, + }, + marginBottom: "2%", + ["@media (min-width:600px)"]: { + marginLeft: "4%", + }, + }, + questionsGrid: { + marginBottom: "20px", + }, + subformSelect: { + width: "90%", + }, + errorGrid: { + marginTop: "1%", + color: "#ff4646", + width: "40%", + fontSize: "13px", + }, + errorGridSubform: { + color: "#ff4646", + marginTop: "2%", + width: "100%", + fontSize: "13px", + }, + textFieldStyle: { + width: "80%", + }, + textFieldDescriptionStyle: { + width: "96%", + ["@media (max-width: 600px)"]: { + width: "80%", + }, + }, + tooltipAdjustment: { + ["@media (max-width: 600px)"]: { + flexDirection: "column-reverse", + }, + }, + footerOptsAdjustment: { + ["@media (min-width: 600px)"]: { + marginBottom: "3%", + }, + }, +})); + +/** Function that returns the component to select te subform to be used. */ +function SubformSelect(props) { + /** State to store the form being used. */ + const [usedForm, setUsedForm] = React.useState({}); + /** Style class. */ + const classes = useStyles(); + /** State to manage errors. */ + const [error, setError] = React.useState(true); + /** Functions that handle the input changes to save it at the father component. */ + const handleChange = (event) => { + setUsedForm(props.array.filter((x) => x.id === event.target.value)); + props.setSubformId(event.target.value, props.idq); + setError(false); + }; + /** Initial error state setting. */ + useEffect(() => { + if ( + props.error.errorMsg.subformUsage || + props.error.errorMsg.subformSelected + ) + setError(true); + }, []); + + return ( + <FormControl variant="outlined" className={classes.subformSelect}> + <InputLabel + // style={{ fontSize: "5px" }} + className={classes.subformSelect} + id="demo-simple-select-outlined-label" + htmlFor="outlined-subform-simple" + > + Selecione um formulário + </InputLabel> + <Select + labelId="demo-simple-select-outlined-label" + id="demo-simple-select-outlined" + value={usedForm.title} + renderValue={usedForm.title} + onChange={handleChange} + label="Selecione um subformulário" + style={{ width: "100%" }} + error={error ? true : false} + > + {props.array.length > 0 ? ( + props.array.map((form) => ( + <MenuItem key={form.id} value={form.id}> + {form.title} + </MenuItem> + )) + ) : ( + <MenuItem key={0} value={0} disabled> + {"Você não tem formulários para usar aqui"} + </MenuItem> + )} + </Select> + </FormControl> + ); +} +/** Main function that returns the 'subform' field. */ +export default function FormFieldSubform(props) { + /** Style class. */ + const classes = useStyles(); + /** State to store the subform options the user can use. */ + const [forms, setForms] = React.useState([]); + /** UseEffect to make an api call and list the forms the current user has to be used as subform. */ + useEffect(() => { + const fetchData = async () => { + var forms_response = await api + .get(`/user/list/${window.sessionStorage.getItem("userId")}`, {}) + .then((response) => { + setForms(response.data); + }); + }; + fetchData(); + }, []); + return ( + <Draggable key={props.id} draggableId={props.id} index={props.idq}> + {(provided, snapshot) => { + return ( + <Paper + className={classes.paper} + ref={provided.innerRef} + {...provided.draggableProps} + {...provided.dragHandleProps} + > + <Grid container> + <Grid container item className={classes.tooltipAdjustment}> + <Grid container item xs={11}> + <DefaultField + question={props.question} + description={props.description} + idq={props.idq} + setQuestionField={props.setQuestionField} + setDescriptionField={props.setDescriptionField} + error={props.error} + /> + </Grid> + <Grid + container + item + xs={12} + sm={1} + className={classes.questionsGrid} + > + <Tooltip + // style={{ position: "absolute" }} + title="Por favor, reordene este campo antes de lhe atribuir valor" + aria-label="Por favor, reordene este campo antes de lhe atribuir valor" + > + <InfoIcon /> + </Tooltip> + </Grid> + </Grid> + <Grid item xs={12} sm={6} className={classes.questionsGrid}> + <SubformSelect + array={forms} + setSubformId={props.setSubformId} + idq={props.idq} + error={props.error} + /> + </Grid> + <Grid item sm={2} xs={12} className={classes.errorGridSubform}> + {props.error.errorMsg.subformUsage} + </Grid> + <Grid + item + container + direction="row" + justify="flex-end" + alignItems="flex-end" + xs={12} + sm={4} + className={classes.footerOptsAdjustment} + > + <FieldFooterOptions + deleteFromForm={props.deleteFromForm} + idq={props.idq} + setRequiredField={props.setRequiredField} + required={props.validation[0].value} + /> + </Grid> + </Grid> + </Paper> + ); + }} + </Draggable> + ); +} diff --git a/src/components/fieldsCreateForm/FormFieldText.js b/src/components/fieldsCreateForm/FormFieldText.js index 7b032df32bef6d8a69b7730ea78b21821a3dfb85..6fc95fb06f26a79882eefb5dd44351334d4b9778 100644 --- a/src/components/fieldsCreateForm/FormFieldText.js +++ b/src/components/fieldsCreateForm/FormFieldText.js @@ -1,56 +1,210 @@ -import React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import Grid from '@material-ui/core/Grid'; -import Paper from '@material-ui/core/Paper'; -import TextField from '@material-ui/core/TextField'; -import DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined'; -import IconButton from '@material-ui/core/IconButton'; +import React, { useEffect } from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import Grid from "@material-ui/core/Grid"; +import Paper from "@material-ui/core/Paper"; +import TextField from "@material-ui/core/TextField"; +import IconButton from "@material-ui/core/IconButton"; +import Select from "@material-ui/core/Select"; +import MenuItem from "@material-ui/core/MenuItem"; +import Tooltip from "@material-ui/core/Tooltip"; +import AddCircleIcon from "@material-ui/icons/AddCircle"; +import FormControl from "@material-ui/core/FormControl"; +import InputLabel from "@material-ui/core/InputLabel"; +import InfoIcon from "@material-ui/icons/Info"; +import { Draggable } from "react-beautiful-dnd"; +import FieldFooterOptions from "./FieldFooterOptions"; +import DefaultField from "./DefaultField"; -import FieldFooterOptions from './FieldFooterOptions'; - -const useStyles = makeStyles(theme => ({ +/** CSS styles used on page components. */ +const useStyles = makeStyles((theme) => ({ paper: { padding: theme.spacing(3), width: theme.spacing(100), - height: theme.spacing(16), - margin: theme.spacing(2) + ["@media (max-width:1050px)"]: { + width: theme.spacing(63), + ["@media (max-width:849px)"]: { + width: "100%", + }, + }, + marginBottom: "2%", + ["@media (min-width:600px)"]: { + marginLeft: "4%", + }, }, questionsGrid: { - marginBottom: '20px' + marginBottom: "20px", + }, + errorGrid: { + marginTop: "1%", + color: "#ff4646", + width: "40%", + fontSize: "13px", + }, + row: { + display: "flex", + flexDirection: "row", }, })); - +/** Main function that returns the content of the option 'question'. */ function FormFieldText(props) { + /** Style class. */ const classes = useStyles(); + /** Representation of the possible 'extra' validations to be used. */ + const validationOpts = [ + { type: "minChar", name: "Mínimo de caracteres", value: "" }, + { type: "maxChar", name: "Máximo de caracteres", value: "" }, + ]; + /** State to store the validation being used. */ + const [usedValidation, setUsedValidation] = React.useState(); + /** State to manage error properties. */ + const [error, setError] = React.useState(true); + /** An specific handle change function that updates the type of the chosen validation. */ + const handleChangeType = (event) => { + setUsedValidation(validationOpts[event.target.value]); + setError(false); + }; + /** An specific handle change function that updates the value of the chosen validation. */ + const handleChangeValue = (event) => { + setUsedValidation({ + type: usedValidation.type, + name: usedValidation.name, + value: event.target.value, + }); + }; + /** useEffect being used as a handle change function to send data (the chosen type of validation and the value) to the father component. */ + useEffect(() => { + if (usedValidation) { + props.setValidation(usedValidation, props.idq); + } + }, [usedValidation]); return ( - <Paper className={classes.paper}> - <Grid container> - <Grid item xs={12} className={classes.questionsGrid}> - <TextField value={props.question} label="sua pergunta" - onChange={e => props.setQuestionField(e.target.value, props.idq)}/> - </Grid> - <Grid item xs={9} className={classes.questionsGrid}> - <TextField - disabled - id="outlined-disabled" - label="" - defaultValue="Resposta curta" - /> - </Grid> - <Grid item container - direction="row" - justify="flex-end" - alignItems="flex-end" - xs={3} - > - <FieldFooterOptions deleteFromForm={props.deleteFromForm} idq={props.idq} - setRequiredField={props.setRequiredField} required={props.required} /> - </Grid> - </Grid> - </Paper> + <Draggable key={props.id} draggableId={props.id} index={props.idq}> + {(provided, snapshot) => { + return ( + <Paper + className={classes.paper} + ref={provided.innerRef} + {...provided.draggableProps} + {...provided.dragHandleProps} + > + <Grid container> + <DefaultField + question={props.question} + description={props.description} + idq={props.idq} + setQuestionField={props.setQuestionField} + setDescriptionField={props.setDescriptionField} + error={props.error} + /> + <Grid item xs={12} sm={8} className={classes.questionsGrid}> + <TextField + disabled + id="outlined-disabled" + label="" + defaultValue="Resposta curta" + /> + </Grid> + <Grid + item + container + direction="row" + justify="flex-end" + alignItems="flex-end" + xs={12} + sm={4} + className={classes.row} + > + <FieldFooterOptions + deleteFromForm={props.deleteFromForm} + idq={props.idq} + setRequiredField={props.setRequiredField} + required={props.validation[0].value} + /> + </Grid> + </Grid> + {props.validation.length > 1 ? ( + <FormControl variant="outlined" className={classes.row}> + <Grid item xs={12} sm={5} className={classes.questionsGrid}> + <InputLabel + className={classes.subformSelect} + id="demo-simple-select-outlined-label" + htmlFor="outlined-subform-simple" + > + Selecione uma validação + </InputLabel> + <Select + labelId="demo-simple-select-outlined-label" + id="demo-simple-select-outlined" + onChange={handleChangeType} + label="Selecione uma validação" + style={{ minWidth: "250px" }} + error={error ? true : false} + > + {validationOpts.map((x, index) => ( + <MenuItem key={index} value={index}> + {x.name} + </MenuItem> + ))} + </Select> + </Grid> + <Grid + container + item + xs={12} + sm={1} + className={classes.questionsGrid} + > + <Tooltip + // style={{ position: "absolute" }} + title="Por favor, reordene este campo antes de lhe atribuir valor" + aria-label="Por favor, reordene este campo antes de lhe atribuir valor" + > + <InfoIcon /> + </Tooltip> + </Grid> + {usedValidation ? ( + <Grid item xs={12} sm={4} className={classes.questionsGrid}> + <TextField + style={{ width: "45%" }} + label="Quantidade" + value={usedValidation.value} + onChange={handleChangeValue} + /> + <Grid className={classes.errorGrid}> + {props.error.errorMsg.validation.value} + </Grid> + </Grid> + ) : null} + </FormControl> + ) : ( + <Grid + item + container + direction="column" + alignItems="center" + xs={6} + > + <Tooltip + title="Adicionar uma validação para a resposta" + aria-label="Adicionar uma validação para a resposta" + > + <IconButton + aria-label="adicionar opção" + onClick={() => { + props.addValidation(props.idq); + }} + > + <AddCircleIcon /> + </IconButton> + </Tooltip> + </Grid> + )} + </Paper> + ); + }} + </Draggable> ); - } -export default FormFieldText; \ No newline at end of file +export default FormFieldText; diff --git a/src/components/fieldsCreateForm/FormFieldTitle.js b/src/components/fieldsCreateForm/FormFieldTitle.js index 019765277d39183f827570683cf2417ca117fc40..2042a9c89fb7e92e9638d62876615c7f55b4b785 100644 --- a/src/components/fieldsCreateForm/FormFieldTitle.js +++ b/src/components/fieldsCreateForm/FormFieldTitle.js @@ -1,66 +1,84 @@ -import React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import Grid from '@material-ui/core/Grid'; -import Paper from '@material-ui/core/Paper'; -import TextField from '@material-ui/core/TextField'; -import DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined'; -import IconButton from '@material-ui/core/IconButton'; +import React from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import Grid from "@material-ui/core/Grid"; +import Paper from "@material-ui/core/Paper"; +import TextField from "@material-ui/core/TextField"; -import FieldFooterOptions from './FieldFooterOptions'; - -const useStyles = makeStyles(theme => ({ +/** CSS styles used on page components. */ +const useStyles = makeStyles((theme) => ({ paper: { padding: theme.spacing(3), width: theme.spacing(100), - height: theme.spacing(16), - margin: theme.spacing(2) + ["@media (max-width:1050px)"]: { + width: theme.spacing(63), + ["@media (max-width:849px)"]: { + width: "100%", + }, + }, + marginBottom: "2%", + ["@media (min-width:600px)"]: { + marginLeft: "4%", + }, }, questionsGrid: { - marginBottom: '20px' - }, - title: { - fontSize: 'xx-large' - }, - description: { - fontSize: 'x-large' - }, + marginBottom: "20px", + }, + title: { + fontSize: "xx-large", + }, + description: { + fontSize: "x-large", + }, + errorGrid: { + marginTop: "1%", + color: "#ff4646", + width: "40%", + fontSize: "13px", + }, })); - +/** Main function that returns the 'title' field. */ function FormFieldText(props) { + /** Style class. */ const classes = useStyles(); return ( <Paper className={classes.paper}> - <Grid container> - <Grid item xs={12} className={classes.questionsGrid}> - <TextField value={props.question} label="Formulário sem título" fullWidth - onChange={e => props.setTitleField(e.target.value, props.idq)} - InputProps={{ - classes: { - input: classes.title, - }, - }}/> - </Grid> - <Grid item xs={9} className={classes.questionsGrid}> - <TextField value={props.question} label="Descrição do formulário" - onChange={e => props.setDescriptionField(e.target.value, props.idq)} - InputProps={{ - classes: { - input: classes.description, - }, - }}/> - </Grid> - <Grid item container - direction="row" - justify="flex-end" - alignItems="flex-end" - xs={3} - > + <TextField + value={props.question} + label="Título do formulário" + fullWidth + onChange={(e) => props.setTitleField(e.target.value, props.idq)} + InputProps={{ + classes: { + input: classes.title, + }, + }} + /> + <Grid className={classes.errorGrid}>{props.error.errorMsg.question}</Grid> + <Grid item xs={9} className={classes.questionsGrid}> + <TextField + label="Descrição do formulário" + onChange={(e) => props.setDescriptionField(e.target.value, props.idq)} + InputProps={{ + classes: { + input: classes.description, + }, + }} + /> + <Grid className={classes.errorGrid}> + {props.error.errorMsg.description} </Grid> </Grid> + <Grid + item + container + direction="row" + justify="flex-end" + alignItems="flex-end" + xs={3} + ></Grid> </Paper> ); - } -export default FormFieldText; \ No newline at end of file +export default FormFieldText; diff --git a/src/components/fieldsCreateForm/SideMenu.js b/src/components/fieldsCreateForm/SideMenu.js new file mode 100644 index 0000000000000000000000000000000000000000..fb514928cd5d7e42ef2880edc25e60d98d36f084 --- /dev/null +++ b/src/components/fieldsCreateForm/SideMenu.js @@ -0,0 +1,128 @@ +import React, { useState } from "react"; +import Paper from "@material-ui/core/Paper"; +import TextField from "@material-ui/core/TextField"; +import AddIcon from "@material-ui/icons/Add"; +import IconButton from "@material-ui/core/IconButton"; +import ReorderIcon from "@material-ui/icons/Reorder"; +import RadioButtonCheckedIcon from "@material-ui/icons/RadioButtonChecked"; +import CheckBoxOutlineBlankIcon from "@material-ui/icons/CheckBoxOutlineBlank"; +import Grid from "@material-ui/core/Grid"; +import { makeStyles } from "@material-ui/core"; +import ListAltIcon from "@material-ui/icons/ListAlt"; +import TextFieldsIcon from "@material-ui/icons/TextFields"; + +const useStyles = makeStyles((theme) => ({ + addButton: { + fontSize: "100%", + }, + outerGrid: { + // alignItems: "flex-start", + + flexDirection: "column", + ["@media(max-width: 600px)"]: { + flexDirection: "row", + justifyContent: "space-between", + }, + ["@media(max-width: 1050px)"]: { + fontSize: "0", + }, + }, + paper: { + ["@media (min-width: 600px)"]: { + position: "fixed", + }, + ["@media (min-width:600px)"]: { + maxWidth: "190px", + }, + ["@media(max-width: 1050px)"]: { + ["@media(min-width: 600px)"]: { + width: "85px", + }, + }, + justifyContent: "flex-start", + // minWidth: "160.167px", + }, + newQuestionGrid: { + marginTop: "5%", + }, + test: { + display: "flex", + flexDirection: "row", + maxWidth: "190px", + // minWidth: "160.167px", + height: "268.5", + }, + flex: {}, + newQuestionGrid: { + ["@media(max-width: 1050px)"]: { + display: "none", + }, + }, +})); +// fazer com que desca comforme a rolagem da página +function SideMenu(props) { + const classes = useStyles(); + return ( + <Paper className={classes.paper}> + <Grid item container justify="flex-start" className={classes.outerGrid}> + <Grid className={classes.newQuestionGrid} container justify="center"> + <h4>Adicionar pergunta:</h4> + </Grid> + {/* <Grid> */} + <IconButton + aria-label="add select" + type="submit" + size="medium" + className={classes.addButton} + onClick={props.addToFormQuestion} + > + <TextFieldsIcon /> + Caixa de texto + </IconButton> + <IconButton + aria-label="add select" + type="submit" + size="medium" + className={classes.addButton} + onClick={props.addToFormSelect} + > + <ReorderIcon /> + Lista Suspensa + </IconButton> + <IconButton + aria-label="add radio" + type="submit" + size="medium" + className={classes.addButton} + onClick={props.addToFormRadio} + > + <RadioButtonCheckedIcon /> + Múltipla escolha + </IconButton> + <IconButton + aria-label="add checkbox" + type="submit" + size="medium" + className={classes.addButton} + onClick={props.addToFormCheckbox} + > + <CheckBoxOutlineBlankIcon /> + Seleção Única + </IconButton> + <IconButton + aria-label="add subform" + type="submit" + size="medium" + className={classes.addButton} + onClick={props.addToFormSubForm} + > + <ListAltIcon /> + Subformulário + </IconButton> + </Grid> + {/* </Grid> */} + </Paper> + ); +} + +export default SideMenu; diff --git a/src/components/fieldsCreateForm/utils/BackendTranslation.js b/src/components/fieldsCreateForm/utils/BackendTranslation.js new file mode 100644 index 0000000000000000000000000000000000000000..6acb5c14142ae9ea2d1089673bde847d3ee3e446 --- /dev/null +++ b/src/components/fieldsCreateForm/utils/BackendTranslation.js @@ -0,0 +1,106 @@ +/** Functions that create the json object to be sent to the backend. */ + +/** Function that pushes the 'translated' object into the new array, wich will be sent to the backend. */ +function setInput(form, index, json, sugestions, validation, subForm, type) { + //the case when the input has a subform -> backend requires it to be different + if (subForm) { + json.inputs.push({ + placement: index, + description: form.description, + question: form.question, + type: type, + validation: validation, + sugestions: sugestions, + subForm: subForm, + }); + } else { + json.inputs.push({ + placement: index, + description: form.description, + question: form.question, + type: type, + validation: validation, + sugestions: sugestions, + }); + } +} + +/** Returns the type of the question as the backend padronization. */ +function getType(stringified_type) { + switch (stringified_type) { + case "question": + return 0; + case "select": + return 3; + case "radio": + return 2; + case "checkbox": + return 1; + case "subForm": + return 4; + default: + return -1; + } +} +/** Translates the 'options' array to the backend padronization. */ +function setSugestions(sugestions) { + let tmp = []; + if (!sugestions) return tmp; + sugestions.forEach((value, index) => { + tmp.push({ + value: value, + placement: index, + }); + }); + return tmp; +} + +/** Sets the validation field to be sent to the backend. */ +function setValidation(form) { + if (!form.validation[0].value) return []; + let val = []; + if (form.type === "checkbox") + val.push({ + type: 6, + arguments: [], + }); + else if (form.type === "question" && form.validation.length > 1) { + if (form.validation[1].type === "maxChar") { + val.push({ type: 3, arguments: [form.validation[1].value] }); + } else { + val.push({ type: 4, arguments: [form.validation[1].value] }); + } + } else + val.push({ + type: 2, + arguments: [], + }); + return val; +} +/** Set the subform as the backend padronization. */ +function setSubform(form, idq) { + if (form.type !== "subForm") return null; + return { + contentFormId: form.subformId, + }; +} +/** The function that triggers the 'translation' */ +export default function createForm(form) { + let json = { + title: form[0].title, + description: form[0].description, + inputs: [], + }; + for (var i = 1; i < form.length; i++) { + setInput( + form[i], + i, + json, + setSugestions(form[i].options), + setValidation(form[i]), + setSubform(form[i], i), + getType(form[i].type) + ); + } + return json; +} diff --git a/src/components/fieldsCreateForm/utils/schemas.js b/src/components/fieldsCreateForm/utils/schemas.js new file mode 100644 index 0000000000000000000000000000000000000000..3255a316bf94e14b7fcf2e6fd230e97233a48467 --- /dev/null +++ b/src/components/fieldsCreateForm/utils/schemas.js @@ -0,0 +1,158 @@ +import * as Yup from "yup"; +/** The validation through Yup is schema based, so there are schemas and it's validations. */ + +/** Schema to validate the question field from every form array object. */ +const questionTextSchema = Yup.string() + .required("Este campo é obrigatório!") + .test("alphabets", "O caractere não é permitido", (value) => { + return /^[A-Za-z!?$%,. 1234567890àèìòùáéíóúâêîôûãõç]+$/.test(value); + }); +/** Function that applies the validation of it's used schema and sets the error messages. */ +export async function testQuestionTextSchema(form, value, index) { + await questionTextSchema + .validate(value) + .then((x) => { + form[index].error.errorMsg.question = ""; + }) + .catch((err) => { + form[index].error.errorMsg.question = err.message; + }); +} +/** Schema to validate the description field from every form array object. */ +const descriptionTextSchema = Yup.string().test( + "alphabets", + "O caractere não é permitido", + (value) => { + if (!value) return true; + return /^[A-Za-z!?$%,. 1234567890àèìòùáéíóúâêîôûãõ\b- ]+$/.test(value); + } +); +/** Function that applies the validation of it's used schema and sets the error messages. */ +export async function testDescriptionTextSchema(form, value, index) { + await descriptionTextSchema + .validate(value) + .then((x) => { + form[index].error.errorMsg.description = ""; + }) + .catch((err) => { + form[index].error.errorMsg.description = err.message; + }); +} +/** Schema to validate the number of options at options field from FormFieldSelect, FormFieldCheckbox and FormFieldRadio. */ +const selectOptionsSchema = Yup.array() + .of(Yup.string()) + .test("minimo 2", "O campo precisa ter pelo menos duas opções!", (value) => { + if (value.length < 2) return false; + else return true; + }); +/** Function that applies the validation of it's used schema and sets the error messages. */ +export async function selectOptionsTesting(form, index) { + await selectOptionsSchema + .validate(form[index].options) + .then((x) => { + form[index].error.errorMsg.optionsNumber = ""; + }) + .catch((err) => { + form[index].error.errorMsg.optionsNumber = err.message; + }); +} +/** Schema to validate the subform field from FormFieldSubform. */ +const subformSchema = Yup.array().test( + "repetition", + "Este formulário já está sendo usado!", + (form) => { + for (let i = 1; i < form.length; i++) { + if (form[i].type === "subForm") { + for (let j = i + 1; j < form.length; j++) { + if ( + form[j].type === "subForm" && + form[j].subformId === form[i].subformId + ) { + return false; + } + } + } + } + return true; + } +); +/** Function that applies the validation of it's used schema and sets the error messages. */ +export async function testSubformSchema(form, index) { + await subformSchema + .validate(form) + .then((x) => { + form[index].error.errorMsg.subformUsage = ""; + form[index].error.errorMsg.subformSelected = false; + }) + .catch((err) => { + form[index].error.errorMsg.subformUsage = err.message; + }); +} +/** Schema to validate the content of the options field from FormFieldSelect, FormFieldCheckbox and FormFieldRadio. */ +const optSchema = Yup.string() + .required("Por favor, preencha esta opção") + .test("alphabets", "O caractere não é permitido", (value) => { + if (!value) return true; + return /^[A-Za-z!?$%,. àèìòùáéíóúâêîôûãõ\b- ]+$/.test(value); + }); +/** Function that applies the validation of it's used schema and sets the error messages. */ +export async function selectOptionTextTesting(form, value, index, idopt) { + await optSchema + .validate(value) + .then((x) => { + form[index].error.errorMsg.options[idopt] = ""; + }) + .catch((err) => { + form[index].error.errorMsg.options[idopt] = err.message; + }); +} +/** Schema to validate the quantity field of the validation from FormFieldText. */ +const textValidationSchema = Yup.string() + .required("Por favor, digite um número") + .test("numeric", "Digite um número válido", (value) => { + return /^\d+$/.test(value); + }); +/** Function that applies the validation of it's used schema and sets the error messages. */ +export async function testTextValidation(form, index, value) { + await textValidationSchema + .validate(value) + .then((x) => { + form[index].error.errorMsg.validation.value = ""; + }) + .catch( + (err) => (form[index].error.errorMsg.validation.value = err.message) + ); +} +/** Functions that verify if the form array can be sent to the backend. */ +export function verifyError(form) { + if (form.length === 1) return false; + let valid = true; + form.map(function (x) { + if (x.error.errorMsg.question || x.error.errorMsg.description) { + valid = false; + return; + } + if (x.type === "question") { + if (x.error.errorMsg.validation.value) { + valid = false; + return; + } + } + if (x.type === "subForm") { + if (x.error.errorMsg.subformUsage || x.error.errorMsg.subformSelected) { + valid = false; + return; + } + } + if (x.type === "checkbox" || x.type === "radio" || x.type === "select") { + if (x.error.errorMsg.optionsNumber) valid = false; + x.error.errorMsg.options.forEach((y) => { + if (y) { + valid = false; + } + }); + return; + } + }); + return valid; +} diff --git a/src/components/footer/footer.js b/src/components/footer/footer.js index 3e2ee4e095d3e2de15e1881b49cb87ce0b31828b..5e01cd89398b7a16ee202f30f0655ffab3a368f4 100644 --- a/src/components/footer/footer.js +++ b/src/components/footer/footer.js @@ -4,15 +4,15 @@ import Grid from "@material-ui/core/Grid"; import Typography from "@material-ui/core/Typography"; import Logo from "./c3sl.png"; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ footer: { background: "#66a6c2", - position: "fixed", + position: "relative", left: 0, bottom: 0, right: 0, width: "100%", - height: "78px" + height: "78px", }, img: { @@ -23,15 +23,15 @@ const useStyles = makeStyles(theme => ({ marginLeft: "auto", marginRight: "auto", ["@media (min-width: 960px)"]: { - marginLeft: "5px", - } + marginLeft: "5px", + }, }, item: { display: "flex", justifyContent: "space-evenly", flexDirection: "column", - alignItems: "center" + alignItems: "center", }, text: { @@ -40,8 +40,8 @@ const useStyles = makeStyles(theme => ({ textAlign: "center", left: "50%", ["@media (max-width: 960px)"]: { - display: "none" - } + display: "none", + }, }, adress: { @@ -55,9 +55,9 @@ const useStyles = makeStyles(theme => ({ fontSize: "12px", textAlign: "right", ["@media (max-width: 960px)"]: { - display: "none" - } - } + display: "none", + }, + }, })); function Footer() { @@ -89,8 +89,6 @@ function Footer() { Telefone: 61 2027-6000 </Typography> </Grid> - - </Grid> ); } diff --git a/src/components/global.css b/src/components/global.css deleted file mode 100644 index deeb81c51a0c0da8fdf7b43bc72f8fcbe4bfc430..0000000000000000000000000000000000000000 --- a/src/components/global.css +++ /dev/null @@ -1,26 +0,0 @@ -@import url("https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap"); - -* { - margin: 0; - padding: 0; - outline: 0; - box-sizing: border-box; - background: "#05a5dd"; -} - -html, -body, -#root { - height: 100%; -} - -body { - background: #eceff3; - -webkit-font-smoothing: antialiased; -} - -body, -input, -button { - font-family: Roboto, sans-serif; -} diff --git a/src/components/header/header.jsx b/src/components/header/header.jsx index 4f5369c4dc560b1caf36ff29a03b081e33f27e9c..4846204ded2748173c23a82a3fe351c037d0b8c4 100644 --- a/src/components/header/header.jsx +++ b/src/components/header/header.jsx @@ -4,14 +4,14 @@ import logo from "./header_imgs/imgsimmc-01.png"; import { makeStyles } from "@material-ui/core"; import MenuListComposition from "./header_components/MenuList"; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ header: { background: "#05a5dd", width: "auto", display: "flex", flexDirection: "column", justifyContent: "center", - height: "13%" + height: "13%", }, simmc: { marginTop: "5%", @@ -19,11 +19,11 @@ const useStyles = makeStyles(theme => ({ color: "#ffffff", marginLeft: "2%", ["@media (max-width:1040px)"]: { - display: "none" + display: "none", }, - ["@media (max-height:681px)"]: { - display: "none" - } + // ["@media (max-height:681px)"]: { + // display: "none" + // } }, form_creator: { color: "#ffffff", @@ -32,37 +32,31 @@ const useStyles = makeStyles(theme => ({ fontSize: "21px", ["@media (max-width:525px)"]: { marginTop: "5%", - marginLeft: "10%" + marginLeft: "10%", }, ["@media (max-width:337px)"]: { - fontSize: "19px" - } + fontSize: "19px", + }, }, - ["@media (max-height:681px)"]: { - marginTop: "5%" - } }, link: { - textDecoration: "none" + textDecoration: "none", }, logo: { marginLeft: "2.5%", marginTop: "4%", width: "85px", - ["@media (max-width:525px)"]: { + ["@media (max-width:600px)"]: { width: "65px", ["@media (max-width:338px)"]: { - marginTop: "3%" - } + marginTop: "3%", + }, }, - ["@media (max-height:681px)"]: { - width: "65px" - } }, userImgContainer: { display: "flex", - flexDirection: "column" - } + flexDirection: "column", + }, })); export default function Header() { diff --git a/src/components/header/header_components/MenuList.jsx b/src/components/header/header_components/MenuList.jsx index 4134513b225adbb03a6fad2ffac77bdde0f15bae..e4491ce3ea454e29e49c014b5e38ab3434a49be4 100644 --- a/src/components/header/header_components/MenuList.jsx +++ b/src/components/header/header_components/MenuList.jsx @@ -11,28 +11,28 @@ import UserImg from "./../header_imgs/user.png"; import { Avatar } from "@material-ui/core"; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ menuPopUp: { alignContent: "start", ["@media (max-width:346px)"]: { - width: "23%" - } + width: "23%", + }, }, menuPopUpText: { ["@media (max-width:525px)"]: { - fontSize: "13px" - } + fontSize: "13px", + }, }, popUpPaper: { marginRight: "14%", ["@media (max-width:525px)"]: { - marginRight: "0" - } + marginRight: "0", + }, }, menuList: { alignItems: "flex-start", - color: "grey" - } + color: "grey", + }, })); /** @@ -47,9 +47,9 @@ function MenuListComposition(props) { const anchorRef = React.useRef(null); const handleToggle = () => { - setOpen(prevOpen => !prevOpen); + setOpen((prevOpen) => !prevOpen); }; - const handleClose = event => { + const handleClose = (event) => { if (anchorRef.current && anchorRef.current.contains(event.target)) { return; } @@ -95,7 +95,7 @@ function MenuListComposition(props) { {...TransitionProps} style={{ transformOrigin: - placement === "bottom" ? "center top" : "center bottom" + placement === "bottom" ? "center top" : "center bottom", }} > <Paper className={classes.popUpPaper}> diff --git a/src/global.css b/src/global.css index 9583b1d0dbc83b28cc633cde22ae98ad54669740..879e608cd8cf467d0490956af673f7df84de1dcd 100644 --- a/src/global.css +++ b/src/global.css @@ -1,15 +1,12 @@ @import url("https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap"); -*{ +* { margin: 0; padding: 0; outline: 0; box-sizing: border-box; color: #667079; } -* :not(.Button){ - color: white; -} html, body, diff --git a/src/pages/AnswerForm.js b/src/pages/AnswerForm.js index edcb312d30a030faf31f0d3a3f000d55208061eb..f123fd561bb6d80f8b7127b20a30462a1e3591b5 100644 --- a/src/pages/AnswerForm.js +++ b/src/pages/AnswerForm.js @@ -47,7 +47,7 @@ function AnwserForm() { setFormData(res.data); }); } - + function answerForm() { axios.post(`${config.genformsapi.url}/form`) .then(res => { @@ -70,7 +70,7 @@ function AnwserForm() { > { - formData ? + formData ? <div> <FormFieldTitle title={formData.title} description={formData.description}/> { diff --git a/src/pages/CreateForm.js b/src/pages/CreateForm.js index 677e396d6f816b35d124c6d3668be7639b644546..b75453fe6aa4cc06c991dc3447668fc264e19094 100644 --- a/src/pages/CreateForm.js +++ b/src/pages/CreateForm.js @@ -1,241 +1,490 @@ -import React, { useState } from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import Grid from '@material-ui/core/Grid'; -import Paper from '@material-ui/core/Paper'; -import TextField from '@material-ui/core/TextField'; -import AddIcon from '@material-ui/icons/Add'; -import IconButton from '@material-ui/core/IconButton'; -import ReorderIcon from '@material-ui/icons/Reorder'; -import RadioButtonCheckedIcon from '@material-ui/icons/RadioButtonChecked'; -import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'; -import Button from '@material-ui/core/Button'; -import axios from 'axios'; +import React, { useState, useEffect } from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import Grid from "@material-ui/core/Grid"; +import Button from "@material-ui/core/Button"; +import { DragDropContext, Droppable } from "react-beautiful-dnd"; +import { createMuiTheme, MuiThemeProvider } from "@material-ui/core"; +import FormFieldText from "../components/fieldsCreateForm/FormFieldText"; +import FormFieldSelect from "../components/fieldsCreateForm/FormFieldSelect"; +import FormFieldRadio from "../components/fieldsCreateForm/FormFieldRadio"; +import FormFieldCheckbox from "../components/fieldsCreateForm/FormFieldCheckbox"; +import FormFieldTitle from "../components/fieldsCreateForm/FormFieldTitle"; +import FormFieldSubForm from "../components/fieldsCreateForm/FormFieldSubform"; +import uuid from "uuid/v4"; +import { + testQuestionTextSchema, + testDescriptionTextSchema, + selectOptionsTesting, + testSubformSchema, + selectOptionTextTesting, + testTextValidation, + verifyError, +} from "../components/fieldsCreateForm/utils/schemas"; +import createForm from "../components/fieldsCreateForm/utils/BackendTranslation"; +import SideMenu from "../components/fieldsCreateForm/SideMenu"; +import api from "../api"; -import FormFieldText from '../components/fieldsCreateForm/FormFieldText'; -import FormFieldSelect from '../components/fieldsCreateForm/FormFieldSelect'; -import FormFieldRadio from '../components/fieldsCreateForm/FormFieldRadio'; -import FormFieldCheckbox from '../components/fieldsCreateForm/FormFieldCheckbox'; -import FormFieldTitle from '../components/fieldsCreateForm/FormFieldTitle'; +import Tooltip from "@material-ui/core/Tooltip"; -import config from '../config'; - - -const useStyles = makeStyles(theme => ({ - menu: { - width: theme.spacing(6), - minheight: theme.spacing(15), - position: 'fixed', - top: theme.spacing(10), - left: '90%', - padding: theme.spacing(1) +/** CSS styles used on page components */ +const useStyles = makeStyles((theme) => ({ + app: { + margin: "0", + padding: "40px", + display: "flex", + ["@media (max-width: 600px)"]: { + flexDirection: "column-reverse", + justifyContent: "flex-end", + }, + paddingBottom: "78px", + ["@media (min-width: 600px)"]: { + minHeight: "calc(100vh - 92.4px - 78px)", + }, + minHeight: "calc(100vh - 71.6px - 78px)", + }, + addButton: { + fontSize: "100%", + }, + buttonOk: { + backgroundColor: "#6ec46c", + "&:hover": { + backgroundColor: "rgb(25, 109, 23)", + }, + width: "20%", + ["@media (max-width:600px)"]: { + marginTop: "52px", + }, + }, + button: { + ["@media (max-width:600px)"]: { + marginTop: "52px", + }, + }, + questionsGrid: { + // da pra mexer no deslocamento do titulo por aqui; + ["@media (max-width:600px)"]: { + // marginBottom: "100%", + // padding: 0, + }, + }, + sideMenuFormatingGrid: { + ["@media (max-width:600px)"]: { + marginTop: "-90px", + }, }, })); - +/** CSS style used through Material Ui. */ +const theme = createMuiTheme({ + overrides: { + MuiInput: { + underline: { + "&:before": { + borderBottom: "1px solid #35c7fc", + }, + "&:after": { + borderBottom: "1px solid #3f51b5", + }, + }, + }, + MuiButton: { + label: { + color: "white", + }, + }, + }, +}); +/** Main function that returns the children that composes the form creation page. */ function CreateForm() { + /** Style class. */ const classes = useStyles(); + /** An unique string to be used as ID for drag and drop function. */ + const columnId = uuid(); + /** Error state. */ + const [validToSend, setValidToSend] = useState(); - const [form, setForm] = useState([{type: "title", title: "", description: ""}]); - + /** Form state being started with the title, it's an array where each position stands for a question selected by the user. */ + const [form, setForm] = useState([ + { + type: "title", + title: "", + description: "", + error: { + errorMsg: { question: "Este campo é obrigatório!", description: "" }, + }, + }, + ]); + /** Function used on 'sidemenu' that adds to the form array the object of a question. */ function addToFormQuestion() { - setForm([...form, {type: "question", required: false, question: ""}]); - console.log(form); + setForm([ + ...form, + { + type: "question", + validation: [{ type: "required", value: false }], + question: "", + description: "", + id: uuid(), + error: { + errorMsg: { + question: "Este campo é obrigatório!", + description: "", + validation: { + value: "", + }, + }, + }, + }, + ]); } - + /** Function used on 'sidemenu' that adds to the form array the object of a select question. */ function addToFormSelect() { - setForm([...form, {type: "select", question: "", required: false, options: [""]}]); - console.log(form); + setForm([ + ...form, + { + type: "select", + question: "", + validation: [{ type: "required", value: false }], + options: [""], + description: "", + id: uuid(), + error: { + errorMsg: { + question: "Este campo é obrigatório!", + description: "", + optionsNumber: "O campo precisa ter pelo menos duas opções!", + options: ["Por favor, preencha esta opção"], + }, + }, + }, + ]); } - + /** Function used on 'sidemenu' that adds to the form array the object of a radio question. */ function addToFormRadio() { - setForm([...form, {type: "radio", question: "", required: false, options: [""]}]); - console.log(form); + setForm([ + ...form, + { + type: "radio", + question: "", + validation: [{ type: "required", value: false }], + options: [""], + description: "", + id: uuid(), + error: { + errorMsg: { + question: "Este campo é obrigatório!", + description: "", + optionsNumber: "O campo precisa ter pelo menos duas opções!", + options: ["Por favor, preencha esta opção"], + }, + }, + }, + ]); } - + /** Function used on 'sidemenu' that adds to the form array the object of a checkbox question. */ function addToFormCheckbox() { - setForm([...form, {type: "checkbox", question: "", required: false, options: [""]}]); - console.log(form); + setForm([ + ...form, + { + type: "checkbox", + question: "", + validation: [{ type: "required", value: false }], + options: [""], + description: "", + id: uuid(), + error: { + errorMsg: { + question: "Este campo é obrigatório!", + description: "", + optionsNumber: "O campo precisa ter pelo menos duas opções!", + options: ["Por favor, preencha esta opção"], + }, + }, + }, + ]); } - - function addSelectOption(index) { + /** Function used on 'sidemenu' that adds to the form array the object of a subform question. */ + function addToFormSubForm() { + setForm([ + ...form, + { + type: "subForm", + validation: [{ type: "required", value: false }], + description: "", + question: "", + subformId: "", + id: uuid(), + error: { + errorMsg: { + question: "Este campo é obrigatório!", + description: "", + subformUsage: "", + subformSelected: true, + }, + }, + }, + ]); + } + /** Function used on FormFieldRadio, FormFieldCheckbox and FormFieldSelect, it adds a new option field for those questions. */ + async function addSelectOption(index) { form[index].options.push(""); + form[index].error.errorMsg.options.push("Por favor, preencha esta opção"); + await selectOptionsTesting(form, index); setForm([...form]); - console.log(form); } - + /** Function used on FormFieldRadio, FormFieldCheckbox and FormFieldSelect, it removes an option field for those questions. */ + async function removeSelectOption(index, idopt) { + form[index].options.splice(idopt, 1); + form[index].error.errorMsg.options.splice(idopt, 1); + await selectOptionsTesting(form, index); + setForm([...form]); + } + /** Function used on every FormField, it deletes the question from the array. */ function deleteFromForm(index) { - console.log(index); - form.splice(index, 1) - console.log(form); + form.splice(index, 1); setForm([...form]); } - - function removeSelectOption(index, idopt) { - form[index].options.splice(idopt, 1); + /** Function used on FormFieldQuestion, it handles the validation the user chooses. + * Currently, only handle max and min number of characters. + */ + function addValidation(index) { + form[index].validation.push({ type: "", value: "" }); + form[index].error.errorMsg.validation.value = "Por favor, digite um número"; setForm([...form]); - console.log(form); } - - function setQuestionField(value, index) { + /** Function used on every FormField, it updates the value of the question property on the form array. */ + async function setQuestionField(value, index) { form[index].question = value; + await testQuestionTextSchema(form, value, index); + setForm([...form]); + } + /** Function used on every FormField, it updates the value of the description property on the array. */ + async function setDescriptionField(value, index) { + form[index].description = value; + await testDescriptionTextSchema(form, value, index); setForm([...form]); - console.log(form); } - - function setSelectOption(value, index, idopt) { + /** Function used on every FormField, it updates the value of the oprion property of the object on the array. */ + async function setSelectOption(value, index, idopt) { form[index].options[idopt] = value; + await selectOptionTextTesting(form, value, index, idopt); setForm([...form]); - console.log(form); } - + /** Function used on every FormField, it updates the value of the required property of a question. */ function setRequiredField(index) { - form[index].required = !form[index].required; + form[index].validation[0].value = !form[index].validation[0].value; setForm([...form]); - console.log(form); } - - function setTitleField(value, index) { - form[index].title = value; + /** Function to update the title, used on FormFieldTitle. */ + async function setTitleField(value) { + await testQuestionTextSchema(form, value, 0); + form[0].title = value; setForm([...form]); - console.log(form); } - - function setDescriptionField(value, index) { - form[index].description = value; + /** Function to store the selected subform Id on it's corresponding object. */ + async function setSubformId(value, index) { + form[index].subformId = value; + await testSubformSchema(form, index); setForm([...form]); - console.log(form); } - - function createForm() { - let json = { - title: form[0].title, - description: form[0].description, - inputs: [] - } - - form.forEach(function(x, index){ - if(x.type === "question") { - json.inputs.push({ - "placement": index-1, - "description": "Adicionar esse campo no front", - "question": x.question, - "enabled": true, - "type": 0, // question type = 0 - "validation": x.required ? [{"type": 2, "arguments": ""}] : [] - }); - } else if(x.type === "select") { - json.inputs.push({ - "placement": index-1, - "description": "Adicionar esse campo no front", - "question": x.question, - "enabled": true, - "type": 3, // select type = 3 - "validation": x.required ? [{"type": 2, "arguments": ""}] : [], - "sugestions": x.options.map(function(y, index) { return {value: y, placement: index} }) - }); - } else if(x.type === "checkbox") { - json.inputs.push({ - "placement": index-1, - "description": "Adicionar esse campo no front", - "question": x.question, - "enabled": true, - "type": 1, // checkbox type = 1 - "validation": x.required ? [{"type": 2, "arguments": ""}] : [], - "sugestions": x.options.map(function(y, index) { return {value: y, placement: index} }) - }); - } else if(x.type === "radio") { - json.inputs.push({ - "placement": index-1, - "description": "Adicionar esse campo no front", - "question": x.question, - "enabled": true, - "type": 2, // radio type = 2 - "validation": x.required ? [{"type": 2, "arguments": ""}] : [], - "sugestions": x.options.map(function(y, index) { return {value: y, placement: index} }) - }); - } - }); - - - console.log(json); - axios.post(`${config.genformsapi.url}/form`, json ) - .then(res => { - console.log(res); - console.log(res.data); - - window.location.reload(); + /** Function used on FormFieldText to set the chosen validation, currently min and max char. */ + async function setValidation(value, index) { + form[index].validation[1] = value; + await testTextValidation(form, index, value.value); + setForm([...form]); + } + /** The submit function. It's triggered when the submit button is pressed on the interface. */ + async function submit(event) { + if (!validToSend) return; + let data = createForm(form); + const post_response = await api + .post(`/form`, data, { + headers: { + authorization: `bearer ${window.sessionStorage.getItem("token")}`, + }, + }) + .then(function (error) { + if (!error.response) alert("Seu formulário foi criado com sucesso."); + }) + .catch(function (error) { + alert("Um erro ocorreu."); }); - } + /** Reordering the form array based on the place the question is being dragged over. */ + const onDragEnd = (result) => { + if (!result.destination) return; + const { source, destination } = result; + + const copiedForm = [...form]; + const [removed] = copiedForm.splice(source.index, 1); + copiedForm.splice(destination.index, 0, removed); + setForm(copiedForm); + }; + /** Error handling -> every time the form object is updated, it is verified to evaluate it's error messages, + * so the submit button can be enabled or disabled. + */ + useEffect(() => { + setValidToSend(verifyError(form)); + }, [form]); return ( - <div> - <Grid - container - direction="column" - alignItems="center" - justify="center" - > - { - form.map((x, index) => { - if(x.type === "question") - return <FormFieldText question={x.question} idq={index} - deleteFromForm={deleteFromForm} setQuestionField={setQuestionField} - setRequiredField={setRequiredField} required={x.required}/> - else if(x.type === "select") - return <FormFieldSelect question={x.question} options={x.options} idq={index} - deleteFromForm={deleteFromForm} addSelectOption={addSelectOption} - removeSelectOption={removeSelectOption} setSelectOption={setSelectOption} - setQuestionField={setQuestionField} setRequiredField={setRequiredField} - required={x.required} /> - else if(x.type === "radio") - return <FormFieldRadio question={x.question} options={x.options} idq={index} - deleteFromForm={deleteFromForm} addSelectOption={addSelectOption} - removeSelectOption={removeSelectOption} setSelectOption={setSelectOption} - setQuestionField={setQuestionField} setRequiredField={setRequiredField} - required={x.required} /> - else if(x.type === "checkbox") - return <FormFieldCheckbox question={x.question} options={x.options} idq={index} - deleteFromForm={deleteFromForm} addSelectOption={addSelectOption} - removeSelectOption={removeSelectOption} setSelectOption={setSelectOption} - setQuestionField={setQuestionField} setRequiredField={setRequiredField} - required={x.required} /> - else if(x.type === "title") - return <FormFieldTitle question={x.question} idq={index} - deleteFromForm={deleteFromForm} setTitleField={setTitleField} - setDescriptionField={setDescriptionField}/> - }) - } - <Button variant="contained" color="primary" onClick={createForm}> - Criar - </Button> - </Grid> - - <Paper className={classes.menu}> - <Grid - container - spacing={0} - direction="column" - alignItems="center" - justify="center" - > - <Grid item xs={0}> - <IconButton aria-label="add question" onClick={addToFormQuestion}> - <AddIcon /> - </IconButton> - <IconButton aria-label="add select" onClick={addToFormSelect}> - <ReorderIcon /> - </IconButton> - <IconButton aria-label="add radio" onClick={addToFormRadio}> - <RadioButtonCheckedIcon /> - </IconButton> - <IconButton aria-label="add checkbox" onClick={addToFormCheckbox}> - <CheckBoxOutlineBlankIcon /> - </IconButton> - </Grid> + <MuiThemeProvider theme={theme}> + <Grid className={classes.app}> + <Grid xs={12} sm={2} className={classes.sideMenuFormatingGrid}> + <SideMenu + addToFormQuestion={addToFormQuestion} + addToFormSelect={addToFormSelect} + addToFormRadio={addToFormRadio} + addToFormCheckbox={addToFormCheckbox} + addToFormSubForm={addToFormSubForm} + /> </Grid> - </Paper> - - </div> + <DragDropContext onDragEnd={onDragEnd}> + <Grid + dragOver + container + xs={12} + sm={8} + direction="column" + alignItems="center" + className={classes.questionsGrid} + > + <Droppable droppableId={columnId}> + {(provided, snapshot) => { + return ( + <Grid {...provided.droppableProps} ref={provided.innerRef}> + {form.map((x, index) => { + if (x.type === "question") + return ( + <FormFieldText + question={x.question} + idq={index} + description={x.description} + deleteFromForm={deleteFromForm} + setQuestionField={setQuestionField} + setRequiredField={setRequiredField} + setDescriptionField={setDescriptionField} + id={x.id} + error={x.error} + validation={x.validation} + addValidation={addValidation} + setValidation={setValidation} + /> + ); + else if (x.type === "select") + return ( + <FormFieldSelect + question={x.question} + options={x.options} + idq={index} + description={x.description} + deleteFromForm={deleteFromForm} + addSelectOption={addSelectOption} + removeSelectOption={removeSelectOption} + setSelectOption={setSelectOption} + setQuestionField={setQuestionField} + setRequiredField={setRequiredField} + setDescriptionField={setDescriptionField} + validation={x.validation} + id={x.id} + error={x.error} + /> + ); + else if (x.type === "radio") + return ( + <FormFieldRadio + question={x.question} + options={x.options} + idq={index} + description={x.description} + deleteFromForm={deleteFromForm} + addSelectOption={addSelectOption} + removeSelectOption={removeSelectOption} + setSelectOption={setSelectOption} + setQuestionField={setQuestionField} + setRequiredField={setRequiredField} + setDescriptionField={setDescriptionField} + validation={x.validation} + id={x.id} + error={x.error} + /> + ); + else if (x.type === "checkbox") + return ( + <FormFieldCheckbox + question={x.question} + options={x.options} + idq={index} + description={x.description} + deleteFromForm={deleteFromForm} + addSelectOption={addSelectOption} + removeSelectOption={removeSelectOption} + setSelectOption={setSelectOption} + setQuestionField={setQuestionField} + setRequiredField={setRequiredField} + setDescriptionField={setDescriptionField} + validation={x.validation} + id={x.id} + error={x.error} + /> + ); + else if (x.type === "subForm") + return ( + <FormFieldSubForm + question={x.question} + idq={index} + description={x.description} + deleteFromForm={deleteFromForm} + setQuestionField={setQuestionField} + setRequiredField={setRequiredField} + setDescriptionField={setDescriptionField} + setSubformId={setSubformId} + validation={x.validation} + id={x.id} + error={x.error} + validToSend={validToSend} + /> + ); + else if (x.type === "title") + return ( + <FormFieldTitle + question={x.question} + idq={index} + deleteFromForm={deleteFromForm} + setTitleField={setTitleField} + setDescriptionField={setDescriptionField} + error={x.error} + /> + ); + })} + {provided.placeholder} + </Grid> + ); + }} + </Droppable> + <Tooltip + title={ + validToSend + ? "Criar seu formulário" + : "Verifique se você criou pelo menos uma pergunta e se as perguntas estão propriamente construídas" + } + aria-label={ + validToSend + ? "Criar seu formulário" + : "Verifique se você criou pelo menos uma pergunta e se as perguntas estão propriamente construídas" + } + > + <Button + className={validToSend ? classes.buttonOk : classes.button} + variant="contained" + type="submit" + onClick={submit} + > + Criar + </Button> + </Tooltip> + </Grid> + </DragDropContext> + </Grid> + </MuiThemeProvider> ); } diff --git a/src/pages/SignIn.js b/src/pages/SignIn.js index ab1441dc2297ac2d7b37a7f66ac003af75c7d69c..4e6b3a5870907e1cfca9806b7c39aa18fbc37d81 100644 --- a/src/pages/SignIn.js +++ b/src/pages/SignIn.js @@ -8,7 +8,7 @@ import FormInput from "../components/fieldsSignUp/FormInput"; import Paper from "@material-ui/core/Paper"; import api from "../api"; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ register: { maxWidth: "1000px", background: "#ffffff", @@ -16,22 +16,22 @@ const useStyles = makeStyles(theme => ({ padding: "2% 1%", margin: "0 auto", marginTop: "9%", - width: "95%" + width: "95%", }, custom_strong: { fontSize: "25px", textAlign: "center", display: "block", - color: "#46525d" + color: "#46525d", }, strong_description: { fontSize: "14px", - color: "#c2c6ca" + color: "#c2c6ca", }, form: { marginTop: "3%", alignItems: "center", - textAlign: "center" + textAlign: "center", }, button: { type: "submit", @@ -42,25 +42,25 @@ const useStyles = makeStyles(theme => ({ padding: "10px 20px", fontSize: "18px", "&:hover": { - backgroundColor: "rgb(25, 109, 23)" + backgroundColor: "rgb(25, 109, 23)", }, ["@media (max-width:550px)"]: { - width: "55%" - } - } + width: "55%", + }, + }, })); export default function SignIn() { const classes = useStyles(); const [values, setValues] = React.useState({ email: "", password: "", - emailError: false + emailError: false, }); async function update(prop, event) { await setValues({ ...values, [prop]: event.target.value }); } - const handleChange = prop => event => { + const handleChange = (prop) => (event) => { if (!checkEmail()) { values.emailError = true; } else { @@ -75,64 +75,65 @@ export default function SignIn() { return false; } function verifyValues() { - if ( - values.email && - values.password - ) { + if (values.email && values.password) { return true; } return false; } function verifyValuesContent() { if (!checkEmail()) { - alert("Falha de autenticação. Certifique-se que email e senha estão corretos."); + alert( + "Falha de autenticação. Certifique-se que email e senha estão corretos." + ); return false; } return true; } async function handleSubmit() { const response = await api - .post(`/user/signIn`, { - email: values.email, - hash: values.password - }) - .then(function(response) { - if (!response.data.error) { - alert("Você logou com sucesso.") - window.sessionStorage.setItem("token", response.data.token); - window.sessionStorage.setItem("userId", response.data.id); - // redirecionar para a main page - } + .post(`/user/signIn`, { + email: values.email, + hash: values.password, }) - .catch(function(error) { + .then(function (response) { + if (!response.data.error) { + alert("Você logou com sucesso."); + window.sessionStorage.setItem("token", response.data.token); + window.sessionStorage.setItem("userId", response.data.id); + // redirecionar para a main page + } + }) + .catch(function (error) { if (error.response) { - alert("Falha de autenticação. Certifique-se que email e senha estão corretos.") + alert( + "Falha de autenticação. Certifique-se que email e senha estão corretos." + ); } }); } function submit() { if (verifyValues()) { if (verifyValuesContent()) { - handleSubmit(); + handleSubmit(); } } } const theme = createMuiTheme({ overrides: { root: { - color: "white" + color: "white", }, MuiInput: { underline: { "&:before": { - borderBottom: "1px solid #35c7fc" + borderBottom: "1px solid #35c7fc", }, "&:after": { - borderBottom: "1px solid #3f51b5" - } - } + borderBottom: "1px solid #3f51b5", + }, + }, }, - } + }, }); return ( <MuiThemeProvider theme={theme}> @@ -154,9 +155,7 @@ export default function SignIn() { /> </Grid> <Grid> - <FormInput - label="Senha" - param="password" onUpdate={handleChange} /> + <FormInput label="Senha" param="password" onUpdate={handleChange} /> </Grid> <Grid> <IconButton diff --git a/src/pages/teste.css b/src/pages/teste.css deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/services/auth.js b/src/services/auth.js new file mode 100644 index 0000000000000000000000000000000000000000..e684aeeef47c4a2890d6225a0edcf9790c1a4638 --- /dev/null +++ b/src/services/auth.js @@ -0,0 +1,9 @@ +export const TOKEN = "token"; + +export function isAuthenticated() { + return localStorage.getItem(TOKEN) !== null ? true : false; +} + +export function getToken() { + return localStorage.getItem(TOKEN); +} diff --git a/yarn-error.log b/yarn-error.log new file mode 100644 index 0000000000000000000000000000000000000000..603f88eea9a96ae81d5fd58108ae843d65c69107 --- /dev/null +++ b/yarn-error.log @@ -0,0 +1,68 @@ +Arguments: + /usr/bin/node /home/gabriel/.npm-packages/bin/yarn add formik + +PATH: + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/gabriel/.npm-packages/bin:/snap/bin:/home/gabriel/.npm-packages/bin:/snap/bin + +Yarn version: + 1.22.4 + +Node version: + 10.20.1 + +Platform: + linux x64 + +Trace: + Error: EACCES: permission denied, rmdir '/home/gabriel/Documents/c3sl/form-creator-ui/node_modules/@testing-library/.react.DELETE/node_modules/@babel' + +npm manifest: + { + "name": "my-app", + "version": "0.1.0", + "private": true, + "dependencies": { + "@material-ui/core": "^4.9.7", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "^4.0.0-alpha.46", + "@testing-library/jest-dom": "^4.2.4", + "@testing-library/react": "^9.5.0", + "@testing-library/user-event": "^7.2.1", + "axios": "^0.19.2", + "material-ui": "^0.20.2", + "react": "^16.13.1", + "react-beautiful-dnd": "^13.0.0", + "react-dom": "^16.13.1", + "react-os": "0.0.9", + "react-router-dom": "^5.1.2", + "react-scripts": "3.3.0", + "yup": "^0.28.3" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": "react-app" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } + } + +yarn manifest: + No manifest + +Lockfile: + No lockfile