diff --git a/package-lock.json b/package-lock.json index 5e04794e..cab8080e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,9 @@ "license": "MIT", "dependencies": { "@craco/craco": "^6.4.3", + "@okta/okta-auth-js": "^6.7.0", + "@okta/okta-react": "^6.5.0", + "@okta/okta-signin-widget": "^6.4.2", "antd": "^4.20.1", "axios": "^0.21.1", "craco-less": "^1.20.0", @@ -17,6 +20,7 @@ "emailjs-com": "^3.2.0", "formik": "^2.2.9", "moment": "^2.29.2", + "okta": "^1.0.0", "plotly.js": "^1.54.6", "react": "^18.1", "react-dom": "^18.1", @@ -2804,6 +2808,157 @@ "node": ">=10" } }, + "node_modules/@okta/okta-auth-js": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@okta/okta-auth-js/-/okta-auth-js-6.7.0.tgz", + "integrity": "sha512-DktQcRQp2DLx9KCGVBlexvxOcp/ZvnMvOcp7TknT9DiLp+k9Uksce8oqKo1d04ZjLvAqnQnhxrdBXN8OZkS7uw==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@babel/runtime-corejs3": "^7.17.0", + "@peculiar/webcrypto": "^1.4.0", + "atob": "^2.1.2", + "Base64": "1.1.0", + "broadcast-channel": "^4.13.0", + "btoa": "^1.2.1", + "core-js": "^3.6.5", + "cross-fetch": "^3.1.5", + "js-cookie": "^3.0.1", + "jsonpath-plus": "^6.0.1", + "node-cache": "^5.1.2", + "p-cancelable": "^2.0.0", + "text-encoding": "^0.7.0", + "tiny-emitter": "1.1.0", + "webcrypto-shim": "^0.1.5", + "xhr2": "0.1.3" + }, + "engines": { + "node": ">=11.0", + "yarn": "^1.7.0" + } + }, + "node_modules/@okta/okta-react": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@okta/okta-react/-/okta-react-6.5.0.tgz", + "integrity": "sha512-hDt4dswFIPp/JVyrbgrwxM3J9QzqJrd5ml28FKh2BvPZSqowRnAg7xdbMiaP6omLbLiygbnnKvkdVrrtB+5n0g==", + "dependencies": { + "@babel/runtime": "^7.11.2", + "compare-versions": "^4.1.2" + }, + "engines": { + "node": ">=10.3", + "yarn": "^1.7.0" + }, + "peerDependencies": { + "@okta/okta-auth-js": "^5.3.1 || ^6.0.0", + "react": ">=16.8.0", + "react-dom": ">=16.8.0", + "react-router-dom": ">=5.1.0" + } + }, + "node_modules/@okta/okta-signin-widget": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/@okta/okta-signin-widget/-/okta-signin-widget-6.4.3.tgz", + "integrity": "sha512-bMx+OCskWk+Pz6fxxoMhcZleHqX+DrSzS2CNkwEEEwRYV0amfe12PI99kQ4s+VmXGa0Ctdwy6g5I6fPBKuDZKw==", + "dependencies": { + "@okta/okta-auth-js": "6.5.1", + "@sindresorhus/to-milliseconds": "^1.0.0", + "@types/backbone": "^1.4.15", + "@types/jquery": "^3.5.14", + "@types/jqueryui": "^1.12.16", + "@types/q": "^1.5.5", + "@types/selectize": "^0.12.35", + "@types/underscore": "^1.11.4", + "clipboard": "^1.5.16", + "cross-fetch": "^3.1.5", + "handlebars": "^4.7.7", + "parse-ms": "^2.0.0", + "q": "1.4.1", + "u2f-api-polyfill": "0.4.3", + "underscore": "1.13.1" + }, + "optionalDependencies": { + "fsevents": "*" + } + }, + "node_modules/@okta/okta-signin-widget/node_modules/@okta/okta-auth-js": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@okta/okta-auth-js/-/okta-auth-js-6.5.1.tgz", + "integrity": "sha512-mBzg+EH1Ey7skxHiimSN/ZYraB3l8ZXZlBi8RXNmRLwPMbFlZkQoKrrQu357S5YSEckF59Lqbb/r9Y3cXBNQBQ==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@babel/runtime-corejs3": "^7.17.0", + "@peculiar/webcrypto": "1.1.6", + "atob": "^2.1.2", + "Base64": "1.1.0", + "broadcast-channel": "^4.10.0", + "btoa": "^1.2.1", + "core-js": "^3.6.5", + "cross-fetch": "^3.1.5", + "js-cookie": "^3.0.1", + "jsonpath-plus": "^6.0.1", + "node-cache": "^5.1.2", + "p-cancelable": "^2.0.0", + "text-encoding": "^0.7.0", + "tiny-emitter": "1.1.0", + "webcrypto-shim": "^0.1.5", + "xhr2": "0.1.3" + }, + "engines": { + "node": ">=11.0", + "yarn": "^1.7.0" + } + }, + "node_modules/@okta/okta-signin-widget/node_modules/@peculiar/webcrypto": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.1.6.tgz", + "integrity": "sha512-xcTjouis4Y117mcsJslWAGypwhxtXslkVdRp7e3tHwtuw0/xCp1te8RuMMv/ia5TsvxomcyX/T+qTbRZGLLvyA==", + "dependencies": { + "@peculiar/asn1-schema": "^2.0.27", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.1.2", + "tslib": "^2.1.0", + "webcrypto-core": "^1.2.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.2.0.tgz", + "integrity": "sha512-1ENEJNY7Lwlua/1wvzpYP194WtjQBfFxvde2FlzfBFh/ln6wvChrtxlORhbKEnYswzn6fOC4c7HdC5izLPMTJg==", + "dependencies": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@peculiar/webcrypto": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.0.tgz", + "integrity": "sha512-U58N44b2m3OuTgpmKgf0LPDOmP3bhwNz01vAnj1mBwxBASRhptWYK+M3zG+HBkDqGQM+bFsoIihTW8MdmPXEqg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0", + "webcrypto-core": "^1.7.4" + }, + "engines": { + "node": ">=10.12.0" + } + }, "node_modules/@plotly/d3-sankey": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/@plotly/d3-sankey/-/d3-sankey-0.7.2.tgz", @@ -2899,6 +3054,14 @@ "integrity": "sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==", "dev": true }, + "node_modules/@sindresorhus/to-milliseconds": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/to-milliseconds/-/to-milliseconds-1.2.0.tgz", + "integrity": "sha512-nHpLEF6oRZJZ0ym8hmxz4jeSdnOqwWd5GC75GNQqNjfSG1IY55RE3AaGEC/QUDElLTuaPSBVa1rnV/C/rUkAUw==", + "engines": { + "node": ">=8" + } + }, "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -3364,6 +3527,15 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/backbone": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@types/backbone/-/backbone-1.4.15.tgz", + "integrity": "sha512-WWeKtYlsIMtDyLbbhkb96taJMEbfQBnuz7yw1u0pkphCOtksemoWhIXhK74VRCY9hbjnsH3rsJu2uUiFtnsEYg==", + "dependencies": { + "@types/jquery": "*", + "@types/underscore": "*" + } + }, "node_modules/@types/eslint": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", @@ -3479,6 +3651,22 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "node_modules/@types/jquery": { + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz", + "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==", + "dependencies": { + "@types/sizzle": "*" + } + }, + "node_modules/@types/jqueryui": { + "version": "1.12.16", + "resolved": "https://registry.npmjs.org/@types/jqueryui/-/jqueryui-1.12.16.tgz", + "integrity": "sha512-6huAQDpNlso9ayaUT9amBOA3kj02OCeUWs+UvDmbaJmwkHSg/HLsQOoap/D5uveN9ePwl72N45Bl+Frp5xyG1Q==", + "dependencies": { + "@types/jquery": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -3572,6 +3760,16 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, + "node_modules/@types/selectize": { + "version": "0.12.35", + "resolved": "https://registry.npmjs.org/@types/selectize/-/selectize-0.12.35.tgz", + "integrity": "sha512-OtutSd9mfyl2qjxNABguUGhwRmHcJRYqRNQEUVBC6QIw0P0DKbhsAF5RUhid1L0GdYGNef8l73kSB1KVpazXqA==" + }, + "node_modules/@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" + }, "node_modules/@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", @@ -3604,6 +3802,11 @@ "source-map": "^0.6.1" } }, + "node_modules/@types/underscore": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.4.tgz", + "integrity": "sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg==" + }, "node_modules/@types/webpack": { "version": "4.41.32", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", @@ -4606,6 +4809,19 @@ "safer-buffer": "^2.1.0" } }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", @@ -5139,6 +5355,11 @@ "node": ">=0.10.0" } }, + "node_modules/Base64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/Base64/-/Base64-1.1.0.tgz", + "integrity": "sha512-qeacf8dvGpf+XAT27ESHMh7z84uRzj/ua2pQdJg483m3bEXv/kVFtDnMgvf70BQGqzbZhR9t6BmASzKvqfJf3Q==" + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -5372,6 +5593,20 @@ "node": ">=8" } }, + "node_modules/broadcast-channel": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-4.13.0.tgz", + "integrity": "sha512-fcDr8QNJ4SOb6jyjUNZatVNmcHtSWfW4PFcs4xIEFZAtorKCIFoEYtjIjaQ4c0jrbr/Bl8NIwOWiLSyspoAnEQ==", + "dependencies": { + "@babel/runtime": "^7.16.0", + "detect-node": "^2.1.0", + "microtime": "3.0.0", + "oblivious-set": "1.1.1", + "p-queue": "6.6.2", + "rimraf": "3.0.2", + "unload": "2.3.1" + } + }, "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -5507,6 +5742,17 @@ "node-int64": "^0.4.0" } }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/buffer": { "version": "4.9.2", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", @@ -6148,6 +6394,21 @@ "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", "dev": true }, + "node_modules/clipboard": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz", + "integrity": "sha512-smkaRaIQsrnKN1F3wd1/vY9Q+DeR4L8ZCXKeHCFC2j8RZuSBbuImcLdnIO4GTxmzJxQuDGNKkyfpGoPW7Ua5bQ==", + "dependencies": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "node_modules/clipboard/node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, "node_modules/cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -6240,6 +6501,14 @@ "node": ">=6" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -6528,6 +6797,11 @@ "compare-cell": "^1.0.0" } }, + "node_modules/compare-versions": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.3.tgz", + "integrity": "sha512-WQfnbDcrYnGr55UwbxKiQKASnTtNnaAWVi8jZyy8NTpVAXWACSne8lMD1iaIo9AiU6mnuLvSVshCzewVuWxHUg==" + }, "node_modules/component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -6900,6 +7174,14 @@ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dependencies": { + "node-fetch": "2.6.7" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -7945,6 +8227,11 @@ "node": ">=0.4.0" } }, + "node_modules/delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -11505,6 +11792,14 @@ "xtend": "~4.0.1" } }, + "node_modules/good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", + "dependencies": { + "delegate": "^3.1.2" + } + }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -11538,6 +11833,26 @@ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -14684,6 +14999,14 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/js-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==", + "engines": { + "node": ">=12" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -14854,6 +15177,14 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonpath-plus": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-6.0.1.tgz", + "integrity": "sha512-EvGovdvau6FyLexFH2OeXfIITlgIbgZoAZe3usiySeaIDm5QS+A10DKNpaPBBqqRSZr2HN6HVNXxtwUAr2apEw==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", @@ -15861,6 +16192,19 @@ "node": ">=8.6" } }, + "node_modules/microtime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/microtime/-/microtime-3.0.0.tgz", + "integrity": "sha512-SirJr7ZL4ow2iWcb54bekS4aWyBQNVcEDBiwAz9D/sTgY59A+uE8UJU15cp5wyZmPBwg/3zf8lyCJ5NUe1nVlQ==", + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^1.2.0", + "node-gyp-build": "^3.8.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -16493,6 +16837,41 @@ "tslib": "^2.0.3" } }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==" + }, + "node_modules/node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-forge": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", @@ -16501,6 +16880,16 @@ "node": ">= 6.0.0" } }, + "node_modules/node-gyp-build": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.9.0.tgz", + "integrity": "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -16906,11 +17295,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oblivious-set": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.1.1.tgz", + "integrity": "sha512-Oh+8fK09mgGmAshFdH6hSVco6KZmd1tTwNFWj35OvzdmJTMZtAkbn05zar2iG3v6sDs1JLEtOiBGNb6BHwkb2w==" + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" }, + "node_modules/okta": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/okta/-/okta-1.0.0.tgz", + "integrity": "sha512-Erk8NsRe1c96rI0tD2ZddwBZVqnuvcV8fvTjh468mJq1FIFaQk1PV9vnz4/ChhIsziFCsuTZUYzBpbZz6R0+ew==" + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -17167,6 +17566,14 @@ "node": ">=0.10.0" } }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, "node_modules/p-each-series": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", @@ -17229,6 +17636,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-retry": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", @@ -17240,6 +17662,17 @@ "node": ">=6" } }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -17328,6 +17761,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", + "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", + "engines": { + "node": ">=6" + } + }, "node_modules/parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", @@ -20525,6 +20966,22 @@ "node": ">=6" } }, + "node_modules/pvtsutils": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.2.tgz", + "integrity": "sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pxls": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/pxls/-/pxls-2.3.2.tgz", @@ -23779,6 +24236,11 @@ "compute-scroll-into-view": "^1.0.17" } }, + "node_modules/select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==" + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -25827,6 +26289,12 @@ "vectorize-text": "^3.2.1" } }, + "node_modules/text-encoding": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", + "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==", + "deprecated": "no longer maintained" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -25894,6 +26362,11 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==" }, + "node_modules/tiny-emitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-1.1.0.tgz", + "integrity": "sha512-HFhr+OKGIHRO6krgzEt9MqbMO98wPDzDPr1BOpM/nZCChkK40UYn8b70nSjcan4jTzDSQecy1KRVVQRohIRWrw==" + }, "node_modules/tiny-invariant": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", @@ -26104,6 +26577,11 @@ "node": ">= 4.0.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/triangulate-hypercube": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/triangulate-hypercube/-/triangulate-hypercube-1.0.1.tgz", @@ -26371,6 +26849,23 @@ "node": ">=4.2.0" } }, + "node_modules/u2f-api-polyfill": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/u2f-api-polyfill/-/u2f-api-polyfill-0.4.3.tgz", + "integrity": "sha512-0DVykdzG3tKft2GciQCGzgO8BinDEfIhTBo7FKbLBmA+sVTPYmNOFbsZuduYQmnc3+ykUadTHNqXVqnvBfLCvg==" + }, + "node_modules/uglify-js": { + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.16.1.tgz", + "integrity": "sha512-X5BGTIDH8U6IQ1TIRP62YC36k+ULAa1d59BxlWvPUJ1NkW5L3FwcGfEzuVvGmhJFBu0YJ5Ge25tmRISqCmLiRQ==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -26385,6 +26880,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/underscore": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -26485,6 +26985,15 @@ "node": ">= 10.0.0" } }, + "node_modules/unload": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.3.1.tgz", + "integrity": "sha512-MUZEiDqvAN9AIDRbbBnVYVvfcR6DrjCqeU2YQMmliFZl9uaBUjTkhuDQkBiyAy8ad5bx1TXVbqZ3gg7namsWjA==", + "dependencies": { + "@babel/runtime": "^7.6.2", + "detect-node": "2.1.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -27364,6 +27873,23 @@ "resolved": "https://registry.npmjs.org/weakmap-shim/-/weakmap-shim-1.1.1.tgz", "integrity": "sha512-/wNyG+1FpiHhnfQo+TuA/XAUpvOOkKVl0A4qpT+oGcj5SlZCLmM+M1Py/3Sj8sy+YrEauCVITOxCsZKo6sPbQg==" }, + "node_modules/webcrypto-core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.5.tgz", + "integrity": "sha512-gaExY2/3EHQlRNNNVSrbG2Cg94Rutl7fAaKILS1w8ZDhGxdFOaw6EbCfHIxPy9vt/xwp5o0VQAx9aySPF6hU1A==", + "dependencies": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/webcrypto-shim": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/webcrypto-shim/-/webcrypto-shim-0.1.7.tgz", + "integrity": "sha512-JAvAQR5mRNRxZW2jKigWMjCMkjSdmP5cColRP1U/pTg69VgHXEi1orv5vVpJ55Zc5MIaPc1aaurzd9pjv2bveg==" + }, "node_modules/webgl-context": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/webgl-context/-/webgl-context-2.2.0.tgz", @@ -28323,6 +28849,20 @@ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/whatwg-url/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -28374,6 +28914,11 @@ "node": ">=0.10.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, "node_modules/workbox-background-sync": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-5.1.4.tgz", @@ -28739,6 +29284,14 @@ } } }, + "node_modules/xhr2": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.3.tgz", + "integrity": "sha512-6RmGK22QwC7yXB1CRwyLWuS2opPcKOlAu0ViAnyZjDlzrEmCKL4kLHkfvB8oMRWeztMsNoDGAjsMZY15w/4tTw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", @@ -30915,6 +31468,130 @@ } } }, + "@okta/okta-auth-js": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@okta/okta-auth-js/-/okta-auth-js-6.7.0.tgz", + "integrity": "sha512-DktQcRQp2DLx9KCGVBlexvxOcp/ZvnMvOcp7TknT9DiLp+k9Uksce8oqKo1d04ZjLvAqnQnhxrdBXN8OZkS7uw==", + "requires": { + "@babel/runtime": "^7.12.5", + "@babel/runtime-corejs3": "^7.17.0", + "@peculiar/webcrypto": "^1.4.0", + "atob": "^2.1.2", + "Base64": "1.1.0", + "broadcast-channel": "^4.13.0", + "btoa": "^1.2.1", + "core-js": "^3.6.5", + "cross-fetch": "^3.1.5", + "js-cookie": "^3.0.1", + "jsonpath-plus": "^6.0.1", + "node-cache": "^5.1.2", + "p-cancelable": "^2.0.0", + "text-encoding": "^0.7.0", + "tiny-emitter": "1.1.0", + "webcrypto-shim": "^0.1.5", + "xhr2": "0.1.3" + } + }, + "@okta/okta-react": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@okta/okta-react/-/okta-react-6.5.0.tgz", + "integrity": "sha512-hDt4dswFIPp/JVyrbgrwxM3J9QzqJrd5ml28FKh2BvPZSqowRnAg7xdbMiaP6omLbLiygbnnKvkdVrrtB+5n0g==", + "requires": { + "@babel/runtime": "^7.11.2", + "compare-versions": "^4.1.2" + } + }, + "@okta/okta-signin-widget": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/@okta/okta-signin-widget/-/okta-signin-widget-6.4.3.tgz", + "integrity": "sha512-bMx+OCskWk+Pz6fxxoMhcZleHqX+DrSzS2CNkwEEEwRYV0amfe12PI99kQ4s+VmXGa0Ctdwy6g5I6fPBKuDZKw==", + "requires": { + "@okta/okta-auth-js": "6.5.1", + "@sindresorhus/to-milliseconds": "^1.0.0", + "@types/backbone": "^1.4.15", + "@types/jquery": "^3.5.14", + "@types/jqueryui": "^1.12.16", + "@types/q": "^1.5.5", + "@types/selectize": "^0.12.35", + "@types/underscore": "^1.11.4", + "clipboard": "^1.5.16", + "cross-fetch": "^3.1.5", + "fsevents": "*", + "handlebars": "^4.7.7", + "parse-ms": "^2.0.0", + "q": "1.4.1", + "u2f-api-polyfill": "0.4.3", + "underscore": "1.13.1" + }, + "dependencies": { + "@okta/okta-auth-js": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@okta/okta-auth-js/-/okta-auth-js-6.5.1.tgz", + "integrity": "sha512-mBzg+EH1Ey7skxHiimSN/ZYraB3l8ZXZlBi8RXNmRLwPMbFlZkQoKrrQu357S5YSEckF59Lqbb/r9Y3cXBNQBQ==", + "requires": { + "@babel/runtime": "^7.12.5", + "@babel/runtime-corejs3": "^7.17.0", + "@peculiar/webcrypto": "1.1.6", + "atob": "^2.1.2", + "Base64": "1.1.0", + "broadcast-channel": "^4.10.0", + "btoa": "^1.2.1", + "core-js": "^3.6.5", + "cross-fetch": "^3.1.5", + "js-cookie": "^3.0.1", + "jsonpath-plus": "^6.0.1", + "node-cache": "^5.1.2", + "p-cancelable": "^2.0.0", + "text-encoding": "^0.7.0", + "tiny-emitter": "1.1.0", + "webcrypto-shim": "^0.1.5", + "xhr2": "0.1.3" + } + }, + "@peculiar/webcrypto": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.1.6.tgz", + "integrity": "sha512-xcTjouis4Y117mcsJslWAGypwhxtXslkVdRp7e3tHwtuw0/xCp1te8RuMMv/ia5TsvxomcyX/T+qTbRZGLLvyA==", + "requires": { + "@peculiar/asn1-schema": "^2.0.27", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.1.2", + "tslib": "^2.1.0", + "webcrypto-core": "^1.2.0" + } + } + } + }, + "@peculiar/asn1-schema": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.2.0.tgz", + "integrity": "sha512-1ENEJNY7Lwlua/1wvzpYP194WtjQBfFxvde2FlzfBFh/ln6wvChrtxlORhbKEnYswzn6fOC4c7HdC5izLPMTJg==", + "requires": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@peculiar/webcrypto": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.0.tgz", + "integrity": "sha512-U58N44b2m3OuTgpmKgf0LPDOmP3bhwNz01vAnj1mBwxBASRhptWYK+M3zG+HBkDqGQM+bFsoIihTW8MdmPXEqg==", + "requires": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0", + "webcrypto-core": "^1.7.4" + } + }, "@plotly/d3-sankey": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/@plotly/d3-sankey/-/d3-sankey-0.7.2.tgz", @@ -30997,6 +31674,11 @@ "integrity": "sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==", "dev": true }, + "@sindresorhus/to-milliseconds": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/to-milliseconds/-/to-milliseconds-1.2.0.tgz", + "integrity": "sha512-nHpLEF6oRZJZ0ym8hmxz4jeSdnOqwWd5GC75GNQqNjfSG1IY55RE3AaGEC/QUDElLTuaPSBVa1rnV/C/rUkAUw==" + }, "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -31318,6 +32000,15 @@ "@babel/types": "^7.3.0" } }, + "@types/backbone": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@types/backbone/-/backbone-1.4.15.tgz", + "integrity": "sha512-WWeKtYlsIMtDyLbbhkb96taJMEbfQBnuz7yw1u0pkphCOtksemoWhIXhK74VRCY9hbjnsH3rsJu2uUiFtnsEYg==", + "requires": { + "@types/jquery": "*", + "@types/underscore": "*" + } + }, "@types/eslint": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", @@ -31426,6 +32117,22 @@ } } }, + "@types/jquery": { + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz", + "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==", + "requires": { + "@types/sizzle": "*" + } + }, + "@types/jqueryui": { + "version": "1.12.16", + "resolved": "https://registry.npmjs.org/@types/jqueryui/-/jqueryui-1.12.16.tgz", + "integrity": "sha512-6huAQDpNlso9ayaUT9amBOA3kj02OCeUWs+UvDmbaJmwkHSg/HLsQOoap/D5uveN9ePwl72N45Bl+Frp5xyG1Q==", + "requires": { + "@types/jquery": "*" + } + }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -31519,6 +32226,16 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, + "@types/selectize": { + "version": "0.12.35", + "resolved": "https://registry.npmjs.org/@types/selectize/-/selectize-0.12.35.tgz", + "integrity": "sha512-OtutSd9mfyl2qjxNABguUGhwRmHcJRYqRNQEUVBC6QIw0P0DKbhsAF5RUhid1L0GdYGNef8l73kSB1KVpazXqA==" + }, + "@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" + }, "@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", @@ -31551,6 +32268,11 @@ "source-map": "^0.6.1" } }, + "@types/underscore": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.4.tgz", + "integrity": "sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg==" + }, "@types/webpack": { "version": "4.41.32", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", @@ -32341,6 +33063,16 @@ "safer-buffer": "^2.1.0" } }, + "asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "requires": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + } + }, "assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", @@ -32772,6 +33504,11 @@ } } }, + "Base64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/Base64/-/Base64-1.1.0.tgz", + "integrity": "sha512-qeacf8dvGpf+XAT27ESHMh7z84uRzj/ua2pQdJg483m3bEXv/kVFtDnMgvf70BQGqzbZhR9t6BmASzKvqfJf3Q==" + }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -32968,6 +33705,20 @@ "fill-range": "^7.0.1" } }, + "broadcast-channel": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-4.13.0.tgz", + "integrity": "sha512-fcDr8QNJ4SOb6jyjUNZatVNmcHtSWfW4PFcs4xIEFZAtorKCIFoEYtjIjaQ4c0jrbr/Bl8NIwOWiLSyspoAnEQ==", + "requires": { + "@babel/runtime": "^7.16.0", + "detect-node": "^2.1.0", + "microtime": "3.0.0", + "oblivious-set": "1.1.1", + "p-queue": "6.6.2", + "rimraf": "3.0.2", + "unload": "2.3.1" + } + }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -33088,6 +33839,11 @@ "node-int64": "^0.4.0" } }, + "btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==" + }, "buffer": { "version": "4.9.2", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", @@ -33593,6 +34349,23 @@ "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", "dev": true }, + "clipboard": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz", + "integrity": "sha512-smkaRaIQsrnKN1F3wd1/vY9Q+DeR4L8ZCXKeHCFC2j8RZuSBbuImcLdnIO4GTxmzJxQuDGNKkyfpGoPW7Ua5bQ==", + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + }, + "dependencies": { + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + } + } + }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -33669,6 +34442,11 @@ } } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -33926,6 +34704,11 @@ "compare-cell": "^1.0.0" } }, + "compare-versions": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.3.tgz", + "integrity": "sha512-WQfnbDcrYnGr55UwbxKiQKASnTtNnaAWVi8jZyy8NTpVAXWACSne8lMD1iaIo9AiU6mnuLvSVshCzewVuWxHUg==" + }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -34241,6 +35024,14 @@ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, + "cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "requires": { + "node-fetch": "2.6.7" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -35076,6 +35867,11 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -37942,6 +38738,14 @@ "resolve": "^1.0.0" } }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", + "requires": { + "delegate": "^3.1.2" + } + }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -37972,6 +38776,18 @@ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -40384,6 +41200,11 @@ } } }, + "js-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -40522,6 +41343,11 @@ "universalify": "^2.0.0" } }, + "jsonpath-plus": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-6.0.1.tgz", + "integrity": "sha512-EvGovdvau6FyLexFH2OeXfIITlgIbgZoAZe3usiySeaIDm5QS+A10DKNpaPBBqqRSZr2HN6HVNXxtwUAr2apEw==" + }, "jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", @@ -41336,6 +42162,15 @@ "picomatch": "^2.3.1" } }, + "microtime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/microtime/-/microtime-3.0.0.tgz", + "integrity": "sha512-SirJr7ZL4ow2iWcb54bekS4aWyBQNVcEDBiwAz9D/sTgY59A+uE8UJU15cp5wyZmPBwg/3zf8lyCJ5NUe1nVlQ==", + "requires": { + "node-addon-api": "^1.2.0", + "node-gyp-build": "^3.8.0" + } + }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -41863,11 +42698,37 @@ "tslib": "^2.0.3" } }, + "node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==" + }, + "node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "requires": { + "clone": "2.x" + } + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, "node-forge": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" }, + "node-gyp-build": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.9.0.tgz", + "integrity": "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A==" + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -42185,11 +43046,21 @@ "es-abstract": "^1.19.1" } }, + "oblivious-set": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.1.1.tgz", + "integrity": "sha512-Oh+8fK09mgGmAshFdH6hSVco6KZmd1tTwNFWj35OvzdmJTMZtAkbn05zar2iG3v6sDs1JLEtOiBGNb6BHwkb2w==" + }, "obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" }, + "okta": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/okta/-/okta-1.0.0.tgz", + "integrity": "sha512-Erk8NsRe1c96rI0tD2ZddwBZVqnuvcV8fvTjh468mJq1FIFaQk1PV9vnz4/ChhIsziFCsuTZUYzBpbZz6R0+ew==" + }, "on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -42387,6 +43258,11 @@ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true }, + "p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" + }, "p-each-series": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", @@ -42422,6 +43298,15 @@ "aggregate-error": "^3.0.0" } }, + "p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "requires": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + } + }, "p-retry": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", @@ -42430,6 +43315,14 @@ "retry": "^0.12.0" } }, + "p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "requires": { + "p-finally": "^1.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -42503,6 +43396,11 @@ "lines-and-columns": "^1.1.6" } }, + "parse-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", + "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==" + }, "parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", @@ -45078,6 +45976,19 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, + "pvtsutils": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.2.tgz", + "integrity": "sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==", + "requires": { + "tslib": "^2.4.0" + } + }, + "pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==" + }, "pxls": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/pxls/-/pxls-2.3.2.tgz", @@ -47546,6 +48457,11 @@ "compute-scroll-into-view": "^1.0.17" } }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==" + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -49215,6 +50131,11 @@ "vectorize-text": "^3.2.1" } }, + "text-encoding": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", + "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==" + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -49281,6 +50202,11 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==" }, + "tiny-emitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-1.1.0.tgz", + "integrity": "sha512-HFhr+OKGIHRO6krgzEt9MqbMO98wPDzDPr1BOpM/nZCChkK40UYn8b70nSjcan4jTzDSQecy1KRVVQRohIRWrw==" + }, "tiny-invariant": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", @@ -49456,6 +50382,11 @@ } } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "triangulate-hypercube": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/triangulate-hypercube/-/triangulate-hypercube-1.0.1.tgz", @@ -49662,6 +50593,17 @@ "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "peer": true }, + "u2f-api-polyfill": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/u2f-api-polyfill/-/u2f-api-polyfill-0.4.3.tgz", + "integrity": "sha512-0DVykdzG3tKft2GciQCGzgO8BinDEfIhTBo7FKbLBmA+sVTPYmNOFbsZuduYQmnc3+ykUadTHNqXVqnvBfLCvg==" + }, + "uglify-js": { + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.16.1.tgz", + "integrity": "sha512-X5BGTIDH8U6IQ1TIRP62YC36k+ULAa1d59BxlWvPUJ1NkW5L3FwcGfEzuVvGmhJFBu0YJ5Ge25tmRISqCmLiRQ==", + "optional": true + }, "unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -49673,6 +50615,11 @@ "which-boxed-primitive": "^1.0.2" } }, + "underscore": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -49752,6 +50699,15 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, + "unload": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.3.1.tgz", + "integrity": "sha512-MUZEiDqvAN9AIDRbbBnVYVvfcR6DrjCqeU2YQMmliFZl9uaBUjTkhuDQkBiyAy8ad5bx1TXVbqZ3gg7namsWjA==", + "requires": { + "@babel/runtime": "^7.6.2", + "detect-node": "2.1.0" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -50497,6 +51453,23 @@ "resolved": "https://registry.npmjs.org/weakmap-shim/-/weakmap-shim-1.1.1.tgz", "integrity": "sha512-/wNyG+1FpiHhnfQo+TuA/XAUpvOOkKVl0A4qpT+oGcj5SlZCLmM+M1Py/3Sj8sy+YrEauCVITOxCsZKo6sPbQg==" }, + "webcrypto-core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.5.tgz", + "integrity": "sha512-gaExY2/3EHQlRNNNVSrbG2Cg94Rutl7fAaKILS1w8ZDhGxdFOaw6EbCfHIxPy9vt/xwp5o0VQAx9aySPF6hU1A==", + "requires": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "webcrypto-shim": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/webcrypto-shim/-/webcrypto-shim-0.1.7.tgz", + "integrity": "sha512-JAvAQR5mRNRxZW2jKigWMjCMkjSdmP5cColRP1U/pTg69VgHXEi1orv5vVpJ55Zc5MIaPc1aaurzd9pjv2bveg==" + }, "webgl-context": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/webgl-context/-/webgl-context-2.2.0.tgz", @@ -51242,6 +52215,22 @@ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + } + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -51278,6 +52267,11 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, "workbox-background-sync": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-5.1.4.tgz", @@ -51599,6 +52593,11 @@ "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==", "requires": {} }, + "xhr2": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.3.tgz", + "integrity": "sha512-6RmGK22QwC7yXB1CRwyLWuS2opPcKOlAu0ViAnyZjDlzrEmCKL4kLHkfvB8oMRWeztMsNoDGAjsMZY15w/4tTw==" + }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", diff --git a/package.json b/package.json index 7049ca52..4340ebb7 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,9 @@ "repository": "github:Lambda-School-Labs/labs-spa-starter", "dependencies": { "@craco/craco": "^6.4.3", + "@okta/okta-auth-js": "^6.7.0", + "@okta/okta-react": "^6.5.0", + "@okta/okta-signin-widget": "^6.4.2", "antd": "^4.20.1", "axios": "^0.21.1", "craco-less": "^1.20.0", @@ -14,6 +17,7 @@ "emailjs-com": "^3.2.0", "formik": "^2.2.9", "moment": "^2.29.2", + "okta": "^1.0.0", "plotly.js": "^1.54.6", "react": "^18.1", "react-dom": "^18.1", diff --git a/src/__tests__/LandingPage.test.js b/src/__tests__/LandingPage.test.js index 7f11e247..69af4965 100644 --- a/src/__tests__/LandingPage.test.js +++ b/src/__tests__/LandingPage.test.js @@ -10,6 +10,15 @@ import { LandingPage } from '../components/pages/Landing'; const store = createStore(rootReducers); +jest.mock('@okta/okta-react', () => ({ + useOktaAuth: () => { + return { + authState: null, + authService: {}, + }; + }, +})); + beforeEach(() => { render( diff --git a/src/__tests__/PaymentSuccess.test.js b/src/__tests__/PaymentSuccess.test.js index 0791a9dc..13f1ac0a 100644 --- a/src/__tests__/PaymentSuccess.test.js +++ b/src/__tests__/PaymentSuccess.test.js @@ -7,7 +7,17 @@ import rootReducers from '../redux/reducers/index'; import PaymentSuccess from '../components/pages/ParentHome/PaymentSuccess'; const store = createStore(rootReducers); -//TO-DO: Implement mock for Auth0 + +jest.mock('@okta/okta-react', () => ({ + useOktaAuth: () => { + return { + authState: { + isAuthenticated: true, + }, + authService: {}, + }; + }, +})); describe('', () => { test('it renders the PaymentSuccess component', () => { diff --git a/src/__tests__/ProfileListContainer.test.js b/src/__tests__/ProfileListContainer.test.js index 80eca331..c5fb401a 100644 --- a/src/__tests__/ProfileListContainer.test.js +++ b/src/__tests__/ProfileListContainer.test.js @@ -6,7 +6,16 @@ import { ProfileListPage } from '../components/pages/ProfileList'; jest.mock('../api', () => { return { getProfileData: () => Promise.resolve([]) }; }); -//TO-DO: Implement mock for Auth0 +jest.mock('@okta/okta-react', () => ({ + useOktaAuth: () => { + return { + authState: { + isAuthenticated: true, + }, + authService: {}, + }; + }, +})); describe('', () => { test('renders a loading state upon loading and calling for profiles', async () => { diff --git a/src/__tests__/Registration.test.js b/src/__tests__/Registration.test.js index b149215d..7bd08512 100644 --- a/src/__tests__/Registration.test.js +++ b/src/__tests__/Registration.test.js @@ -10,7 +10,17 @@ import { createMemoryHistory } from 'history'; import InstructorWelcome from '../components/pages/Registration/InstructorWelcome'; const store = createStore(rootReducers); -//TO-DO: Implement mock for Auth0 + +jest.mock('@okta/okta-react', () => ({ + useOktaAuth: () => { + return { + authState: { + isAuthenticated: true, + }, + authService: {}, + }; + }, +})); describe('', () => { test('it renders the instructorWelcome component', () => { diff --git a/src/api/index.js b/src/api/index.js index 8c42982b..ac1c58f7 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -1,8 +1,6 @@ import axios from 'axios'; -//TO-DO: Implement Auth0 // we will define a bunch of API calls here. -//NOTE: apiUrl will be used below once auth0 is implemented // const apiUrl = `${process.env.REACT_APP_API_URI}/profiles`; const sleep = time => @@ -16,28 +14,33 @@ const getExampleData = () => { .then(response => response.data); }; -const getDSData = url => { +const getAuthHeader = authState => { + if (!authState.isAuthenticated) { + throw new Error('Not authenticated'); + } + return { Authorization: `Bearer ${authState.idToken}` }; +}; + +const getDSData = (url, authState) => { // here's another way you can compose together your API calls. // Note the use of GetAuthHeader here is a little different than in the getProfileData call. + const headers = getAuthHeader(authState); if (!url) { throw new Error('No URL provided'); } return axios - .get(url) + .get(url, { headers }) .then(res => JSON.parse(res.data)) - .catch(err => { - console.log(err); - }); + .catch(err => err); }; -// NOTE: Once auth0 is implemented these lines can be refactored or reused // -// const apiAuthGet = authHeader => { -// return axios.get(apiUrl, { headers: authHeader }); -// }; +const apiAuthGet = authHeader => { + return axios.get(apiUrl, { headers: authHeader }); +}; -const getProfileData = () => { +const getProfileData = authState => { try { - return 'Hi, need to Implement Auth0'; + return apiAuthGet(getAuthHeader(authState)).then(response => response.data); } catch (error) { return new Promise(() => { console.log(error); @@ -46,4 +49,4 @@ const getProfileData = () => { } }; -export { sleep, getExampleData, getProfileData, getDSData }; +export { sleep, getExampleData, getProfileData, getDSData, getAuthHeader }; diff --git a/src/components/common/Header.js b/src/components/common/Header.js index 55d5cc67..17b42fa1 100644 --- a/src/components/common/Header.js +++ b/src/components/common/Header.js @@ -1,9 +1,9 @@ import React from 'react'; import { Menu } from 'antd'; +import { useOktaAuth } from '@okta/okta-react'; export default function MainHeader() { - //TO-DO: Implement Auth0 - // const { authService, authState } = 'Update the hook with auth0'; + const { authService, authState } = useOktaAuth(); return (
@@ -12,7 +12,7 @@ export default function MainHeader() { Booking Scholarships Contact Us (button) - {/* {authState.isAuthenticated ? ( + {authState.isAuthenticated ? ( { @@ -23,7 +23,7 @@ export default function MainHeader() { ) : ( <> - )} */} + )}
); diff --git a/src/components/common/JoinUpdate.js b/src/components/common/JoinUpdate.js index 511c4ed1..d7d898c7 100644 --- a/src/components/common/JoinUpdate.js +++ b/src/components/common/JoinUpdate.js @@ -45,7 +45,6 @@ const Form = props => { }) .catch(err => { console.log(err); - return value; }); setValues({ 'First Name': '', diff --git a/src/components/common/Navbars/InstructorNavBar.js b/src/components/common/Navbars/InstructorNavBar.js index 4aea230e..d3fcbcfe 100644 --- a/src/components/common/Navbars/InstructorNavBar.js +++ b/src/components/common/Navbars/InstructorNavBar.js @@ -4,6 +4,7 @@ import { ThunderboltFilled } from '@ant-design/icons'; import { Drawer, Menu, Layout } from 'antd'; import { NavLink } from 'react-router-dom'; // eslint-disable-next-line +import { useOktaAuth } from '@okta/okta-react'; import { ProfileIcon } from '../../pages/LandingInstructor/Icons'; const { Header } = Layout; diff --git a/src/components/common/Navbars/NavBar.js b/src/components/common/Navbars/NavBar.js index 2d6e2abd..f8001b83 100644 --- a/src/components/common/Navbars/NavBar.js +++ b/src/components/common/Navbars/NavBar.js @@ -28,8 +28,6 @@ import { connect } from 'react-redux'; import navLogo from '../../../img/navbar-logo.png'; import handleLogout from '../../../utils/logout.js'; -//TO-DO: Implement Auth0 - const { SubMenu } = Menu; const { Header } = Layout; @@ -43,7 +41,7 @@ function NavBar(props) { useEffect(() => { if (role_id === 5) setBgColor('#9FB222'); - else if (role_id < 5 && role_id > 2) setBgColor('#21C5B5'); + else if (role_id < 5) setBgColor('#21C5B5'); else setBgColor('#FEAD2A'); }, [role_id]); @@ -72,7 +70,7 @@ function NavBar(props) { style={{ backgroundColor: bgColor, minHeight: '98px', - lineHeight: '0px', + lineHeight: '0', padding: '0', }} > @@ -101,15 +99,21 @@ function NavBar(props) { )} - - - {/* {localStorage.getItem({}) && ( */} - -
- -
+
- {/* )} */} + {localStorage.getItem('okta-token-storage') && ( + +
+ +
+
+ )}
@@ -123,12 +127,16 @@ function NavBar(props) { }> Home - }> - Login - - }> - My Dashboard - + {!localStorage.getItem('okta-token-storage') && ( + }> + Login + + )} + {localStorage.getItem('okta-token-storage') && ( + }> + My Dashboard + + )} }> - - Dashboard + + DASHBOARD - Components + COMPONENTS - Utilities + UTILITIES - Pages + PAGES
); diff --git a/src/components/common/calendar/Calendar.js b/src/components/common/calendar/Calendar.js index d73f2ada..1e34c42b 100644 --- a/src/components/common/calendar/Calendar.js +++ b/src/components/common/calendar/Calendar.js @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { useOktaAuth } from '@okta/okta-react'; import '../../../styles/calendar.less'; import 'antd/dist/antd.css'; import { @@ -13,8 +14,7 @@ import { } from 'antd'; import moment from 'moment'; import CalendarModal from './CalendarModal'; -import axios from 'axios'; -// import axiosWithAuth from '../../../utils/axiosWithAuth'; +import axiosWithAuth from '../../../utils/axiosWithAuth'; function CalendarApp() { const [isModalVisible, setIsModalVisible] = useState(false); @@ -27,20 +27,25 @@ function CalendarApp() { const [eventFlag, setEventFlag] = useState(true); const [form] = Form.useForm(); - // TO-DO: Implement Auth0 + const { authState, oktaAuth } = useOktaAuth(); + const { idToken } = authState; + + // const token = oktaAuth.getIdToken(); + useEffect(() => { if (eventFlag) { - // axiosWithAuth(idToken) - // .get('/calendar-events/user') - Promise.resolve({ data: { events: [] }, message: '' }) + console.log(authState); + console.log(oktaAuth); + axiosWithAuth(idToken) + .get('/calendar-events/user') .then(res => { setEventsArr(res.data.events); }) .catch(err => console.error(err)); - setEventFlag(false); - // eslint-disable-next-line } - }, [eventFlag]); + setEventFlag(false); + // eslint-disable-next-line + }, [eventFlag, idToken]); useEffect(() => { if (event) { @@ -73,14 +78,13 @@ function CalendarApp() { // edit event form submission handler const onFinish = values => { - // axiosWithAuth() - // .put(`/calendar-events/${event.event_id}`, { - // ...values, - // type: 'success', - // date: values.date.format('MM/DD/YYYY'), - // time: values.time.format('h:mm A'), - // }) - Promise.resolve({ data: [], message: '' }) + axiosWithAuth() + .put(`/calendar-events/${event.event_id}`, { + ...values, + type: 'success', + date: values.date.format('MM/DD/YYYY'), + time: values.time.format('h:mm A'), + }) .then(() => { setEventFlag(true); setIsModalVisible(false); @@ -91,9 +95,8 @@ function CalendarApp() { }; const handleDelete = () => { - // axiosWithAuth() - // .delete(`/calendar-events/${event.event_id}`) - Promise.resolve({ data: [], message: '' }) + axiosWithAuth() + .delete(`/calendar-events/${event.event_id}`) .then(() => { setEventFlag(true); setIsModalVisible(false); diff --git a/src/components/common/calendar/CalendarModal.js b/src/components/common/calendar/CalendarModal.js index 4661e1f5..1a2db9fd 100644 --- a/src/components/common/calendar/CalendarModal.js +++ b/src/components/common/calendar/CalendarModal.js @@ -1,14 +1,16 @@ import React from 'react'; import { Modal, Form, Input, Button, DatePicker, TimePicker } from 'antd'; -// import axiosWithAuth from '../../../utils/axiosWithAuth'; -import axios from 'axios'; -//TO-DO: Implement Auth0 +import axiosWithAuth from '../../../utils/axiosWithAuth'; +import { useOktaAuth } from '@okta/okta-react'; export default function CalendarModal(props) { const { isModalVisible, setIsModalVisible, setEventFlag } = props; const [form] = Form.useForm(); + const { authState } = useOktaAuth(); + const { idToken } = authState; + const handleCancel = () => { setIsModalVisible(false); }; @@ -20,9 +22,8 @@ export default function CalendarModal(props) { time: values.time.format('h:mm A'), type: 'success', }; - // axiosWithAuth(idToken) - // .post('/calendar-events', newEvent) - Promise.resolve({ data: [], message: '' }) + axiosWithAuth(idToken) + .post('/calendar-events', newEvent) .then(() => setEventFlag(true)) .catch(err => console.error(err)); setIsModalVisible(false); diff --git a/src/components/pages/AdminAddCourse/AdminAddCoursesForm.js b/src/components/pages/AdminAddCourse/AdminAddCoursesForm.js index 3b3dfe3a..8590e693 100644 --- a/src/components/pages/AdminAddCourse/AdminAddCoursesForm.js +++ b/src/components/pages/AdminAddCourse/AdminAddCoursesForm.js @@ -1,10 +1,7 @@ import React, { useState } from 'react'; -// import axiosWithAuth from '../../../utils/axiosWithAuth'; -import { useDispatch } from 'react-redux'; -import { getCurrentUser } from '../../../redux/actions/userActions'; import { connect } from 'react-redux'; -import { useHistory } from 'react-router-dom'; -//import moment from 'moment'; you may need this for auto-pop +import { useDispatch } from 'react-redux'; +import { useOktaAuth } from '@okta/okta-react'; import { editCourse, addCourse } from '../../../redux/actions/coursesActions'; // Styles @@ -21,8 +18,6 @@ import { Select, } from 'antd'; import TextArea from 'antd/lib/input/TextArea'; - -//TO-DO: Implement Auth0 const { Option } = Select; const initialFormValues = { @@ -55,6 +50,8 @@ function AdminAddCoursesForm(props) { const [formValues, setFormValues] = useState(initialFormValues); const { courseinfo } = props; const [isModalVisible, setIsModalVisible] = useState(false); + const dispatch = useDispatch(); + const idToken = useOktaAuth().oktaAuth.getIdToken(); const numberFields = [ { @@ -73,9 +70,6 @@ function AdminAddCoursesForm(props) { value: formValues.course_min_age, }, ]; - const [formPreReqs, setFormPreReqs] = useState({ prereq: '' }); - - const daysOfWeek = []; const showModal = () => { setIsModalVisible(true); @@ -102,13 +96,11 @@ function AdminAddCoursesForm(props) { setIsModalVisible(false); }; - const { dispatch } = useDispatch(); - const handleSubmit = e => { if (props.button_name === 'Add Course') { - dispatch(addCourse(formValues)); + dispatch(addCourse(idToken, formValues)); } else { - dispatch(editCourse(formValues)); + dispatch(editCourse(idToken, formValues)); alert('Edits Submitted!'); } @@ -116,30 +108,6 @@ function AdminAddCoursesForm(props) { window.location.reload(); }; - let history = useHistory(); - - //TO-DO: Implement axiosWithAuth once we've adjusted it to work with Auth0 - - //currently being blocked from the BE due to only a instructor can add courses.. BE middleware will need to be added for admin. - // function handleSubmit(e) { - // e.preventDefault(); - // axios - // .post('/courses', formValues) - // .then(() => { - // history.push('/admin-courses'); - // }) - // .catch(err => { - // console.error(err); - // }); - // const merged = { - // ...formValues, - // prereq: placeHolder, - // }; - // program_list.push(props.addClass(merged).payload); - // setFormValues(initialFormValues); - // clearPrereq(); - // } - const handleChange = e => { setFormValues({ ...formValues, diff --git a/src/components/pages/AdminAddCourse/AdminAddCoursesPage.js b/src/components/pages/AdminAddCourse/AdminAddCoursesPage.js index 81dfbc81..4b75b661 100644 --- a/src/components/pages/AdminAddCourse/AdminAddCoursesPage.js +++ b/src/components/pages/AdminAddCourse/AdminAddCoursesPage.js @@ -1,6 +1,7 @@ import React, { useState } from 'react'; import { connect } from 'react-redux'; +import { useOktaAuth } from '@okta/okta-react'; import { useDispatch } from 'react-redux'; import { addCourse } from '../../../redux/actions/coursesActions'; import '../../../styles/AdminAddCoursesStyles/AdminAddCoursesPage.less'; @@ -8,7 +9,6 @@ import '../../../styles/AdminAddCoursesStyles/AdminAddCoursesPage.less'; import AdminAddCoursesForm from './AdminAddCoursesForm'; import { Button } from 'antd'; -//TO-DO: Implement Auth0 const initialFormValues = { course_id: '', course_name: '', @@ -30,6 +30,8 @@ const initialFormValues = { function AdminAddCoursesPage(props) { const dispatch = useDispatch(); + const { authState } = useOktaAuth(); + const { idToken } = authState; const [isModalVisible, setIsModalVisible] = useState(false); const showModal = () => { @@ -38,11 +40,11 @@ function AdminAddCoursesPage(props) { const handleOk = course => { if (!course.course_id) { - dispatch(addCourse(course)); + dispatch(addCourse(idToken, course)); } if (course.course_id) { // this will eventually be used for editing existing courses - // dispatch(editCourse(course)); + // dispatch(editCourse(idToken, course)); } setIsModalVisible(false); diff --git a/src/components/pages/AdminHome/AdminCourses.js b/src/components/pages/AdminHome/AdminCourses.js index ed0ea3ab..2b2f8ade 100644 --- a/src/components/pages/AdminHome/AdminCourses.js +++ b/src/components/pages/AdminHome/AdminCourses.js @@ -4,13 +4,19 @@ import AdminSidebar from './AdminSidebar'; import CourseCard from './AdminCourseCard'; import { useDispatch, connect } from 'react-redux'; import { getCourses } from '../../../redux/actions/coursesActions'; +import { useOktaAuth } from '@okta/okta-react'; import { Layout } from 'antd'; -//TO-DO: Implement Auth0 // need to upgrade the courses router/modal to get the instructor name (2 seconds update in modal) function AdminCourses(props) { const { courses } = props; + const dispatch = useDispatch(); + const idToken = useOktaAuth().oktaAuth.getIdToken(); + + useEffect(() => { + dispatch(getCourses(idToken)); + }, [dispatch, idToken]); const history = useHistory(); diff --git a/src/components/pages/AdminHome/AdminHomeContent.js b/src/components/pages/AdminHome/AdminHomeContent.js index 214c3c99..94ed41d2 100644 --- a/src/components/pages/AdminHome/AdminHomeContent.js +++ b/src/components/pages/AdminHome/AdminHomeContent.js @@ -1,5 +1,4 @@ import React from 'react'; -import { Link } from 'react-router-dom'; import CourseCard from './CourseCard'; import ApplicationCard from './ApplicationCard'; import { Layout } from 'antd'; @@ -16,15 +15,11 @@ const AdminHomeContent = () => {

Recent Courses

- - See All - + See All

Instructor Applications

- - See All - + See All
diff --git a/src/components/pages/AdminHome/AdminInstructors.js b/src/components/pages/AdminHome/AdminInstructors.js index 18f04294..171d627a 100644 --- a/src/components/pages/AdminHome/AdminInstructors.js +++ b/src/components/pages/AdminHome/AdminInstructors.js @@ -2,12 +2,12 @@ import React, { useEffect, useState } from 'react'; import { connect } from 'react-redux'; import { useDispatch } from 'react-redux'; import { getInstructors } from '../../../redux/actions/instructorActions'; +import { useOktaAuth } from '@okta/okta-react'; import AdminSidebar from './AdminSidebar'; import { Layout } from 'antd'; import AdminInstructorCard from './AdminInstructorCard'; import LoadingComponent from '../../common/LoadingComponent'; import PaginatePage from '../../common/PaginatePage'; -//TO-DO: Implement Auth0 const { Content } = Layout; @@ -20,6 +20,12 @@ function AdminInstructors(props) { const [displayed, setDisplayed] = useState(filtered); const [minValue, setMinValue] = useState(0); const [maxValue, setMaxValue] = useState(10); + const dispatch = useDispatch(); + const idToken = useOktaAuth().oktaAuth.getIdToken(); + + useEffect(() => { + dispatch(getInstructors(idToken)); + }, [dispatch, idToken]); useEffect(() => { setDisplayed(filtered); diff --git a/src/components/pages/AdminHome/AdminPurchases.js b/src/components/pages/AdminHome/AdminPurchases.js index e489bab2..6edb111a 100644 --- a/src/components/pages/AdminHome/AdminPurchases.js +++ b/src/components/pages/AdminHome/AdminPurchases.js @@ -1,12 +1,14 @@ import React, { useState, useEffect } from 'react'; -// import axiosWithAuth from '../../../utils/axiosWithAuth'; +import { useOktaAuth } from '@okta/okta-react'; +import axiosWithAuth from '../../../utils/axiosWithAuth'; import AdminSidebar from './AdminSidebar'; import { Layout } from 'antd'; import PurchasesTable from './AdminPurchasesTable'; import '../../../styles/index.less'; -//TO-DO: Implement Auth0 const PurchasesList = () => { + const { authState } = useOktaAuth(); + const { idToken } = authState; const [purchases, setPurchases] = useState([ { purchase_date: 20220816, @@ -20,15 +22,12 @@ const PurchasesList = () => { // this is going out to an unspecified URL to gather the info - could be the backend, could be Stripe useEffect(() => { - // axiosWithAuth(idToken) - // .get(`${URL}/admin-purchases`) - Promise.resolve({ data: [], message: '' }) + axiosWithAuth(idToken) + .get(`${URL}/admin-purchases`) .then(res => { setPurchases(res.data); }) - .catch(err => { - console.error(err); - }); + .catch(err => console.error(err)); }, []); const { Content } = Layout; diff --git a/src/components/pages/AdminHome/AdminSidebar.js b/src/components/pages/AdminHome/AdminSidebar.js index 99132078..8870fd30 100644 --- a/src/components/pages/AdminHome/AdminSidebar.js +++ b/src/components/pages/AdminHome/AdminSidebar.js @@ -1,11 +1,16 @@ import { Menu } from 'antd'; import React, { useState } from 'react'; -import { Link, useHistory } from 'react-router-dom'; -import '../../../styles/AdminStyles/index.less'; +import '../../../styles/InstructorStyles/index.less'; import { - DashboardOutlined, - TableOutlined, - ProfileOutlined, + DesktopOutlined, + HomeOutlined, + ThunderboltOutlined, + PlusOutlined, + BellOutlined, + CalculatorOutlined, + FormOutlined, + DollarOutlined, + FolderOpenOutlined, } from '@ant-design/icons'; import { Layout } from 'antd'; @@ -13,13 +18,14 @@ const { Sider } = Layout; function AdminSidebar() { const [collapsed, setCollapsed] = useState(false); - let { location } = useHistory(); - const path = location.pathname; const onCollapse = () => { - setCollapsed(!collapsed); + if (collapsed === true) { + setCollapsed(false); + } else { + setCollapsed(true); + } }; - return (
- - }> - Dashboard - - - }> - - Instructors - - - - Programs - - - - }> - Messages + + } + className="dashboard-logo" + > + Coderheroes + + + }> + Home + + + }> + Instructors + + + }> + Courses + + + }> + Add Courses + + + }> + Edit Programs + + + }> + Purchases + + + + Instructors + + + }> + Applications diff --git a/src/components/pages/AdminHome/ApplicationCard.js b/src/components/pages/AdminHome/ApplicationCard.js index 3fe7ec53..003c875b 100644 --- a/src/components/pages/AdminHome/ApplicationCard.js +++ b/src/components/pages/AdminHome/ApplicationCard.js @@ -3,12 +3,18 @@ import { useHistory } from 'react-router-dom'; import { Card } from 'antd'; import { connect, useDispatch } from 'react-redux'; import { getInstructors } from '../../../redux/actions/instructorActions'; +import { useOktaAuth } from '@okta/okta-react'; import '../../../styles/AdminDashboardHome/index.less'; -//TO-DO: Implement Auth0 const ApplicationCard = props => { const history = useHistory(); const dispatch = useDispatch(); + const { authState } = useOktaAuth(); + + useEffect(() => { + if (!authState) return; + dispatch(getInstructors(authState.idToken.idToken)); + }, [authState, dispatch]); const handleOnClick = id => { history.push(`/instructors/${id}`); // Might have to change the route. diff --git a/src/components/pages/AdminHome/CourseCard.js b/src/components/pages/AdminHome/CourseCard.js index 90461cfa..8913fdab 100644 --- a/src/components/pages/AdminHome/CourseCard.js +++ b/src/components/pages/AdminHome/CourseCard.js @@ -3,11 +3,18 @@ import { useHistory } from 'react-router-dom'; import { Card } from 'antd'; import { connect, useDispatch } from 'react-redux'; import { getCourses } from '../../../redux/actions/coursesActions'; +import { useOktaAuth } from '@okta/okta-react'; import '../../../styles/AdminDashboardHome/index.less'; -//TO-DO: Implement Auth0 const CourseCard = props => { const history = useHistory(); + const dispatch = useDispatch(); + const idToken = useOktaAuth().oktaAuth.getIdToken(); + + useEffect(() => { + if (!idToken) return; + dispatch(getCourses(idToken)); + }, [dispatch, idToken]); const handleOnClick = id => { history.push(`/course/${id}`); // Might have to change the route diff --git a/src/components/pages/Classroom/FeedbackBadge.js b/src/components/pages/Classroom/FeedbackBadge.js index 78788403..51817de5 100644 --- a/src/components/pages/Classroom/FeedbackBadge.js +++ b/src/components/pages/Classroom/FeedbackBadge.js @@ -1,16 +1,17 @@ import React from 'react'; import { Card, Avatar, Button } from 'antd'; +import { useOktaAuth } from '@okta/okta-react'; import { connect, useDispatch } from 'react-redux'; import { addBadgeToStudent, removeBadgeFromStudent, } from '../../../redux/actions/classroomActions'; -//TO-DO: Implement Auth0 - const { Meta } = Card; const FeedbackBadges = props => { const { badge, studentBadges } = props; + const { authState } = useOktaAuth(); + const { idToken } = authState; const dispatch = useDispatch(); @@ -24,6 +25,7 @@ const FeedbackBadges = props => { e.preventDefault(); dispatch( addBadgeToStudent( + idToken, badgeValues.badge_id, badgeValues.student_id, badgeValues.badge @@ -35,6 +37,7 @@ const FeedbackBadges = props => { e.preventDefault(); dispatch( removeBadgeFromStudent( + idToken, badgeValues.badge_id, badgeValues.student_id, badgeValues.badge diff --git a/src/components/pages/Classroom/FeedbackBadgePage.js b/src/components/pages/Classroom/FeedbackBadgePage.js index c17c34b1..8457cbd1 100644 --- a/src/components/pages/Classroom/FeedbackBadgePage.js +++ b/src/components/pages/Classroom/FeedbackBadgePage.js @@ -1,4 +1,5 @@ import React, { useEffect } from 'react'; +import { useOktaAuth } from '@okta/okta-react'; import InstructorSidebar from '../InstructorHome/InstructorSidebar'; import '../../../styles/ClassroomStyles/badges.less'; import { Layout } from 'antd'; @@ -9,25 +10,25 @@ import { getBadgesById, getBadges, } from '../../../redux/actions/classroomActions'; -//TO-DO: Implement Auth0 const { Content } = Layout; const FeedbackBadgesPage = props => { const dispatch = useDispatch(); - + const { authState } = useOktaAuth(); + const { idToken } = authState; const { course } = props; - // useEffect(() => { - // // dispatch(getBadgesById(course.currentStudentId)); - // // dispatch(getBadges(profile.id)); - // // }, []) + useEffect(() => { + dispatch(getBadgesById(idToken, course.currentStudentId)); + dispatch(getBadges(idToken)); + }, []); - // useEffect(() => { - // const timer = setTimeout(() => { - // dispatch(getBadgesById(course.currentStudentId)); - // }, 100); - // return () => clearTimeout(timer); - // }, [course.badge_request]); + useEffect(() => { + const timer = setTimeout(() => { + dispatch(getBadgesById(idToken, course.currentStudentId)); + }, 100); + return () => clearTimeout(timer); + }, [course.badge_request]); return ( <> diff --git a/src/components/pages/Classroom/index.js b/src/components/pages/Classroom/index.js index 7cc6db67..233871af 100644 --- a/src/components/pages/Classroom/index.js +++ b/src/components/pages/Classroom/index.js @@ -8,25 +8,27 @@ import { getStudents, setCurrentStudentId, } from '../../../redux/actions/classroomActions'; +import { useOktaAuth } from '@okta/okta-react'; import { useHistory } from 'react-router-dom'; -//TO-DO: Implement Auth0 const { Content } = Layout; const { Title } = Typography; const Classroom = props => { + const { authState } = useOktaAuth(); + const { idToken } = authState; const dispatch = useDispatch(); useEffect(() => { - props.getStudents(props.course.course_id); + props.getStudents(idToken, props.course.course_id); }, []); const navigate = useHistory(); - // const handleNavigate = e => { - // e.preventDefault(); - // dispatch(setCurrentStudentId(parseInt(e.target.parentElement.value))); - // navigate.push('/feedback-badges'); - // }; + const handleNavigate = e => { + e.preventDefault(); + dispatch(setCurrentStudentId(parseInt(e.target.parentElement.value))); + navigate.push('/feedback-badges'); + }; return ( <> @@ -41,7 +43,7 @@ const Classroom = props => { + + +
+ {selectProgramArray.map((subject, index) => { + return ( + + + {subject} + + + ); + })} +
+
+ + +
+ + ); +}; + +export default BookingProgram; diff --git a/src/components/pages/ParentBooking/ParentBookingCard.js b/src/components/pages/ParentBooking/ParentBookingCard.js index 7c58c960..69548895 100644 --- a/src/components/pages/ParentBooking/ParentBookingCard.js +++ b/src/components/pages/ParentBooking/ParentBookingCard.js @@ -1,90 +1,187 @@ // WE ARE CURRENTLY TRYING OUT THE SingleBookingComponent.js PLEASE REFER TO THAT COMPONENT FOR BOOKING FOR NOW +import React, { useState } from 'react'; +import { Typography, Layout, Form, Button } from 'antd'; +import { parentDummyData } from '../../../parentDummyData'; +import BookingCalendar from './BookingCalendar'; +import PreferredCourseOptions from './PreferredCourseOptions.js'; +import '../../../styles/ParentStyles/booking.less'; +import BookingProgram from './BookingProgram'; +import SelectedCourseDetails from './SelectedCourseDetails'; -import React from 'react'; -import { connect } from 'react-redux'; -import { Card, Button } from 'antd'; -import { dateConverter } from '../../common/dateHelpers'; -import { timeConverter } from '../../common/timeHelpers'; -import axios from 'axios'; -// import axiosWithAuth from '../../../utils/axiosWithAuth'; -import { addToCart } from '../../../redux/actions/parentActions'; - -//TO-DO: Implement Auth0 -const ParentBookingCard = props => { - const { - child_name, - subject, - description, - start_date, - end_date, - start_time, - end_time, - location, - instructor_name, - size, - course_id, - } = props.booking; - - const { addToCart } = props; - - //TO-DO: Implement axiosWithAuth once we've adjusted it to work with Auth0 - const handleClick = e => { - // axiosWithAuth(idToken) - // .post( - // '/children/1/enrollments', // TODO: Hook this request up to pass the ID of the parent/child involved once we have this data in state. - // { child_id: 1, class_id: course_id, completed: true } - // ) - Promise.resolve({ data: [], message: '' }) - .then(res => console.log(res)) // TODO: Let's perform some action with this result. - .catch(err => console.log(`message: ${err.message}`)); +const courseDetails = { + instructor_name: '', + size: '', + subject: '', + description: '', + start_date: '', + end_date: '', + start_time: '', + end_time: '', + price: '', +}; + +const ParentBookingCard = () => { + const { Content } = Layout; + const { Item } = Form; + const { Title } = Typography; + const [searchResults, setSearchResults] = useState([]); + + const [show, setShow] = useState(true); + const [disabled, setDisabled] = useState(false); + const [render, setRender] = useState(false); + const [selectedOption, setSelectedOption] = useState(courseDetails); + + let valuesObject = {}; + + let newArray = []; + let resultArray = []; + + const toggleDisabled = () => { + setDisabled(!disabled); + }; + + const handleRadioClick = e => { + let program = e.target.value; + valuesObject.program = program; + }; + + const handleCalendarClick = value => { + let date = value.format('MM/DD/YYYY'); + valuesObject.date = date; + }; + + const handleAvailability = e => { + newArray = parentDummyData.availableCourses.filter(course => { + let programDate = course.start_date; + let selectedDate = valuesObject.date; + let programMonth = programDate.substring(0, 2); + let selectedMonth = selectedDate.substring(0, 2); + let programYear = programDate.substring(6); + let selectedYear = selectedDate.substring(6); + + return parseInt(programMonth) >= parseInt(selectedMonth) && + programYear === selectedYear + ? course + : null; + }); + + resultArray = newArray.filter( + course => course.subject === valuesObject.program + ); + setSearchResults(resultArray); + setSelectedOption(resultArray[0]); + if (valuesObject.program && valuesObject.date) { + setShow(!show); + } + + toggleDisabled(); + }; + + const handleRefresh = () => { + window.location.reload(); + }; + + const handleSelectedCourse = () => { + setRender(!render); }; - const data = [ - { title: 'student name', text: child_name }, - { title: 'course', text: subject }, - { title: 'description', text: description }, - { title: 'first day of class', text: dateConverter(start_date) }, - { title: 'last day of class', text: dateConverter(end_date) }, - { - title: 'time', - text: `${timeConverter(start_time)} - ${timeConverter(end_time)}`, - }, - { title: 'location', text: location }, - { title: 'instructor', text: instructor_name }, - { title: 'class size', text: size }, - ]; - - const handleAddCourse = booking => { - addToCart(booking); + const updateSelection = (inputName, inputValue) => { + setSelectedOption({ ...selectedOption, [inputName]: inputValue }); }; return ( - - {data.map((itm, idx) => { - return ( -
- {itm.title}: {itm.text} + + + + <p> + BOOK WITH US. + <br /> + LEARN MORE THAN JUST CODE! + </p> + +
+
+
Select Program
+ + + + +
Select Date
+
+ +
+ + + + +
+ {show && ( + + )} +
+ {!show && !render && ( + + )} + + {!show && render && ( + + )} + {!show && ( + + )} +
+ {render && ( + + )} +
+ {!show && !render && ( + + )} +
+ {!show && !render && ( +
+

+ All times are in Central Standard Time (US & Canada) +

+
+ )} +
+
- ); - })} - - +
+
+
); }; -const mapStateToProps = state => ({ - cart: state.parentReducer.cart, - bookings: state.parentReducer.bookings, -}); - -export default connect(mapStateToProps, { - addToCart, -})(ParentBookingCard); +export default ParentBookingCard; diff --git a/src/components/pages/ParentBooking/ParentBookingContainer.js b/src/components/pages/ParentBooking/ParentBookingContainer.js index a1e32ee1..de7d2e42 100644 --- a/src/components/pages/ParentBooking/ParentBookingContainer.js +++ b/src/components/pages/ParentBooking/ParentBookingContainer.js @@ -55,14 +55,14 @@ const ParentBookingContainer = props => { {tabs.map((item, index) => ( - {currentTab && + {/* {currentTab && currentTab.map((item, idx) => { return ( -
- -
+
*/} + + {/*
); - })} + })} */}
))} diff --git a/src/components/pages/ParentBooking/PreferredCourseOptions.js.js b/src/components/pages/ParentBooking/PreferredCourseOptions.js.js new file mode 100644 index 00000000..e2d6be31 --- /dev/null +++ b/src/components/pages/ParentBooking/PreferredCourseOptions.js.js @@ -0,0 +1,28 @@ +import React from 'react'; +import { timeConverter } from '../../common/timeHelpers'; + +const PreferredCourseOptions = ({ searchResults, updateSelection }) => { + const onChange = e => { + const { value } = e.target; + updateSelection(value); + }; + + return ( + + ); +}; + +export default PreferredCourseOptions; diff --git a/src/components/pages/ParentBooking/SelectedCourseDetails.js b/src/components/pages/ParentBooking/SelectedCourseDetails.js new file mode 100644 index 00000000..ae8b93dd --- /dev/null +++ b/src/components/pages/ParentBooking/SelectedCourseDetails.js @@ -0,0 +1,20 @@ +import React from 'react'; + +const SelectedCourseDetails = ({ selectedOption }) => { + return ( +
+

Course Details:

+

Instructor: {selectedOption.instructor_name}

+

Size: {selectedOption.size}

+

Subject: {selectedOption.subject}

+

Description: {selectedOption.description}

+

Start Date: {selectedOption.start_date}

+

End Date : {selectedOption.end_date}

+

Start Time: {selectedOption.start_time}

+

End Time: {selectedOption.end_time}

+

Price: {selectedOption.price}

+
+ ); +}; + +export default SelectedCourseDetails; diff --git a/src/components/pages/ParentBooking/index.js b/src/components/pages/ParentBooking/index.js index a332e55e..399b0b98 100644 --- a/src/components/pages/ParentBooking/index.js +++ b/src/components/pages/ParentBooking/index.js @@ -13,7 +13,6 @@ function ParentBooking() { - diff --git a/src/components/pages/ParentFamily/CreateNewStudent.js b/src/components/pages/ParentFamily/CreateNewStudent.js index 657991ef..d1d326bb 100644 --- a/src/components/pages/ParentFamily/CreateNewStudent.js +++ b/src/components/pages/ParentFamily/CreateNewStudent.js @@ -1,10 +1,9 @@ import React from 'react'; -import axios from 'axios'; -// import axiosWithAuth from '../../../utils/axiosWithAuth'; +import axiosWithAuth from '../../../utils/axiosWithAuth'; import { Form, Input, Button, InputNumber } from 'antd'; import '../../../styles/ParentStyles/index.less'; +import { useOktaAuth } from '@okta/okta-react'; -//TO-DO: Implement Auth0 const CreateNewStudent = props => { const { setAddStudentVisible, setAlertMsg } = props; @@ -13,11 +12,12 @@ const CreateNewStudent = props => { wrapperCol: { span: 16 }, }; - //TO-DO: Implement axiosWithAuth once we've adjusted it to work with Auth0 + const { authState } = useOktaAuth(); + const { idToken } = authState; + const onFinish = values => { - // axiosWithAuth(idToken) - // .post('/children', values.student) - Promise.resolve({ data: [], message: '' }) + axiosWithAuth(idToken) + .post('/children', values.student) .then(resp => { setAddStudentVisible(false); setAlertMsg(1); diff --git a/src/components/pages/ParentFamily/CurrentCoursesDetails.js b/src/components/pages/ParentFamily/CurrentCoursesDetails.js index 41735068..4ab8bd0a 100644 --- a/src/components/pages/ParentFamily/CurrentCoursesDetails.js +++ b/src/components/pages/ParentFamily/CurrentCoursesDetails.js @@ -4,19 +4,20 @@ import '../../../styles/ParentStyles/index.less'; import { connect } from 'react-redux'; import { getCourses } from '../../../redux/actions/childAction'; import { useDispatch } from 'react-redux'; +import { useOktaAuth } from '@okta/okta-react'; import { Card, Button } from 'antd'; -//TO-DO: Implement Auth0 const { Column } = Table; const CurrentCoursesDetails = props => { + const { authState } = useOktaAuth(); + const { idToken } = authState; const dispatch = useDispatch(); const { courses, child_id } = props; - //TO-DO: Implement Auth0 - getCourses useEffect(() => { - dispatch(getCourses(child_id)); - }, [dispatch, child_id]); + dispatch(getCourses(idToken, child_id)); + }, [dispatch, idToken, child_id]); return (
diff --git a/src/components/pages/ParentFamily/ParentFamilyHome.js b/src/components/pages/ParentFamily/ParentFamilyHome.js index adc98b7b..7a817dcd 100644 --- a/src/components/pages/ParentFamily/ParentFamilyHome.js +++ b/src/components/pages/ParentFamily/ParentFamilyHome.js @@ -17,10 +17,11 @@ import 'antd/dist/antd.css'; import cloudbg from '../../../img/Assets/beige-faded-clouds.png'; import { connect } from 'react-redux'; import { useDispatch } from 'react-redux'; +import { useOktaAuth } from '@okta/okta-react'; import { getChildren } from '../../../redux/actions/parentActions'; -//TO-DO: Implement Auth0 const ParentFamilyHome = props => { + console.log(`the user is: ${JSON.stringify(props.user)}`); const { Meta } = Card; const { Content } = Layout; const { Text } = Typography; @@ -31,15 +32,18 @@ const ParentFamilyHome = props => { false ); const [alertMsg, setAlertMsg] = useState(0); - const dispatch = useDispatch(); - // useEffect(() => { - // TODO: In the following line, "4" is hardcoded instead of profile_id because currently profile_id is not being passed along in props.user . profile_id 4 exists in our seeds, so it has been hardcoded to display the existing seeded child. currentUser is initializing as empty object {} and is not being updated. When this is fixed, change the hardcoded "4" to "profile_id" and it should work. - // dispatch(getChildren(idToken, 4)); - // }, [dispatch, idToken]); + const { authState, oktaAuth } = useOktaAuth(); + const dispatch = useDispatch(); const { user, children } = props; + useEffect(() => { + oktaAuth.token.getUserInfo().then(dataProfile => { + dispatch(getChildren(authState.idToken.idToken, dataProfile.sub)); + }); + }, [dispatch, oktaAuth.token, authState.idToken.idToken]); + const showAddStudentModal = () => { setAddStudentVisible(true); }; diff --git a/src/components/pages/ParentHome/Messages/ActiveMessage.js b/src/components/pages/ParentHome/Messages/ActiveMessage.js index 6dc47fb9..432fd471 100644 --- a/src/components/pages/ParentHome/Messages/ActiveMessage.js +++ b/src/components/pages/ParentHome/Messages/ActiveMessage.js @@ -5,11 +5,22 @@ import 'antd/dist/antd.css'; import '../../../../styles/ParentStyles/index.less'; import '../../../../styles/ParentStyles/messages.less'; import { connect, useDispatch } from 'react-redux'; +import { useOktaAuth } from '@okta/okta-react'; import { getCurrentUser } from '../../../../redux/actions/userActions'; -//TO-DO: Implement Auth0 function ActiveMessage(props) { + const dispatch = useDispatch(); + const { authState, oktaAuth } = useOktaAuth(); + + useEffect(() => { + if (authState !== null) { + if (authState.isAuthenticated !== false) { + dispatch(getCurrentUser(authState.idToken.idToken, oktaAuth)); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); const sortByDate = arr => { return arr.sort((a, b) => { const dateA = new Date(a.sent_at); diff --git a/src/components/pages/ParentHome/Messages/MessageList.js b/src/components/pages/ParentHome/Messages/MessageList.js index 1b52ee1b..ccda864a 100644 --- a/src/components/pages/ParentHome/Messages/MessageList.js +++ b/src/components/pages/ParentHome/Messages/MessageList.js @@ -1,5 +1,6 @@ import React, { useEffect, useState, useLayoutEffect } from 'react'; import { connect, useDispatch } from 'react-redux'; +import { useOktaAuth } from '@okta/okta-react'; import { List, Avatar } from 'antd'; import 'antd/dist/antd.css'; import '../../../../styles/ParentStyles/messages.less'; @@ -7,14 +8,23 @@ import '../../../../styles/ParentStyles/index.less'; import { getCurrentUser } from '../../../../redux/actions/userActions'; import { getActiveConversation } from '../../../../redux/actions/userActions'; -//TO-DO: Implement Auth0 const MessageList = props => { const currentUser = props.currentUser; + const { authState, oktaAuth } = useOktaAuth(); const dispatch = useDispatch(); const [filteredConversations, setFilteredConversations] = useState([[]]); const [currentConversation, setCurrentConversation] = useState(''); const [activeSenderId, setActiveSenderId] = useState(null); + useEffect(() => { + if (authState !== null) { + if (authState.isAuthenticated !== false) { + dispatch(getCurrentUser(authState.idToken.idToken, oktaAuth)); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + useEffect(() => { if (activeSenderId) { const currentConversation = filteredConversations.filter( diff --git a/src/components/pages/ParentHome/Messages/MessagesContainer.js b/src/components/pages/ParentHome/Messages/MessagesContainer.js index 6ecd4ef2..7de003ca 100644 --- a/src/components/pages/ParentHome/Messages/MessagesContainer.js +++ b/src/components/pages/ParentHome/Messages/MessagesContainer.js @@ -7,12 +7,20 @@ import ActiveMessage from './ActiveMessage'; import MessageList from './MessageList'; import '../../../../styles/ParentStyles/messages.less'; import { getCurrentUser } from '../../../../redux/actions/userActions'; -import { connect } from 'react-redux'; +import { useOktaAuth } from '@okta/okta-react'; +import { connect, useDispatch } from 'react-redux'; -//TO-DO: Implement Auth0 function ParentMessages(props) { const { Content } = Layout; - + const dispatch = useDispatch(); + const { authState, oktaAuth } = useOktaAuth(); + useEffect(() => { + if (authState !== null) { + if (authState.isAuthenticated !== false) { + dispatch(getCurrentUser(authState.idToken.idToken, oktaAuth)); + } + } + }, []); return ( diff --git a/src/components/pages/ParentHome/Messages/ReplyEditor.js b/src/components/pages/ParentHome/Messages/ReplyEditor.js index 3742bdc8..a2865390 100644 --- a/src/components/pages/ParentHome/Messages/ReplyEditor.js +++ b/src/components/pages/ParentHome/Messages/ReplyEditor.js @@ -2,10 +2,9 @@ import React, { useState, useEffect, useLayoutEffect } from 'react'; import { Comment, Form, Button, Input } from 'antd'; import '../../../../styles/ParentStyles/messages.less'; import { useDispatch, connect } from 'react-redux'; +import { useOktaAuth } from '@okta/okta-react'; import { addMessage } from '../../../../redux/actions/userActions'; import { getCurrentUser } from '../../../../redux/actions/userActions'; - -//TO-DO: Implement Auth0 const { TextArea } = Input; const Editor = ({ onChange, onSubmit, submitting, value }) => ( @@ -31,6 +30,15 @@ const ReplyEditor = (props, { onChange, onSubmit }) => { const [value, setValue] = useState(''); const dispatch = useDispatch(); + const { authState, oktaAuth } = useOktaAuth(); + useEffect(() => { + if (authState !== null) { + if (authState.isAuthenticated !== false) { + dispatch(getCurrentUser(authState.idToken.idToken, oktaAuth)); + } + } + }, [authState, dispatch, oktaAuth]); + useLayoutEffect(() => {}, [props]); const handleSubmit = () => { if (!value) { @@ -41,6 +49,7 @@ const ReplyEditor = (props, { onChange, onSubmit }) => { setValue(''); dispatch( addMessage( + authState.idToken, value, props.getActiveConversation ? props.getActiveConversation[0].sender_id !== diff --git a/src/components/pages/ParentHome/ParentSidebar.js b/src/components/pages/ParentHome/ParentSidebar.js index d8e766bc..7fd8119b 100644 --- a/src/components/pages/ParentHome/ParentSidebar.js +++ b/src/components/pages/ParentHome/ParentSidebar.js @@ -2,6 +2,7 @@ import React, { useState } from 'react'; import { Link } from 'react-router-dom'; import { connect } from 'react-redux'; import { Menu, Layout } from 'antd'; +import { useOktaAuth } from '@okta/okta-react'; import 'antd/dist/antd.css'; import { HomeFilled, @@ -13,12 +14,12 @@ import { } from '@ant-design/icons'; import { FaShoppingCart } from 'react-icons/fa'; -//TO-DO: Implement Auth0 const { Sider } = Layout; const ParentSideBar = props => { const { cart, active, user } = props; const [collapsed, setCollapsed] = useState(false); + const { authService } = useOktaAuth(); const { role_id } = props.user.currentUser; console.log(`user role is ${role_id}`); diff --git a/src/components/pages/ParentNewsFeed/NewsContainer.js b/src/components/pages/ParentNewsFeed/NewsContainer.js index 11ceb6f9..d1613759 100644 --- a/src/components/pages/ParentNewsFeed/NewsContainer.js +++ b/src/components/pages/ParentNewsFeed/NewsContainer.js @@ -3,17 +3,17 @@ import '../../../styles/index.less'; import IndividualNewsParent from './IndividualNewsParent'; import { connect } from 'react-redux'; import { getNewsFeedsParent } from '../../../redux/actions/parentActions'; +import { useOktaAuth } from '@okta/okta-react'; import { Layout } from 'antd'; -//TO-DO: Implement Auth0 function NewsContainer(props) { const { Content } = props; const { newsfeed, dispatch } = props; - - //TO-DO: Implement Auth0 - getNewsFeedParent + const { authState } = useOktaAuth(); + const { idToken } = authState; useEffect(() => { - dispatch(getNewsFeedsParent()); - }, [dispatch]); + dispatch(getNewsFeedsParent(idToken)); + }, [dispatch, idToken]); return ( diff --git a/src/components/pages/ProfileList/ProfileListContainer.js b/src/components/pages/ProfileList/ProfileListContainer.js index 841fd5ef..85916264 100644 --- a/src/components/pages/ProfileList/ProfileListContainer.js +++ b/src/components/pages/ProfileList/ProfileListContainer.js @@ -1,4 +1,5 @@ import React from 'react'; +import { useOktaAuth } from '@okta/okta-react'; import { getProfileData } from '../../../api'; @@ -6,13 +7,14 @@ import { List } from '../../common'; import RenderProfileListPage from './RenderProfileListPage'; -//TO-DO: Implement Auth0 // Here is an example of using our reusable List component to display some list data to the UI. const ProfileList = () => { + const { authState } = useOktaAuth(); + return ( getProfileData(authState)} + getItemsData={() => getProfileData(authState)} // Here we are passing in a component we want to show whilst waiting for our API request // to complete. LoadingComponent={() =>
Loading Profiles...
} diff --git a/src/components/pages/Registration/ConfirmEmail.js b/src/components/pages/Registration/ConfirmEmail.js index 804b3a49..347965a6 100644 --- a/src/components/pages/Registration/ConfirmEmail.js +++ b/src/components/pages/Registration/ConfirmEmail.js @@ -15,7 +15,7 @@ const ConfirmEmail = props => {

- {/* update href after finding correct path from "Auth0" */} + {/* update href after finding correct path from Okta */}
diff --git a/src/components/pages/Registration/InstructorRegistration/InstructorFlow_Step2.js b/src/components/pages/Registration/InstructorRegistration/InstructorFlow_Step2.js index 5d2d0c34..4b2d0aa4 100644 --- a/src/components/pages/Registration/InstructorRegistration/InstructorFlow_Step2.js +++ b/src/components/pages/Registration/InstructorRegistration/InstructorFlow_Step2.js @@ -1,14 +1,14 @@ import React, { useState, useEffect } from 'react'; +import { useDispatch } from 'react-redux'; import { useHistory } from 'react-router-dom'; +import { useOktaAuth } from '@okta/okta-react'; import { getCurrentUser } from '../../../../redux/actions/userActions'; import InstructorFormSchema from './InstructorFormSchema'; import RegistrationProgress from '../RegistrationProgress'; -import axios from 'axios'; -// import axiosWithAuth from '../../../../utils/axiosWithAuth'; +import axiosWithAuth from '../../../../utils/axiosWithAuth'; import * as yup from 'yup'; import '../../../../styles/registration.less'; -//TO-DO: Implement Auth0 const initialValues = { name: '', email: '', @@ -38,6 +38,17 @@ const InstrRegForm = () => { const [formErrors, setFormErrors] = useState(initialErrors); const [disabled, setDisabled] = useState(initialSaveDisabled); const [formWarning, setFormWarning] = useState(initialWarning); + const { authState, oktaAuth } = useOktaAuth(); + const dispatch = useDispatch(); + + useEffect(() => { + if (authState !== null) { + if (authState.isAuthenticated !== false) { + dispatch(getCurrentUser(authState.idToken.idToken, oktaAuth)); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); const validate = (name, value) => { yup @@ -57,20 +68,19 @@ const InstrRegForm = () => { let history = useHistory(); - //TO-DO: Implement axiosWithAuth once we've adjusted it to work with Auth0 const onSubmit = evt => { evt.preventDefault(); - // axiosWithAuth(authState.idToken) - // .post('/instructors/register', { - // name: formValues.name, - // email: formValues.email, - // location: formValues.location, - // phone: formValues.phone, - // education: formValues.education, - // technical: formValues.tech, - // notes: formValues.notes, - // }) - Promise.resolve({ data: [], message: '' }) + + axiosWithAuth(authState.idToken) + .post('/instructors/register', { + name: formValues.name, + email: formValues.email, + location: formValues.location, + phone: formValues.phone, + education: formValues.education, + technical: formValues.tech, + notes: formValues.notes, + }) .then(res => { history.push('/instructor-register-success'); }) diff --git a/src/components/pages/Registration/InstructorRegistration/SuccessfulSubmission.js b/src/components/pages/Registration/InstructorRegistration/SuccessfulSubmission.js index 9a2d5c35..0a7ba137 100644 --- a/src/components/pages/Registration/InstructorRegistration/SuccessfulSubmission.js +++ b/src/components/pages/Registration/InstructorRegistration/SuccessfulSubmission.js @@ -1,7 +1,6 @@ import React from 'react'; import '../../../../styles/registration.less'; import RegistrationProgress from '../RegistrationProgress'; -//TO-DO: Implement Auth0 export default function SuccessfulSubmission() { return ( @@ -19,7 +18,7 @@ export default function SuccessfulSubmission() {
{/* eslint-disable-next-line*/} LEARN MORE - {/* update href after finding correct path from "Auth0" */} + {/* update href after finding correct path from Okta */}
diff --git a/src/components/pages/Registration/RegisterStep1.js b/src/components/pages/Registration/RegisterStep1.js index ebadc4f8..cca20f01 100644 --- a/src/components/pages/Registration/RegisterStep1.js +++ b/src/components/pages/Registration/RegisterStep1.js @@ -1,8 +1,7 @@ import React from 'react'; import RegistrationProgress from './RegistrationProgress'; import '../../../styles/registration.less'; -//TO DO: Lines 16 + 17 need to be a component Link from react router -//TO DO: Rename registration flows to semantically match instructor and parent + export default function RegisterStep1() { return (
diff --git a/src/components/pages/Stripe/StripeCheckoutButton.js b/src/components/pages/Stripe/StripeCheckoutButton.js index 7076178d..419ba617 100644 --- a/src/components/pages/Stripe/StripeCheckoutButton.js +++ b/src/components/pages/Stripe/StripeCheckoutButton.js @@ -8,13 +8,20 @@ const StripeCheckoutButton = ({ price }) => { 'pk_test_51KW2lbBKjoE9XTUg0egVFw0BOv1qLHRAalJAI0tzcCrPQZiuT33aJjmlKJkDp0FrfvbcY6JR2Pl7I2tSukYUyQTk00OSmOo3M2'; const onToken = token => { - // axios.post(`/payments/payments`,{ amount: priceForStripe, token }) - Promise.resolve({ data: [], message: '' }) + axios({ + url: `payments/payments`, + method: 'post', + data: { + amount: priceForStripe, + token, + }, + }) .then(response => { alert( 'Payment successful ,you will receive a receipt in your email', response.data ); + console.log(response.data); }) .catch(error => { console.log('payment error:', error.message); diff --git a/src/components/pages/StudentHome/StudentSidebar.js b/src/components/pages/StudentHome/StudentSidebar.js index abc1edde..c645f74a 100644 --- a/src/components/pages/StudentHome/StudentSidebar.js +++ b/src/components/pages/StudentHome/StudentSidebar.js @@ -13,12 +13,13 @@ import { ExportOutlined, ReadOutlined, } from '@ant-design/icons'; +import { useOktaAuth } from '@okta/okta-react'; -//TO-DO: Implement Auth0 const { Sider } = Layout; const StudentSideBar = props => { const [collapsed, setCollapsed] = useState(false); + const { authService } = useOktaAuth(); const onCollapse = () => { if (collapsed === true) { setCollapsed(false); @@ -77,7 +78,7 @@ const StudentSideBar = props => { key="logout" icon={} onClick={() => { - // authService.logout(); + authService.logout(); }} > Logout diff --git a/src/index.js b/src/index.js index 86a33843..a8503e90 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,5 @@ +/* eslint-disable */ + import React from 'react'; import { createRoot } from 'react-dom/client'; @@ -8,6 +10,8 @@ import { useHistory, Switch, } from 'react-router-dom'; +import { Security, LoginCallback, SecureRoute } from '@okta/okta-react'; +import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js'; import './styles/index.less'; import 'antd/dist/antd.less'; @@ -24,6 +28,7 @@ import { LoginPage } from './components/pages/Login/index'; import { HomePage } from './components/pages/Home'; import { LandingPage } from './components/pages/Landing'; import { ExampleDataViz } from './components/pages/ExampleDataViz'; +import config from './utils/oktaConfig'; import { LoadingComponent } from './components/common'; import InstructorHome from './components/pages/InstructorHome'; import ParentFamilyHome from './components/pages/ParentFamily/ParentFamilyHome'; @@ -50,8 +55,13 @@ import ParentResources from './components/pages/ParentHome/ParentResources'; import ParentProgress from './components/pages/ParentHome/Progress'; import NavBar from './components/common/Navbars/NavBar'; import PaymentSuccess from './components/pages/ParentHome/PaymentSuccess'; +import Cart from './components/pages/ParentHome/Cart'; import SingleCourseBooking from './components/pages/SingleCourseBooking'; +import CourseDescription from './components/pages/CourseDescriptions'; +// eslint-disable-next-line +import InstructorNavBar from './components/common/Navbars/InstructorNavBar'; import AllClasses from './components/pages/InstructorHome/AllClassesView'; +import Progress from './components/pages/ParentHome/Progress'; import Messages from './components/pages/Messages'; import Classroom from './components/pages/Classroom'; import FeedbackBadgePage from './components/pages/Classroom/FeedbackBadgePage'; @@ -80,8 +90,8 @@ import Faq from './components/pages/Services/Faq'; import SiteMap from './components/pages/Services/SiteMap'; import CourseDetails from './components/pages/AdminHome/CourseDetails'; import AdminEditCourse from './components/pages/AdminDispCourse/index'; + import StudentMessages from './components/pages/StudentHome/messages/MessagesContainer'; -//TO-DO: IMPLEMENT AUTH0 ADD SECURE ROUTES const store = createStore(rootReducers, applyMiddleware(thunk)); window.store = store; // Remove before full deployment. In here for development purposes. @@ -114,86 +124,129 @@ function App() { // React Router has a nifty useHistory hook we can use at this level to ensure we have security around our routes. const history = useHistory(); + const authHandler = () => { + // We pass this to our component that wraps our routes. + // It'll automatically check if userToken is available and push back to login if not :) + const previousAuthState = oktaAuth.authStateManager.getPreviousAuthState(); + if (!previousAuthState || !previousAuthState.isAuthenticated) { + // App initialization stage + history.push('/login'); + } + }; + + const oktaAuth = new OktaAuth(config); + + const restoreOriginalUri = async (_oktaAuth, originalUri) => { + history.replace(toRelativeUrl(originalUri || '/', window.location.origin)); + }; + return ( - - - - ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {/* any of the routes you need secured should be registered as SecureRoutes */} - } - /> - {/* The above route exists for developmental purposes, but the "/" path will be for the home page ("/landing") in the deployed version */} - - - - {/* The above route exists for developmental purposes, The dashboard should be determined by the role logging in */} - - - {/* The above route exists for developmental purposes, the admin applications route will be for the page leading to the instructor application */} - - - - - - - - - - - - - + + + + + ; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* any of the routes you need secured should be registered as SecureRoutes */} + } + /> + {/* The above route exists for developmental purposes, but the "/" path will be for the home page ("/landing") in the deployed version */} + + + + + + {/* The above route exists for developmental purposes, The dashboard should be determined by the role logging in */} + + + {/* The above route exists for developmental purposes, the admin applications route will be for the page leading to the instructor application */} + + + + + + + + + + + + + + ); } diff --git a/src/parentDummyData.js b/src/parentDummyData.js index d659fc71..fd40f523 100644 --- a/src/parentDummyData.js +++ b/src/parentDummyData.js @@ -27,7 +27,7 @@ export const parentDummyData = { messages: [ { - sent_at: '2021-11-02T01:51:39+00:00', + sent_at: '2021/11/02T01:51:39+00:00', title: 'Help with Homework?', read: true, message: 'I need the answers to the assignment please.', @@ -35,7 +35,7 @@ export const parentDummyData = { sender_id: 1, }, { - sent_at: '2021-11-02T01:51:39+00:00', + sent_at: '2021/11/02T01:51:39+00:00', title: "What's my grade?", read: true, message: 'Hey Ms. Teacher can you tell me my grade?', @@ -43,7 +43,7 @@ export const parentDummyData = { sender_id: 1, }, { - sent_at: '2021-11-02T01:51:39+00:00', + sent_at: '2021/11/02T01:51:39+00:00', title: 'Going to need to cancel.', read: false, message: 'My child has to miss the class', @@ -51,7 +51,7 @@ export const parentDummyData = { sender_id: 2, }, { - sent_at: '2021-11-02T01:51:39+00:00', + sent_at: '2021/11/02T01:51:39+00:00', title: 'Kid is sick', read: true, message: 'Can we get a refund for this class?', @@ -59,7 +59,7 @@ export const parentDummyData = { sender_id: 3, }, { - sent_at: '2021-11-02T01:51:39+00:00', + sent_at: '2021/11/02T01:51:39+00:00', title: 'When is class?', read: false, message: 'I noticed the time was funky and had to ask.', @@ -67,7 +67,7 @@ export const parentDummyData = { sender_id: 5, }, { - sent_at: '2021-11-02T01:51:39+00:00', + sent_at: '2021/11/02T01:51:39+00:00', title: 'Is this a yoga course?', read: false, message: 'How is yoga and coding taught together?', @@ -75,7 +75,7 @@ export const parentDummyData = { sender_id: 7, }, { - sent_at: '2021-11-02T01:51:39+00:00', + sent_at: '2021/11/02T01:51:39+00:00', title: 'Where is my achievement?', read: false, message: "my achievement didn't pop up when I did class.", @@ -97,8 +97,8 @@ export const parentDummyData = { subject: 'CS101', description: 'Computer Science fundamentals', prereqs: null, - start_date: '2021-05-30T07:00:00.000Z', - end_date: '2022-10-10T07:00:00.000Z', + start_date: '2021/05/30T07:00:00.000Z', + end_date: '2022/10/10T07:00:00.000Z', start_time: '17:00:00', end_time: '18:00:00', location: 'https://zoom.us/my/john123', @@ -114,8 +114,8 @@ export const parentDummyData = { subject: 'JavaScriptB', description: 'Intermediate JavaScript.', prereqs: ['JavaScriptA'], - start_date: '2021-12-15T07:00:00.000Z', - end_date: '2022-10-11T07:00:00.000Z', + start_date: '2021/12/15T07:00:00.000Z', + end_date: '2022/10/11T07:00:00.000Z', start_time: '15:00:00', end_time: '16:00:00', location: 'https://zoom.us/my/john321', @@ -131,8 +131,8 @@ export const parentDummyData = { subject: 'CS101', description: 'Computer Science fundamentals', prereqs: null, - start_date: '2021-12-22T07:00:00.000Z', // mm-dd-yyyy - end_date: '2022-10-10T07:00:00.000Z', + start_date: '2021/12/22T07:00:00.000Z', // mm/dd/yyyy + end_date: '2022/10/10T07:00:00.000Z', start_time: '17:00:00', end_time: '18:00:00', location: 'https://zoom.us/my/john123', @@ -148,8 +148,8 @@ export const parentDummyData = { subject: 'JavaScriptB', description: 'Intermediate JavaScript.', prereqs: ['JavaScriptA'], - start_date: '2021-12-20T07:00:00.000Z', - end_date: '2022-10-11T07:00:00.000Z', + start_date: '2021/12/20T07:00:00.000Z', + end_date: '2022/10/11T07:00:00.000Z', start_time: '15:00:00', end_time: '16:00:00', location: 'https://zoom.us/my/john321', @@ -159,6 +159,138 @@ export const parentDummyData = { }, availableCourses: [ + { + schedule_id: 0, + course_id: 0, + instructor_id: 1, + instructor_name: 'Test007', + size: 20, + subject: 'App Building Fundamentals', + description: + 'A month/long course where students with design, build, and deploy an app from beginning to end!', + prereqs: [' JavaScript', 'HTML', 'CSS'], + start_date: '12/04/2022', + end_date: '12/28/2022', + start_time: '08:00:00', + end_time: '09:00:00', + location: "Children's Coding Center", + price: 1200, + }, + + { + schedule_id: 0, + course_id: 0, + instructor_id: 2, + instructor_name: 'Test013', + size: 16, + subject: 'App Building Fundamentals', + description: + 'A month/long course where students with design, build, and deploy an app from beginning to end!', + prereqs: ['JavaScript', 'HTML', 'CSS'], + start_date: '04/04/2022', + end_date: '04/28/2022', + start_time: '08:30:00', + end_time: '09:30:00', + location: 'https://zoom.us/my/john321', + price: 800, + }, + { + schedule_id: 0, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test009', + size: 14, + subject: 'Welcome to Python!', + description: 'Please select a course!', + prereqs: ['javascript,css,html'], + start_date: '10/07/2022', + end_date: '11/06/2022', + start_time: '09:00:00', + end_time: '10:00:00', + location: 'https://zoom.us/my/haleyh', + price: 500, + }, + { + schedule_id: 1, + course_id: 1, + instructor_id: 3, + instructor_name: 'Test011', + size: 15, + subject: 'JavaScriptB', + description: 'Intermediate JavaScript.', + prereqs: ['JavaScriptA'], + start_date: '10/19/2022', + end_date: '11/20/2022', + start_time: '10:00:00', + end_time: '11:00:00', + location: 'https://zoom.us/my/john321', + price: 1200, + }, + { + schedule_id: 0, + course_id: 0, + instructor_id: 2, + instructor_name: 'Test013', + size: 16, + subject: 'Intro to HTML', + description: + ' A course where students with design, build, and deploy an app from beginning to end!', + prereqs: [''], + start_date: '03/05/2022', + end_date: '03/25/2022', + start_time: '13:00:00', + end_time: '14:00:00', + location: 'https://zoom.us/my/tommy', + price: 450, + }, + { + schedule_id: 2, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test006', + size: 16, + subject: 'JavaScriptB', + description: 'Intermediate JavaScript.', + prereqs: ['JavaScriptA'], + start_date: '05/01/2022', + end_date: '06/04/2022', + start_time: '15:00:00', + end_time: '16:00:00', + location: 'https://zoom.us/my/john321', + price: 1200, + }, + { + schedule_id: 3, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test008', + size: 12, + subject: 'Intro to CSS', + description: 'Welcome to CSS!', + prereqs: ['Html'], + start_date: '09/01/2022', + end_date: '10/04/2022', + start_time: '15:30:00', + end_time: '17:45:00', + location: 'https://zoom.us/my/john321', + price: 500, + }, + { + schedule_id: 2, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test010', + size: 15, + subject: ' Intro JavaScript', + description: 'Welcome to JavaScript!', + prereqs: ['Html,css'], + start_date: '11/19/2022', + end_date: '12/10/2022', + start_time: '15:45:00', + end_time: '16:45:00', + location: 'https://zoom.us/my/john321', + price: 600, + }, { schedule_id: 1, course_id: 1, @@ -168,8 +300,8 @@ export const parentDummyData = { subject: 'CS101', description: 'Computer Science fundamentals', prereqs: [], - start_date: '2021-12-10T07:00:00.000Z', - end_date: '2022-10-10T07:00:00.000Z', + start_date: '01/19/2022', + end_date: '02/10/2022', start_time: '17:00:00', end_time: '18:00:00', location: 'https://zoom.us/my/john123', @@ -184,13 +316,159 @@ export const parentDummyData = { subject: 'Fundamental Python', description: 'Computer Science fundamentals', prereqs: ['JavaScript', 'HTML', 'CSS'], - start_date: '2021-12-10T07:00:00.000Z', - end_date: '2022-10-10T07:00:00.000Z', + start_date: '04/04/2022', + end_date: '04/28/2022', + start_time: '17:00:00', + end_time: '18:00:00', + location: 'https://zoom.us/my/john123', + price: 500, + }, + { + schedule_id: 5, + course_id: 8, + instructor_id: 80, + instructor_name: 'Mark', + size: 20, + subject: 'App Building Fundamentals', + description: + 'A month/long course where students with design, build, and deploy an app from beginning to end!', + prereqs: ['JavaScript', 'HTML', 'CSS'], + start_date: '10/30/2022', + end_date: '11/28/2022', start_time: '17:00:00', end_time: '18:00:00', location: 'https://zoom.us/my/john123', price: 500, }, + { + schedule_id: 5, + course_id: 8, + instructor_id: 80, + instructor_name: 'Mark', + size: 20, + subject: 'App Building Fundamentals', + description: + 'A month/long course where students with design, build, and deploy an app from beginning to end!', + prereqs: ['JavaScript', 'HTML', 'CSS'], + start_date: '05/12/2022', + end_date: '06/28/2022', + start_time: '10:10:00', + end_time: '11:15:00', + location: 'https://zoom.us/my/john123', + price: 500, + }, + { + schedule_id: 0, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test009', + size: 14, + subject: 'Welcome to Python!', + description: 'Please select a course!', + prereqs: ['javascript,css,html'], + start_date: '06/1/2022', + end_date: '07/31/2022', + start_time: '14:00:00', + end_time: '15:00:00', + location: 'https://zoom.us/my/haleyh', + price: 500, + }, + { + schedule_id: 0, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test009', + size: 14, + subject: 'Welcome to Python!', + description: 'Please select a course!', + prereqs: ['javascript,css,html'], + start_date: '01/13/2023', + end_date: '02/24/202', + start_time: '16:30:00', + end_time: '17:40:00', + location: 'https://zoom.us/my/haleyh', + price: 500, + }, + { + schedule_id: 0, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test009', + size: 14, + subject: 'Welcome to Python!', + description: 'Please select a course!', + prereqs: ['javascript,css,html'], + start_date: '11/07/2022', + end_date: '11/06/2022', + start_time: '11:00:00', + end_time: '12:10:00', + location: 'https://zoom.us/my/haleyh', + price: 500, + }, + { + schedule_id: 0, + course_id: 0, + instructor_id: 2, + instructor_name: 'Test013', + size: 16, + subject: 'Intro to HTML', + description: 'Welcome to HTML!', + prereqs: [''], + start_date: '08/15/2022', + end_date: '09/25/2022', + start_time: '10:00:00', + end_time: '11:00:00', + location: 'https://zoom.us/my/tommy', + price: 450, + }, + { + schedule_id: 0, + course_id: 0, + instructor_id: 2, + instructor_name: 'Test013', + size: 16, + subject: 'Intro to HTML', + description: 'Welcome to HTML!', + prereqs: [''], + start_date: '12/03/2022', + end_date: '12/18/2022', + start_time: '8:10:00', + end_time: '9:10:00', + location: 'https://zoom.us/my/tommy', + price: 450, + }, + { + schedule_id: 0, + course_id: 0, + instructor_id: 2, + instructor_name: 'Test013', + size: 16, + subject: 'Intro to HTML', + description: 'Welcome to HTML!', + prereqs: [''], + start_date: '03/15/2022', + end_date: '04/25/2022', + start_time: '10:00:00', + end_time: '11:00:00', + location: 'https://zoom.us/my/tommy', + price: 450, + }, + { + schedule_id: 0, + course_id: 0, + instructor_id: 2, + instructor_name: 'Test013', + size: 16, + subject: 'Intro to HTML', + description: 'Welcome to HTML!', + prereqs: [''], + start_date: '07/10/2022', + end_date: '07/26/2022', + start_time: '16:30:00', + end_time: '17:30:00', + location: 'https://zoom.us/my/tommy', + price: 450, + }, { schedule_id: 2, course_id: 3, @@ -200,13 +478,271 @@ export const parentDummyData = { subject: 'JavaScriptB', description: 'Intermediate JavaScript.', prereqs: ['JavaScriptA'], - start_date: '2021-12-05T07:00:00.000Z', - end_date: '2022-10-11T07:00:00.000Z', - start_time: '15:00:00', - end_time: '16:00:00', + start_date: '06/16/2022', + end_date: '07/20/2022', + start_time: '9:00:00', + end_time: '10:00:00', location: 'https://zoom.us/my/john321', price: 1200, }, + { + schedule_id: 2, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test006', + size: 16, + subject: 'JavaScriptB', + description: 'Intermediate JavaScript.', + prereqs: ['JavaScriptA'], + start_date: '12/01/2022', + end_date: '01/04/2023', + start_time: '11:10:00', + end_time: '12:10:00', + location: 'https://zoom.us/my/john321', + price: 1200, + }, + { + schedule_id: 2, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test006', + size: 16, + subject: 'JavaScriptB', + description: 'Intermediate JavaScript.', + prereqs: ['JavaScriptA'], + start_date: '03/10/2022', + end_date: '06/15/2022', + start_time: '15:30:00', + end_time: '14:30:00', + location: 'https://zoom.us/my/john321', + price: 1200, + }, + { + schedule_id: 3, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test008', + size: 12, + subject: 'Intro to CSS', + description: 'Welcome to CSS!', + prereqs: ['Html'], + start_date: '04/15/2022', + end_date: '05/14/2022', + start_time: '10:30:00', + end_time: '11:45:00', + location: 'https://zoom.us/my/john321', + price: 500, + }, + { + schedule_id: 3, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test008', + size: 12, + subject: 'Intro to CSS', + description: 'Welcome to CSS!', + prereqs: ['Html'], + start_date: '1/01/2022', + end_date: '01/04/2023', + start_time: '13:00:00', + end_time: '14:00:00', + location: 'https://zoom.us/my/john321', + price: 500, + }, + { + schedule_id: 3, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test008', + size: 12, + subject: 'Intro to CSS', + description: 'Welcome to CSS!', + prereqs: ['Html'], + start_date: '07/01/2022', + end_date: '08/04/2022', + start_time: '08:30:00', + end_time: '09:45:00', + location: 'https://zoom.us/my/john321', + price: 500, + }, + { + schedule_id: 2, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test010', + size: 15, + subject: ' Intro JavaScript', + description: 'Welcome to JavaScript!', + prereqs: ['Html,css'], + start_date: '03/12/2022', + end_date: '04/20/2022', + start_time: '08:45:00', + end_time: '09:45:00', + location: 'https://zoom.us/my/john321', + price: 600, + }, + { + schedule_id: 2, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test010', + size: 15, + subject: ' Intro JavaScript', + description: 'Welcome to JavaScript!', + prereqs: ['Html,css'], + start_date: '08/19/2022', + end_date: '09/10/2022', + start_time: '10:35:00', + end_time: '11:35:00', + location: 'https://zoom.us/my/john321', + price: 600, + }, + { + schedule_id: 2, + course_id: 3, + instructor_id: 2, + instructor_name: 'Test010', + size: 15, + subject: ' Intro JavaScript', + description: 'Welcome to JavaScript!', + prereqs: ['Html,css'], + start_date: '10/14/2022', + end_date: '11/13/2022', + start_time: '14:15:00', + end_time: '15:15:00', + location: 'https://zoom.us/my/john321', + price: 600, + }, + { + schedule_id: 1, + course_id: 1, + instructor_id: 1, + instructor_name: 'Test003', + size: 15, + subject: 'CS101', + description: 'Computer Science fundamentals', + prereqs: [], + start_date: '05/28/2022', + end_date: '06/28/2022', + start_time: '15:00:00', + end_time: '16:00:00', + location: 'https://zoom.us/my/john123', + price: 1000, + }, + { + schedule_id: 1, + course_id: 1, + instructor_id: 1, + instructor_name: 'Test003', + size: 15, + subject: 'CS101', + description: 'Computer Science fundamentals', + prereqs: [], + start_date: '12/10/2022', + end_date: '01/10/2023', + start_time: '11:00:00', + end_time: '12:00:00', + location: 'https://zoom.us/my/john123', + price: 1000, + }, + + { + schedule_id: 3, + course_id: 5, + instructor_id: 10, + instructor_name: 'Mark', + size: 20, + subject: 'Fundamental Python', + description: 'Computer Science fundamentals', + prereqs: ['JavaScript', 'HTML', 'CSS'], + start_date: '09/22/2022', + end_date: '10/28/2022', + start_time: '9:00:00', + end_time: '10:00:00', + location: 'https://zoom.us/my/john123', + price: 500, + }, + { + schedule_id: 3, + course_id: 5, + instructor_id: 10, + instructor_name: 'Mark', + size: 20, + subject: 'Fundamental Python', + description: 'Computer Science fundamentals', + prereqs: ['JavaScript', 'HTML', 'CSS'], + start_date: '03/24/2022', + end_date: '04/08/2022', + start_time: '13:10:00', + end_time: '14:15:00', + location: 'https://zoom.us/my/john123', + price: 500, + }, + { + schedule_id: 3, + course_id: 5, + instructor_id: 10, + instructor_name: 'Mark', + size: 20, + subject: 'Intro to React', + description: 'Welcome to React', + prereqs: ['JavaScript', 'HTML', 'CSS'], + start_date: '03/15/2022', + end_date: '04/18/2022', + start_time: '13:30:00', + end_time: '14:45:00', + location: 'https://zoom.us/my/john123', + price: 500, + }, + { + schedule_id: 3, + course_id: 5, + instructor_id: 10, + instructor_name: 'Mark', + size: 20, + subject: 'Intro to React', + description: 'Welcome to React', + prereqs: ['JavaScript', 'HTML', 'CSS'], + start_date: '08/03/2022', + end_date: '09/08/2022', + start_time: '10:10:00', + end_time: '11:15:00', + location: 'https://zoom.us/my/john123', + price: 500, + }, + { + schedule_id: 3, + course_id: 5, + instructor_id: 10, + instructor_name: 'Mark', + size: 20, + subject: 'Intro to React', + description: 'Welcome to React', + prereqs: ['JavaScript', 'HTML', 'CSS'], + start_date: '06/01/2023', + end_date: '07/05/2023', + start_time: '08:00:00', + end_time: '09:05:00', + location: 'https://zoom.us/my/john123', + price: 500, + }, + { + schedule_id: 3, + course_id: 5, + instructor_id: 10, + instructor_name: 'Mark', + size: 20, + subject: 'Intro to React', + description: 'Welcome to React', + prereqs: ['JavaScript', 'HTML', 'CSS'], + start_date: '10/30/2022', + end_date: '11/28/2022', + start_time: '17:00:00', + end_time: '18:00:00', + location: 'https://zoom.us/my/john123', + price: 500, + }, ], + newsfeed: [], }; diff --git a/src/redux/actions/adminActions.js b/src/redux/actions/adminActions.js index 9c181736..879722c5 100644 --- a/src/redux/actions/adminActions.js +++ b/src/redux/actions/adminActions.js @@ -6,11 +6,10 @@ export const FAIL_FETCH = 'FAIL_FETCH'; export const ADD_CLASS = 'ADD_CLASS'; export const DELETE_CLASS = 'DELETE_CLASS'; export const EDIT_CLASS = 'EDIT_CLASS'; -//TO-DO: Implement Auth0 // waiting for backend to implement this and reducer / actions // -// const token = JSON.parse(localStorage.getItem('Auth0 token storage')); +// const token = JSON.parse(localStorage.getItem('okta-token-storage')); // const config = { // headers: { Authorization: `Bearer ${token.idToken.value}` }, // }; @@ -26,7 +25,6 @@ export const EDIT_CLASS = 'EDIT_CLASS'; // // axios // .post(`https://coder-heroes-api.herokuapp.com/course_types`, body, config) -// Promise.resolve({ data: [], message: '' }) // .then(resp => { // console.log('axiosCall', resp); // }) @@ -40,14 +38,13 @@ export const fetchClasses = () => dispatch => { dispatch(startFetch()); // waiting for backend to implement this and reducer / actions - // Promise.resolve({ data: [], message: '' }) - // .then(resp => { - // dispatch(successFetch(resp.data)); - // }) - // .catch(err => { - // dispatch(failFetch(setError)); - // }); - // }) + // axios.get('backend...') + // .then(resp => { + // dispatch(successFetch(resp.data)); + // }) + // .catch(err => { + // dispatch(failFetch(setError)); + // }); }; export const startFetch = () => { @@ -75,7 +72,6 @@ export const addClass = item => { // waiting for backend to implement this and reducer / actions // // axios.post("backend...", item) - // Promise.resolve({ data: [], message: '' }) // .then (resp =>{ // console.log('post success', resp); // }) diff --git a/src/redux/actions/childAction.js b/src/redux/actions/childAction.js index 20713fef..a02f4064 100644 --- a/src/redux/actions/childAction.js +++ b/src/redux/actions/childAction.js @@ -1,18 +1,14 @@ -// import axiosWithAuth from '../../utils/axiosWithAuth'; -import axios from 'axios'; +import axiosWithAuth from '../../utils/axiosWithAuth'; export const ERROR_ACTION = 'ERROR_ACTION'; export const GET_CHILDREN_ACTION = 'GET_CHILDREN_ACTION'; export const GET_CHILDREN_SUCCESS = 'GET_CHILDREN_SUCCESS'; export const GET_COURSES_ACTION = 'GET_COURSES_ACTION'; export const GET_COURSES_SUCCESS = 'GET_COURSES_SUCCESS'; -// stubbed - export const getChildren = idToken => dispatch => { dispatch({ type: GET_CHILDREN_ACTION }); - // axiosWithAuth(idToken) - // .get(`${process.env.REACT_APP_API_URI}/children`) - Promise.resolve({ data: [], message: '' }) + axiosWithAuth(idToken) + .get(`${process.env.REACT_APP_API_URI}/children`) .then(res => { dispatch({ type: GET_CHILDREN_SUCCESS, payload: res.data }); }) @@ -21,11 +17,10 @@ export const getChildren = idToken => dispatch => { }); }; -export const getCourses = (profile_id, child_id) => dispatch => { +export const getCourses = (idToken, child_id) => dispatch => { dispatch({ type: GET_COURSES_ACTION }); - // axiosWithAuth(idToken) - // .get(`/children/${child_id}/enrollments`) - Promise.resolve({ data: { enrollments: [] }, message: '' }) + axiosWithAuth(idToken) + .get(`/children/${child_id}/enrollments`) .then(res => { dispatch({ type: GET_COURSES_SUCCESS, payload: res.data.enrollments }); }) diff --git a/src/redux/actions/classroomActions.js b/src/redux/actions/classroomActions.js index 45eea957..583f595e 100644 --- a/src/redux/actions/classroomActions.js +++ b/src/redux/actions/classroomActions.js @@ -1,5 +1,4 @@ -// import axiosWithAuth from '../../utils/axiosWithAuth'; -import axios from 'axios'; +import axiosWithAuth from '../../utils/axiosWithAuth'; export const SET_COURSE_ID = 'SET_COURSE_ID'; export const GET_STUDENTS = 'GET_STUDENTS'; @@ -11,8 +10,6 @@ export const GET_BADGES = 'GET_BADGES'; export const ADD_BADGE_TO_STUDENT = 'ADD_BADGE_TO_STUDENT'; export const REMOVE_BADGE_FROM_STUDENT = 'REMOVE_BADGE_FROM_STUDENT'; -// stubbed - export const setCourseId = course_id => { return { type: SET_COURSE_ID, payload: course_id }; }; @@ -21,74 +18,68 @@ export const setCurrentStudentId = student_id => { return { type: SET_CURRENT_STUDENT_ID, payload: student_id }; }; -export const getStudents = (profile_id, course_id) => async dispatch => { +export const getStudents = (idToken, course_id) => async dispatch => { dispatch({ type: FETCHING, payload: true, }); - // axiosWithAuth(idToken) - // .get(`/classroom/students/${course_id}`) - Promise.resolve({ data: [], message: '' }) - .then(res => { - dispatch({ - type: GET_STUDENTS, - payload: res.data, - }); - }) - .catch(err => { - dispatch({ - type: ERROR, - payload: true, - }); + try { + const res = await axiosWithAuth(idToken).get( + `/classroom/students/${course_id}` + ); + dispatch({ + type: GET_STUDENTS, + payload: res.data, }); + } catch (error) { + dispatch({ + type: ERROR, + payload: true, + }); + } }; - export const getBadges = idToken => async dispatch => { dispatch({ type: FETCHING, payload: true, }); - // axiosWithAuth(idToken) - // .get(`/classroom/badges/`) - Promise.resolve({ data: [], message: '' }) - .then(res => { - dispatch({ - type: GET_BADGES, - payload: res.data, - }); - }) - .catch(err => { - dispatch({ - type: ERROR, - payload: true, - }); + try { + const res = await axiosWithAuth(idToken).get(`/classroom/badges/`); + dispatch({ + type: GET_BADGES, + payload: res.data, }); + } catch (error) { + dispatch({ + type: ERROR, + payload: true, + }); + } }; -export const getBadgesById = (profile_id, student_id) => async dispatch => { +export const getBadgesById = (idToken, student_id) => async dispatch => { dispatch({ type: FETCHING, payload: true, }); - // axiosWithAuth(idToken) - // .get(`/classroom/badges/${student_id}`) - Promise.resolve({ data: [], message: '' }) - .then(res => { - dispatch({ - type: GET_BADGES_BY_ID, - payload: res.data, - }); - }) - .catch(err => { - dispatch({ - type: ERROR, - payload: true, - }); + try { + const res = await axiosWithAuth(idToken).get( + `/classroom/badges/${student_id}` + ); + dispatch({ + type: GET_BADGES_BY_ID, + payload: res.data, + }); + } catch (error) { + dispatch({ + type: ERROR, + payload: true, }); + } }; export const addBadgeToStudent = ( - profile_id, + idToken, badge_id, student_id, badge @@ -97,19 +88,18 @@ export const addBadgeToStudent = ( type: FETCHING, payload: true, }); - // axiosWithAuth(idToken) - // .post(`/classroom/assign`, { - // badge_id: badge_id, - // child_id: student_id, - // }) - Promise.resolve({ data: [], message: '' }) - .then(res => { + axiosWithAuth(idToken) + .post(`/classroom/assign`, { + badge_id: badge_id, + child_id: student_id, + }) + .then(() => { dispatch({ type: ADD_BADGE_TO_STUDENT, - payload: res.data, + payload: badge, }); }) - .catch(err => { + .catch(() => { dispatch({ type: ERROR, payload: true, @@ -118,7 +108,7 @@ export const addBadgeToStudent = ( }; export const removeBadgeFromStudent = ( - profile_id, + idToken, badge_id, student_id, badge @@ -128,14 +118,14 @@ export const removeBadgeFromStudent = ( payload: true, }); try { - // axiosWithAuth(idToken) - // .delete(`/classroom/remove/${badge_id}/${student_id}`) - Promise.resolve({ data: [], message: '' }).then(res => { - dispatch({ - type: REMOVE_BADGE_FROM_STUDENT, - payload: res.data, + axiosWithAuth(idToken) + .delete(`/classroom/remove/${badge_id}/${student_id}`) + .then(() => { + dispatch({ + type: REMOVE_BADGE_FROM_STUDENT, + payload: badge, + }); }); - }); } catch (error) { dispatch({ type: ERROR, diff --git a/src/redux/actions/coursesActions.js b/src/redux/actions/coursesActions.js index 4a3bd693..6a1ef093 100644 --- a/src/redux/actions/coursesActions.js +++ b/src/redux/actions/coursesActions.js @@ -1,5 +1,4 @@ -// import axiosWithAuth from '../../utils/axiosWithAuth'; -import axios from 'axios'; +import axiosWithAuth from '../../utils/axiosWithAuth'; export const EDITING = 'EDITING'; export const ADD_COURSE = 'ADD_COURSE'; @@ -9,8 +8,6 @@ export const DELETE_COURSE = 'DELETE_COURSE'; export const CANCEL_EDIT = 'CANCEL_EDIT'; export const ERROR = 'ERROR'; -//TO-DO: Implement axiosWithAuth once we've adjusted it to work with Auth0 - export const setEditing = id => { return { type: EDITING, payload: id }; }; @@ -20,31 +17,26 @@ export const cancelEdit = () => { }; export const getCourses = idToken => async dispatch => { - // axiosWithAuth(idToken) - // .get(`/courses`) - Promise.resolve({ data: [], message: '' }) - .then(res => { - dispatch({ - type: GET_COURSES, - payload: res.data, - }); - }) - .catch(err => { - dispatch({ - type: ERROR, - payload: err.message, - }); + try { + const res = await axiosWithAuth(idToken).get(`/courses`); + dispatch({ + type: GET_COURSES, + payload: res.data, }); + } catch (error) { + dispatch({ + type: ERROR, + payload: error.message, + }); + } }; -export const delCourse = (profile_id, id) => async dispatch => { +export const delCourse = (idToken, id) => async dispatch => { try { - // await axiosWithAuth(idToken).delete(`/courses/${id}`); - Promise.resolve({ data: { id: '' }, message: '' }).then(res => { - dispatch({ - type: DELETE_COURSE, - payload: res.data.id, - }); + await axiosWithAuth(idToken).delete(`/courses/${id}`); + dispatch({ + type: DELETE_COURSE, + payload: id, }); } catch (error) { dispatch({ @@ -54,17 +46,15 @@ export const delCourse = (profile_id, id) => async dispatch => { } }; -export const editCourse = (profile_id, course) => async dispatch => { +export const editCourse = (idToken, course) => async dispatch => { try { - // const res = await axiosWithAuth(idToken).put( - // `/courses/${course.course_id}`, - // course - // ); - Promise.resolve({ data: { course: [] }, message: '' }).then(res => { - dispatch({ - type: UPDATE_COURSE, - payload: res.data.course[0], - }); + const res = await axiosWithAuth(idToken).put( + `/courses/${course.course_id}`, + course + ); + dispatch({ + type: UPDATE_COURSE, + payload: res.data.course[0], }); } catch (error) { dispatch({ @@ -75,9 +65,8 @@ export const editCourse = (profile_id, course) => async dispatch => { }; export const addCourse = (idToken, course) => async dispatch => { - // axiosWithAuth(idToken) - // .post('/course', course) - Promise.resolve({ data: { created_course: '' }, message: '' }) + axiosWithAuth(idToken) + .post('/course', course) .then(res => { dispatch({ type: ADD_COURSE, diff --git a/src/redux/actions/instructorActions.js b/src/redux/actions/instructorActions.js index aa9e1740..bf23e5f8 100644 --- a/src/redux/actions/instructorActions.js +++ b/src/redux/actions/instructorActions.js @@ -1,6 +1,6 @@ // Declare Actions import axios from 'axios'; -// import axiosWithAuth from '../../utils/axiosWithAuth'; +import axiosWithAuth from '../../utils/axiosWithAuth'; export const GET_INSTRUCTORS = 'GET_INSTRUCTORS'; export const ERROR_ACTION = 'ERROR'; @@ -23,8 +23,6 @@ export const GET_INSTRUCTOR = 'GET_INSTRUCTOR'; export const SET_POST_ID = 'SET_POST_ID'; export const SET_POST_OPTIONS = 'SET_POST_OPTIONS'; -//TO-DO: Implement axiosWithAuth once we've adjusted it to work with Auth0 - export const setSelectedCourse = course => { return { type: SET_SELECTED_COURSE, @@ -33,9 +31,8 @@ export const setSelectedCourse = course => { }; export const getUser = idToken => async dispatch => { - // axiosWithAuth(idToken) - // .get('/user') - Promise.resolve({ data: [], message: '' }) + axiosWithAuth(idToken) + .get('/user') .then(res => { dispatch({ type: GET_USER_ACTION, @@ -50,10 +47,9 @@ export const getUser = idToken => async dispatch => { }); }; -export const getCourses = profile_id => async dispatch => { +export const getCourses = idToken => async dispatch => { try { - //const res = await axiosWithAuth(idToken).get(`/instructor/courses`); - const res = Promise.resolve({ data: [], message: '' }); + const res = await axiosWithAuth(idToken).get(`/instructor/courses`); const courses = res.data.map(course => { const now = Date.now(); return { ...course, active: now < new Date(course.end_date).getTime() }; @@ -62,6 +58,7 @@ export const getCourses = profile_id => async dispatch => { type: GET_INSTRUCTOR_COURSES, payload: courses, }); + console.log(courses); } catch (error) { dispatch({ type: ERROR_ACTION, @@ -71,9 +68,8 @@ export const getCourses = profile_id => async dispatch => { }; export const getPrograms = idToken => async dispatch => { - // axiosWithAuth(idToken) - // .get('/programs') - Promise.resolve({ data: [], message: '' }) + axiosWithAuth(idToken) + .get('/programs') .then(res => { dispatch({ type: GET_PROGRAMS, @@ -90,10 +86,9 @@ export const getPrograms = idToken => async dispatch => { export const getInbox = () => async dispatch => { try { - // const res = await axios.get( - // `${process.env.REACT_APP_API_URI}/inbox/:profile_id` - // ); - const res = Promise.resolve({ data: [], message: '' }); + const res = await axios.get( + `${process.env.REACT_APP_API_URI}/inbox/:profile_id` + ); dispatch({ type: GET_INBOX_ACTION, payload: res.data, @@ -108,8 +103,7 @@ export const getInbox = () => async dispatch => { export const addCourse = () => async dispatch => { try { - // const res = await axios.post(``); - const res = Promise.resolve({ data: [], message: '' }); + const res = await axios.post(``); dispatch({ type: ADD_COURSE_ACTION, payload: res.data, @@ -122,37 +116,39 @@ export const addCourse = () => async dispatch => { } }; -export const addProgram = () => async dispatch => { - try { - // axios - // .post(`${process.env.REACT_APP_API_URI}/program`, newProgram) - Promise.resolve({ data: [], message: '' }).then(res => { - dispatch({ - type: ADD_NEW_PROGRAM, - payload: res.data, +export const addProgram = newProgram => { + return dispatch => { + dispatch(addNewProgram()); + axios + .post(`${process.env.REACT_APP_API_URI}/program`, newProgram) + .then(res => { + dispatch({ type: FETCH_SUCCESS, payload: res.data }); + }) + .catch(error => { + dispatch({ type: FETCH_FAIL, payload: error.response.data.Error }); }); - }); - } catch (error) { - dispatch({ - type: ERROR_ACTION, - payload: error.message, - }); - } + }; +}; + +export const addNewProgram = programs => { + return { + type: ADD_NEW_PROGRAM, + payload: programs, + }; }; export const setError = error => { return { type: SET_ERROR }; }; -export const getNewsFeeds = profile_id => dispatch => { +export const getNewsFeeds = idToken => dispatch => { try { - // axiosWithAuth(idToken) - // .get('/news') - Promise.resolve({ data: [], message: '' }) - .then(res => { + axiosWithAuth(idToken) + .get('/news') + .then(resp => { dispatch({ type: GET_NEWSFEEDS, - payload: res.data, + payload: resp.data, }); }) .catch(err => console.log(err)); @@ -164,15 +160,14 @@ export const getNewsFeeds = profile_id => dispatch => { } }; -export const getNewsFeed = (profile_id, postID) => dispatch => { +export const getNewsFeed = (idToken, postID) => dispatch => { try { - // axiosWithAuth(idToken) - // .get(`/news/${postID}`) - Promise.resolve({ data: [], message: '' }) - .then(res => { + axiosWithAuth(idToken) + .get(`/news/${postID}`) + .then(resp => { dispatch({ type: GET_NEWSFEED, - payload: res.data, + payload: resp.data, }); }) .catch(err => console.log(err)); @@ -184,15 +179,14 @@ export const getNewsFeed = (profile_id, postID) => dispatch => { } }; -export const postNewsFeed = (profile_id, values) => dispatch => { +export const postNewsFeed = (idToken, values) => dispatch => { try { - // axiosWithAuth(idToken) - // .post(`/news/`, values) - Promise.resolve({ data: [], message: '' }) - .then(res => { + axiosWithAuth(idToken) + .post(`/news/`, values) + .then(resp => { dispatch({ type: POST_NEWSFEED, - payload: res.data, + payload: resp.data, }); }) .catch(err => console.log(err)); @@ -204,15 +198,14 @@ export const postNewsFeed = (profile_id, values) => dispatch => { } }; -export const putNewsFeed = (profile_id, postID, formValues) => dispatch => { +export const putNewsFeed = (idToken, postID, formValues) => dispatch => { try { - // axiosWithAuth(idToken) - // .put(`/news/${postID}`, formValues) - Promise.resolve({ data: [], message: '' }) - .then(res => { + axiosWithAuth(idToken) + .put(`/news/${postID}`, formValues) + .then(resp => { dispatch({ type: PUT_NEWSFEED, - payload: res.data, + payload: formValues, }); }) .catch(err => console.log(err)); @@ -224,15 +217,14 @@ export const putNewsFeed = (profile_id, postID, formValues) => dispatch => { } }; -export const deleteNewsFeed = (profile_id, postID, post) => dispatch => { +export const deleteNewsFeed = (idToken, postID, post) => dispatch => { try { - // axiosWithAuth(idToken) - // .delete(`/news/${postID}`) - Promise.resolve({ data: [], message: '' }) - .then(res => { + axiosWithAuth(idToken) + .delete(`/news/${postID}`) + .then(resp => { dispatch({ type: DELETE_NEWSFEED, - payload: res.data, + payload: post, }); }) .catch(err => console.log(err)); @@ -244,10 +236,9 @@ export const deleteNewsFeed = (profile_id, postID, post) => dispatch => { } }; -export const getInstructors = profile_id => async dispatch => { +export const getInstructors = idToken => async dispatch => { try { - // const res = await axiosWithAuth(idToken).get(`profiles/role/3`); - const res = Promise.resolve({ data: [], message: '' }); + const res = await axiosWithAuth(idToken).get(`profiles/role/3`); dispatch({ type: GET_INSTRUCTORS, payload: res.data, @@ -260,12 +251,11 @@ export const getInstructors = profile_id => async dispatch => { } }; -export const getInstructor = profile_id => async dispatch => { +export const getInstructor = (idToken, profile_id) => async dispatch => { try { - // const res = await axiosWithAuth(idToken).get( - // `instructor/profile/${profile_id}` - // ); - const res = Promise.resolve({ data: [], message: '' }); + const res = await axiosWithAuth(idToken).get( + `instructor/profile/${profile_id}` + ); dispatch({ type: GET_INSTRUCTOR, payload: res.data, diff --git a/src/redux/actions/parentActions.js b/src/redux/actions/parentActions.js index 9c1c397f..ae2fb3b3 100644 --- a/src/redux/actions/parentActions.js +++ b/src/redux/actions/parentActions.js @@ -1,5 +1,5 @@ import axios from 'axios'; -// import axiosWithAuth from '../../utils/axiosWithAuth'; +import axiosWithAuth from '../../utils/axiosWithAuth'; export const ERROR_ACTION = 'ERROR'; export const GET_CHILDREN_ACTION = 'GET_CHILDREN'; export const GET_CHILDREN_SUCCESS = 'GET_CHILDREN_SUCCESS'; @@ -18,32 +18,22 @@ export const ADD_TO_CART = 'ADD_TO_CART'; export const CANCEL_CART_ITEM = 'CANCEL_CART_ITEM'; export const CLEAR_CART = 'CLEAR_CART'; export const GET_NEWSFEEDS_PARENT = 'GET_NEWSFEEDS_PARENT'; -//TO-DO: Implement axiosWithAuth once we've adjusted it to work with Auth0 -export const getChildren = profile_id => async dispatch => { +export const getChildren = (idToken, profile_id) => async dispatch => { dispatch({ type: GET_CHILDREN_ACTION }); - // axiosWithAuth(idToken) - // .get(`/parent/${profile_id}/children`) - Promise.resolve({ data: [], message: '' }) + axiosWithAuth(idToken) + .get(`/parent/${profile_id}/children`) .then(res => { - dispatch({ - type: GET_CHILDREN_SUCCESS, - payload: res.data, - }); + dispatch({ type: GET_CHILDREN_SUCCESS, payload: res.data }); }) .catch(err => { - dispatch({ - type: ERROR_ACTION, - payload: err.message, - }); + dispatch({ type: ERROR_ACTION, payload: err }); }); }; - export const getCourses = dispatch => { dispatch({ type: GET_COURSES_ACTION }); - // axios - // .get(`${process.env.REACT_APP_API_URI}/course`) - Promise.resolve({ data: [], message: '' }) + axios + .get(`${process.env.REACT_APP_API_URI}/course`) .then(res => { dispatch({ type: GET_COURSES_SUCCESS, payload: res.data }); }) @@ -54,11 +44,10 @@ export const getCourses = dispatch => { export const signupForCourse = () => dispatch => { dispatch({ type: SIGNUP_COURSE_ACTION }); - // axios - // .get(`${process.env.REACT_APP_API_URI}/children/:id/enrollments}`, { - // crossdomain: true, - // }) - Promise.resolve({ data: [], message: '' }) + axios + .get(`${process.env.REACT_APP_API_URI}/children/:id/enrollments}`, { + crossdomain: true, + }) .then(res => { dispatch({ type: SIGNUP_COURSE_ACTION, payload: res.data }); }) @@ -66,12 +55,10 @@ export const signupForCourse = () => dispatch => { dispatch({ type: ERROR_ACTION, payload: err }); }); }; - export const fetchBookings = () => dispatch => { dispatch({ type: FETCH_BOOKINGS_START }); - // axios - // .get(`${process.env.REACT_APP_API_URI}/parent/:profile_id/schedules`) - Promise.resolve({ data: [], message: '' }) + axios + .get(`${process.env.REACT_APP_API_URI}/parent/:profile_id/schedules`) .then(res => { dispatch({ type: FETCH_BOOKINGS_SUCCESS, payload: res.data }); }) @@ -79,7 +66,6 @@ export const fetchBookings = () => dispatch => { dispatch({ type: FETCH_BOOKINGS_FAILURE, payload: err }); }); }; - export const addToCart = booking => dispatch => { return dispatch({ type: ADD_TO_CART, payload: booking }); }; @@ -90,11 +76,10 @@ export const clearCart = () => dispatch => { return dispatch({ type: CLEAR_CART }); }; -export const getNewsFeedsParent = profile_id => dispatch => { +export const getNewsFeedsParent = idToken => dispatch => { try { - // axiosWithAuth(idToken) - // .get('/news') - Promise.resolve({ data: [], message: '' }) + axiosWithAuth(idToken) + .get('/news') .then(resp => { dispatch({ type: GET_NEWSFEEDS_PARENT, diff --git a/src/redux/actions/userActions.js b/src/redux/actions/userActions.js index 343ac2e5..f2c82a05 100644 --- a/src/redux/actions/userActions.js +++ b/src/redux/actions/userActions.js @@ -1,4 +1,4 @@ -// import axiosWithAuth from '../../utils/axiosWithAuth'; +import axiosWithAuth from '../../utils/axiosWithAuth'; import axios from 'axios'; export const GET_CURRENT_USER = 'GET_CURRENT_USER'; export const SET_ERROR = 'SET_ERROR'; @@ -8,22 +8,21 @@ export const ERROR_ACTION = 'ERROR'; export const POST_INBOX_ACTION = 'POST_INBOX_ACTION'; export const POST_INBOX_SUCCESS = 'POST_INBOX_SUCCESS'; export const SET_ACTIVE_CONVERSATION = 'SET_ACTIVE_CONVERSATION'; -//TO-DO: Implement Auth0 -//TO-DO: Implement axiosWithAuth once we've adjusted it to work with Auth0 export const getCurrentUser = (idToken, oktaAuth) => async dispatch => { + console.log(oktaAuth); if (oktaAuth.isAuthenticated) { oktaAuth .getUser() .then(parsedJWT => { - // axiosWithAuth(idToken) - // .get(`/profiles/${parsedJWT.sub}`) - Promise.resolve({ data: [], message: '' }).then(res => { - dispatch({ - type: GET_CURRENT_USER, - payload: res.data, + axiosWithAuth(idToken) + .get(`/profiles/${parsedJWT.sub}`) + .then(res => { + dispatch({ + type: GET_CURRENT_USER, + payload: res.data, + }); }); - }); }) .catch(err => { dispatch({ @@ -38,39 +37,43 @@ export const getActiveConversation = activeConversation => { return { type: SET_ACTIVE_CONVERSATION, payload: activeConversation }; }; -export const addMessage = ( - idToken, - message, - profile_id, - title, - sender_id -) => dispatch => { - // axios - // .post(`${process.env.REACT_APP_API_URI}/conversation_id/messages/`, { - // message, - // sent_at: date.toISOString(), - // sender_id: profile_id, - // title: title, - // inbox_id: recipient, - // read: false, - // crossdomain: true, - // }) - Promise.resolve({ data: [], message: '' }) - .then(res => { - dispatch({ type: POST_INBOX_SUCCESS, payload: res.data }); - }) - .catch(err => { - dispatch({ type: ERROR_ACTION, payload: err }); - }); +export const addMessage = (idToken, message, profile_id, title, sender_id) => { + return { + type: POST_INBOX_ACTION, + payload: { + message, + sender_id: sender_id, + title, + profile_id: profile_id, + sent_at: new Date(), + read: false, + }, + }; + // This endpoint is not working/not built yet + // axios + // .post(`${process.env.REACT_APP_API_URI}/conversation_id/messages/`, { + // message, + // sent_at: date.toISOString(), + // sender_id: profile_id, + // title: title, + // inbox_id: recipient, + // read: false, + // crossdomain: true, + // }) + // .then(res => { + // dispatch({ type: POST_INBOX_SUCCESS, payload: res.data }); + // }) + // .catch(err => { + // dispatch({ type: ERROR_ACTION, payload: err }); + // }); }; export const getInbox = dispatch => { dispatch({ type: GET_INBOX_ACTION }); - // axios - // .get(`${process.env.REACT_APP_API_URI}/inbox/:profile_id`, { - // crossdomain: true, - // }) - Promise.resolve({ data: [], message: '' }) + axios + .get(`${process.env.REACT_APP_API_URI}/inbox/:profile_id`, { + crossdomain: true, + }) .then(res => { dispatch({ type: GET_INBOX_SUCCESS, payload: res.data }); }) diff --git a/src/redux/reducers/parentReducer.js b/src/redux/reducers/parentReducer.js index 3e7c7a97..ad3fda16 100644 --- a/src/redux/reducers/parentReducer.js +++ b/src/redux/reducers/parentReducer.js @@ -1,3 +1,4 @@ +import { parentDummyData } from '../../parentDummyData'; import { ADD_TO_CART, CANCEL_CART_ITEM, @@ -14,17 +15,6 @@ import { GET_NEWSFEEDS_PARENT, } from '../actions/parentActions'; -const initialState = { - availableCourses: [], - bookings: null, - cart: [], - children: [], - courses: [], - inbox: [], - newsfeed: [], - sessions: [], -}; - const removeCartItem = (cart, booking) => { for (let i = 0; i < cart.length; i++) { if ( @@ -38,7 +28,7 @@ const removeCartItem = (cart, booking) => { return cart; }; -const parentReducer = (state = initialState, action) => { +const reducer = (state = parentDummyData, action) => { switch (action.type) { case GET_COURSES_ACTION: return { @@ -65,6 +55,7 @@ const parentReducer = (state = initialState, action) => { ...state, inbox: action.payload, }; + case SIGNUP_COURSE_ACTION: return { ...state, @@ -123,4 +114,4 @@ const parentReducer = (state = initialState, action) => { } }; -export default parentReducer; +export default reducer; diff --git a/src/styles/AdminDashboardHome/index.less b/src/styles/AdminDashboardHome/index.less index 6e3694cd..ae21b9e8 100644 --- a/src/styles/AdminDashboardHome/index.less +++ b/src/styles/AdminDashboardHome/index.less @@ -12,6 +12,7 @@ h2 { padding-top: 0.5%; padding-left: 1%; padding-bottom: 1%; + font-family: Roboto; font-size: 30px; } @@ -35,20 +36,6 @@ h2 { margin-left: 10px; } -.see-all-link { - color: white; - background-color: #21C5B5; - padding: 0px .5rem 0px .5rem; - border-radius: .15rem; - flex-shrink: 0; - width: 4.8rem; - font-size: 1rem; -} - -.see-all-link:hover { - color: black; -} - .AdminDashHeaders { display: flex; flex-flow: row nowrap; diff --git a/src/styles/AdminStyles/index.less b/src/styles/AdminStyles/index.less index 714a734c..dcf198f3 100644 --- a/src/styles/AdminStyles/index.less +++ b/src/styles/AdminStyles/index.less @@ -60,31 +60,21 @@ .approvedBtn { margin: 5% 33%; } -// styles for admin SideNav -aside.ant-layout-sider { - display: flex; - flex-direction: column; - justify-content: space-between; -} -div.ant-layout-sider-trigger { - margin-top: auto; - justify-self: flex-end; -} // styles for admin-purchases - div.header-container { - padding-left: 1%; - padding-bottom:1%; +div.header-container{ +padding-left: 1%; +padding-bottom:1%; } -div.table-container { +div.table-container{ padding:3%; } // styles for admin-purchases-table // makes the rows alternating colors -.table-container { -tr:nth-child(odd) { +.table-container{ +tr:nth-child(odd){ background-color:#FDF2DD; } -tr:nth-child(even) { +tr:nth-child(even){ background-color:#fcdfaa; } tr:nth-child(odd) > td.ant-table-cell { @@ -103,31 +93,31 @@ thead.ant-table-thead > tr > th.ant-table-cell, th.ant-table-column-sort { thead.ant-table-thead > tr > th { background-color:#263E47; } -.ant-table-column-title { +.ant-table-column-title{ font-size:medium; } .ant-table-thead { background-color:#263E47; } // makes the links black instead of blue -.ant-table-cell a { +.ant-table-cell a{ color:black; } // makes the sorters black & the filter black -.ant-table-column-sorter-inner { +.ant-table-column-sorter-inner{ color:white; } -.ant-table-column-sorters { +.ant-table-column-sorters{ color:white; } -.anticon, .anticon-filter { +.anticon, .anticon-filter{ color:white; } -.anticon-download { +.anticon-download{ color:black; font-size:large; } -.right { +.right{ text-align:right; padding-right:2%; padding-bottom:1%; @@ -135,38 +125,38 @@ thead.ant-table-thead > tr > th { } } // styles for the admin add course modal and form -.ant-modal-content { +.ant-modal-content{ width: 120%; margin-top:-10%; margin-left:-10%; background-color:#FCDFAA; border:#F1C461; } -.ant-modal-header { +.ant-modal-header{ background-color:#FCDFAA; border-bottom:none; } -.ant-modal-body { +.ant-modal-body{ border-top: 1px solid #096A70; } -.ant-modal-title { +.ant-modal-title{ font-size:1.7rem; } -.ant-modal-close-icon { +.ant-modal-close-icon{ color:black; } // attempted to apply font-size styles in this CSS sheet instead of inline. It was not responding to anything but inline styling. .ant-form-item-label { font-weight: bold; } -.ant-form-item-label > label { +.ant-form-item-label > label{ color: #096A70; } -.ant-modal-footer { +.ant-modal-footer{ display:flex; justify-content: flex-end; border-top: 1px solid #FCDFAA; - .ant-btn-default { + .ant-btn-default{ width:30%; justify-content:center; background-color:#21C5B5; @@ -178,7 +168,7 @@ thead.ant-table-thead > tr > th { font-size:1rem; padding-bottom:5px; } - .ant-btn-primary { + .ant-btn-primary{ width:30%; justify-content:center; background-color:#6A0C49; @@ -193,21 +183,21 @@ thead.ant-table-thead > tr > th { } //Admin view instructor styles -.ant-card-container { +.ant-card-container{ width:100%; } -.ant-card { +.ant-card{ background-color: #fcdfaa; border: none; margin:2%; } -.instructor-card-container { +.instructor-card-container{ max-width: 100%; display: flex; flex-direction: row; flex-wrap: wrap; } -.tgl-container { +.tgl-container{ width: 100%; text-align: right; } @@ -222,29 +212,29 @@ thead.ant-table-thead > tr > th { width: 15%; } -div.instructor-button-container { +div.instructor-button-container{ display:flex; flex-direction:row; width:100%; justify-content: space-around; } -.ant-card-head { +.ant-card-head{ border-bottom: 1px solid #096A70; } -.ant-card-head-title { +.ant-card-head-title{ color: #096A70; font-size:large; font-weight:bold; } -.ant-card-body > h3 { +.ant-card-body > h3{ color: #096A70; font-weight:bold; } -.black { +.black{ color:black; font-weight:normal; } -button.instructor-button { +button.instructor-button{ background-color:white; color:black; border:none; @@ -254,72 +244,72 @@ button.instructor-button { } //media queries for submit new program -.admin-add-courses-page { +.admin-add-courses-page{ font-size:1.5rem; } // admin-search -.ant-input-group-wrapper { +.ant-input-group-wrapper{ margin:0 0 0 3%; } -.ant-input-search-button { +.ant-input-search-button{ justify-content: center; margin:0; width:inherit; } -.anticon-search { +.anticon-search{ color:black; } // admin-courses styling (cards) -.ant-card-container { +.ant-card-container{ width:100%; } -.courses-page-flex { +.courses-page-flex{ display:flex; justify-content: space-between; } -.ant-card { +.ant-card{ background-color: #fcdfaa; border: none; margin:2%; } -.admin-courses-container { +.admin-courses-container{ display:flex; flex-flow:row wrap; } -.admin-course-card-container { +.admin-course-card-container{ width:45%; } -.courses-button-container { +.courses-button-container{ display:flex; flex-direction:row; width:100%; justify-content: space-around; } -.ant-input-search-button { +.ant-input-search-button{ font-size:large; } -.ant-input-group-addon { +.ant-input-group-addon{ width:5rem; } .ant-card-head{ border-bottom: 1px solid #096A70; } -.ant-card-head-title { +.ant-card-head-title{ color: #096A70; font-size:large; font-weight:bold; } -.ant-card-body > h3 { +.ant-card-body > h3{ color: #096A70; font-weight:bold; } -.black { +.black{ color:black; font-weight:normal; } -button.courses-button { +button.courses-button{ background-color:white; color:black; border:none; @@ -328,11 +318,11 @@ button.courses-button { filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25)); } -.courses-right { +.courses-right{ margin-right:16%; margin-bottom:2%; } -.add-course { +.add-course{ background-color: #21C5B5; border:none; color:black; @@ -375,4 +365,4 @@ button.courses-button { padding: 0.5rem; } } -} +} \ No newline at end of file diff --git a/src/styles/NavbarStyles/index.less b/src/styles/NavbarStyles/index.less index e7270eb0..afb89c67 100644 --- a/src/styles/NavbarStyles/index.less +++ b/src/styles/NavbarStyles/index.less @@ -42,24 +42,28 @@ .navbar__links { display: flex; align-items: center; - justify-content: space-around; + justify-content: space-evenly; width: 65%; .navbar__navLink { height: 55px; + width: 25%; display: flex; align-items: center; justify-content: center; color: @text__color--maroon; font-size: 1rem; font-weight: 600; - transition: 100ms all ease-in-out; + border-right: 2px solid #3b0e2b; + transition: 250ms all ease-in-out; } .last_navLink { border: none; } .navbar__navLink:hover { - border-bottom: 3px solid @text__color--maroon; + color: @text__color--white; + text-decoration: underline; + text-decoration-thickness: 10px; } @media screen and (max-width: 1220px) { .navbar__navLink { diff --git a/src/styles/ParentStyles/booking.less b/src/styles/ParentStyles/booking.less index ffb495da..2575a6e8 100644 --- a/src/styles/ParentStyles/booking.less +++ b/src/styles/ParentStyles/booking.less @@ -1,4 +1,190 @@ +@import 'antd/dist/antd.css'; -.image{ - max-width: 100%; -} \ No newline at end of file +.image { + max-width: 100%; +} + +.main-container { + display: flex; + + .title { + margin: 30px 0 40px 0; + p { + width: 735px; + text-align: center; + color: #3a072c; + margin-left: 600px; + font-family: 'Staatliches', 'cursive'; + } + } + + .form-container { + text-align: left; + justify-content: center; + margin-left: 155px; + + .sub-heading { + color: #3a072c; + font-size: 21px; + font-weight: bold; + margin: 20px 0 15px 0; + } + + .sub-heading { + color: #3a072c; + font-size: 21px; + font-weight: bold; + margin: 20px 0 15px 0; + } + + .course-availability-container { + display: flex; + flex-wrap: wrap; + } + + .booking-calendar-container { + padding-bottom: 30px; + flex: 1; + + .booking-calendar { + min-width: 600px; + max-width: 800px; + } + .calendar-text { + padding: 15px; + } + } + + .btn-drop-down-container { + display: flex; + min-width: 525px; + flex-direction: column; + flex: 1; + + .time-zone-container { + display: flex; + flex: 1; + flex-direction: column; + + .time-zone-card { + background-color: white; + border-radius: 5px; + margin: 6px 6px 10px 6px; + } + + .time-zone { + color: #6e4964; + font-size: 16px; + margin: 6px; + padding: 3px 0; + text-align: center; + } + } + + .booking-card-container { + display: flex; + flex-direction: column; + max-width: 500px; + + .selected-course-details { + border: 2px solid black; + margin-left: 100px; + background-color: rgb(224, 227, 209); + border-radius: 5px; + padding: 45px 45px 30px 45px; + min-width: 500px; + p { + color: black; + font-size: 16px; + } + } + + .show-availability-btn { + background-color: #680049; + margin: 150px 6px 6px 150px; + font-size: 16px; + padding: 7px 0; + text-transform: uppercase; + justify-content: center; + border-radius: 5px; + + span { + color: #eeedd9; + margin: 0; + } + } + + .booking-card-btns { + display: flex; + min-width: 500px; + + .booking-card-btn:nth-child(1) { + margin-left: 40px; + } + .booking-card-btn:nth-child(2) { + margin-right: 40px; + } + + .booking-card-btn { + background-color: #680049; + color: white; + margin: 20px 6px 6px 6px; + font-size: 16px; + padding: 7px 0; + text-transform: uppercase; + border-radius: 5px; + min-width: 255px; + justify-content: center; + + span { + color: #eeedd9; + margin: 0; + } + } + } + } + } + } +} + +.select-program-container { + display: flex; + + .arrows-icon { + color: #4a1e3c; + font-weight: bold; + } + + .radio-group { + width: 60vw; + background-color: #eeedd9; + + .select-program-cards { + padding: 5px 0 5px 5px; + background: #f35f24; + align-items: center; + min-width: 250px; + flex: 1; + margin: 0 10px; + + .radio-btn { + font-size: 20px; + } + } + } + + .arrow-btns { + background: none; + } +} + +.drop-down-container { + font-size: 20px; + width: auto; + padding: 10px; + margin: 6px; + border-radius: 15px; + background-color: rgba(58, 201, 176, 0.8); + color: #680049; + text-align: center; +} diff --git a/src/styles/calendar.less b/src/styles/calendar.less index 13a50aa4..fa51e997 100644 --- a/src/styles/calendar.less +++ b/src/styles/calendar.less @@ -161,3 +161,12 @@ div.ant-picker-calendar-date-value { margin: 0 4%; } } +//Calendar Card for +input[type='date']::before { + color: #999; + content: attr(placeholder); + margin-right: 122px; +} +input[type='date']:focus::before { + display: none; +} diff --git a/src/styles/login.less b/src/styles/login.less index e0157d0e..66d0d59a 100644 --- a/src/styles/login.less +++ b/src/styles/login.less @@ -47,8 +47,6 @@ color: @login__text__color--grey; } -//TO-DO: Implement Auth0 Form styles - // OKTA FORM STYLES .input-focus() { border: none; diff --git a/src/utils/axiosWithAuth.js b/src/utils/axiosWithAuth.js index 4f007d96..0a2745a3 100644 --- a/src/utils/axiosWithAuth.js +++ b/src/utils/axiosWithAuth.js @@ -1,12 +1,11 @@ import axios from 'axios'; -//TO-DO: Implement Auth0 const axiosWithAuth = idToken => { return axios.create({ baseURL: process.env.REACT_APP_API_URI, - // headers: { - // Authorization: 'Bearer ' + idToken, - // }, + headers: { + Authorization: 'Bearer ' + idToken, + }, }); }; diff --git a/src/utils/logout.js b/src/utils/logout.js index ba887790..77a81f02 100644 --- a/src/utils/logout.js +++ b/src/utils/logout.js @@ -1,5 +1,5 @@ -////TO-DO: Implement Auth0 const handleLogout = () => { + localStorage.removeItem('okta-token-storage'); window.location.reload(); }; diff --git a/src/utils/oktaConfig.js b/src/utils/oktaConfig.js index 8087f56f..01f96eb6 100644 --- a/src/utils/oktaConfig.js +++ b/src/utils/oktaConfig.js @@ -1,5 +1,5 @@ const config = { - //TO-DO: IMPLEMENT AUTH0// + issuer: process.env.REACT_APP_OKTA_ISSUER_URI, redirectUri: window.location.origin + '/implicit/callback', clientId: process.env.REACT_APP_CLIENT_ID, pkce: false,