diff --git a/jsconfig.json b/jsconfig.json index a40157ac93..4a810717ee 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,4 +1,7 @@ { + "compilerOptions": { + "experimentalDecorators": true + }, "typeAcquisition": { "include": [ "jest" diff --git a/package-lock.json b/package-lock.json index 16414403e9..d2b1cda734 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3511,6 +3511,11 @@ "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz", "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==" }, + "@remix-run/router": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.1.tgz", + "integrity": "sha512-eBV5rvW4dRFOU1eajN7FmYxjAIVz/mRHgUE9En9mBn6m3mulK3WTR5C3iQhL9MZ14rWAq+xOlEaCkDiW0/heOg==" + }, "@saithodev/semantic-release-backmerge": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@saithodev/semantic-release-backmerge/-/semantic-release-backmerge-2.1.2.tgz", @@ -4504,7 +4509,7 @@ "ansicolors": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", - "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", "dev": true }, "anymatch": { @@ -4535,7 +4540,7 @@ "argv-formatter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz", - "integrity": "sha1-oMoMvCmltz6Dbuvhy/bF4OTrgvk=", + "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", "dev": true }, "array-flatten": { @@ -4546,7 +4551,7 @@ "array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "dev": true }, "array-includes": { @@ -5154,7 +5159,7 @@ "cardinal": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", - "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", "dev": true, "requires": { "ansicolors": "~0.3.2", @@ -6401,7 +6406,7 @@ "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", "dev": true, "requires": { "readable-stream": "^2.0.2" @@ -7722,7 +7727,7 @@ "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -7883,7 +7888,7 @@ "git-log-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", - "integrity": "sha1-LmpMGxP8AAKCB7p5WnrDFme5/Uo=", + "integrity": "sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA==", "dev": true, "requires": { "argv-formatter": "~1.0.0", @@ -7912,7 +7917,7 @@ "split2": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", - "integrity": "sha1-UuLiIdiMdfmnP5BVbiY/+WdysxQ=", + "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", "dev": true, "requires": { "through2": "~2.0.0" @@ -8163,19 +8168,6 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", - "requires": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" - } - }, "hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -8794,7 +8786,7 @@ "is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", "dev": true, "requires": { "text-extensions": "^1.0.0" @@ -10698,7 +10690,7 @@ "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "dev": true }, "jsprim": { @@ -10795,7 +10787,7 @@ "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -10807,7 +10799,7 @@ "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, "requires": { "error-ex": "^1.3.1", @@ -10867,7 +10859,7 @@ "lodash.capitalize": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", - "integrity": "sha1-+CbJtOKoUR2E46yinbBeGk87cqk=", + "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", "dev": true }, "lodash.curry": { @@ -10884,7 +10876,7 @@ "lodash.escaperegexp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", "dev": true }, "lodash.flow": { @@ -10905,25 +10897,25 @@ "lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", + "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", "dev": true }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "dev": true }, "lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "dev": true }, "lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", "dev": true }, "log-symbols": { @@ -11261,15 +11253,6 @@ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true }, - "mini-create-react-context": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", - "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", - "requires": { - "@babel/runtime": "^7.12.1", - "tiny-warning": "^1.0.3" - } - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -11389,7 +11372,7 @@ "nerf-dart": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", - "integrity": "sha1-5tq3/r9a2Bbqgc9cYpxaDr3nLBo=", + "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", "dev": true }, "nice-try": { @@ -14501,12 +14484,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "path-to-regexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==", - "dev": true - }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -14551,7 +14528,7 @@ "pkg-conf": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", - "integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=", + "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", "dev": true, "requires": { "find-up": "^2.0.0", @@ -14561,7 +14538,7 @@ "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, "requires": { "locate-path": "^2.0.0" @@ -14570,7 +14547,7 @@ "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, "requires": { "p-locate": "^2.0.0", @@ -14589,7 +14566,7 @@ "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, "requires": { "p-limit": "^1.1.0" @@ -14598,13 +14575,13 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true } } @@ -14976,7 +14953,7 @@ "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", "dev": true }, "qrcode": { @@ -15373,49 +15350,20 @@ } }, "react-router": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", - "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", - "requires": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "requires": { - "isarray": "0.0.1" - } - } + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.1.tgz", + "integrity": "sha512-OJASKp5AykDWFewgWUim1vlLr7yfD4vO/h+bSgcP/ix8Md+LMHuAjovA74MQfsfhQJGGN1nHRhwS5qQQbbBt3A==", + "requires": { + "@remix-run/router": "1.0.1" } }, "react-router-dom": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", - "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.1.tgz", + "integrity": "sha512-MY7NJCrGNVJtGp8ODMOBHu20UaIkmwD2V3YsAOUQoCXFk7Ppdwf55RdcGyrSj+ycSL9Uiwrb3gTLYSnzcRoXww==", "requires": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.2.1", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "@remix-run/router": "1.0.1", + "react-router": "6.4.1" } }, "react-side-effect": { @@ -15595,7 +15543,7 @@ "redeyed": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", - "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", "dev": true, "requires": { "esprima": "~4.0.0" @@ -15834,11 +15782,6 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - }, "resolve.exports": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", @@ -16370,7 +16313,7 @@ "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" @@ -16434,7 +16377,7 @@ "spawn-error-forwarder": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", - "integrity": "sha1-Gv2Uc46ZmwNG17n8NzvlXgdXcCk=", + "integrity": "sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==", "dev": true }, "spdx-correct": { @@ -16541,7 +16484,7 @@ "stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", "dev": true, "requires": { "duplexer2": "~0.1.0", @@ -16699,7 +16642,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true }, "strip-final-newline": { @@ -17037,11 +16980,6 @@ "readable-stream": "3" } }, - "tiny-invariant": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", - "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" - }, "tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", @@ -17104,7 +17042,7 @@ "traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", + "integrity": "sha512-kdf4JKs8lbARxWdp7RKdNzoJBhGUcIalSYibuGyHJbmk40pOysQ0+QPvlkCOICOivDWU2IJo2rkrxyTK2AH4fw==", "dev": true }, "trim-newlines": { @@ -17443,11 +17381,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -17798,7 +17731,7 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true }, "wrap-ansi": { diff --git a/package.json b/package.json index 5925b8026f..5bf02a9928 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "express": "4.18.1", "graphiql": "2.0.7", "graphql": "16.6.0", - "history": "4.10.1", "immutable": "4.1.0", "immutable-devtools": "0.1.5", "inquirer": "8.2.4", @@ -68,8 +67,7 @@ "react-helmet": "6.1.0", "react-json-view": "1.21.3", "react-popper-tooltip": "4.4.2", - "react-router": "5.2.1", - "react-router-dom": "5.3.0", + "react-router-dom": "6.4.1", "regenerator-runtime": "0.13.9", "semver": "7.3.7", "typescript": "4.8.2" @@ -103,7 +101,6 @@ "madge": "5.0.1", "marked": "4.0.10", "null-loader": "4.0.1", - "path-to-regexp": "3.2.0", "puppeteer": "18.0.5", "react-test-renderer": "16.13.1", "request": "2.88.2", diff --git a/src/components/Autocomplete/Autocomplete.react.js b/src/components/Autocomplete/Autocomplete.react.js index 937a526702..be6d4e953f 100644 --- a/src/components/Autocomplete/Autocomplete.react.js +++ b/src/components/Autocomplete/Autocomplete.react.js @@ -6,7 +6,7 @@ * the root directory of this source tree. */ import Position from 'lib/Position'; -import PropTypes from 'prop-types' +import PropTypes from 'lib/PropTypes' import React, { Component } from 'react'; import styles from 'components/Autocomplete/Autocomplete.scss'; import SuggestionsList from 'components/SuggestionsList/SuggestionsList.react'; diff --git a/src/components/Chip/Chip.react.js b/src/components/Chip/Chip.react.js index 678063337e..c737699cf9 100644 --- a/src/components/Chip/Chip.react.js +++ b/src/components/Chip/Chip.react.js @@ -7,7 +7,7 @@ */ import React from 'react'; import styles from 'components/Chip/Chip.scss'; -import PropTypes from 'prop-types' +import PropTypes from 'lib/PropTypes' import Icon from 'components/Icon/Icon.react' let Chip = ({ value, onClose }) => ( diff --git a/src/components/FourOhFour/FourOhFour.react.js b/src/components/FourOhFour/FourOhFour.react.js index 53aba06e1a..2e53789d92 100644 --- a/src/components/FourOhFour/FourOhFour.react.js +++ b/src/components/FourOhFour/FourOhFour.react.js @@ -5,13 +5,14 @@ * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ -import history from 'dashboard/history'; import React from 'react'; import styles from 'components/FourOhFour/FourOhFour.scss'; +import { withRouter } from 'lib/withRouter'; const EMOJI_COUNT = 30; -export default class FourOhFour extends React.Component { +@withRouter +class FourOhFour extends React.Component { constructor() { super(); @@ -51,10 +52,12 @@ export default class FourOhFour extends React.Component {
Oh no, we can't find that page!
- +
); } } + +export default FourOhFour; diff --git a/src/components/Sidebar/AppsMenu.react.js b/src/components/Sidebar/AppsMenu.react.js index 62e906f3cd..cbee4edd80 100644 --- a/src/components/Sidebar/AppsMenu.react.js +++ b/src/components/Sidebar/AppsMenu.react.js @@ -23,7 +23,7 @@ const AppsMenu = ({ apps, current, height, onSelect, onPinClick }) => ( return null; } return ( - + {app.name} diff --git a/src/components/Toolbar/Toolbar.react.js b/src/components/Toolbar/Toolbar.react.js index b73378ff86..505c37021e 100644 --- a/src/components/Toolbar/Toolbar.react.js +++ b/src/components/Toolbar/Toolbar.react.js @@ -9,17 +9,17 @@ import PropTypes from 'lib/PropTypes'; import React from 'react'; import Icon from 'components/Icon/Icon.react'; import styles from 'components/Toolbar/Toolbar.scss'; -import history from 'dashboard/history'; - -const goBack = () => history.goBack(); +import { useNavigate, useNavigationType, NavigationType } from 'react-router-dom'; let Toolbar = (props) => { + const action = useNavigationType(); + const navigate = useNavigate(); let backButton; - if ((props.relation || (props.filters && props.filters.size)) && history.action !== 'POP') { + if ((props.relation || (props.filters && props.filters.size)) && action !== NavigationType.Pop) { backButton = ( navigate(-1)} > { let name = [query.source]; @@ -38,8 +39,8 @@ let buildFriendlyName = (query) => { return name.join(' '); }; -export default @subscribeTo('AnalyticsQuery', 'customQueries') +@withRouter class Explorer extends DashboardView { constructor() { super(); @@ -547,3 +548,5 @@ class Explorer extends DashboardView { ); } } + +export default Explorer; diff --git a/src/dashboard/AppData.react.js b/src/dashboard/AppData.react.js index ff113bde60..de33aa0703 100644 --- a/src/dashboard/AppData.react.js +++ b/src/dashboard/AppData.react.js @@ -8,30 +8,33 @@ import React from 'react'; import AppSelector from 'dashboard/AppSelector.react'; import AppsManager from 'lib/AppsManager'; -import history from 'dashboard/history'; import { CurrentApp } from 'context/currentApp'; +import { Outlet, useNavigate , useParams} from 'react-router-dom'; -class AppData extends React.Component { - render() { - if (this.props.params.appId === '_') { - return ; - } - //Find by name to catch edge cases around escaping apostrophes in URLs - let current = AppsManager.findAppBySlugOrName(this.props.params.appId); - if (current) { - current.setParseKeys(); - } else { - history.replace('/apps'); - return
; - } - return ( - -
- {this.props.children} -
-
- ); + +function AppData() { + const navigate = useNavigate(); + const params = useParams(); + + if (params.appId === '_') { + return ; + } + + // Find by name to catch edge cases around escaping apostrophes in URLs + let current = AppsManager.findAppBySlugOrName(params.appId); + + if (current) { + current.setParseKeys(); + } else { + navigate('/apps', { replace: true }); + return
; } + + return ( + + + + ); } export default AppData; diff --git a/src/dashboard/AppSelector.react.js b/src/dashboard/AppSelector.react.js index 722cfdb6f8..aba0f84ca7 100644 --- a/src/dashboard/AppSelector.react.js +++ b/src/dashboard/AppSelector.react.js @@ -8,13 +8,14 @@ import AppsManager from 'lib/AppsManager'; import Dropdown from 'components/Dropdown/Dropdown.react'; import Field from 'components/Field/Field.react'; -import history from 'dashboard/history'; import Label from 'components/Label/Label.react'; import Modal from 'components/Modal/Modal.react'; import Option from 'components/Dropdown/Option.react'; import React from 'react'; +import { withRouter } from 'lib/withRouter'; -export default class AppSelector extends React.Component { +@withRouter +class AppSelector extends React.Component { constructor(props) { super(props); let apps = AppsManager.apps(); @@ -25,12 +26,12 @@ export default class AppSelector extends React.Component { } handleConfirm() { - let newPath = location.pathname.replace(/\/_(\/|$)/, '/' + this.state.slug + '/'); - history.push(newPath); + let newPath = this.location.pathname.replace(/\/_(\/|$)/, '/' + this.state.slug + '/'); + this.props.navigate(newPath); } handleCancel() { - history.push('/apps'); + this.props.navigate('/apps'); } render() { @@ -58,3 +59,5 @@ export default class AppSelector extends React.Component { ); } } + +export default AppSelector; diff --git a/src/dashboard/Apps/AppsIndex.react.js b/src/dashboard/Apps/AppsIndex.react.js index eca859d94b..4b1d5efbd5 100644 --- a/src/dashboard/Apps/AppsIndex.react.js +++ b/src/dashboard/Apps/AppsIndex.react.js @@ -7,7 +7,6 @@ */ import AppsManager from 'lib/AppsManager'; import FlowFooter from 'components/FlowFooter/FlowFooter.react'; -import history from 'dashboard/history'; import html from 'lib/htmlString'; import Icon from 'components/Icon/Icon.react'; import joinWithFinal from 'lib/joinWithFinal'; @@ -17,6 +16,8 @@ import React from 'react'; import styles from 'dashboard/Apps/AppsIndex.scss'; import baseStyles from 'stylesheets/base.scss'; import AppBadge from 'components/AppBadge/AppBadge.react'; +import { withRouter } from 'lib/withRouter'; +import { useNavigate } from 'react-router-dom'; function dash(value, content) { if (value === undefined) { @@ -64,7 +65,8 @@ let AppCard = ({ app, icon, }) => { - let canBrowse = app.serverInfo.error ? null : () => history.push(html`/apps/${app.slug}/browser`); + const navigate = useNavigate(); + let canBrowse = app.serverInfo.error ? null : () => navigate(html`/apps/${app.slug}/browser`); let versionMessage = app.serverInfo.error ?
Server not reachable: {app.serverInfo.error.toString()}
:
@@ -88,7 +90,8 @@ let AppCard = ({ } -export default class AppsIndex extends React.Component { +@withRouter +class AppsIndex extends React.Component { constructor() { super(); this.state = { search: '' }; @@ -99,7 +102,7 @@ export default class AppsIndex extends React.Component { componentWillMount() { if (AppsManager.apps().length === 1) { const [app] = AppsManager.apps(); - history.push(`/apps/${app.slug}/browser`); + this.props.navigate(`/apps/${app.slug}/browser`); return; } document.body.addEventListener('keydown', this.focusField); @@ -169,3 +172,5 @@ export default class AppsIndex extends React.Component { ); } } + +export default AppsIndex; diff --git a/src/dashboard/Dashboard.js b/src/dashboard/Dashboard.js index ebde1004f4..3a639cdb79 100644 --- a/src/dashboard/Dashboard.js +++ b/src/dashboard/Dashboard.js @@ -19,7 +19,6 @@ import Explorer from './Analytics/Explorer/Explorer.react'; import FourOhFour from 'components/FourOhFour/FourOhFour.react'; import GeneralSettings from './Settings/GeneralSettings.react'; import GraphQLConsole from './Data/ApiConsole/GraphQLConsole.react'; -import history from 'dashboard/history'; import HostingSettings from './Settings/HostingSettings.react'; import Icon from 'components/Icon/Icon.react'; import JobEdit from 'dashboard/Data/Jobs/JobEdit.react'; @@ -49,11 +48,7 @@ import { AsyncStatus } from 'lib/Constants'; import baseStyles from 'stylesheets/base.scss'; import { get } from 'lib/AJAX'; import { setBasePath } from 'lib/AJAX'; -import { - Router, - Switch, -} from 'react-router'; -import { Route, Redirect } from 'react-router-dom'; +import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; import { Helmet } from 'react-helmet'; import Playground from './Data/Playground/Playground.react'; @@ -202,146 +197,121 @@ export default class Dashboard extends React.Component { ); - const SettingsRoute = ({ match }) => ( - - - - - - - - - + const SettingsRoute = ( + }> + } /> + } /> + } /> + } /> + } /> + } /> + ) - const JobsRoute = (props) => ( - - ( - - - - )} /> - ( - - - - )} /> - ( - - - - )} /> - - + const JobsRoute = ( + }> + } /> + } /> + } /> + } /> + ) - const AnalyticsRoute = ({ match }) => ( - - - - - - - - - ); + const AnalyticsRoute = ( + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + ) - const BrowserRoute = (props) => { - if (ShowSchemaOverview) { - return - } - return - } + const BrowserRoute = ShowSchemaOverview ? SchemaOverview : Browser; - const ApiConsoleRoute = (props) => ( - - ( - - - - )} /> - ( - - - - )} /> - ( - - - - )} /> - - + const ApiConsoleRoute = ( + }> + } /> + } /> + } /> + } /> + ) - const AppRoute = ({ match }) => ( - - - - - - - - - + const AppRoute = ( + }> + } /> + + } /> + + } /> + } /> + } /> + + } /> + } /> + } /> - + + {JobsRoute} + - ( - - )} /> - + } /> + } /> - - - + } /> + + {ApiConsoleRoute} + - - + } /> - ( - - )} /> - - - ( - - )} /> + } /> + } /> - {/* Unused routes... */} - - - - - - + } /> + } /> + } /> + } /> + + {/* Unused routes... */} + + {AnalyticsRoute} + + + + {SettingsRoute} + + ) - const Index = () => ( -
- - - - - -
+ const Index = ( + + } /> + + {AppRoute} + + ) + return ( - -
- - Parse Dashboard - - - - - - - - -
-
+ + + Parse Dashboard + + + + {Index} + + } /> + } /> + } /> + } /> + + ); } } diff --git a/src/dashboard/Data/ApiConsole/ApiConsole.react.js b/src/dashboard/Data/ApiConsole/ApiConsole.react.js index 46ab64cef9..513e26c683 100644 --- a/src/dashboard/Data/ApiConsole/ApiConsole.react.js +++ b/src/dashboard/Data/ApiConsole/ApiConsole.react.js @@ -8,8 +8,11 @@ import React from 'react'; import CategoryList from 'components/CategoryList/CategoryList.react'; import DashboardView from 'dashboard/DashboardView.react'; +import { Outlet } from 'react-router-dom'; +import { withRouter } from 'lib/withRouter'; -export default class ApiConsole extends DashboardView { +@withRouter +class ApiConsole extends DashboardView { constructor() { super(); this.section = 'Core'; @@ -17,8 +20,8 @@ export default class ApiConsole extends DashboardView { } renderSidebar() { - const { path } = this.props.match; - const current = path.substr(path.lastIndexOf('/') + 1, path.length - 1); + const { pathname } = this.props.location; + const current = pathname.substr(pathname.lastIndexOf('/') + 1, pathname.length - 1); return ( ; } } + +export default ApiConsole; diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 23702a7419..9cfecb36ba 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -21,7 +21,6 @@ import AttachSelectedRowsDialog from 'dashboard/Data/Browser/AttachSel import CloneSelectedRowsDialog from 'dashboard/Data/Browser/CloneSelectedRowsDialog.react'; import EditRowDialog from 'dashboard/Data/Browser/EditRowDialog.react'; import ExportSelectedRowsDialog from 'dashboard/Data/Browser/ExportSelectedRowsDialog.react'; -import history from 'dashboard/history'; import { List, Map } from 'immutable'; import Notification from 'dashboard/Data/Browser/Notification.react'; import Parse from 'parse'; @@ -37,12 +36,13 @@ import subscribeTo from 'lib/subscribeTo'; import * as ColumnPreferences from 'lib/ColumnPreferences'; import { Helmet } from 'react-helmet'; import generatePath from 'lib/generatePath'; +import { withRouter } from 'lib/withRouter'; // The initial and max amount of rows fetched by lazy loading const MAX_ROWS_FETCHED = 200; -export default @subscribeTo('Schema', 'schema') +@withRouter class Browser extends DashboardView { constructor() { super(); @@ -147,6 +147,7 @@ class Browser extends DashboardView { this.saveEditCloneRow = this.saveEditCloneRow.bind(this); this.abortEditCloneRow = this.abortEditCloneRow.bind(this); this.cancelPendingEditRows = this.cancelPendingEditRows.bind(this); + this.redirectToFirstClass = this.redirectToFirstClass.bind(this); this.dataBrowserRef = React.createRef(); window.addEventListener('popstate', () => { @@ -246,7 +247,7 @@ class Browser extends DashboardView { } return a.toUpperCase() < b.toUpperCase() ? -1 : 1; }); - history.replace(generatePath(context || this.context, 'browser/' + classes[0])); + this.props.navigate(generatePath(context || this.context, 'browser/' + classes[0]), { replace: true }); } } @@ -299,7 +300,7 @@ class Browser extends DashboardView { createClass(className) { this.props.schema.dispatch(ActionTypes.CREATE_CLASS, { className }).then(() => { this.state.counts[className] = 0; - history.push(generatePath(this.context, 'browser/' + className)); + this.props.navigate(generatePath(this.context, 'browser/' + className)); }).finally(() => { this.setState({ showCreateClassDialog: false }); }); @@ -309,7 +310,7 @@ class Browser extends DashboardView { this.props.schema.dispatch(ActionTypes.DROP_CLASS, { className }).then(() => { this.setState({showDropClassDialog: false }); delete this.state.counts[className]; - history.push(generatePath(this.context, 'browser')); + this.props.navigate(generatePath(this.context, 'browser')); }, (error) => { let msg = typeof error === 'string' ? error : error.message; if (msg) { @@ -802,7 +803,7 @@ class Browser extends DashboardView { const _filters = JSON.stringify(filters.toJSON()); const url = `browser/${source}${(filters.size === 0 ? '' : `?filters=${(encodeURIComponent(_filters))}`)}`; // filters param change is making the fetch call - history.push(generatePath(this.context, url)); + this.props.navigate(generatePath(this.context, url)); } } @@ -837,7 +838,7 @@ class Browser extends DashboardView { filterQueryString = encodeURIComponent(JSON.stringify(filters.toJSON())); } const url = `${this.getRelationURL()}${filterQueryString ? `?filters=${filterQueryString}` : ''}`; - history.push(url); + this.props.navigate(url); }); this.fetchRelation(relation, filters); } @@ -848,7 +849,7 @@ class Browser extends DashboardView { constraint: 'eq', compareTo: id }]); - history.push(generatePath(this.context, `browser/${className}?filters=${encodeURIComponent(filters)}`)); + this.props.navigate(generatePath(this.context, `browser/${className}?filters=${encodeURIComponent(filters)}`)); } handlePointerCmdClick({ className, id, field = 'objectId' }) { @@ -1784,3 +1785,5 @@ class Browser extends DashboardView { ); } } + +export default Browser; diff --git a/src/dashboard/Data/Browser/CreateClassDialog.react.js b/src/dashboard/Data/Browser/CreateClassDialog.react.js index e54f345157..9c2747bccf 100644 --- a/src/dashboard/Data/Browser/CreateClassDialog.react.js +++ b/src/dashboard/Data/Browser/CreateClassDialog.react.js @@ -13,13 +13,14 @@ import Option from 'components/Dropdown/Option.react'; import React from 'react'; import { SpecialClasses } from 'lib/Constants'; import TextInput from 'components/TextInput/TextInput.react'; -import history from 'dashboard/history'; +import { withRouter } from 'lib/withRouter'; function validClassName(name) { return !!name.match(/^[a-zA-Z][_a-zA-Z0-9]*$/); } -export default class CreateClassDialog extends React.Component { +@withRouter +class CreateClassDialog extends React.Component { constructor() { super(); this.state = { @@ -76,7 +77,7 @@ export default class CreateClassDialog extends React.Component { let type = this.state.type; let className = type === 'Custom' ? this.state.name : type; await this.props.onConfirm(className); - history.push(`/apps/${this.props.currentAppSlug}/browser/${className}`); + this.props.navigate(`/apps/${this.props.currentAppSlug}/browser/${className}`); this.props.onAddColumn(); }} onConfirm={() => { @@ -101,3 +102,5 @@ export default class CreateClassDialog extends React.Component { ); } } + +export default CreateClassDialog; diff --git a/src/dashboard/Data/CloudCode/CloudCode.react.js b/src/dashboard/Data/CloudCode/CloudCode.react.js index e75324db7f..8af0698389 100644 --- a/src/dashboard/Data/CloudCode/CloudCode.react.js +++ b/src/dashboard/Data/CloudCode/CloudCode.react.js @@ -9,17 +9,18 @@ import CodeSnippet from 'components/CodeSnippet/CodeSnippet.react'; import DashboardView from 'dashboard/DashboardView.react'; import EmptyState from 'components/EmptyState/EmptyState.react'; import FileTree from 'components/FileTree/FileTree.react'; -import history from 'dashboard/history'; import React from 'react'; import styles from 'dashboard/Data/CloudCode/CloudCode.scss'; import Toolbar from 'components/Toolbar/Toolbar.react'; import generatePath from 'lib/generatePath'; +import { withRouter } from 'lib/withRouter'; function getPath(params) { return params.splat; } -export default class CloudCode extends DashboardView { +@withRouter +class CloudCode extends DashboardView { constructor() { super(); this.section = 'Core'; @@ -53,7 +54,7 @@ export default class CloudCode extends DashboardView { if (!fileName || release.files[fileName] === undefined) { // Means we're still in /cloud_code/. Let's redirect to /cloud_code/main.js - history.replace(generatePath(this.context, 'cloud_code/main.js')) + this.props.navigate(generatePath(this.context, 'cloud_code/main.js'), { replace: true }); } else { // Means we can load /cloud_code/ app.getSource(fileName).then( @@ -129,3 +130,5 @@ export default class CloudCode extends DashboardView { ); } } + +export default CloudCode; diff --git a/src/dashboard/Data/Jobs/JobEdit.react.js b/src/dashboard/Data/Jobs/JobEdit.react.js index 1c7008156c..6e1111ffe4 100644 --- a/src/dashboard/Data/Jobs/JobEdit.react.js +++ b/src/dashboard/Data/Jobs/JobEdit.react.js @@ -6,14 +6,15 @@ * the root directory of this source tree. */ import { ActionTypes } from 'lib/stores/JobsStore'; -import history from 'dashboard/history'; import JobsForm from 'dashboard/Data/Jobs/JobsForm.react'; import React from 'react'; import subscribeTo from 'lib/subscribeTo'; import generatePath from 'lib/generatePath'; import { CurrentApp } from 'context/currentApp'; +import { withRouter } from 'lib/withRouter'; @subscribeTo('Jobs', 'jobs') +@withRouter class JobEdit extends React.Component { static contextType = CurrentApp; @@ -51,7 +52,7 @@ class JobEdit extends React.Component { let promise = this.props.params.jobId ? this.props.jobs.dispatch(ActionTypes.EDIT, { jobId: this.props.params.jobId, updates: schedule }) : this.props.jobs.dispatch(ActionTypes.CREATE, { schedule }); - promise.then(() => {history.push(generatePath(this.context, 'jobs/scheduled'))}); + promise.then(() => {this.props.navigate(generatePath(this.context, 'jobs/scheduled'))}); return promise; } diff --git a/src/dashboard/Data/Jobs/Jobs.react.js b/src/dashboard/Data/Jobs/Jobs.react.js index 5d1521f9fd..d163847db8 100644 --- a/src/dashboard/Data/Jobs/Jobs.react.js +++ b/src/dashboard/Data/Jobs/Jobs.react.js @@ -10,7 +10,6 @@ import Button from 'components/Button/Button.react'; import * as DateUtils from 'lib/DateUtils'; import CategoryList from 'components/CategoryList/CategoryList.react'; import EmptyState from 'components/EmptyState/EmptyState.react'; -import history from 'dashboard/history'; import Icon from 'components/Icon/Icon.react'; import JobScheduleReminder from 'dashboard/Data/Jobs/JobScheduleReminder.react'; import Modal from 'components/Modal/Modal.react'; @@ -26,6 +25,7 @@ import TableHeader from 'components/Table/TableHeader.react'; import TableView from 'dashboard/TableView.react'; import Toolbar from 'components/Toolbar/Toolbar.react'; import generatePath from 'lib/generatePath'; +import { withRouter } from 'lib/withRouter'; let subsections = { all: 'All Jobs', @@ -61,8 +61,8 @@ function scheduleString(data) { } // TODO: create scrollable view component that handles lazy fetch container on scroll -export default @subscribeTo('Jobs', 'jobs') +@withRouter class Jobs extends TableView { constructor() { super(); @@ -92,11 +92,11 @@ class Jobs extends TableView { } navigateToNew() { - history.push(generatePath(this.context, 'jobs/new')); + this.props.navigate(generatePath(this.context, 'jobs/new')); } navigateToJob(jobId) { - history.push(generatePath(this.context, `jobs/edit/${jobId}`)) + this.props.navigate(generatePath(this.context, `jobs/edit/${jobId}`)) } loadData() { @@ -300,3 +300,5 @@ class Jobs extends TableView { return null; } } + +export default Jobs; diff --git a/src/dashboard/Data/Jobs/JobsData.react.js b/src/dashboard/Data/Jobs/JobsData.react.js index 574ba5453c..441dd7c25b 100644 --- a/src/dashboard/Data/Jobs/JobsData.react.js +++ b/src/dashboard/Data/Jobs/JobsData.react.js @@ -7,6 +7,7 @@ */ import React from 'react'; import { CurrentApp } from 'context/currentApp'; +import { Outlet } from 'react-router-dom'; export default class JobsData extends React.Component { static contextType = CurrentApp; @@ -58,15 +59,14 @@ export default class JobsData extends React.Component { } render() { - let child = React.Children.only(this.props.children); - return React.cloneElement( - child, - { - ...child.props, - availableJobs: this.state.jobs, - jobsInUse: this.state.inUse, - release: this.state.release - } + return ( + ); } } diff --git a/src/dashboard/Data/Logs/Logs.react.js b/src/dashboard/Data/Logs/Logs.react.js index 2e2a5c5027..27ce8eb8f6 100644 --- a/src/dashboard/Data/Logs/Logs.react.js +++ b/src/dashboard/Data/Logs/Logs.react.js @@ -15,13 +15,15 @@ import ReleaseInfo from 'components/ReleaseInfo/ReleaseInfo'; import Toolbar from 'components/Toolbar/Toolbar.react'; import styles from 'dashboard/Data/Logs/Logs.scss'; +import { withRouter } from 'lib/withRouter'; let subsections = { info: 'Info', error: 'Error' }; -export default class Logs extends DashboardView { +@withRouter +class Logs extends DashboardView { constructor() { super(); this.section = 'Core'; @@ -120,3 +122,5 @@ export default class Logs extends DashboardView { ); } } + +export default Logs; diff --git a/src/dashboard/Push/PushAudiencesIndex.react.js b/src/dashboard/Push/PushAudiencesIndex.react.js index 9168f0ea69..1120719f29 100644 --- a/src/dashboard/Push/PushAudiencesIndex.react.js +++ b/src/dashboard/Push/PushAudiencesIndex.react.js @@ -12,7 +12,6 @@ import Button from 'components/Button/Button.react'; import DashboardView from 'dashboard/DashboardView.react'; import EmptyState from 'components/EmptyState/EmptyState.react'; import FormModal from 'components/FormModal/FormModal.react'; -import history from 'dashboard/history'; import LoaderContainer from 'components/LoaderContainer/LoaderContainer.react'; import Modal from 'components/Modal/Modal.react'; import PushAudienceDialog from 'components/PushAudienceDialog/PushAudienceDialog.react'; @@ -27,12 +26,13 @@ import Toolbar from 'components/Toolbar/Toolbar.react'; import { formatAudienceSchema } from 'lib/PushUtils'; import { List } from 'immutable'; import generatePath from 'lib/generatePath'; +import { withRouter } from 'lib/withRouter'; const XHR_KEY = 'PushAudiencesIndex'; -export default @subscribeTo('Schema', 'schema') @subscribeTo('PushAudiences', 'pushaudiences') +@withRouter class PushAudiencesIndex extends DashboardView { constructor() { super(); @@ -111,7 +111,7 @@ class PushAudiencesIndex extends DashboardView { } handleSendPush(objectId) { - history.push(generatePath(this.context, `push/new?audienceId=${objectId}`)); + this.props.navigate(generatePath(this.context, `push/new?audienceId=${objectId}`)); } renderRow(audience) { @@ -276,3 +276,5 @@ class PushAudiencesIndex extends DashboardView { ); } } + +export default PushAudiencesIndex; diff --git a/src/dashboard/Push/PushDetails.react.js b/src/dashboard/Push/PushDetails.react.js index cc022301b7..3ab30046bc 100644 --- a/src/dashboard/Push/PushDetails.react.js +++ b/src/dashboard/Push/PushDetails.react.js @@ -15,7 +15,6 @@ import Field from 'components/Field/Field.react'; import Fieldset from 'components/Fieldset/Fieldset.react'; import FieldStyles from 'components/Field/Field.scss'; import FlowView from 'components/FlowView/FlowView.react'; -import history from 'dashboard/history'; import Label from 'components/Label/Label.react'; import LoaderContainer from 'components/LoaderContainer/LoaderContainer.react'; import Parse from 'parse'; @@ -33,6 +32,7 @@ import { Directions } from 'lib/Constants'; import { Link } from 'react-router-dom'; import { tableInfoBuilder } from 'lib/PushUtils'; import generatePath from 'lib/generatePath'; +import { withRouter } from 'lib/withRouter'; const EXP_STATS_URL = 'http://docs.parseplatform.org/ios/guide/#push-experiments'; @@ -200,8 +200,8 @@ const COLOR_MAP = { const DROPDOWN_KEY_GROUP_A = 'Group A'; const DROPDOWN_KEY_GROUP_B = 'Group B'; -export default @subscribeTo('Schema', 'schema') +@withRouter class PushDetails extends DashboardView { constructor() { super(); @@ -472,7 +472,7 @@ class PushDetails extends DashboardView { prevLaunchGroup = (
- This push is the Launch Group for a previous experiment. + This push is the Launch Group for a previous experiment.
); @@ -586,7 +586,7 @@ class PushDetails extends DashboardView { if (error) { promise.reject({ error }); } else { - history.push(generatePath(this.context, 'push/activity')); + this.props.navigate(generatePath(this.context, 'push/activity')); } }, (error) => { promise.reject({ error }); @@ -744,3 +744,5 @@ class PushDetails extends DashboardView { ); } } + +export default PushDetails; diff --git a/src/dashboard/Push/PushIndex.react.js b/src/dashboard/Push/PushIndex.react.js index 5e025fb0b6..79f39d55ff 100644 --- a/src/dashboard/Push/PushIndex.react.js +++ b/src/dashboard/Push/PushIndex.react.js @@ -11,7 +11,6 @@ import Button from 'components/Button/Button.react'; import CategoryList from 'components/CategoryList/CategoryList.react'; import DashboardView from 'dashboard/DashboardView.react'; import EmptyState from 'components/EmptyState/EmptyState.react'; -import history from 'dashboard/history'; import LoaderContainer from 'components/LoaderContainer/LoaderContainer.react'; import LoaderDots from 'components/LoaderDots/LoaderDots.react'; import React from 'react'; @@ -22,6 +21,7 @@ import stylesTable from 'dashboard/TableView.scss'; import TableHeader from 'components/Table/TableHeader.react'; import Toolbar from 'components/Toolbar/Toolbar.react'; import generatePath from 'lib/generatePath'; +import { withRouter } from 'lib/withRouter'; const PUSH_TYPE_ALL = 'all'; const PUSH_TYPE_CAMPAIGN = 'campaign'; @@ -227,7 +227,8 @@ let getPushTime = (pushTime, updatedAt) => { return result; } -export default class PushIndex extends DashboardView { +@withRouter +class PushIndex extends DashboardView { constructor() { super(); this.section = 'Push'; @@ -294,11 +295,11 @@ export default class PushIndex extends DashboardView { } navigateToNew() { - history.push(generatePath(this.context, 'push/new')); + this.props.navigate(generatePath(this.context, 'push/new')); } navigateToDetails(objectId) { - history.push(generatePath(this.context, `push/${objectId}`)); + this.props.navigate(generatePath(this.context, `push/${objectId}`)); } handleShowMore(page) { @@ -447,3 +448,5 @@ export default class PushIndex extends DashboardView { ); } } + +export default PushIndex; diff --git a/src/dashboard/Push/PushNew.react.js b/src/dashboard/Push/PushNew.react.js index 3c964a161c..48b056f5dd 100644 --- a/src/dashboard/Push/PushNew.react.js +++ b/src/dashboard/Push/PushNew.react.js @@ -17,7 +17,6 @@ import Field from 'components/Field/Field.react'; import Fieldset from 'components/Fieldset/Fieldset.react'; import FieldStyles from 'components/Field/Field.scss'; import FlowView from 'components/FlowView/FlowView.react'; -import history from 'dashboard/history'; import joinWithFinal from 'lib/joinWithFinal'; import Label from 'components/Label/Label.react'; import Option from 'components/Dropdown/Option.react'; @@ -37,6 +36,7 @@ import Toolbar from 'components/Toolbar/Toolbar.react'; import { Directions } from 'lib/Constants'; import { extractExpiration, extractPushTime } from 'lib/extractTime'; import generatePath from 'lib/generatePath'; +import { withRouter } from 'lib/withRouter'; const PARSE_SERVER_SUPPORTS_AB_TESTING = false; @@ -121,9 +121,9 @@ let LocalizedMessageField = ({ const XHR_KEY = 'PushNew'; -export default @subscribeTo('Schema', 'schema') @subscribeTo('PushAudiences', 'pushaudiences') +@withRouter class PushNew extends DashboardView { constructor() { super(); @@ -230,7 +230,7 @@ class PushNew extends DashboardView { //TODO: global success message banner for passing successful creation - store should also be cleared const PARSE_SERVER_SUPPORTS_PUSH_INDEX = false; if (PARSE_SERVER_SUPPORTS_PUSH_INDEX) { - history.push(generatePath(this.context, 'push/activity')); + this.props.navigate(generatePath(this.context, 'push/activity')); } else { return; } @@ -895,3 +895,5 @@ class PushNew extends DashboardView { }}/>; } } + +export default PushNew; diff --git a/src/dashboard/Settings/GeneralSettings.react.js b/src/dashboard/Settings/GeneralSettings.react.js index 8cff83780a..9a9981ab54 100644 --- a/src/dashboard/Settings/GeneralSettings.react.js +++ b/src/dashboard/Settings/GeneralSettings.react.js @@ -18,7 +18,6 @@ import FormButton from 'components/FormButton/FormButton. import FormModal from 'components/FormModal/FormModal.react'; import FormNote from 'components/FormNote/FormNote.react'; import getSiteDomain from 'lib/getSiteDomain'; -import history from 'dashboard/history'; import joinWithFinal from 'lib/joinWithFinal'; import KeyField from 'components/KeyField/KeyField.react'; import Label from 'components/Label/Label.react'; @@ -37,7 +36,8 @@ import Toolbar from 'components/Toolbar/Toolbar.react' import unique from 'lib/unique'; import validateAndSubmitConnectionString from 'lib/validateAndSubmitConnectionString'; import styles from 'dashboard/Settings/GeneralSettings.scss'; -import { Link } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; +import { withRouter } from 'lib/withRouter'; const DEFAULT_SETTINGS_LABEL_WIDTH = 62; @@ -204,6 +204,7 @@ let ManageAppFields = ({ transferAppMessage, deleteApp, }) => { + const navigate = useNavigate(); let migrateAppField = null; if (!mongoURL && !hasInProgressMigration) { migrateAppField = } input={ history.push(`/apps/${appSlug}/migration`)} + onClick={() => navigate(`/apps/${appSlug}/migration`)} value='View progress' />} /> } else { migrateAppField = [ -
{cloneAppMessage} Check out the progress on your apps page!
+
{cloneAppMessage} Check out the progress on your apps page!
: null} {!isCollaborator ? ); } -export default class GeneralSettings extends DashboardView { +@withRouter +class GeneralSettings extends DashboardView { constructor() { super(); this.section = 'App Settings'; @@ -424,7 +426,7 @@ export default class GeneralSettings extends DashboardView { return promise; }} onClose={closeModalWithConnectionString} - onSuccess={() => history.push(`/apps/${this.context.slug}/migration`)} + onSuccess={() => this.props.navigate(`/apps/${this.context.slug}/migration`)} clearFields={() => this.setState({ migrationMongoURL: '', migrationWarnings: [], @@ -535,7 +537,7 @@ export default class GeneralSettings extends DashboardView { inProgressText={'Deleting\u2026'} enabled={this.state.password.length > 0} onSubmit={() => AppsManager.deleteApp(this.context.slug, this.state.password)} - onSuccess={() => history.push('/apps')} + onSuccess={() => this.props.navigate('/apps')} onClose={() => this.setState({showDeleteAppModal: false})} clearFields={() => this.setState({password: ''})}> {passwordField} @@ -797,3 +799,5 @@ let generalFieldsOptions = { friendlyName: 'other URL', }, }; + +export default GeneralSettings; diff --git a/src/dashboard/Settings/SettingsData.react.js b/src/dashboard/Settings/SettingsData.react.js index 4b2a37e931..161ea0614b 100644 --- a/src/dashboard/Settings/SettingsData.react.js +++ b/src/dashboard/Settings/SettingsData.react.js @@ -7,6 +7,7 @@ */ import React from 'react'; import { CurrentApp } from 'context/currentApp'; +import { Outlet } from 'react-router-dom'; export default class SettingsData extends React.Component { static contextType = CurrentApp; @@ -43,14 +44,13 @@ export default class SettingsData extends React.Component { } render() { - let child = React.Children.only(this.props.children); - return React.cloneElement( - child, - { - ...child.props, - initialFields: this.state.fields, - saveChanges: this.saveChanges.bind(this) - } + return ( + ); } } diff --git a/src/dashboard/history.js b/src/dashboard/history.js deleted file mode 100644 index 35dd81d965..0000000000 --- a/src/dashboard/history.js +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2016-present, Parse, LLC - * All rights reserved. - * - * This source code is licensed under the license found in the LICENSE file in - * the root directory of this source tree. - */ - -import { createBrowserHistory } from 'history'; - -const path = window.PARSE_DASHBOARD_PATH || '/'; -export default createBrowserHistory({ basename: path }); diff --git a/src/lib/withRouter.js b/src/lib/withRouter.js new file mode 100644 index 0000000000..707c1a6e6e --- /dev/null +++ b/src/lib/withRouter.js @@ -0,0 +1,18 @@ +import React from 'react'; +import { useParams, useNavigate, useOutletContext, useLocation } from 'react-router-dom'; + +export function withRouter(Component) { + function render(props) { + const params = useParams(); + const navigate = useNavigate(); + const outletContext = useOutletContext(); + const location = useLocation(); + + return ; + } + + const name = Component.displayName || Component.name; + render.displayName = `withRouter(${name})`; + + return render; +} diff --git a/src/parse-interface-guide/PIG.react.js b/src/parse-interface-guide/PIG.react.js index 15a009dc8a..800ef521b1 100644 --- a/src/parse-interface-guide/PIG.react.js +++ b/src/parse-interface-guide/PIG.react.js @@ -6,20 +6,22 @@ * the root directory of this source tree. */ import * as ComponentsMap from 'parse-interface-guide/ComponentsMap'; -import { Link } from 'react-router-dom'; +import { NavLink } from 'react-router-dom'; import Icon from 'components/Icon/Icon.react'; import PropsTable from 'parse-interface-guide/PropsTable.react'; import React from 'react'; import styles from 'parse-interface-guide/PIG.scss'; import beautify from 'js-beautify'; import CodeSnippet from 'components/CodeSnippet/CodeSnippet.react'; +import { withRouter } from 'lib/withRouter'; let PIGRow = ({ title, children }) =>
{title}
{children}
; -export default class PIG extends React.Component { +@withRouter +class PIG extends React.Component { constructor() { super(); @@ -46,7 +48,7 @@ export default class PIG extends React.Component { }}/> {components.map((name) => { return name.toLowerCase().indexOf(this.state.query.toLowerCase()) !== -1 - ? {name} + ? isActive ? styles.active : undefined} key={name} to={`/${name}`}>{name} : null; })}
@@ -54,7 +56,7 @@ export default class PIG extends React.Component { } renderContent() { - let componentInfo = ComponentsMap[this.props.params.component]; + let componentInfo = ComponentsMap[this.props.params['*']]; if (!componentInfo) { componentInfo = ComponentsMap[Object.keys(ComponentsMap)[0]]; } @@ -89,3 +91,5 @@ export default class PIG extends React.Component { ); } } + +export default PIG; diff --git a/src/parse-interface-guide/routes.js b/src/parse-interface-guide/routes.js index c270bb8f64..d6cc233d0a 100644 --- a/src/parse-interface-guide/routes.js +++ b/src/parse-interface-guide/routes.js @@ -7,18 +7,14 @@ */ import PIG from 'parse-interface-guide/PIG.react'; import React from 'react'; -import { Router, Route } from 'react-router'; -import { createBrowserHistory } from 'history'; -const history = createBrowserHistory({}); +import { BrowserRouter, Routes, Route } from 'react-router-dom'; const routes = ( - -
- { - return - }} /> -
-
+ + + } /> + + ); export default routes