Implemented notification & switched to async/await & added file choocer
This commit is contained in:
parent
8305d58933
commit
5ee29023a2
11 changed files with 531 additions and 73 deletions
201
package-lock.json
generated
201
package-lock.json
generated
|
@ -18,33 +18,26 @@
|
||||||
"integrity": "sha512-3eJJ841uKxeV8dcN/2yGEUy+RfgQspPEgQat85umsE1rotuquQ2AbIub4S6j7c50a2d+4myc+zSlnXeIHrOnhQ=="
|
"integrity": "sha512-3eJJ841uKxeV8dcN/2yGEUy+RfgQspPEgQat85umsE1rotuquQ2AbIub4S6j7c50a2d+4myc+zSlnXeIHrOnhQ=="
|
||||||
},
|
},
|
||||||
"@babel/core": {
|
"@babel/core": {
|
||||||
"version": "7.12.3",
|
"version": "7.13.13",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.13.tgz",
|
||||||
"integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==",
|
"integrity": "sha512-1xEs9jZAyKIouOoCmpsgk/I26PoKyvzQ2ixdRpRzfbcp1fL+ozw7TUgdDgwonbTovqRaTfRh50IXuw4QrWO0GA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/code-frame": "^7.10.4",
|
"@babel/code-frame": "^7.12.13",
|
||||||
"@babel/generator": "^7.12.1",
|
"@babel/generator": "^7.13.9",
|
||||||
"@babel/helper-module-transforms": "^7.12.1",
|
"@babel/helper-compilation-targets": "^7.13.13",
|
||||||
"@babel/helpers": "^7.12.1",
|
"@babel/helper-module-transforms": "^7.13.12",
|
||||||
"@babel/parser": "^7.12.3",
|
"@babel/helpers": "^7.13.10",
|
||||||
"@babel/template": "^7.10.4",
|
"@babel/parser": "^7.13.13",
|
||||||
"@babel/traverse": "^7.12.1",
|
"@babel/template": "^7.12.13",
|
||||||
"@babel/types": "^7.12.1",
|
"@babel/traverse": "^7.13.13",
|
||||||
|
"@babel/types": "^7.13.13",
|
||||||
"convert-source-map": "^1.7.0",
|
"convert-source-map": "^1.7.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"gensync": "^1.0.0-beta.1",
|
"gensync": "^1.0.0-beta.2",
|
||||||
"json5": "^2.1.2",
|
"json5": "^2.1.2",
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.19",
|
||||||
"resolve": "^1.3.2",
|
"semver": "^6.3.0",
|
||||||
"semver": "^5.4.1",
|
|
||||||
"source-map": "^0.5.0"
|
"source-map": "^0.5.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"semver": {
|
|
||||||
"version": "5.7.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
|
||||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/generator": {
|
"@babel/generator": {
|
||||||
|
@ -1211,6 +1204,15 @@
|
||||||
"@hapi/hoek": "^8.3.0"
|
"@hapi/hoek": "^8.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@hypnosphi/create-react-context": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz",
|
||||||
|
"integrity": "sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A==",
|
||||||
|
"requires": {
|
||||||
|
"gud": "^1.0.0",
|
||||||
|
"warning": "^4.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@istanbuljs/load-nyc-config": {
|
"@istanbuljs/load-nyc-config": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
||||||
|
@ -3870,6 +3872,29 @@
|
||||||
"babel-plugin-transform-react-remove-prop-types": "0.4.24"
|
"babel-plugin-transform-react-remove-prop-types": "0.4.24"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/core": {
|
||||||
|
"version": "7.12.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz",
|
||||||
|
"integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/code-frame": "^7.10.4",
|
||||||
|
"@babel/generator": "^7.12.1",
|
||||||
|
"@babel/helper-module-transforms": "^7.12.1",
|
||||||
|
"@babel/helpers": "^7.12.1",
|
||||||
|
"@babel/parser": "^7.12.3",
|
||||||
|
"@babel/template": "^7.10.4",
|
||||||
|
"@babel/traverse": "^7.12.1",
|
||||||
|
"@babel/types": "^7.12.1",
|
||||||
|
"convert-source-map": "^1.7.0",
|
||||||
|
"debug": "^4.1.0",
|
||||||
|
"gensync": "^1.0.0-beta.1",
|
||||||
|
"json5": "^2.1.2",
|
||||||
|
"lodash": "^4.17.19",
|
||||||
|
"resolve": "^1.3.2",
|
||||||
|
"semver": "^5.4.1",
|
||||||
|
"source-map": "^0.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@babel/plugin-proposal-class-properties": {
|
"@babel/plugin-proposal-class-properties": {
|
||||||
"version": "7.12.1",
|
"version": "7.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz",
|
||||||
|
@ -4606,6 +4631,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"classnames": {
|
||||||
|
"version": "2.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
|
||||||
|
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
|
||||||
|
},
|
||||||
"clean-css": {
|
"clean-css": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
|
||||||
|
@ -7849,6 +7879,11 @@
|
||||||
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
|
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"gud": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
|
||||||
|
},
|
||||||
"gzip-size": {
|
"gzip-size": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz",
|
||||||
|
@ -14469,6 +14504,10 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
|
||||||
"integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew=="
|
"integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew=="
|
||||||
},
|
},
|
||||||
|
"react-file-picker": {
|
||||||
|
"version": "git+https://github.com/dantheuber/react-file-picker.git#61c15b0c863987a80aa80c22a9b5caf6b975dc7e",
|
||||||
|
"from": "git+https://github.com/dantheuber/react-file-picker.git#master"
|
||||||
|
},
|
||||||
"react-ga": {
|
"react-ga": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-ga/-/react-ga-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-ga/-/react-ga-3.3.0.tgz",
|
||||||
|
@ -14479,6 +14518,37 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
},
|
},
|
||||||
|
"react-lifecycles-compat": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||||
|
},
|
||||||
|
"react-notifications-component": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-notifications-component/-/react-notifications-component-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-qq+zgqVIa2zhlw+RvO2QSPk7xHLvZWTHl9VKRO56sMUef/UrcUTqOswL0DSJtRIpZYZhclquQUfDxD6H2w8aWA=="
|
||||||
|
},
|
||||||
|
"react-popper": {
|
||||||
|
"version": "1.3.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz",
|
||||||
|
"integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.1.2",
|
||||||
|
"@hypnosphi/create-react-context": "^0.3.1",
|
||||||
|
"deep-equal": "^1.1.1",
|
||||||
|
"popper.js": "^1.14.4",
|
||||||
|
"prop-types": "^15.6.1",
|
||||||
|
"typed-styles": "^0.0.7",
|
||||||
|
"warning": "^4.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"popper.js": {
|
||||||
|
"version": "1.16.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
|
||||||
|
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-refresh": {
|
"react-refresh": {
|
||||||
"version": "0.8.3",
|
"version": "0.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
|
||||||
|
@ -14550,6 +14620,36 @@
|
||||||
"workbox-webpack-plugin": "5.1.4"
|
"workbox-webpack-plugin": "5.1.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/core": {
|
||||||
|
"version": "7.12.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz",
|
||||||
|
"integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/code-frame": "^7.10.4",
|
||||||
|
"@babel/generator": "^7.12.1",
|
||||||
|
"@babel/helper-module-transforms": "^7.12.1",
|
||||||
|
"@babel/helpers": "^7.12.1",
|
||||||
|
"@babel/parser": "^7.12.3",
|
||||||
|
"@babel/template": "^7.10.4",
|
||||||
|
"@babel/traverse": "^7.12.1",
|
||||||
|
"@babel/types": "^7.12.1",
|
||||||
|
"convert-source-map": "^1.7.0",
|
||||||
|
"debug": "^4.1.0",
|
||||||
|
"gensync": "^1.0.0-beta.1",
|
||||||
|
"json5": "^2.1.2",
|
||||||
|
"lodash": "^4.17.19",
|
||||||
|
"resolve": "^1.3.2",
|
||||||
|
"semver": "^5.4.1",
|
||||||
|
"source-map": "^0.5.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"fs-extra": {
|
"fs-extra": {
|
||||||
"version": "9.1.0",
|
"version": "9.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||||
|
@ -14593,6 +14693,47 @@
|
||||||
"prop-types": "^15.6.2"
|
"prop-types": "^15.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"reactstrap": {
|
||||||
|
"version": "8.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-8.9.0.tgz",
|
||||||
|
"integrity": "sha512-pmf33YjpNZk1IfrjqpWCUMq9hk6GzSnMWBAofTBNIRJQB1zQ0Au2kzv3lPUAFsBYgWEuI9iYa/xKXHaboSiMkQ==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.12.5",
|
||||||
|
"classnames": "^2.2.3",
|
||||||
|
"prop-types": "^15.5.8",
|
||||||
|
"react-popper": "^1.3.6",
|
||||||
|
"react-transition-group": "^2.3.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": {
|
||||||
|
"version": "7.13.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz",
|
||||||
|
"integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==",
|
||||||
|
"requires": {
|
||||||
|
"regenerator-runtime": "^0.13.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dom-helpers": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-transition-group": {
|
||||||
|
"version": "2.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
|
||||||
|
"integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
|
||||||
|
"requires": {
|
||||||
|
"dom-helpers": "^3.4.0",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.6.2",
|
||||||
|
"react-lifecycles-compat": "^3.0.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"read-pkg": {
|
"read-pkg": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
||||||
|
@ -16822,6 +16963,11 @@
|
||||||
"mime-types": "~2.1.24"
|
"mime-types": "~2.1.24"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"typed-styles": {
|
||||||
|
"version": "0.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz",
|
||||||
|
"integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q=="
|
||||||
|
},
|
||||||
"typedarray": {
|
"typedarray": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||||
|
@ -16835,6 +16981,11 @@
|
||||||
"is-typedarray": "^1.0.0"
|
"is-typedarray": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"typescript": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw=="
|
||||||
|
},
|
||||||
"unbox-primitive": {
|
"unbox-primitive": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
|
||||||
|
@ -17173,6 +17324,14 @@
|
||||||
"makeerror": "1.0.x"
|
"makeerror": "1.0.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"warning": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"watchpack": {
|
"watchpack": {
|
||||||
"version": "1.7.5",
|
"version": "1.7.5",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/core": "^7.13.13",
|
||||||
"@material-ui/core": "^4.11.3",
|
"@material-ui/core": "^4.11.3",
|
||||||
"@material-ui/icons": "^4.11.2",
|
"@material-ui/icons": "^4.11.2",
|
||||||
"@testing-library/jest-dom": "^4.2.4",
|
"@testing-library/jest-dom": "^4.2.4",
|
||||||
|
@ -13,8 +14,12 @@
|
||||||
"react-copy-to-clipboard": "^5.0.3",
|
"react-copy-to-clipboard": "^5.0.3",
|
||||||
"react-dom": "^16.14.0",
|
"react-dom": "^16.14.0",
|
||||||
"react-dropzone": "^11.3.2",
|
"react-dropzone": "^11.3.2",
|
||||||
|
"react-file-picker": "git+https://github.com/dantheuber/react-file-picker.git#master",
|
||||||
"react-ga": "^3.3.0",
|
"react-ga": "^3.3.0",
|
||||||
"react-scripts": "^4.0.3"
|
"react-notifications-component": "^3.1.0",
|
||||||
|
"react-scripts": "^4.0.3",
|
||||||
|
"reactstrap": "^8.9.0",
|
||||||
|
"typescript": "^4.2.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"predeploy": "npm run build",
|
"predeploy": "npm run build",
|
||||||
|
|
|
@ -17,14 +17,21 @@ import FileCopyOutlined from '@material-ui/icons/FileCopyOutlined';
|
||||||
import PublishOutlined from '@material-ui/icons/PublishOutlined';
|
import PublishOutlined from '@material-ui/icons/PublishOutlined';
|
||||||
|
|
||||||
// import { useFilePicker } from 'react-sage'
|
// import { useFilePicker } from 'react-sage'
|
||||||
//import { FilePicker } from 'react-file-picker'
|
// import { FilePicker } from 'react-file-picker'
|
||||||
|
|
||||||
|
import { FilePicker } from '../src/Components'
|
||||||
|
|
||||||
|
|
||||||
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||||
|
|
||||||
import ControlledAccordions from './ControlledAccordions'
|
import ControlledAccordions from './ControlledAccordions'
|
||||||
|
|
||||||
|
import 'react-notifications-component/dist/theme.css'
|
||||||
|
|
||||||
|
import ReactNotification from 'react-notifications-component'
|
||||||
|
import { store } from 'react-notifications-component';
|
||||||
|
// import 'animate.css/animate.compat.css'
|
||||||
|
|
||||||
|
|
||||||
const useStyles = theme => ({
|
const useStyles = theme => ({
|
||||||
paper: {
|
paper: {
|
||||||
|
@ -108,34 +115,51 @@ class ChecksumResolver extends React.Component {
|
||||||
return !this.isChecksumValid();
|
return !this.isChecksumValid();
|
||||||
};
|
};
|
||||||
|
|
||||||
requestActivationBytes = () => {
|
addNotification = function (text, success = true) {
|
||||||
|
store.addNotification({
|
||||||
|
message: text,
|
||||||
|
type: success ? "success" : "danger",
|
||||||
|
// type: "danger",
|
||||||
|
insert: "bottom-left",
|
||||||
|
container: "top-full",
|
||||||
|
animationIn: ["animate__animated", "animate__fadeIn"],
|
||||||
|
animationOut: ["animate__animated", "animate__fadeOut"],
|
||||||
|
dismiss: {
|
||||||
|
duration: 3000,
|
||||||
|
onScreen: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
requestActivationBytes = async () => {
|
||||||
const { checksum } = this.state;
|
const { checksum } = this.state;
|
||||||
|
try {
|
||||||
fetch("https://aax.api.j-kit.me/api/v2/activation/" + checksum)
|
let request = await fetch("https://aax.api.j-kit.me/api/v2/activation/" + checksum);
|
||||||
.then(res => res.json())
|
let result = await request.json();
|
||||||
.then(
|
const { success, activationBytes } = result;
|
||||||
(result) => {
|
if (success === true) {
|
||||||
const { success, activationBytes } = result;
|
this.setState({ activationBytes: activationBytes });
|
||||||
if (success === true) {
|
this.addNotification("Successfully resolved the activation bytes");
|
||||||
this.setState({ activationBytes: result.activationBytes });
|
} else {
|
||||||
} else {
|
this.setState({ activationBytes: 'UNKNOWN' });
|
||||||
this.setState({ activationBytes: 'UNKNOWN' });
|
this.addNotification("An error occured while resolving the activation bytes, please check your inputs", false);
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.setState({ activationBytes: error });
|
||||||
},
|
this.addNotification("An error occured while resolving the activation bytes, please check your inputs", false);
|
||||||
(error) => {
|
}
|
||||||
this.setState({ activationBytes: 'UNKNOWN' });
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf2hex(buffer) { // buffer is an ArrayBuffer
|
buf2hex(buffer) { // buffer is an ArrayBuffer
|
||||||
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
|
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
acceptFile = async files => {
|
acceptFiles = async files => {
|
||||||
const file = files[0];
|
const file = files[0];
|
||||||
|
await this.acceptFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptFile = async file => {
|
||||||
// if (!file.name.toLowerCase().endsWith(".aax")) {
|
// if (!file.name.toLowerCase().endsWith(".aax")) {
|
||||||
// alert('FileType not supported!');
|
// alert('FileType not supported!');
|
||||||
// return;
|
// return;
|
||||||
|
@ -177,7 +201,7 @@ class ChecksumResolver extends React.Component {
|
||||||
noClick
|
noClick
|
||||||
onDrop={acceptedFiles => {
|
onDrop={acceptedFiles => {
|
||||||
console.log(acceptedFiles);
|
console.log(acceptedFiles);
|
||||||
this.acceptFile(acceptedFiles);
|
this.acceptFiles(acceptedFiles);
|
||||||
}}>
|
}}>
|
||||||
{({ getRootProps, getInputProps }) => (
|
{({ getRootProps, getInputProps }) => (
|
||||||
<section>
|
<section>
|
||||||
|
@ -196,35 +220,19 @@ class ChecksumResolver extends React.Component {
|
||||||
autoFocus
|
autoFocus
|
||||||
onChange={(x) => this.setChecksum(x.target.value)}
|
onChange={(x) => this.setChecksum(x.target.value)}
|
||||||
value={checksum}
|
value={checksum}
|
||||||
|
|
||||||
InputProps={{
|
InputProps={{
|
||||||
readOnly: true,
|
readOnly: false,
|
||||||
// endAdornment: (
|
endAdornment: (
|
||||||
// // <IconButton onClick={() => {
|
<FilePicker
|
||||||
|
extensions={['aax', 'AAX']}
|
||||||
// // alert('hi')
|
maxSize={99999}
|
||||||
// // }}>
|
onChange={this.acceptFile}
|
||||||
// // <PublishOutlined />
|
>
|
||||||
// // </IconButton>
|
<IconButton >
|
||||||
|
<PublishOutlined />
|
||||||
// // <IconButton>
|
</IconButton>
|
||||||
// // <HiddenFileInput accept=".jpg, .jpeg, .png" multiple={false} />
|
</FilePicker>
|
||||||
|
)
|
||||||
// // <PublishOutlined />
|
|
||||||
// // </IconButton>
|
|
||||||
// //accept="image/*"
|
|
||||||
// // <FilePicker
|
|
||||||
// // accept="image/*"
|
|
||||||
// // extensions={['aax','AAX']}
|
|
||||||
// // acceptFile="image/*"
|
|
||||||
// // onChange={FileObject => { }}
|
|
||||||
// // onError={errMsg => { }}
|
|
||||||
// // >
|
|
||||||
// // <IconButton >
|
|
||||||
// // <PublishOutlined />
|
|
||||||
// // </IconButton>
|
|
||||||
// // </FilePicker>
|
|
||||||
// )
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
@ -280,6 +288,7 @@ class ChecksumResolver extends React.Component {
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
45
src/Components/FileInput/index.js
Normal file
45
src/Components/FileInput/index.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// external imports
|
||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
|
class FileInput extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this._handleUpload = this._handleUpload.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleUpload(evt) {
|
||||||
|
const file = evt.target.files[0]
|
||||||
|
this.props.onChange(file)
|
||||||
|
|
||||||
|
// free up the fileInput again
|
||||||
|
this.fileInput.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div style={this.props.style}>
|
||||||
|
<input
|
||||||
|
accept={this.props.accept}
|
||||||
|
type="file"
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
onChange={this._handleUpload}
|
||||||
|
ref={ele => (this.fileInput = ele)}
|
||||||
|
/>
|
||||||
|
{React.cloneElement(this.props.children, {
|
||||||
|
onClick: () => this.fileInput.click()
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInput.propTypes = {
|
||||||
|
style: PropTypes.object,
|
||||||
|
accept: PropTypes.string,
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FileInput
|
80
src/Components/FilePicker/index.js
Normal file
80
src/Components/FilePicker/index.js
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
// external imports
|
||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
// local imports
|
||||||
|
import FileInput from '../FileInput'
|
||||||
|
|
||||||
|
class FilePicker extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this._validate = this._validate.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
_validate(file) {
|
||||||
|
const { onError, onChange, maxSize, extensions } = this.props
|
||||||
|
|
||||||
|
// make sure a file was provided in the first place
|
||||||
|
if (!file) {
|
||||||
|
onError('Failed to upload a file.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we care about file extensions
|
||||||
|
if (extensions) {
|
||||||
|
const uploadedFileExt = file.name
|
||||||
|
.split('.')
|
||||||
|
.pop()
|
||||||
|
.toLowerCase()
|
||||||
|
const isValidFileExt = extensions
|
||||||
|
.map(ext => ext.toLowerCase())
|
||||||
|
.includes(uploadedFileExt)
|
||||||
|
|
||||||
|
if (!isValidFileExt) {
|
||||||
|
onError(`Must upload a file of type: ${extensions.join(' or ')}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert maxSize from megabytes to bytes
|
||||||
|
const maxBytes = maxSize * 1000000
|
||||||
|
|
||||||
|
if (file.size > maxBytes) {
|
||||||
|
onError(`File size must be less than ${maxSize} MB.`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// return native file object
|
||||||
|
onChange(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { children, style } = this.props;
|
||||||
|
const accept = this.props.extensions.map(ext => `.${ext}`).join(',')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FileInput onChange={this._validate} style={style} accept={accept}>
|
||||||
|
{children}
|
||||||
|
</FileInput>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePicker.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
onError: PropTypes.func.isRequired,
|
||||||
|
// max file size in MB
|
||||||
|
maxSize: PropTypes.number,
|
||||||
|
// file extension
|
||||||
|
extensions: PropTypes.array,
|
||||||
|
// validate file contents
|
||||||
|
validateContent: PropTypes.func,
|
||||||
|
style: PropTypes.object
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePicker.defaultProps = {
|
||||||
|
maxSize: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FilePicker
|
103
src/Components/FilePicker/test.js
Normal file
103
src/Components/FilePicker/test.js
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
// external imports
|
||||||
|
import React from 'react'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
// local imports
|
||||||
|
import FilePicker from '.'
|
||||||
|
|
||||||
|
describe('File Picker', () => {
|
||||||
|
let onChange
|
||||||
|
let onError
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
onChange = jest.fn()
|
||||||
|
onError = jest.fn()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('returns a valid component with required props', () => {
|
||||||
|
const ele = (
|
||||||
|
<FilePicker onChange={() => ({})} onError={() => ({})}>
|
||||||
|
<button>Click to upload</button>
|
||||||
|
</FilePicker>
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(React.isValidElement(ele)).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('call error handler when no file uploaded', () => {
|
||||||
|
// mount the select with a few options
|
||||||
|
const wrapper = mount(
|
||||||
|
<FilePicker onChange={onChange} onError={onError}>
|
||||||
|
<div>Click here</div>
|
||||||
|
</FilePicker>
|
||||||
|
)
|
||||||
|
|
||||||
|
// trigger the onChange callback on file input
|
||||||
|
wrapper.find('input').simulate('change', { target: { files: [] } })
|
||||||
|
|
||||||
|
expect(onError.mock.calls.length).toBe(1)
|
||||||
|
expect(onChange.mock.calls.length).toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('call error handler when a file with incorrect extension is uploaded', () => {
|
||||||
|
// mount the select with a few options
|
||||||
|
const wrapper = mount(
|
||||||
|
<FilePicker onChange={onChange} onError={onError} extensions={['md']}>
|
||||||
|
<div>Click here</div>
|
||||||
|
</FilePicker>
|
||||||
|
)
|
||||||
|
|
||||||
|
const file = new Blob(['file contents'], { type: 'text/plain' })
|
||||||
|
file.name = 'file.txt'
|
||||||
|
|
||||||
|
// trigger the onChange callback on file input
|
||||||
|
wrapper.find('input').simulate('change', { target: { files: [file] } })
|
||||||
|
|
||||||
|
expect(onError.mock.calls.length).toBe(1)
|
||||||
|
expect(onChange.mock.calls.length).toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('call error handler when a file that is too large is uploaded', () => {
|
||||||
|
// mount the select with a few options
|
||||||
|
const wrapper = mount(
|
||||||
|
<FilePicker
|
||||||
|
onChange={onChange}
|
||||||
|
onError={onError}
|
||||||
|
// set unreasonably small max size so that our tiny blob is too big
|
||||||
|
maxSize={0.0000000001}
|
||||||
|
>
|
||||||
|
<div>Click here</div>
|
||||||
|
</FilePicker>
|
||||||
|
)
|
||||||
|
|
||||||
|
const file = new Blob(['file contents'], { type: 'text/plain' })
|
||||||
|
|
||||||
|
// trigger the onChange callback on file input
|
||||||
|
wrapper.find('input').simulate('change', { target: { files: [file] } })
|
||||||
|
|
||||||
|
expect(onError.mock.calls.length).toBe(1)
|
||||||
|
expect(onChange.mock.calls.length).toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('call change handler when a file with correct size and extension is uploaded', () => {
|
||||||
|
// mount the select with a few options
|
||||||
|
const wrapper = mount(
|
||||||
|
<FilePicker
|
||||||
|
onChange={onChange}
|
||||||
|
onError={onError}
|
||||||
|
extensions={['txt']}
|
||||||
|
maxSize={1}
|
||||||
|
>
|
||||||
|
<div>Click here</div>
|
||||||
|
</FilePicker>
|
||||||
|
)
|
||||||
|
|
||||||
|
const file = new Blob(['file contents'], { type: 'text/plain' })
|
||||||
|
file.name = 'file.txt'
|
||||||
|
|
||||||
|
// trigger the onChange callback on file input
|
||||||
|
wrapper.find('input').simulate('change', { target: { files: [file] } })
|
||||||
|
|
||||||
|
expect(onError.mock.calls.length).toBe(0)
|
||||||
|
expect(onChange.mock.calls.length).toBe(1)
|
||||||
|
})
|
||||||
|
})
|
1
src/Components/index.js
Normal file
1
src/Components/index.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { default as FilePicker } from './FilePicker'
|
2
src/Components/utils/index.js
Normal file
2
src/Components/utils/index.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default as loadImage } from './load-image'
|
||||||
|
export { default as loadFile } from './load-file'
|
11
src/Components/utils/load-file.js
Normal file
11
src/Components/utils/load-file.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
export default function loadFile(file) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader()
|
||||||
|
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
|
||||||
|
reader.onloadend = loadedFIle => resolve(loadedFIle.target.result)
|
||||||
|
|
||||||
|
reader.onerror = () => reject(new Error('There was an error uploading the file'))
|
||||||
|
})
|
||||||
|
}
|
35
src/Components/utils/load-image.js
Normal file
35
src/Components/utils/load-image.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
export default function loadImg(dataUrl, dims) {
|
||||||
|
// destructure props from dims
|
||||||
|
const { minWidth, maxWidth, minHeight, maxHeight } = dims
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// create a new html image element
|
||||||
|
const img = new Image()
|
||||||
|
// set the image src attribute to our dataUrl
|
||||||
|
img.src = dataUrl
|
||||||
|
|
||||||
|
// listen for onload event
|
||||||
|
img.onload = () => {
|
||||||
|
// validate the min and max image dimensions
|
||||||
|
if (img.width < minWidth || img.height < minHeight) {
|
||||||
|
reject(
|
||||||
|
new Error(
|
||||||
|
`The uploaded image is too small. Must be at least ${minWidth}px by ${minHeight}px.`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (img.width > maxWidth || img.height > maxHeight) {
|
||||||
|
reject(
|
||||||
|
new Error(
|
||||||
|
`The uploaded image is too large. Must be no more than ${maxWidth}px by ${maxHeight}px.`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
img.onerror = () => reject(new Error('There was an error uploading the image'))
|
||||||
|
})
|
||||||
|
}
|
10
src/index.js
10
src/index.js
|
@ -3,13 +3,21 @@ import ReactDOM from 'react-dom';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import * as serviceWorker from './serviceWorker';
|
import * as serviceWorker from './serviceWorker';
|
||||||
import ChecksumResolver from './ChecksumResolver';
|
import ChecksumResolver from './ChecksumResolver';
|
||||||
|
import ReactNotification from 'react-notifications-component'
|
||||||
|
|
||||||
import ReactGA from 'react-ga';
|
import ReactGA from 'react-ga';
|
||||||
ReactGA.initialize('UA-174657678-1');
|
ReactGA.initialize('UA-174657678-1');
|
||||||
ReactGA.pageview(window.location.pathname + window.location.search);
|
ReactGA.pageview(window.location.pathname + window.location.search);
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<ChecksumResolver />,
|
<div>
|
||||||
|
<div style={{display:'flex'}}>
|
||||||
|
<ReactNotification />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ChecksumResolver />
|
||||||
|
</div>,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue