From 7daef4ceaee027594b4078bc4f0208c3bf9a32b4 Mon Sep 17 00:00:00 2001 From: En Rong <53928333+chownces@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:31:37 +0800 Subject: [PATCH 01/12] Upgrade React and corresponding types to latest version --- package.json | 12 ++++-------- yarn.lock | 48 +++++++++++++++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 8c499c1df9..277f04f1c8 100644 --- a/package.json +++ b/package.json @@ -56,10 +56,10 @@ "phaser": "^3.55.2", "query-string": "^7.1.1", "re-resizable": "^6.9.9", - "react": "^17.0.2", + "react": "^18.2.0", "react-ace": "^10.1.0", "react-copy-to-clipboard": "^5.1.0", - "react-dom": "^17.0.2", + "react-dom": "^18.2.0", "react-draggable": "^4.4.5", "react-dropzone": "^14.2.3", "react-hotkeys": "^2.0.0", @@ -100,9 +100,9 @@ "@types/jest": "^28.1.6", "@types/lodash": "^4.14.195", "@types/lz-string": "^1.3.34", - "@types/react": "^17.0.38", + "@types/react": "^18.2.13", "@types/react-copy-to-clipboard": "^5.0.4", - "@types/react-dom": "^17.0.20", + "@types/react-dom": "^18.2.6", "@types/react-redux": "^7.1.24", "@types/react-responsive": "^8.0.5", "@types/react-router": "^5.1.20", @@ -141,10 +141,6 @@ "url": "^0.11.0", "webpack-bundle-analyzer": "^4.9.0" }, - "resolutions": { - "//": "React 18's types are much stricter and upgrading to it (even if indirectly via a dependency) results in many type errors. FIXME: Remove this after upgrading fully to React 18 and fixing all of the type errors.", - "@types/react": "^17.0.38" - }, "browserslist": { "production": [ "Firefox ESR", diff --git a/yarn.lock b/yarn.lock index 0ec549442f..be5f552400 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2840,12 +2840,12 @@ dependencies: "@types/react" "*" -"@types/react-dom@^17.0.20": - version "17.0.20" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.20.tgz#e0c8901469d732b36d8473b40b679ad899da1b53" - integrity sha512-4pzIjSxDueZZ90F52mU3aPoogkHIoSIDG+oQ+wQK7Cy2B9S+MvOqY0uEA/qawKz381qrEDkvpwyt8Bm31I8sbA== +"@types/react-dom@^18.2.6": + version "18.2.6" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.6.tgz#ad621fa71a8db29af7c31b41b2ea3d8a6f4144d1" + integrity sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A== dependencies: - "@types/react" "^17" + "@types/react" "*" "@types/react-reconciler@~0.26.2": version "0.26.7" @@ -2909,7 +2909,7 @@ dependencies: react-textarea-autosize "*" -"@types/react@*", "@types/react@^17", "@types/react@^17.0.38": +"@types/react@*", "@types/react@^17": version "17.0.53" resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.53.tgz#10d4d5999b8af3d6bc6a9369d7eb953da82442ab" integrity sha512-1yIpQR2zdYu1Z/dc1OxC+MA6GR240u3gcnP4l6mvj/PJiVaqHsQPmWttsvHsfnhfPbU2FuGmo0wSITPygjBmsw== @@ -2918,6 +2918,15 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@^18.2.13": + version "18.2.13" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.13.tgz#a98c09bde8b18f80021935b11d2d29ef5f4dcb2f" + integrity sha512-vJ+zElvi/Zn9cVXB5slX2xL8PZodPCwPRDpittQdw43JR2AJ5k3vKdgJJyneV/cYgIbLQUwXa9JVDvUZXGba+Q== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + "@types/redux-mock-store@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@types/redux-mock-store/-/redux-mock-store-1.0.3.tgz#895de4a364bc4836661570aec82f2eef5989d1fb" @@ -10370,14 +10379,13 @@ react-dev-utils@^12.0.1: strip-ansi "^6.0.1" text-table "^0.2.0" -react-dom@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" - integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== +react-dom@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler "^0.20.2" + scheduler "^0.23.0" react-draggable@^4.4.5: version "4.4.5" @@ -10699,13 +10707,12 @@ react-transition-state@^1.1.5: resolved "https://registry.yarnpkg.com/react-transition-state/-/react-transition-state-1.1.5.tgz#22accee21d0011b1d0245be24b6262ae67f494c3" integrity sha512-ITY2mZqc2dWG2eitJkYNdcSFW8aKeOlkL2A/vowRrLL8GH3J6Re/SpD/BLvQzrVOTqjsP0b5S9N10vgNNzwMUQ== -react@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" - integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== +react@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" read-cache@^1.0.0: version "1.0.0" @@ -11167,6 +11174,13 @@ scheduler@^0.20.2: loose-envify "^1.1.0" object-assign "^4.1.1" +scheduler@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== + dependencies: + loose-envify "^1.1.0" + schema-utils@2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" From 3fe9c0c18b11b0479b1ccca5c6cfad17b7c5e995 Mon Sep 17 00:00:00 2001 From: En Rong <53928333+chownces@users.noreply.github.com> Date: Fri, 9 Jun 2023 11:38:50 +0800 Subject: [PATCH 02/12] Deprecate usage of React.SFC --- src/commons/dropdown/DropdownAbout.tsx | 2 +- src/commons/dropdown/DropdownHelp.tsx | 2 +- src/commons/notificationBadge/NotificationBadge.tsx | 2 +- src/pages/notFound/NotFound.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commons/dropdown/DropdownAbout.tsx b/src/commons/dropdown/DropdownAbout.tsx index b38fde67d3..6163db2b04 100644 --- a/src/commons/dropdown/DropdownAbout.tsx +++ b/src/commons/dropdown/DropdownAbout.tsx @@ -9,7 +9,7 @@ type DialogProps = { onClose: () => void; }; -const DropdownAbout: React.SFC = props => ( +const DropdownAbout: React.FC = props => ( void; }; -const DropdownHelp: React.SFC = props => { +const DropdownHelp: React.FC = props => { const moduleHelpText = useTypedSelector(store => store.session.moduleHelpText); return ( diff --git a/src/commons/notificationBadge/NotificationBadge.tsx b/src/commons/notificationBadge/NotificationBadge.tsx index 57770cc538..764ec1c601 100644 --- a/src/commons/notificationBadge/NotificationBadge.tsx +++ b/src/commons/notificationBadge/NotificationBadge.tsx @@ -17,7 +17,7 @@ type OwnProps = { notificationFilter?: (notifications: Notification[]) => Notification[]; }; -const NotificationBadge: React.SFC = props => { +const NotificationBadge: React.FC = props => { const dispatch = useDispatch(); const initialNotifications = useTypedSelector(state => state.session.notifications); diff --git a/src/pages/notFound/NotFound.tsx b/src/pages/notFound/NotFound.tsx index c052f33d64..3ff63750aa 100644 --- a/src/pages/notFound/NotFound.tsx +++ b/src/pages/notFound/NotFound.tsx @@ -3,7 +3,7 @@ import { IconNames } from '@blueprintjs/icons'; import classNames from 'classnames'; import * as React from 'react'; -const NotFound: React.SFC<{}> = () => ( +const NotFound: React.FC = () => (
Date: Fri, 9 Jun 2023 12:00:45 +0800 Subject: [PATCH 03/12] Fix miscellaneous type errors --- src/commons/editor/UseHighlighting.tsx | 8 ++++---- .../githubAssessments/SideContentTestcaseEditor.tsx | 2 +- src/pages/githubAssessments/GitHubAssessmentWorkspace.tsx | 2 +- src/pages/login/Login.tsx | 5 ++++- src/pages/playground/Playground.tsx | 4 ++-- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/commons/editor/UseHighlighting.tsx b/src/commons/editor/UseHighlighting.tsx index e3f0cc3e67..9cc327194d 100644 --- a/src/commons/editor/UseHighlighting.tsx +++ b/src/commons/editor/UseHighlighting.tsx @@ -78,16 +78,16 @@ const useHighlighting: EditorHook = (inProps, outProps, keyBindings, reactAceRef const { onChange: prevOnChange, onCursorChange: prevOnCursorChange } = outProps; outProps.onChange = React.useCallback( - (v, e) => { + (value: string, event?: any) => { handleVariableHighlighting(); - prevOnChange && prevOnChange(v, e); + prevOnChange && prevOnChange(value, event); }, [handleVariableHighlighting, prevOnChange] ); outProps.onCursorChange = React.useCallback( - (v, e) => { + (value: any, event?: any) => { handleVariableHighlighting(); - prevOnCursorChange && prevOnCursorChange(v, e); + prevOnCursorChange && prevOnCursorChange(value, event); }, [handleVariableHighlighting, prevOnCursorChange] ); diff --git a/src/commons/sideContent/githubAssessments/SideContentTestcaseEditor.tsx b/src/commons/sideContent/githubAssessments/SideContentTestcaseEditor.tsx index 0597f8195a..34d3f93c28 100644 --- a/src/commons/sideContent/githubAssessments/SideContentTestcaseEditor.tsx +++ b/src/commons/sideContent/githubAssessments/SideContentTestcaseEditor.tsx @@ -99,7 +99,7 @@ const SideContentTestcaseEditor: React.FunctionComponent< ); const convertToTestcaseCard = React.useCallback( - (testcase, index) => { + (testcase: Testcase, index: number) => { if (allowEdits) { return ( { }, [isMobileBreakpoint, selectedTab]); const onEditorValueChange = useCallback( - val => { + (editorTabIndex: number, val: string) => { // TODO: Hardcoded to make use of the first editor tab. Refactoring is needed for this workspace to enable Folder mode. handleEditorValueChange(0, val); editCode(currentTaskNumber, val); diff --git a/src/pages/login/Login.tsx b/src/pages/login/Login.tsx index aeac327287..4783167dd7 100644 --- a/src/pages/login/Login.tsx +++ b/src/pages/login/Login.tsx @@ -29,7 +29,10 @@ const Login: React.FunctionComponent<{}> = () => { const location = useLocation(); const { code, provider: providerId } = parseQuery(location.search); - const handleLogin = React.useCallback(providerId => dispatch(login(providerId)), [dispatch]); + const handleLogin = React.useCallback( + (providerId: string) => dispatch(login(providerId)), + [dispatch] + ); React.useEffect(() => { if (code) { diff --git a/src/pages/playground/Playground.tsx b/src/pages/playground/Playground.tsx index 2cfa3e983d..4461460bd0 100644 --- a/src/pages/playground/Playground.tsx +++ b/src/pages/playground/Playground.tsx @@ -402,8 +402,8 @@ const Playground: React.FC = props => { [isGreen] ); - const onEditorValueChange = useCallback( - (editorTabIndex, newEditorValue) => { + const onEditorValueChange = React.useCallback( + (editorTabIndex: number, newEditorValue: string) => { setLastEdit(new Date()); handleEditorValueChange(editorTabIndex, newEditorValue); }, From f2bf59c4c082c3c02408ef78669fc6238184aac3 Mon Sep 17 00:00:00 2001 From: En Rong <53928333+chownces@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:37:38 +0800 Subject: [PATCH 04/12] Upgrade react-konva to fix type errors with react18 --- package.json | 4 ++-- yarn.lock | 49 ++++++++++++++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 277f04f1c8..786bf4720c 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "flexboxgrid": "^6.3.1", "flexboxgrid-helpers": "^1.1.3", "js-slang": "^1.0.23", - "konva": "^8.3.14", + "konva": "^9.2.0", "lodash": "^4.17.21", "lz-string": "^1.4.4", "moment": "^2.29.4", @@ -63,7 +63,7 @@ "react-draggable": "^4.4.5", "react-dropzone": "^14.2.3", "react-hotkeys": "^2.0.0", - "react-konva": "^17.0.2-5", + "react-konva": "^18.2.10", "react-latex-next": "^2.1.0", "react-mde": "^11.5.0", "react-papaparse": "^4.0.2", diff --git a/yarn.lock b/yarn.lock index be5f552400..59b0eaa717 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2847,10 +2847,10 @@ dependencies: "@types/react" "*" -"@types/react-reconciler@~0.26.2": - version "0.26.7" - resolved "https://registry.yarnpkg.com/@types/react-reconciler/-/react-reconciler-0.26.7.tgz#0c4643f30821ae057e401b0d9037e03e8e9b2a36" - integrity sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ== +"@types/react-reconciler@^0.28.0", "@types/react-reconciler@^0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@types/react-reconciler/-/react-reconciler-0.28.2.tgz#f16b0e8cc4748af70ca975eaaace0d79582c71fa" + integrity sha512-8tu6lHzEgYPlfDf/J6GOQdIc+gs+S2yAqlby3zTsB3SP2svlqTYe5fwZNtZyfactP74ShooP2vvi1BOp9ZemWw== dependencies: "@types/react" "*" @@ -7518,6 +7518,13 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +its-fine@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/its-fine/-/its-fine-1.1.1.tgz#e74b93fddd487441f978a50f64f0f5af4d2fc38e" + integrity sha512-v1Ia1xl20KbuSGlwoaGsW0oxsw8Be+TrXweidxD9oT/1lAh6O3K3/GIM95Tt6WCiv6W+h2M7RB1TwdoAjQyyKw== + dependencies: + "@types/react-reconciler" "^0.28.0" + jake@^10.8.5: version "10.8.5" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46" @@ -8302,10 +8309,10 @@ klona@^2.0.4, klona@^2.0.5: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== -konva@^8.3.14: - version "8.4.2" - resolved "https://registry.yarnpkg.com/konva/-/konva-8.4.2.tgz#6de2b9d54f2b56b8c7c76eba66955f7255dd9afb" - integrity sha512-4VQcrgj/PI8ydJjtLcTuinHBE8o0WGX0YoRwbiN5mpYQiC52aOzJ0XbpKNDJdRvORQphK5LP+jeM0hQJEYIuUA== +konva@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/konva/-/konva-9.2.0.tgz#3739e539724b0e6b76d697a322efdaa01baa1508" + integrity sha512-+woI76Sk+VFVl9z7zPkuTnN2zFpEYg27YWz8BCdQXpt5IS3pdnSPAPQVPPMidcbDi9/G5b/IOIp35/KqMGiYPA== language-subtag-registry@~0.3.2: version "0.3.22" @@ -10436,14 +10443,15 @@ react-is@^17.0.1, react-is@^17.0.2: resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-konva@^17.0.2-5: - version "17.0.2-6" - resolved "https://registry.yarnpkg.com/react-konva/-/react-konva-17.0.2-6.tgz#80b3fdebfd915878eafe554c191bec282cdda0de" - integrity sha512-cfRsBKxqAQ6gTBmyrKptKRWhHD+C068dvyqcZ4h8qzKbAacTXQtfLMSpOI+d+ptxSMvayIbbCdbsBmk3bWiClQ== +react-konva@^18.2.10: + version "18.2.10" + resolved "https://registry.yarnpkg.com/react-konva/-/react-konva-18.2.10.tgz#5b5edc5e9ed452755d21babc353747828868decc" + integrity sha512-ohcX1BJINL43m4ynjZ24MxFI1syjBdrXhqVxYVDw2rKgr3yuS0x/6m1Y2Z4sl4T/gKhfreBx8KHisd0XC6OT1g== dependencies: - "@types/react-reconciler" "~0.26.2" - react-reconciler "~0.26.2" - scheduler "^0.20.2" + "@types/react-reconciler" "^0.28.2" + its-fine "^1.1.1" + react-reconciler "~0.29.0" + scheduler "^0.23.0" react-latex-next@^2.1.0: version "2.2.0" @@ -10500,14 +10508,13 @@ react-qr-reader@^3.0.0-beta-1: "@zxing/library" "^0.18.3" rollup "^2.67.2" -react-reconciler@~0.26.2: - version "0.26.2" - resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.26.2.tgz#bbad0e2d1309423f76cf3c3309ac6c96e05e9d91" - integrity sha512-nK6kgY28HwrMNwDnMui3dvm3rCFjZrcGiuwLc5COUipBK5hWHLOxMJhSnSomirqWwjPBJKV1QcbkI0VJr7Gl1Q== +react-reconciler@~0.29.0: + version "0.29.0" + resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.29.0.tgz#ee769bd362915076753f3845822f2d1046603de7" + integrity sha512-wa0fGj7Zht1EYMRhKWwoo1H9GApxYLBuhoAuXN0TlltESAjDssB+Apf0T/DngVqaMyPypDmabL37vw/2aRM98Q== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler "^0.20.2" + scheduler "^0.23.0" react-redux@^8.0.7: version "8.0.7" From 3245f6ce5a299976ddb5c002870601e11bc1eda4 Mon Sep 17 00:00:00 2001 From: En Rong <53928333+chownces@users.noreply.github.com> Date: Fri, 9 Jun 2023 14:34:13 +0800 Subject: [PATCH 05/12] Fix typings for react-sortable-hoc --- src/commons/utils/SortableList.tsx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/commons/utils/SortableList.tsx b/src/commons/utils/SortableList.tsx index c134a83249..4f0b06819d 100644 --- a/src/commons/utils/SortableList.tsx +++ b/src/commons/utils/SortableList.tsx @@ -1,18 +1,31 @@ import { Button } from '@blueprintjs/core'; import { arrayMoveImmutable } from 'array-move'; import React from 'react'; -import { SortableContainer, SortableElement } from 'react-sortable-hoc'; +import { + SortableContainer, + SortableContainerProps, + SortableElement, + SortableElementProps +} from 'react-sortable-hoc'; + +type SortableItemProps = SortableElementProps & { + value: any; +}; const SortableItem = React.memo( - SortableElement(({ value }: any) => ( + SortableElement(({ value }: any) => (
)) ); +type SortableListProps = SortableContainerProps & { + items: string[]; +}; + export const SortableList = React.memo( - SortableContainer(({ items }: any) => { + SortableContainer(({ items }: any) => { return (
{items && From c2e29587d09814e7a03d1b13bfa12915465b9635 Mon Sep 17 00:00:00 2001 From: En Rong <53928333+chownces@users.noreply.github.com> Date: Fri, 9 Jun 2023 15:56:24 +0800 Subject: [PATCH 06/12] Shift root render to new API --- src/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 4262c2b621..b6e8898952 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,7 +2,7 @@ import 'src/styles/index.scss'; import * as Sentry from '@sentry/browser'; import { setModulesStaticURL } from 'js-slang/dist/modules/moduleLoader'; -import { render } from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { Provider } from 'react-redux'; import Constants, { Links } from 'src/commons/utils/Constants'; import { showWarningMessage } from 'src/commons/utils/NotificationsHelper'; @@ -24,6 +24,7 @@ if (Constants.sentryDsn) { } const rootContainer = document.getElementById('root') as HTMLElement; +const root = createRoot(rootContainer); (window as any).__REDUX_STORE__ = store; // need this for slang's display console.log( `%cSource Academy ${Constants.sourceAcademyEnvironment}-${Constants.sourceAcademyVersion}; ` + @@ -38,11 +39,10 @@ console.log(`Using module backend: ${Constants.moduleBackendUrl}`); createInBrowserFileSystem(store) .catch(err => console.error(err)) .finally(() => { - render( + root.render( - , - rootContainer + ); }); From 7bd88feb3a1da9a4551472873d284278de7ebaeb Mon Sep 17 00:00:00 2001 From: En Rong <53928333+chownces@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:55:03 +0800 Subject: [PATCH 07/12] Fix @types/react versioning --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 59b0eaa717..9905374a0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2909,19 +2909,19 @@ dependencies: react-textarea-autosize "*" -"@types/react@*", "@types/react@^17": - version "17.0.53" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.53.tgz#10d4d5999b8af3d6bc6a9369d7eb953da82442ab" - integrity sha512-1yIpQR2zdYu1Z/dc1OxC+MA6GR240u3gcnP4l6mvj/PJiVaqHsQPmWttsvHsfnhfPbU2FuGmo0wSITPygjBmsw== +"@types/react@*", "@types/react@^18.2.13": + version "18.2.13" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.13.tgz#a98c09bde8b18f80021935b11d2d29ef5f4dcb2f" + integrity sha512-vJ+zElvi/Zn9cVXB5slX2xL8PZodPCwPRDpittQdw43JR2AJ5k3vKdgJJyneV/cYgIbLQUwXa9JVDvUZXGba+Q== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" csstype "^3.0.2" -"@types/react@^18.2.13": - version "18.2.13" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.13.tgz#a98c09bde8b18f80021935b11d2d29ef5f4dcb2f" - integrity sha512-vJ+zElvi/Zn9cVXB5slX2xL8PZodPCwPRDpittQdw43JR2AJ5k3vKdgJJyneV/cYgIbLQUwXa9JVDvUZXGba+Q== +"@types/react@^17": + version "17.0.62" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.62.tgz#2efe8ddf8533500ec44b1334dd1a97caa2f860e3" + integrity sha512-eANCyz9DG8p/Vdhr0ZKST8JV12PhH2ACCDYlFw6DIO+D+ca+uP4jtEDEpVqXZrh/uZdXQGwk7whJa3ah5DtyLw== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" From 01273309a7cfa11cf028299b2dd4d7ff01bf2c6b Mon Sep 17 00:00:00 2001 From: En Rong <53928333+chownces@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:58:21 +0800 Subject: [PATCH 08/12] Fix navigation bar typing --- src/commons/navigationBar/NavigationBar.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commons/navigationBar/NavigationBar.tsx b/src/commons/navigationBar/NavigationBar.tsx index 8cbe58cc93..31457d87ea 100644 --- a/src/commons/navigationBar/NavigationBar.tsx +++ b/src/commons/navigationBar/NavigationBar.tsx @@ -40,7 +40,7 @@ export type NavbarEntryInfo = { hiddenInBreakpoints?: ('xs' | 'sm' | 'md' | 'lg')[]; // hide text in Blueprint breakpoints }; -type CreateNavlinkFunction = (navbarEntry: NavbarEntryInfo) => React.ReactFragment; +type CreateNavlinkFunction = (navbarEntry: NavbarEntryInfo) => React.ReactElement; const NavigationBar: React.FC = () => { const [mobileSideMenuOpen, setMobileSideMenuOpen] = useState(false); @@ -96,7 +96,7 @@ const NavigationBar: React.FC = () => { [setMobileSideMenuOpen] ); - const wrapWithMobileHamburger = (navlinks: (React.ReactFragment | null)[]) => { + const wrapWithMobileHamburger = (navlinks: (React.ReactElement | null)[]) => { // Don't render drawer when there are 0 navlinks in it const nonNullNavlinks = navlinks.filter(e => e !== null); const renderDrawer = nonNullNavlinks.length > 0; @@ -352,7 +352,7 @@ const playgroundOnlyNavbarLeftInfo: NavbarEntryInfo[] = [ export const renderNavlinksFromInfo = ( navbarEntries: NavbarEntryInfo[], createNavlink: CreateNavlinkFunction -): (React.ReactFragment | null)[] => +): (React.ReactElement | null)[] => navbarEntries.map(entry => { if (entry.disabled) { return null; From 7bc5c84d7850eca1bf9a34e11d3c53bbf2467c1b Mon Sep 17 00:00:00 2001 From: En Rong <53928333+chownces@users.noreply.github.com> Date: Fri, 9 Jun 2023 15:32:06 +0800 Subject: [PATCH 09/12] Fix useEffect return type --- src/commons/ContentDisplay.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/commons/ContentDisplay.tsx b/src/commons/ContentDisplay.tsx index fbdee7be0d..30f77584f7 100644 --- a/src/commons/ContentDisplay.tsx +++ b/src/commons/ContentDisplay.tsx @@ -8,8 +8,10 @@ export type ContentDisplayProps = { }; const ContentDisplay: React.FC = props => { - // eslint-disable-next-line react-hooks/exhaustive-deps - useEffect(() => props.loadContentDispatch?.(), []); + useEffect(() => { + props.loadContentDispatch?.(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); return (
From 78657deeb8659f2b8774f35e0f26fd4bed41b529 Mon Sep 17 00:00:00 2001 From: En Rong <53928333+chownces@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:04:46 +0800 Subject: [PATCH 10/12] Upgrade @testing-library/react and react-test-renderer to match react v18 and fix tests --- package.json | 8 +-- .../__snapshots__/Assessment.tsx.snap | 4 +- .../__tests__/FileExplorerDialog.tsx | 7 +- .../__tests__/SideContentEnvVisualizer.tsx | 6 +- .../__snapshots__/Playground.tsx.snap | 2 - yarn.lock | 71 +++++++------------ 6 files changed, 39 insertions(+), 59 deletions(-) diff --git a/package.json b/package.json index 786bf4720c..0fa9db28c1 100644 --- a/package.json +++ b/package.json @@ -89,8 +89,8 @@ "@craco/craco": "^7.1.0", "@svgr/webpack": "^6.3.1", "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "12.1.2", - "@testing-library/user-event": "^14.3.0", + "@testing-library/react": "^14.0.0", + "@testing-library/user-event": "^14.4.3", "@types/acorn": "^6.0.0", "@types/gapi": "^0.0.44", "@types/gapi.auth2": "^0.0.57", @@ -108,7 +108,7 @@ "@types/react-router": "^5.1.20", "@types/react-router-dom": "^5.3.3", "@types/react-syntax-highlighter": "^15.5.7", - "@types/react-test-renderer": "^17.0.2", + "@types/react-test-renderer": "^18.0.0", "@types/react-textarea-autosize": "^8.0.0", "@types/redux-mock-store": "^1.0.3", "@types/showdown": "^2.0.1", @@ -130,7 +130,7 @@ "process": "^0.11.10", "react-error-overlay": "^6.0.11", "react-scripts": "^5.0.1", - "react-test-renderer": "^17.0.2", + "react-test-renderer": "^18.2.0", "redux-saga-test-plan": "^4.0.6", "resize-observer-polyfill": "^1.5.1", "sass": "^1.62.1", diff --git a/src/commons/assessment/__tests__/__snapshots__/Assessment.tsx.snap b/src/commons/assessment/__tests__/__snapshots__/Assessment.tsx.snap index 999cc77446..86e6ef8772 100644 --- a/src/commons/assessment/__tests__/__snapshots__/Assessment.tsx.snap +++ b/src/commons/assessment/__tests__/__snapshots__/Assessment.tsx.snap @@ -1091,9 +1091,7 @@ exports[`Assessment page with multiple loaded missions renders correctly 1`] = ` - - + /> diff --git a/src/commons/gitHubOverlay/__tests__/FileExplorerDialog.tsx b/src/commons/gitHubOverlay/__tests__/FileExplorerDialog.tsx index 145a179967..0819a42318 100644 --- a/src/commons/gitHubOverlay/__tests__/FileExplorerDialog.tsx +++ b/src/commons/gitHubOverlay/__tests__/FileExplorerDialog.tsx @@ -57,8 +57,9 @@ test('Opening folder for first time causes child files to be loaded', async () = await screen.findByText('Select a File'); + const dropdownCaret = await screen.findByText('Expand group'); act(() => { - fireEvent.click(screen.getByText('Expand group')); + fireEvent.click(dropdownCaret); }); await waitFor(() => expect(screen.getAllByText('TestFolder').length).toBe(2)); @@ -87,7 +88,7 @@ test('Closing folder hides child files', async () => { await screen.findByText('Select a File'); - const dropdownCaret = screen.getByText('Expand group'); + const dropdownCaret = await screen.findByText('Expand group'); // Open the folder for the first time, now there should be 2 TestFolders act(() => { @@ -129,7 +130,7 @@ test('Opening folder for second time does not cause child files to be loaded', a await screen.findByText('Select a File'); - const dropdownCaret = screen.getByText('Expand group'); + const dropdownCaret = await screen.findByText('Expand group'); // Open the folder, there should be 2 TestFolders in the render act(() => { diff --git a/src/commons/sideContent/__tests__/SideContentEnvVisualizer.tsx b/src/commons/sideContent/__tests__/SideContentEnvVisualizer.tsx index 8b0f3a6fa1..b83715dbd1 100644 --- a/src/commons/sideContent/__tests__/SideContentEnvVisualizer.tsx +++ b/src/commons/sideContent/__tests__/SideContentEnvVisualizer.tsx @@ -1,4 +1,4 @@ -import { render, screen } from '@testing-library/react'; +import { act, render, screen } from '@testing-library/react'; import { runInContext } from 'js-slang/dist/'; import { Provider } from 'react-redux'; import { mockInitialStore } from 'src/commons/mocks/StoreMocks'; @@ -26,8 +26,8 @@ test('EnvVisualizer sets visualization state and renders', async () => { expect(screen.queryAllByTestId('sa-env-visualizer')).toHaveLength(0); const context = mockContext(); - await runInContext('const hello="world"; debugger;', context); - visualizeEnv({ context }); + runInContext('const hello="world"; debugger;', context); + act(() => visualizeEnv({ context })); expect(screen.queryAllByTestId('env-visualizer-default-text')).toHaveLength(0); expect(screen.queryAllByTestId('sa-env-visualizer')).toHaveLength(1); diff --git a/src/pages/playground/__tests__/__snapshots__/Playground.tsx.snap b/src/pages/playground/__tests__/__snapshots__/Playground.tsx.snap index 5d55167963..8ecffb2227 100644 --- a/src/pages/playground/__tests__/__snapshots__/Playground.tsx.snap +++ b/src/pages/playground/__tests__/__snapshots__/Playground.tsx.snap @@ -27,7 +27,6 @@ exports[`Playground tests Playground renders correctly 1`] = ` -
-
Date: Thu, 22 Jun 2023 17:05:44 +0800 Subject: [PATCH 11/12] Workaround deprecated ReactDOM.render used by Blueprintjs v4 --- src/commons/utils/DialogHelper.tsx | 25 +++++++----- .../NotificationsHelper.ts | 8 ++-- .../notifications/createNotification.tsx | 38 +++++++++++++++++++ src/setupTests.ts | 6 +++ 4 files changed, 63 insertions(+), 14 deletions(-) rename src/commons/utils/{ => notifications}/NotificationsHelper.ts (75%) create mode 100644 src/commons/utils/notifications/createNotification.tsx diff --git a/src/commons/utils/DialogHelper.tsx b/src/commons/utils/DialogHelper.tsx index f879b9d85b..85bdf4c366 100644 --- a/src/commons/utils/DialogHelper.tsx +++ b/src/commons/utils/DialogHelper.tsx @@ -1,6 +1,6 @@ import { IconName, Intent } from '@blueprintjs/core'; import * as React from 'react'; -import * as ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { ConfirmDialog, ConfirmDialogProps } from '../dialogs/ConfirmDialog'; import { PromptDialog, PromptDialogProps } from '../dialogs/PromptDialog'; @@ -20,14 +20,20 @@ class DialogHelper extends React.PureComponent<{}, DialogHelperState> { dialogOnClose: null }; - public static create(): DialogHelper { + /** + * Blueprintjs v4 OverlayToaster still uses ReactDOM.render, which is deprecated in React v18. + * Temporary custom workaround as follows. + * + * https://github.com/palantir/blueprint/issues/5212 + */ + public static create() { const containerElement = document.createElement('div'); document.body.appendChild(containerElement); - const dialogHelper = ReactDOM.render<{}>(, containerElement) as DialogHelper; - if (dialogHelper == null) { - throw new Error('Could not create DialogHelper - are you in a React lifecycle method?'); - } - return dialogHelper; + const root = createRoot(containerElement); + + const dialogRef = React.createRef(); + root.render(); + return dialogRef; } public show(dialog: DialogHelperState['dialog'], onClose?: () => void) { @@ -48,12 +54,13 @@ class DialogHelper extends React.PureComponent<{}, DialogHelperState> { const singleton = DialogHelper.create(); +// singleton should be rendered by the time React lifecycle completes export function showDialog(dialog: DialogHelperState['dialog'], dialogOnClose?: () => void) { - singleton.show(dialog, dialogOnClose); + singleton.current!.show(dialog, dialogOnClose); } export function closeDialog() { - singleton.close(); + singleton.current!.close(); } export function promisifyDialog

, R>( diff --git a/src/commons/utils/NotificationsHelper.ts b/src/commons/utils/notifications/NotificationsHelper.ts similarity index 75% rename from src/commons/utils/NotificationsHelper.ts rename to src/commons/utils/notifications/NotificationsHelper.ts index 973c897d80..1f6f43226c 100644 --- a/src/commons/utils/NotificationsHelper.ts +++ b/src/commons/utils/notifications/NotificationsHelper.ts @@ -1,8 +1,6 @@ -import { Intent, IToastProps, Position, Toaster } from '@blueprintjs/core'; +import { Intent, ToastProps } from '@blueprintjs/core'; -const notification = Toaster.create({ - position: Position.TOP -}); +import { notification } from './createNotification'; export const showSuccessMessage = ( message: string | JSX.Element, @@ -46,6 +44,6 @@ export const showDangerMessage = ( key ); -export const showMessage = (props: IToastProps, key?: string) => notification.show(props, key); +export const showMessage = (props: ToastProps, key?: string) => notification.show(props, key); export const dismiss = (key: string) => notification.dismiss(key); diff --git a/src/commons/utils/notifications/createNotification.tsx b/src/commons/utils/notifications/createNotification.tsx new file mode 100644 index 0000000000..34c0af4cf2 --- /dev/null +++ b/src/commons/utils/notifications/createNotification.tsx @@ -0,0 +1,38 @@ +import { OverlayToaster, OverlayToasterProps, Position } from '@blueprintjs/core'; +import { createRoot } from 'react-dom/client'; + +/** + * Blueprintjs v4 OverlayToaster still uses ReactDOM.render, which is deprecated in React v18. + * They plan to migrate out of ReactDOM.render in v6. Temporary custom workaround `Toaster.create` as follows. + * + * https://github.com/palantir/blueprint/issues/5212 + * + * SEPARATE NOTE: `notification` is intentionally exported from this separate file in order for us to mock it in `NotificationsHelper.tsx` + * - `ReactDOM.render` was deprecated in react v18, which previously returned the instance of the class component `OverlayToaster` from Blueprint v4 + * - the new React `createRoot.render` returns `void` + * - we are able to circumvent this by accessing the `OverlayToaster` instance from the `ref` prop based on the linked GitHub suggestion above + * - HOWEVER, React Testing Library (@testing-library/react) does not support refs and accessing component instances based on their [Guiding Principles](https://testing-library.com/docs/guiding-principles) and [FAQ](https://testing-library.com/docs/dom-testing-library/faq/) + * - thus we have to mock `notification` in our tests from this file (see `src/setupTests.ts`) + * - this also means we can't test UI changes related to notification toasters since we are mocking the toaster (e.g. checking that the toast appears in our test UI) + */ +export let notification: OverlayToaster; + +const createToaster = (props?: OverlayToasterProps, container = document.body) => { + const containerElement = document.createElement('div'); + container.appendChild(containerElement); + const root = createRoot(containerElement); + + root.render( + { + notification = instance!; + }} + /> + ); +}; + +createToaster({ + position: Position.TOP +}); diff --git a/src/setupTests.ts b/src/setupTests.ts index c3733eb35c..76c28e4cfc 100644 --- a/src/setupTests.ts +++ b/src/setupTests.ts @@ -2,3 +2,9 @@ import '@testing-library/jest-dom/extend-expect'; // Mock ResizeObserver in tests global.ResizeObserver = require('resize-observer-polyfill'); + +jest.mock('./commons/utils/notifications/createNotification', () => ({ + notification: { + show: jest.fn() + } +})); From 395817a5af4e69f4c17790840871e60d4c9a2574 Mon Sep 17 00:00:00 2001 From: En Rong <53928333+chownces@users.noreply.github.com> Date: Thu, 22 Jun 2023 17:12:28 +0800 Subject: [PATCH 12/12] Update notification import lines --- src/commons/achievement/AchievementCommentCard.tsx | 2 +- src/commons/achievement/AchievementManualEditor.tsx | 2 +- .../control/achievementEditor/AchievementUuidCopier.tsx | 2 +- src/commons/achievement/control/common/ItemSaver.tsx | 5 ++++- src/commons/achievement/utils/AchievementInferencer.ts | 2 +- src/commons/achievement/utils/EventHandler.ts | 2 +- src/commons/controlBar/ControlBarSessionButton.tsx | 2 +- src/commons/controlBar/github/ControlBarTaskAddButton.tsx | 2 +- src/commons/controlBar/github/ControlBarTaskDeleteButton.tsx | 2 +- src/commons/dropdown/DropdownCreateCourse.tsx | 2 +- src/commons/gitHubOverlay/RepositoryDialog.tsx | 2 +- src/commons/gitHubOverlay/__tests__/RepositoryDialog.tsx | 4 +++- src/commons/githubAssessments/GitHubMissionCreateDialog.tsx | 2 +- src/commons/githubAssessments/GitHubMissionDataUtils.ts | 2 +- src/commons/mcqChooser/McqChooser.tsx | 2 +- src/commons/mocks/BackendMocks.ts | 2 +- src/commons/sagas/BackendSaga.ts | 2 +- src/commons/sagas/GitHubPersistenceSaga.ts | 2 +- src/commons/sagas/LoginSaga.ts | 2 +- src/commons/sagas/PersistenceSaga.tsx | 2 +- src/commons/sagas/PlaygroundSaga.ts | 2 +- src/commons/sagas/RequestsSaga.ts | 2 +- src/commons/sagas/WorkspaceSaga.ts | 2 +- src/commons/sagas/__tests__/BackendSaga.ts | 5 ++++- src/commons/sagas/__tests__/PlaygroundSaga.ts | 5 ++++- src/commons/sagas/__tests__/WorkspaceSaga.ts | 5 ++++- .../sideContent/SideContentContestVotingContainer.tsx | 2 +- .../remoteExecution/SideContentRemoteExecution.tsx | 2 +- src/commons/utils/WarningDialogHelper.tsx | 2 +- src/features/assessments/AssessmentUtils.ts | 2 +- src/features/github/GitHubUtils.tsx | 5 ++++- src/index.tsx | 2 +- .../assessmentConfigPanel/AssessmentConfigPanel.tsx | 2 +- .../subcomponents/userConfigPanel/UserActionsCell.tsx | 2 +- src/pages/academy/grading/subcomponents/GradingEditor.tsx | 2 +- .../groundControl/subcomponents/GroundControlDropzone.tsx | 2 +- .../groundControl/subcomponents/GroundControlEditCell.tsx | 2 +- src/pages/githubAssessments/GitHubAssessmentWorkspace.tsx | 2 +- src/pages/githubAssessments/GitHubClassroom.tsx | 2 +- src/pages/localStorage.ts | 2 +- 40 files changed, 57 insertions(+), 40 deletions(-) diff --git a/src/commons/achievement/AchievementCommentCard.tsx b/src/commons/achievement/AchievementCommentCard.tsx index 2bac0a8f06..7ad0975e38 100644 --- a/src/commons/achievement/AchievementCommentCard.tsx +++ b/src/commons/achievement/AchievementCommentCard.tsx @@ -3,7 +3,7 @@ import { useNavigate } from 'react-router'; import { Assessment } from '../assessment/AssessmentTypes'; import { useTypedSelector } from '../utils/Hooks'; -import { showWarningMessage } from '../utils/NotificationsHelper'; +import { showWarningMessage } from '../utils/notifications/NotificationsHelper'; import { assessmentTypeLink } from '../utils/ParamParseHelper'; const AchievementCommentCard = ({ diff --git a/src/commons/achievement/AchievementManualEditor.tsx b/src/commons/achievement/AchievementManualEditor.tsx index 19413f8c12..bde34b4ead 100644 --- a/src/commons/achievement/AchievementManualEditor.tsx +++ b/src/commons/achievement/AchievementManualEditor.tsx @@ -8,7 +8,7 @@ import { GoalProgress } from 'src/features/achievement/AchievementTypes'; -import { showSuccessMessage, showWarningMessage } from '../utils/NotificationsHelper'; +import { showSuccessMessage, showWarningMessage } from '../utils/notifications/NotificationsHelper'; type AchievementManualEditorProps = { hiddenState: [boolean, any]; diff --git a/src/commons/achievement/control/achievementEditor/AchievementUuidCopier.tsx b/src/commons/achievement/control/achievementEditor/AchievementUuidCopier.tsx index 97f5321b6a..3b636a4ee0 100644 --- a/src/commons/achievement/control/achievementEditor/AchievementUuidCopier.tsx +++ b/src/commons/achievement/control/achievementEditor/AchievementUuidCopier.tsx @@ -1,7 +1,7 @@ import { Button } from '@blueprintjs/core'; import { IconNames } from '@blueprintjs/icons'; import { Tooltip2 } from '@blueprintjs/popover2'; -import { showSuccessMessage } from 'src/commons/utils/NotificationsHelper'; +import { showSuccessMessage } from 'src/commons/utils/notifications/NotificationsHelper'; type AchievementUuidCopierProps = { uuid: string; diff --git a/src/commons/achievement/control/common/ItemSaver.tsx b/src/commons/achievement/control/common/ItemSaver.tsx index 2a11ef9967..3505f7ee1d 100644 --- a/src/commons/achievement/control/common/ItemSaver.tsx +++ b/src/commons/achievement/control/common/ItemSaver.tsx @@ -1,7 +1,10 @@ import { Button } from '@blueprintjs/core'; import { IconNames } from '@blueprintjs/icons'; import { Tooltip2 } from '@blueprintjs/popover2'; -import { showSuccessMessage, showWarningMessage } from 'src/commons/utils/NotificationsHelper'; +import { + showSuccessMessage, + showWarningMessage +} from 'src/commons/utils/notifications/NotificationsHelper'; type ItemSaverProps = { discardChanges: () => void; diff --git a/src/commons/achievement/utils/AchievementInferencer.ts b/src/commons/achievement/utils/AchievementInferencer.ts index 7e1b70867c..f83478ac7d 100644 --- a/src/commons/achievement/utils/AchievementInferencer.ts +++ b/src/commons/achievement/utils/AchievementInferencer.ts @@ -10,7 +10,7 @@ import { GoalProgress, GoalType } from '../../../features/achievement/AchievementTypes'; -import { showDangerMessage } from '../../utils/NotificationsHelper'; +import { showDangerMessage } from '../../utils/notifications/NotificationsHelper'; import { isExpired, isReleased } from './DateHelper'; /** diff --git a/src/commons/achievement/utils/EventHandler.ts b/src/commons/achievement/utils/EventHandler.ts index 0269f93066..b2673650f1 100644 --- a/src/commons/achievement/utils/EventHandler.ts +++ b/src/commons/achievement/utils/EventHandler.ts @@ -6,7 +6,7 @@ import { GoalProgress, GoalType } from '../../../features/achievement/AchievementTypes'; -import { showSuccessMessage } from '../../utils/NotificationsHelper'; +import { showSuccessMessage } from '../../utils/notifications/NotificationsHelper'; import AchievementInferencer from './AchievementInferencer'; import { isExpired, isReleased, isWithinTimeRange } from './DateHelper'; diff --git a/src/commons/controlBar/ControlBarSessionButton.tsx b/src/commons/controlBar/ControlBarSessionButton.tsx index 9043a0f9c3..46d487110c 100644 --- a/src/commons/controlBar/ControlBarSessionButton.tsx +++ b/src/commons/controlBar/ControlBarSessionButton.tsx @@ -6,7 +6,7 @@ import * as CopyToClipboard from 'react-copy-to-clipboard'; import { checkSessionIdExists, createNewSession } from '../collabEditing/CollabEditingHelper'; import ControlButton from '../ControlButton'; -import { showWarningMessage } from '../utils/NotificationsHelper'; +import { showWarningMessage } from '../utils/notifications/NotificationsHelper'; type ControlBarSessionButtonsProps = DispatchProps & StateProps; diff --git a/src/commons/controlBar/github/ControlBarTaskAddButton.tsx b/src/commons/controlBar/github/ControlBarTaskAddButton.tsx index 3c211c89a6..edb49a79a6 100644 --- a/src/commons/controlBar/github/ControlBarTaskAddButton.tsx +++ b/src/commons/controlBar/github/ControlBarTaskAddButton.tsx @@ -2,7 +2,7 @@ import { IconNames } from '@blueprintjs/icons'; import ControlButton from '../../ControlButton'; import { maximumTasksPerMission } from '../../githubAssessments/GitHubMissionDataUtils'; -import { showWarningMessage } from '../../utils/NotificationsHelper'; +import { showWarningMessage } from '../../utils/notifications/NotificationsHelper'; export type ControlBarTaskAddButtonProps = { addNewQuestion: () => void; diff --git a/src/commons/controlBar/github/ControlBarTaskDeleteButton.tsx b/src/commons/controlBar/github/ControlBarTaskDeleteButton.tsx index d4fffa5847..e385314a70 100644 --- a/src/commons/controlBar/github/ControlBarTaskDeleteButton.tsx +++ b/src/commons/controlBar/github/ControlBarTaskDeleteButton.tsx @@ -2,7 +2,7 @@ import { IconNames } from '@blueprintjs/icons'; import ControlButton from '../../ControlButton'; import { showSimpleConfirmDialog } from '../../utils/DialogHelper'; -import { showWarningMessage } from '../../utils/NotificationsHelper'; +import { showWarningMessage } from '../../utils/notifications/NotificationsHelper'; export type ControlBarTaskDeleteButtonProps = { deleteCurrentQuestion: () => void; diff --git a/src/commons/dropdown/DropdownCreateCourse.tsx b/src/commons/dropdown/DropdownCreateCourse.tsx index 39b4a34fde..7c5b7f70e1 100644 --- a/src/commons/dropdown/DropdownCreateCourse.tsx +++ b/src/commons/dropdown/DropdownCreateCourse.tsx @@ -21,7 +21,7 @@ import { CourseHelpTextEditorTab } from '../../pages/academy/adminPanel/subcompo import { sourceLanguages } from '../application/ApplicationTypes'; import { UpdateCourseConfiguration } from '../application/types/SessionTypes'; import Markdown from '../Markdown'; -import { showWarningMessage } from '../utils/NotificationsHelper'; +import { showWarningMessage } from '../utils/notifications/NotificationsHelper'; type DialogProps = { isOpen: boolean; diff --git a/src/commons/gitHubOverlay/RepositoryDialog.tsx b/src/commons/gitHubOverlay/RepositoryDialog.tsx index e9c3a993c1..6139059d8a 100644 --- a/src/commons/gitHubOverlay/RepositoryDialog.tsx +++ b/src/commons/gitHubOverlay/RepositoryDialog.tsx @@ -10,7 +10,7 @@ import { import classNames from 'classnames'; import React, { useState } from 'react'; -import { showWarningMessage } from '../utils/NotificationsHelper'; +import { showWarningMessage } from '../utils/notifications/NotificationsHelper'; export type RepositoryDialogProps = { userRepos: any[]; diff --git a/src/commons/gitHubOverlay/__tests__/RepositoryDialog.tsx b/src/commons/gitHubOverlay/__tests__/RepositoryDialog.tsx index 832c5d3bbb..48c7fce7af 100644 --- a/src/commons/gitHubOverlay/__tests__/RepositoryDialog.tsx +++ b/src/commons/gitHubOverlay/__tests__/RepositoryDialog.tsx @@ -1,8 +1,10 @@ import { act, fireEvent, render, screen } from '@testing-library/react'; +import * as NotificationHelper from '../../utils/notifications/NotificationsHelper'; import RepositoryDialog from '../RepositoryDialog'; test('Submitting without selecting causes error message to be displayed', async () => { + const notificationMock = jest.spyOn(NotificationHelper, 'showWarningMessage'); function onSubmit(inputValue: string) {} const userRepos = [ @@ -17,7 +19,7 @@ test('Submitting without selecting causes error message to be displayed', async fireEvent.click(screen.getByText('Select')); - await screen.findByText('No repository selected!'); + expect(notificationMock).toBeCalledTimes(1); }); test('Selection sets repoName for submission', () => { diff --git a/src/commons/githubAssessments/GitHubMissionCreateDialog.tsx b/src/commons/githubAssessments/GitHubMissionCreateDialog.tsx index e96c846101..9f81e9038c 100644 --- a/src/commons/githubAssessments/GitHubMissionCreateDialog.tsx +++ b/src/commons/githubAssessments/GitHubMissionCreateDialog.tsx @@ -2,7 +2,7 @@ import { AnchorButton, Button, Classes, Dialog, InputGroup, Intent } from '@blue import classNames from 'classnames'; import React, { useState } from 'react'; -import { showWarningMessage } from '../utils/NotificationsHelper'; +import { showWarningMessage } from '../utils/notifications/NotificationsHelper'; export type GitHubMissionCreateDialogResolution = { confirmSave: boolean; diff --git a/src/commons/githubAssessments/GitHubMissionDataUtils.ts b/src/commons/githubAssessments/GitHubMissionDataUtils.ts index eecea36e14..c6285e68bf 100644 --- a/src/commons/githubAssessments/GitHubMissionDataUtils.ts +++ b/src/commons/githubAssessments/GitHubMissionDataUtils.ts @@ -7,7 +7,7 @@ import { Chapter } from 'js-slang/dist/types'; import { isEqual } from 'lodash'; import { IMCQQuestion, Testcase } from '../assessment/AssessmentTypes'; -import { showWarningMessage } from '../utils/NotificationsHelper'; +import { showWarningMessage } from '../utils/notifications/NotificationsHelper'; import { MissionData, MissionMetadata, MissionRepoData, TaskData } from './GitHubMissionTypes'; export const maximumTasksPerMission = 20; diff --git a/src/commons/mcqChooser/McqChooser.tsx b/src/commons/mcqChooser/McqChooser.tsx index 4c5cf40867..3e2d543f3b 100644 --- a/src/commons/mcqChooser/McqChooser.tsx +++ b/src/commons/mcqChooser/McqChooser.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { IMCQQuestion } from '../assessment/AssessmentTypes'; import Markdown from '../Markdown'; -import { showSuccessMessage, showWarningMessage } from '../utils/NotificationsHelper'; +import { showSuccessMessage, showWarningMessage } from '../utils/notifications/NotificationsHelper'; export type McqChooserProps = { mcq: IMCQQuestion; diff --git a/src/commons/mocks/BackendMocks.ts b/src/commons/mocks/BackendMocks.ts index 6534b11858..0d027e84cb 100644 --- a/src/commons/mocks/BackendMocks.ts +++ b/src/commons/mocks/BackendMocks.ts @@ -43,7 +43,7 @@ import { } from '../notificationBadge/NotificationBadgeTypes'; import { routerNavigate } from '../sagas/BackendSaga'; import { actions } from '../utils/ActionsHelper'; -import { showSuccessMessage, showWarningMessage } from '../utils/NotificationsHelper'; +import { showSuccessMessage, showWarningMessage } from '../utils/notifications/NotificationsHelper'; import { WorkspaceLocation } from '../workspace/WorkspaceTypes'; import { mockAssessmentConfigurations, diff --git a/src/commons/sagas/BackendSaga.ts b/src/commons/sagas/BackendSaga.ts index c7bc781261..a2f0a97235 100644 --- a/src/commons/sagas/BackendSaga.ts +++ b/src/commons/sagas/BackendSaga.ts @@ -82,7 +82,7 @@ import { } from '../notificationBadge/NotificationBadgeTypes'; import { actions } from '../utils/ActionsHelper'; import { computeRedirectUri, getClientId, getDefaultProvider } from '../utils/AuthHelper'; -import { showSuccessMessage, showWarningMessage } from '../utils/NotificationsHelper'; +import { showSuccessMessage, showWarningMessage } from '../utils/notifications/NotificationsHelper'; import { CHANGE_SUBLANGUAGE, WorkspaceLocation } from '../workspace/WorkspaceTypes'; import { deleteAssessment, diff --git a/src/commons/sagas/GitHubPersistenceSaga.ts b/src/commons/sagas/GitHubPersistenceSaga.ts index 1c693ca8ba..84b96f1173 100644 --- a/src/commons/sagas/GitHubPersistenceSaga.ts +++ b/src/commons/sagas/GitHubPersistenceSaga.ts @@ -20,7 +20,7 @@ import RepositoryDialog, { RepositoryDialogProps } from '../gitHubOverlay/Reposi import { actions } from '../utils/ActionsHelper'; import Constants from '../utils/Constants'; import { promisifyDialog } from '../utils/DialogHelper'; -import { showSuccessMessage, showWarningMessage } from '../utils/NotificationsHelper'; +import { showSuccessMessage, showWarningMessage } from '../utils/notifications/NotificationsHelper'; import { EditorTabState } from '../workspace/WorkspaceTypes'; export function* GitHubPersistenceSaga(): SagaIterator { diff --git a/src/commons/sagas/LoginSaga.ts b/src/commons/sagas/LoginSaga.ts index 04d82db1f6..aa68a1a174 100644 --- a/src/commons/sagas/LoginSaga.ts +++ b/src/commons/sagas/LoginSaga.ts @@ -6,7 +6,7 @@ import { LOG_OUT } from '../application/types/CommonsTypes'; import { LOGIN, SET_USER } from '../application/types/SessionTypes'; import { actions } from '../utils/ActionsHelper'; import { computeEndpointUrl } from '../utils/AuthHelper'; -import { showWarningMessage } from '../utils/NotificationsHelper'; +import { showWarningMessage } from '../utils/notifications/NotificationsHelper'; import { safeTakeEvery as takeEvery } from './SafeEffects'; export default function* LoginSaga(): SagaIterator { diff --git a/src/commons/sagas/PersistenceSaga.tsx b/src/commons/sagas/PersistenceSaga.tsx index 2054dfd9bd..e87e2f923d 100644 --- a/src/commons/sagas/PersistenceSaga.tsx +++ b/src/commons/sagas/PersistenceSaga.tsx @@ -22,7 +22,7 @@ import { showMessage, showSuccessMessage, showWarningMessage -} from '../utils/NotificationsHelper'; +} from '../utils/notifications/NotificationsHelper'; import { AsyncReturnType } from '../utils/TypeHelper'; import { safeTakeEvery as takeEvery, safeTakeLatest as takeLatest } from './SafeEffects'; diff --git a/src/commons/sagas/PlaygroundSaga.ts b/src/commons/sagas/PlaygroundSaga.ts index 4552939fef..1f21129a0c 100644 --- a/src/commons/sagas/PlaygroundSaga.ts +++ b/src/commons/sagas/PlaygroundSaga.ts @@ -15,7 +15,7 @@ import { OverallState } from '../application/ApplicationTypes'; import { ExternalLibraryName } from '../application/types/ExternalTypes'; import { retrieveFilesInWorkspaceAsRecord } from '../fileSystem/utils'; import Constants from '../utils/Constants'; -import { showSuccessMessage, showWarningMessage } from '../utils/NotificationsHelper'; +import { showSuccessMessage, showWarningMessage } from '../utils/notifications/NotificationsHelper'; import { EditorTabState } from '../workspace/WorkspaceTypes'; import { safeTakeEvery as takeEvery } from './SafeEffects'; diff --git a/src/commons/sagas/RequestsSaga.ts b/src/commons/sagas/RequestsSaga.ts index 029c2fc7a0..dd115f1445 100644 --- a/src/commons/sagas/RequestsSaga.ts +++ b/src/commons/sagas/RequestsSaga.ts @@ -50,7 +50,7 @@ import { Notification } from '../notificationBadge/NotificationBadgeTypes'; import { actions } from '../utils/ActionsHelper'; import { castLibrary } from '../utils/CastBackend'; import Constants from '../utils/Constants'; -import { showWarningMessage } from '../utils/NotificationsHelper'; +import { showWarningMessage } from '../utils/notifications/NotificationsHelper'; /** * @property accessToken - backend access token diff --git a/src/commons/sagas/WorkspaceSaga.ts b/src/commons/sagas/WorkspaceSaga.ts index 54d2a176f0..90a5576476 100644 --- a/src/commons/sagas/WorkspaceSaga.ts +++ b/src/commons/sagas/WorkspaceSaga.ts @@ -59,7 +59,7 @@ import { makeElevatedContext, visualizeEnv } from '../utils/JsSlangHelper'; -import { showSuccessMessage, showWarningMessage } from '../utils/NotificationsHelper'; +import { showSuccessMessage, showWarningMessage } from '../utils/notifications/NotificationsHelper'; import { makeExternalBuiltins as makeSourcerorExternalBuiltins } from '../utils/SourcerorHelper'; import { showFullJSDisclaimer, showFullTSDisclaimer } from '../utils/WarningDialogHelper'; import { notifyProgramEvaluated } from '../workspace/WorkspaceActions'; diff --git a/src/commons/sagas/__tests__/BackendSaga.ts b/src/commons/sagas/__tests__/BackendSaga.ts index b09e5f7173..2e10e6c601 100644 --- a/src/commons/sagas/__tests__/BackendSaga.ts +++ b/src/commons/sagas/__tests__/BackendSaga.ts @@ -80,7 +80,10 @@ import { mockNotifications } from '../../mocks/UserMocks'; import { Notification } from '../../notificationBadge/NotificationBadgeTypes'; import { computeRedirectUri } from '../../utils/AuthHelper'; import Constants from '../../utils/Constants'; -import { showSuccessMessage, showWarningMessage } from '../../utils/NotificationsHelper'; +import { + showSuccessMessage, + showWarningMessage +} from '../../utils/notifications/NotificationsHelper'; import { updateHasUnsavedChanges } from '../../workspace/WorkspaceActions'; import { CHANGE_SUBLANGUAGE, diff --git a/src/commons/sagas/__tests__/PlaygroundSaga.ts b/src/commons/sagas/__tests__/PlaygroundSaga.ts index aeaef5c963..bde0b82eac 100644 --- a/src/commons/sagas/__tests__/PlaygroundSaga.ts +++ b/src/commons/sagas/__tests__/PlaygroundSaga.ts @@ -15,7 +15,10 @@ import { } from '../../application/ApplicationTypes'; import { ExternalLibraryName } from '../../application/types/ExternalTypes'; import Constants from '../../utils/Constants'; -import { showSuccessMessage, showWarningMessage } from '../../utils/NotificationsHelper'; +import { + showSuccessMessage, + showWarningMessage +} from '../../utils/notifications/NotificationsHelper'; import PlaygroundSaga, { shortenURLRequest } from '../PlaygroundSaga'; describe('Playground saga tests', () => { diff --git a/src/commons/sagas/__tests__/WorkspaceSaga.ts b/src/commons/sagas/__tests__/WorkspaceSaga.ts index 059717fd88..a3a95c02d2 100644 --- a/src/commons/sagas/__tests__/WorkspaceSaga.ts +++ b/src/commons/sagas/__tests__/WorkspaceSaga.ts @@ -33,7 +33,10 @@ import { import { Library, Testcase, TestcaseType, TestcaseTypes } from '../../assessment/AssessmentTypes'; import { mockRuntimeContext } from '../../mocks/ContextMocks'; import { mockTestcases } from '../../mocks/GradingMocks'; -import { showSuccessMessage, showWarningMessage } from '../../utils/NotificationsHelper'; +import { + showSuccessMessage, + showWarningMessage +} from '../../utils/notifications/NotificationsHelper'; import { beginClearContext, changeExternalLibrary, diff --git a/src/commons/sideContent/SideContentContestVotingContainer.tsx b/src/commons/sideContent/SideContentContestVotingContainer.tsx index f7681ef027..90712f83e7 100644 --- a/src/commons/sideContent/SideContentContestVotingContainer.tsx +++ b/src/commons/sideContent/SideContentContestVotingContainer.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { showWarningMessage } from 'src/commons/utils/NotificationsHelper'; +import { showWarningMessage } from 'src/commons/utils/notifications/NotificationsHelper'; import { ContestEntry } from '../assessment/AssessmentTypes'; import SideContentContestVoting from './SideContentContestVoting'; diff --git a/src/commons/sideContent/remoteExecution/SideContentRemoteExecution.tsx b/src/commons/sideContent/remoteExecution/SideContentRemoteExecution.tsx index 8c4e53392d..48ed1b929e 100644 --- a/src/commons/sideContent/remoteExecution/SideContentRemoteExecution.tsx +++ b/src/commons/sideContent/remoteExecution/SideContentRemoteExecution.tsx @@ -15,7 +15,7 @@ import BrickSvg from 'src/assets/BrickSvg'; import PortSvg from 'src/assets/PortSvg'; import { deleteDevice } from 'src/commons/sagas/RequestsSaga'; import { showSimpleConfirmDialog } from 'src/commons/utils/DialogHelper'; -import { showWarningMessage } from 'src/commons/utils/NotificationsHelper'; +import { showWarningMessage } from 'src/commons/utils/notifications/NotificationsHelper'; import PeripheralContainer from 'src/features/remoteExecution/PeripheralContainer'; import RemoteExecutionAddDeviceDialog from 'src/features/remoteExecution/RemoteExecutionDeviceDialog'; import { diff --git a/src/commons/utils/WarningDialogHelper.tsx b/src/commons/utils/WarningDialogHelper.tsx index d162bfbbeb..4f4a7620fb 100644 --- a/src/commons/utils/WarningDialogHelper.tsx +++ b/src/commons/utils/WarningDialogHelper.tsx @@ -1,5 +1,5 @@ import { showSimpleConfirmDialog, SimpleConfirmDialogProps } from './DialogHelper'; -import { showWarningMessage } from './NotificationsHelper'; +import { showWarningMessage } from './notifications/NotificationsHelper'; // Full JS const FULL_JS_DISCLAIMER_DIALOG_PROPS: SimpleConfirmDialogProps = { diff --git a/src/features/assessments/AssessmentUtils.ts b/src/features/assessments/AssessmentUtils.ts index 9ad637e1bc..029d2d80d0 100644 --- a/src/features/assessments/AssessmentUtils.ts +++ b/src/features/assessments/AssessmentUtils.ts @@ -6,7 +6,7 @@ import { QuestionTypes, Testcase } from '../../commons/assessment/AssessmentTypes'; -import { showWarningMessage } from '../../commons/utils/NotificationsHelper'; +import { showWarningMessage } from '../../commons/utils/notifications/NotificationsHelper'; /** * Returns a nullary function that defers the navigation of the browser window, until the diff --git a/src/features/github/GitHubUtils.tsx b/src/features/github/GitHubUtils.tsx index c6d160a14a..21866465b4 100644 --- a/src/features/github/GitHubUtils.tsx +++ b/src/features/github/GitHubUtils.tsx @@ -6,7 +6,10 @@ import { import { actions } from '../../commons/utils/ActionsHelper'; import { showSimpleConfirmDialog } from '../../commons/utils/DialogHelper'; -import { showSuccessMessage, showWarningMessage } from '../../commons/utils/NotificationsHelper'; +import { + showSuccessMessage, + showWarningMessage +} from '../../commons/utils/notifications/NotificationsHelper'; import { store } from '../../pages/createStore'; /** diff --git a/src/index.tsx b/src/index.tsx index b6e8898952..36a303b9df 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -5,7 +5,7 @@ import { setModulesStaticURL } from 'js-slang/dist/modules/moduleLoader'; import { createRoot } from 'react-dom/client'; import { Provider } from 'react-redux'; import Constants, { Links } from 'src/commons/utils/Constants'; -import { showWarningMessage } from 'src/commons/utils/NotificationsHelper'; +import { showWarningMessage } from 'src/commons/utils/notifications/NotificationsHelper'; import { register as registerServiceWorker } from 'src/commons/utils/RegisterServiceWorker'; import { triggerSyncLogs } from 'src/features/eventLogging/client'; import { store } from 'src/pages/createStore'; diff --git a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx index c4f6f44efb..f7ae3efde6 100644 --- a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx +++ b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/AssessmentConfigPanel.tsx @@ -3,7 +3,7 @@ import { CellValueChangedEvent, GridApi, GridReadyEvent, RowDragEvent } from 'ag import { AgGridReact } from 'ag-grid-react'; import { isEqual } from 'lodash'; import React from 'react'; -import { showWarningMessage } from 'src/commons/utils/NotificationsHelper'; +import { showWarningMessage } from 'src/commons/utils/notifications/NotificationsHelper'; import { AssessmentConfiguration } from '../../../../../commons/assessment/AssessmentTypes'; import BooleanCell from './BooleanCell'; diff --git a/src/pages/academy/adminPanel/subcomponents/userConfigPanel/UserActionsCell.tsx b/src/pages/academy/adminPanel/subcomponents/userConfigPanel/UserActionsCell.tsx index 18afa927e1..60ad048816 100644 --- a/src/pages/academy/adminPanel/subcomponents/userConfigPanel/UserActionsCell.tsx +++ b/src/pages/academy/adminPanel/subcomponents/userConfigPanel/UserActionsCell.tsx @@ -5,7 +5,7 @@ import React from 'react'; import { Role } from 'src/commons/application/ApplicationTypes'; import { AdminPanelCourseRegistration } from 'src/commons/application/types/SessionTypes'; import ControlButton from 'src/commons/ControlButton'; -import { showWarningMessage } from 'src/commons/utils/NotificationsHelper'; +import { showWarningMessage } from 'src/commons/utils/notifications/NotificationsHelper'; type DeleteUserCellProps = OwnProps; diff --git a/src/pages/academy/grading/subcomponents/GradingEditor.tsx b/src/pages/academy/grading/subcomponents/GradingEditor.tsx index c56b3c64d1..bd00000e57 100644 --- a/src/pages/academy/grading/subcomponents/GradingEditor.tsx +++ b/src/pages/academy/grading/subcomponents/GradingEditor.tsx @@ -21,7 +21,7 @@ import { showSimpleConfirmDialog } from '../../../../commons/utils/DialogHelper' import { showSuccessMessage, showWarningMessage -} from '../../../../commons/utils/NotificationsHelper'; +} from '../../../../commons/utils/notifications/NotificationsHelper'; import { convertParamToInt } from '../../../../commons/utils/ParamParseHelper'; type GradingEditorProps = DispatchProps & OwnProps; diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlDropzone.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlDropzone.tsx index e10818f5b8..95ed442d43 100644 --- a/src/pages/academy/groundControl/subcomponents/GroundControlDropzone.tsx +++ b/src/pages/academy/groundControl/subcomponents/GroundControlDropzone.tsx @@ -6,7 +6,7 @@ import { FileRejection, useDropzone } from 'react-dropzone'; import { AssessmentConfiguration } from 'src/commons/assessment/AssessmentTypes'; import ControlButton from '../../../../commons/ControlButton'; -import { showWarningMessage } from '../../../../commons/utils/NotificationsHelper'; +import { showWarningMessage } from '../../../../commons/utils/notifications/NotificationsHelper'; export type DropzoneProps = DispatchProps & StateProps; diff --git a/src/pages/academy/groundControl/subcomponents/GroundControlEditCell.tsx b/src/pages/academy/groundControl/subcomponents/GroundControlEditCell.tsx index d6d1254994..ba9c58083e 100644 --- a/src/pages/academy/groundControl/subcomponents/GroundControlEditCell.tsx +++ b/src/pages/academy/groundControl/subcomponents/GroundControlEditCell.tsx @@ -6,7 +6,7 @@ import * as React from 'react'; import { AssessmentOverview } from '../../../../commons/assessment/AssessmentTypes'; import ControlButton from '../../../../commons/ControlButton'; -import { showWarningMessage } from '../../../../commons/utils/NotificationsHelper'; +import { showWarningMessage } from '../../../../commons/utils/notifications/NotificationsHelper'; export type EditCellProps = DispatchProps & StateProps; diff --git a/src/pages/githubAssessments/GitHubAssessmentWorkspace.tsx b/src/pages/githubAssessments/GitHubAssessmentWorkspace.tsx index e65a23d07c..18db93619c 100644 --- a/src/pages/githubAssessments/GitHubAssessmentWorkspace.tsx +++ b/src/pages/githubAssessments/GitHubAssessmentWorkspace.tsx @@ -87,7 +87,7 @@ import { SideContentProps } from '../../commons/sideContent/SideContent'; import { SideContentTab, SideContentType } from '../../commons/sideContent/SideContentTypes'; import Constants from '../../commons/utils/Constants'; import { promisifyDialog, showSimpleConfirmDialog } from '../../commons/utils/DialogHelper'; -import { showWarningMessage } from '../../commons/utils/NotificationsHelper'; +import { showWarningMessage } from '../../commons/utils/notifications/NotificationsHelper'; import Workspace, { WorkspaceProps } from '../../commons/workspace/Workspace'; import { WorkspaceLocation, WorkspaceState } from '../../commons/workspace/WorkspaceTypes'; import { diff --git a/src/pages/githubAssessments/GitHubClassroom.tsx b/src/pages/githubAssessments/GitHubClassroom.tsx index 27dbd658c8..ca6448c799 100644 --- a/src/pages/githubAssessments/GitHubClassroom.tsx +++ b/src/pages/githubAssessments/GitHubClassroom.tsx @@ -12,7 +12,7 @@ import { useTypedSelector } from 'src/commons/utils/Hooks'; import ContentDisplay from '../../commons/ContentDisplay'; import { MissionRepoData } from '../../commons/githubAssessments/GitHubMissionTypes'; import GitHubAssessmentsNavigationBar from '../../commons/navigationBar/subcomponents/GitHubAssessmentsNavigationBar'; -import { showWarningMessage } from '../../commons/utils/NotificationsHelper'; +import { showWarningMessage } from '../../commons/utils/notifications/NotificationsHelper'; import { assessmentTypeLink } from '../../commons/utils/ParamParseHelper'; import GitHubAssessmentListing from './GitHubAssessmentListing'; import GitHubAssessmentWorkspace from './GitHubAssessmentWorkspace'; diff --git a/src/pages/localStorage.ts b/src/pages/localStorage.ts index e23f818b18..0c5da166be 100644 --- a/src/pages/localStorage.ts +++ b/src/pages/localStorage.ts @@ -4,7 +4,7 @@ import { compressToUTF16, decompressFromUTF16 } from 'lz-string'; import { OverallState, SALanguage } from '../commons/application/ApplicationTypes'; import { ExternalLibraryName } from '../commons/application/types/ExternalTypes'; import { SessionState } from '../commons/application/types/SessionTypes'; -import { showWarningMessage } from '../commons/utils/NotificationsHelper'; +import { showWarningMessage } from '../commons/utils/notifications/NotificationsHelper'; import { EditorTabState } from '../commons/workspace/WorkspaceTypes'; import { AchievementItem } from '../features/achievement/AchievementTypes';