From 9a83d67d788f70be8de0c3e0991f807c36fa9697 Mon Sep 17 00:00:00 2001 From: Braden MacDonald Date: Mon, 7 Oct 2024 10:23:24 -0700 Subject: [PATCH] refactor: Enable TypeScript support in this repo (#1459) --- Makefile | 1 + package.json | 7 +-- .../{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 src/{constants.js => constants.ts} | 11 ++-- .../{messages.js => messages.ts} | 0 src/course-home/data/slice.js | 10 ++-- .../dates-tab/{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../outline-tab/{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../grades/{messages.js => messages.ts} | 0 .../progress-tab/{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 src/course-tabs/{messages.js => messages.ts} | 0 .../celebration/{messages.js => messages.ts} | 0 .../calculator/{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../course-exit/CourseRecommendations.jsx | 2 +- .../course/course-exit/data/slice.js | 9 ++-- .../course-exit/{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../course/{messages.js => messages.ts} | 0 .../new-sidebar/{Sidebar.jsx => Sidebar.tsx} | 0 .../course/new-sidebar/SidebarContext.js | 5 -- .../course/new-sidebar/SidebarContext.ts | 37 +++++++++++++ ...rovider.jsx => SidebarContextProvider.tsx} | 19 +++---- ...idebarTriggers.jsx => SidebarTriggers.tsx} | 0 .../{SidebarBase.jsx => SidebarBase.tsx} | 51 +++++++----------- ...debarFilled.jsx => RightSidebarFilled.tsx} | 2 - ...rOutlined.jsx => RightSidebarOutlined.tsx} | 2 - .../new-sidebar/icons/{index.js => index.ts} | 0 .../new-sidebar/{messages.js => messages.ts} | 0 ...sx => DiscussionsNotificationsSidebar.tsx} | 0 ...sx => DiscussionsNotificationsTrigger.tsx} | 0 ...et.test.jsx => DiscussionsWidget.test.tsx} | 2 +- ...ssionsWidget.jsx => DiscussionsWidget.tsx} | 0 .../{index.js => index.ts} | 0 ....test.jsx => NotificationsWidget.test.tsx} | 52 +++++++++---------- ...ionsWidget.jsx => NotificationsWidget.tsx} | 2 +- .../sidebars/{index.js => index.ts} | 4 +- src/courseware/course/sequence/Sequence.jsx | 2 +- .../content-lock/{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../honor-code/{messages.js => messages.ts} | 0 .../lock-paywall/{messages.js => messages.ts} | 0 .../sequence/{messages.js => messages.ts} | 0 .../SequenceNavigation.jsx | 2 +- .../{messages.js => messages.ts} | 0 .../course/share/{messages.js => messages.ts} | 0 .../course-outline/CourseOutlineTray.jsx | 2 +- .../{messages.js => messages.ts} | 0 .../discussions/{messages.js => messages.ts} | 0 .../notifications/NotificationTray.jsx | 1 + src/courseware/data/redux.test.js | 2 +- src/courseware/data/selectors.js | 2 +- src/courseware/data/slice.js | 10 ++-- src/courseware/{messages.js => messages.ts} | 0 .../social-share/{messages.js => messages.ts} | 0 src/frontend-platform.d.ts | 41 +++++++++++++++ src/generic/CourseAccessErrorPage.jsx | 2 +- src/generic/{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 .../UpgradeNotification.jsx | 6 +-- .../{messages.js => messages.ts} | 0 src/preferences-unsubscribe/index.jsx | 2 +- .../{messages.js => messages.ts} | 0 .../{messages.js => messages.ts} | 0 src/setupTest.js | 4 +- .../{messages.js => messages.ts} | 0 .../StreakCelebrationModal.jsx | 2 +- .../{messages.js => messages.ts} | 0 src/tab-page/{messages.js => messages.ts} | 0 src/utils.js | 17 ------ src/utils.ts | 23 ++++++++ tsconfig.json | 13 +++++ 84 files changed, 213 insertions(+), 134 deletions(-) rename src/alerts/access-expiration-alert/{messages.js => messages.ts} (100%) rename src/alerts/active-enteprise-alert/{messages.js => messages.ts} (100%) rename src/alerts/enrollment-alert/{messages.js => messages.ts} (100%) rename src/alerts/logistration-alert/{messages.js => messages.ts} (100%) rename src/alerts/sequence-alerts/{messages.js => messages.ts} (100%) rename src/{constants.js => constants.ts} (80%) rename src/course-home/courseware-search/{messages.js => messages.ts} (100%) rename src/course-home/dates-tab/{messages.js => messages.ts} (100%) rename src/course-home/goal-unsubscribe/{messages.js => messages.ts} (100%) rename src/course-home/outline-tab/alerts/certificate-status-alert/{messages.js => messages.ts} (100%) rename src/course-home/outline-tab/alerts/private-course-alert/{messages.js => messages.ts} (100%) rename src/course-home/outline-tab/{messages.js => messages.ts} (100%) rename src/course-home/progress-tab/certificate-status/{messages.js => messages.ts} (100%) rename src/course-home/progress-tab/course-completion/{messages.js => messages.ts} (100%) rename src/course-home/progress-tab/credit-information/{messages.js => messages.ts} (100%) rename src/course-home/progress-tab/grades/{messages.js => messages.ts} (100%) rename src/course-home/progress-tab/{messages.js => messages.ts} (100%) rename src/course-home/progress-tab/related-links/{messages.js => messages.ts} (100%) rename src/course-home/suggested-schedule-messaging/{messages.js => messages.ts} (100%) rename src/course-tabs/{messages.js => messages.ts} (100%) rename src/courseware/course/celebration/{messages.js => messages.ts} (100%) rename src/courseware/course/content-tools/calculator/{messages.js => messages.ts} (100%) rename src/courseware/course/content-tools/notes-visibility/{messages.js => messages.ts} (100%) rename src/courseware/course/course-exit/{messages.js => messages.ts} (100%) rename src/courseware/course/course-license/{messages.js => messages.ts} (100%) rename src/courseware/course/{messages.js => messages.ts} (100%) rename src/courseware/course/new-sidebar/{Sidebar.jsx => Sidebar.tsx} (100%) delete mode 100644 src/courseware/course/new-sidebar/SidebarContext.js create mode 100644 src/courseware/course/new-sidebar/SidebarContext.ts rename src/courseware/course/new-sidebar/{SidebarContextProvider.jsx => SidebarContextProvider.tsx} (95%) rename src/courseware/course/new-sidebar/{SidebarTriggers.jsx => SidebarTriggers.tsx} (100%) rename src/courseware/course/new-sidebar/common/{SidebarBase.jsx => SidebarBase.tsx} (77%) rename src/courseware/course/new-sidebar/icons/{RightSidebarFilled.jsx => RightSidebarFilled.tsx} (91%) rename src/courseware/course/new-sidebar/icons/{RightSidebarOutlined.jsx => RightSidebarOutlined.tsx} (91%) rename src/courseware/course/new-sidebar/icons/{index.js => index.ts} (100%) rename src/courseware/course/new-sidebar/{messages.js => messages.ts} (100%) rename src/courseware/course/new-sidebar/sidebars/discussions-notifications/{DiscussionsNotificationsSidebar.jsx => DiscussionsNotificationsSidebar.tsx} (100%) rename src/courseware/course/new-sidebar/sidebars/discussions-notifications/{DiscussionsNotificationsTrigger.jsx => DiscussionsNotificationsTrigger.tsx} (100%) rename src/courseware/course/new-sidebar/sidebars/discussions-notifications/discussions/{DiscussionsWidget.test.jsx => DiscussionsWidget.test.tsx} (97%) rename src/courseware/course/new-sidebar/sidebars/discussions-notifications/discussions/{DiscussionsWidget.jsx => DiscussionsWidget.tsx} (100%) rename src/courseware/course/new-sidebar/sidebars/discussions-notifications/{index.js => index.ts} (100%) rename src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/{NotificationsWidget.test.jsx => NotificationsWidget.test.tsx} (85%) rename src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/{NotificationsWidget.jsx => NotificationsWidget.tsx} (97%) rename src/courseware/course/new-sidebar/sidebars/{index.js => index.ts} (93%) rename src/courseware/course/sequence/content-lock/{messages.js => messages.ts} (100%) rename src/courseware/course/sequence/hidden-after-due/{messages.js => messages.ts} (100%) rename src/courseware/course/sequence/honor-code/{messages.js => messages.ts} (100%) rename src/courseware/course/sequence/lock-paywall/{messages.js => messages.ts} (100%) rename src/courseware/course/sequence/{messages.js => messages.ts} (100%) rename src/courseware/course/sequence/sequence-navigation/{messages.js => messages.ts} (100%) rename src/courseware/course/share/{messages.js => messages.ts} (100%) rename src/courseware/course/sidebar/sidebars/course-outline/{messages.js => messages.ts} (100%) rename src/courseware/course/sidebar/sidebars/discussions/{messages.js => messages.ts} (100%) rename src/courseware/{messages.js => messages.ts} (100%) rename src/courseware/social-share/{messages.js => messages.ts} (100%) create mode 100644 src/frontend-platform.d.ts rename src/generic/{messages.js => messages.ts} (100%) rename src/generic/upgrade-button/{messages.js => messages.ts} (100%) rename src/instructor-toolbar/masquerade-widget/{messages.js => messages.ts} (100%) rename src/preferences-unsubscribe/{messages.js => messages.ts} (100%) rename src/product-tours/{messages.js => messages.ts} (100%) rename src/shared/effort-estimate/{messages.js => messages.ts} (100%) rename src/shared/streak-celebration/{messages.js => messages.ts} (100%) rename src/tab-page/{messages.js => messages.ts} (100%) delete mode 100644 src/utils.js create mode 100644 src/utils.ts create mode 100644 tsconfig.json diff --git a/Makefile b/Makefile index 5aeb200efd..d219ae32d0 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,7 @@ validate: make validate-no-uncommitted-package-lock-changes npm run i18n_extract npm run lint -- --max-warnings 0 + npm run types npm run test npm run build npm run bundlewatch diff --git a/package.json b/package.json index 1bbf8f76e8..7898c9ef5e 100644 --- a/package.json +++ b/package.json @@ -13,14 +13,15 @@ "build": "fedx-scripts webpack", "bundlewatch": "bundlewatch", "i18n_extract": "fedx-scripts formatjs extract", - "lint": "fedx-scripts eslint --ext .js --ext .jsx .", - "lint:fix": "fedx-scripts eslint --fix --ext .js --ext .jsx .", + "lint": "fedx-scripts eslint --ext .js --ext .jsx --ext .ts --ext .tsx .", + "lint:fix": "fedx-scripts eslint --fix --ext .js --ext .jsx --ext .ts --ext .tsx .", "prepare": "husky install", "postinstall": "patch-package", "snapshot": "fedx-scripts jest --updateSnapshot", "start": "fedx-scripts webpack-dev-server --progress", "dev": "PUBLIC_PATH=/learning/ MFE_CONFIG_API_URL='http://localhost:8000/api/mfe_config/v1' fedx-scripts webpack-dev-server --progress --host apps.local.openedx.io", - "test": "fedx-scripts jest --coverage --passWithNoTests" + "test": "fedx-scripts jest --coverage --passWithNoTests", + "types": "tsc --noEmit" }, "author": "edX", "license": "AGPL-3.0", diff --git a/src/alerts/access-expiration-alert/messages.js b/src/alerts/access-expiration-alert/messages.ts similarity index 100% rename from src/alerts/access-expiration-alert/messages.js rename to src/alerts/access-expiration-alert/messages.ts diff --git a/src/alerts/active-enteprise-alert/messages.js b/src/alerts/active-enteprise-alert/messages.ts similarity index 100% rename from src/alerts/active-enteprise-alert/messages.js rename to src/alerts/active-enteprise-alert/messages.ts diff --git a/src/alerts/enrollment-alert/messages.js b/src/alerts/enrollment-alert/messages.ts similarity index 100% rename from src/alerts/enrollment-alert/messages.js rename to src/alerts/enrollment-alert/messages.ts diff --git a/src/alerts/logistration-alert/messages.js b/src/alerts/logistration-alert/messages.ts similarity index 100% rename from src/alerts/logistration-alert/messages.js rename to src/alerts/logistration-alert/messages.ts diff --git a/src/alerts/sequence-alerts/messages.js b/src/alerts/sequence-alerts/messages.ts similarity index 100% rename from src/alerts/sequence-alerts/messages.js rename to src/alerts/sequence-alerts/messages.ts diff --git a/src/constants.js b/src/constants.ts similarity index 80% rename from src/constants.js rename to src/constants.ts index 7cd914a08a..ac8ec85151 100644 --- a/src/constants.js +++ b/src/constants.ts @@ -16,7 +16,7 @@ export const DECODE_ROUTES = { ], REDIRECT_HOME: 'home/:courseId', REDIRECT_SURVEY: 'survey/:courseId', -}; +} as const satisfies Readonly<{ [k: string]: string | readonly string[] }>; export const ROUTES = { UNSUBSCRIBE: '/goal-unsubscribe/:token', @@ -25,7 +25,7 @@ export const ROUTES = { DASHBOARD: 'dashboard', ENTERPRISE_LEARNER_DASHBOARD: 'enterprise-learner-dashboard', CONSENT: 'consent', -}; +} as const satisfies Readonly<{ [k: string]: string }>; export const REDIRECT_MODES = { DASHBOARD_REDIRECT: 'dashboard-redirect', @@ -33,7 +33,7 @@ export const REDIRECT_MODES = { CONSENT_REDIRECT: 'consent-redirect', HOME_REDIRECT: 'home-redirect', SURVEY_REDIRECT: 'survey-redirect', -}; +} as const satisfies Readonly<{ [k: string]: string }>; export const VERIFIED_MODES = [ 'professional', @@ -44,14 +44,15 @@ export const VERIFIED_MODES = [ 'executive-education', 'paid-executive-education', 'paid-bootcamp', -]; +] as const satisfies readonly string[]; export const WIDGETS = { DISCUSSIONS: 'DISCUSSIONS', NOTIFICATIONS: 'NOTIFICATIONS', -}; +} as const satisfies Readonly<{ [k: string]: string }>; export const LOADING = 'loading'; export const LOADED = 'loaded'; export const FAILED = 'failed'; export const DENIED = 'denied'; +export type StatusValue = typeof LOADING | typeof LOADED | typeof FAILED | typeof DENIED; diff --git a/src/course-home/courseware-search/messages.js b/src/course-home/courseware-search/messages.ts similarity index 100% rename from src/course-home/courseware-search/messages.js rename to src/course-home/courseware-search/messages.ts diff --git a/src/course-home/data/slice.js b/src/course-home/data/slice.js index e23801db07..21c804d3f3 100644 --- a/src/course-home/data/slice.js +++ b/src/course-home/data/slice.js @@ -1,10 +1,12 @@ /* eslint-disable no-param-reassign */ import { createSlice } from '@reduxjs/toolkit'; -export const LOADING = 'loading'; -export const LOADED = 'loaded'; -export const FAILED = 'failed'; -export const DENIED = 'denied'; +import { + LOADING, + LOADED, + FAILED, + DENIED, +} from '@src/constants'; const slice = createSlice({ name: 'course-home', diff --git a/src/course-home/dates-tab/messages.js b/src/course-home/dates-tab/messages.ts similarity index 100% rename from src/course-home/dates-tab/messages.js rename to src/course-home/dates-tab/messages.ts diff --git a/src/course-home/goal-unsubscribe/messages.js b/src/course-home/goal-unsubscribe/messages.ts similarity index 100% rename from src/course-home/goal-unsubscribe/messages.js rename to src/course-home/goal-unsubscribe/messages.ts diff --git a/src/course-home/outline-tab/alerts/certificate-status-alert/messages.js b/src/course-home/outline-tab/alerts/certificate-status-alert/messages.ts similarity index 100% rename from src/course-home/outline-tab/alerts/certificate-status-alert/messages.js rename to src/course-home/outline-tab/alerts/certificate-status-alert/messages.ts diff --git a/src/course-home/outline-tab/alerts/private-course-alert/messages.js b/src/course-home/outline-tab/alerts/private-course-alert/messages.ts similarity index 100% rename from src/course-home/outline-tab/alerts/private-course-alert/messages.js rename to src/course-home/outline-tab/alerts/private-course-alert/messages.ts diff --git a/src/course-home/outline-tab/messages.js b/src/course-home/outline-tab/messages.ts similarity index 100% rename from src/course-home/outline-tab/messages.js rename to src/course-home/outline-tab/messages.ts diff --git a/src/course-home/progress-tab/certificate-status/messages.js b/src/course-home/progress-tab/certificate-status/messages.ts similarity index 100% rename from src/course-home/progress-tab/certificate-status/messages.js rename to src/course-home/progress-tab/certificate-status/messages.ts diff --git a/src/course-home/progress-tab/course-completion/messages.js b/src/course-home/progress-tab/course-completion/messages.ts similarity index 100% rename from src/course-home/progress-tab/course-completion/messages.js rename to src/course-home/progress-tab/course-completion/messages.ts diff --git a/src/course-home/progress-tab/credit-information/messages.js b/src/course-home/progress-tab/credit-information/messages.ts similarity index 100% rename from src/course-home/progress-tab/credit-information/messages.js rename to src/course-home/progress-tab/credit-information/messages.ts diff --git a/src/course-home/progress-tab/grades/messages.js b/src/course-home/progress-tab/grades/messages.ts similarity index 100% rename from src/course-home/progress-tab/grades/messages.js rename to src/course-home/progress-tab/grades/messages.ts diff --git a/src/course-home/progress-tab/messages.js b/src/course-home/progress-tab/messages.ts similarity index 100% rename from src/course-home/progress-tab/messages.js rename to src/course-home/progress-tab/messages.ts diff --git a/src/course-home/progress-tab/related-links/messages.js b/src/course-home/progress-tab/related-links/messages.ts similarity index 100% rename from src/course-home/progress-tab/related-links/messages.js rename to src/course-home/progress-tab/related-links/messages.ts diff --git a/src/course-home/suggested-schedule-messaging/messages.js b/src/course-home/suggested-schedule-messaging/messages.ts similarity index 100% rename from src/course-home/suggested-schedule-messaging/messages.js rename to src/course-home/suggested-schedule-messaging/messages.ts diff --git a/src/course-tabs/messages.js b/src/course-tabs/messages.ts similarity index 100% rename from src/course-tabs/messages.js rename to src/course-tabs/messages.ts diff --git a/src/courseware/course/celebration/messages.js b/src/courseware/course/celebration/messages.ts similarity index 100% rename from src/courseware/course/celebration/messages.js rename to src/courseware/course/celebration/messages.ts diff --git a/src/courseware/course/content-tools/calculator/messages.js b/src/courseware/course/content-tools/calculator/messages.ts similarity index 100% rename from src/courseware/course/content-tools/calculator/messages.js rename to src/courseware/course/content-tools/calculator/messages.ts diff --git a/src/courseware/course/content-tools/notes-visibility/messages.js b/src/courseware/course/content-tools/notes-visibility/messages.ts similarity index 100% rename from src/courseware/course/content-tools/notes-visibility/messages.js rename to src/courseware/course/content-tools/notes-visibility/messages.ts diff --git a/src/courseware/course/course-exit/CourseRecommendations.jsx b/src/courseware/course/course-exit/CourseRecommendations.jsx index 0d7ab351ca..22d6f7e5ac 100644 --- a/src/courseware/course/course-exit/CourseRecommendations.jsx +++ b/src/courseware/course/course-exit/CourseRecommendations.jsx @@ -12,9 +12,9 @@ import { } from '@openedx/paragon'; import PropTypes from 'prop-types'; import truncate from 'truncate-html'; +import { FAILED, LOADED, LOADING } from '@src/constants'; import { useModel } from '../../../generic/model-store'; import fetchCourseRecommendations from './data/thunks'; -import { FAILED, LOADED, LOADING } from './data/slice'; import CatalogSuggestion from './CatalogSuggestion'; import PageLoading from '../../../generic/PageLoading'; import { logClick } from './utils'; diff --git a/src/courseware/course/course-exit/data/slice.js b/src/courseware/course/course-exit/data/slice.js index 6da3f61b1d..0eb55d622a 100644 --- a/src/courseware/course/course-exit/data/slice.js +++ b/src/courseware/course/course-exit/data/slice.js @@ -1,9 +1,10 @@ /* eslint-disable no-param-reassign */ import { createSlice } from '@reduxjs/toolkit'; - -export const LOADING = 'loading'; -export const LOADED = 'loaded'; -export const FAILED = 'failed'; +import { + LOADING, + LOADED, + FAILED, +} from '@src/constants'; const slice = createSlice({ courseId: null, diff --git a/src/courseware/course/course-exit/messages.js b/src/courseware/course/course-exit/messages.ts similarity index 100% rename from src/courseware/course/course-exit/messages.js rename to src/courseware/course/course-exit/messages.ts diff --git a/src/courseware/course/course-license/messages.js b/src/courseware/course/course-license/messages.ts similarity index 100% rename from src/courseware/course/course-license/messages.js rename to src/courseware/course/course-license/messages.ts diff --git a/src/courseware/course/messages.js b/src/courseware/course/messages.ts similarity index 100% rename from src/courseware/course/messages.js rename to src/courseware/course/messages.ts diff --git a/src/courseware/course/new-sidebar/Sidebar.jsx b/src/courseware/course/new-sidebar/Sidebar.tsx similarity index 100% rename from src/courseware/course/new-sidebar/Sidebar.jsx rename to src/courseware/course/new-sidebar/Sidebar.tsx diff --git a/src/courseware/course/new-sidebar/SidebarContext.js b/src/courseware/course/new-sidebar/SidebarContext.js deleted file mode 100644 index 023b868cc9..0000000000 --- a/src/courseware/course/new-sidebar/SidebarContext.js +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react'; - -const SidebarContext = React.createContext({}); - -export default SidebarContext; diff --git a/src/courseware/course/new-sidebar/SidebarContext.ts b/src/courseware/course/new-sidebar/SidebarContext.ts new file mode 100644 index 0000000000..13646a0685 --- /dev/null +++ b/src/courseware/course/new-sidebar/SidebarContext.ts @@ -0,0 +1,37 @@ +import React from 'react'; +import type { WIDGETS } from '@src/constants'; +import type { SIDEBARS } from './sidebars'; + +export type SidebarId = keyof typeof SIDEBARS; +export type WidgetId = keyof typeof WIDGETS; +export type UpgradeNotificationState = ( + | 'accessLastHour' + | 'accessHoursLeft' + | 'accessDaysLeft' + | 'FPDdaysLeft' + | 'FPDLastHour' + | 'accessDateView' + | 'PastExpirationDate' +); + +export interface SidebarContextData { + toggleSidebar: (sidebarId?: SidebarId | null, widgetId?: WidgetId | null) => void; + onNotificationSeen: () => void; + setNotificationStatus: React.Dispatch<'active' | 'inactive'>; + currentSidebar: SidebarId | null; + notificationStatus: 'active' | 'inactive'; + upgradeNotificationCurrentState: UpgradeNotificationState; + setUpgradeNotificationCurrentState: React.Dispatch; + shouldDisplaySidebarOpen: boolean; + shouldDisplayFullScreen: boolean; + courseId: string; + unitId: string; + hideDiscussionbar: boolean; + hideNotificationbar: boolean; + isNotificationbarAvailable: boolean; + isDiscussionbarAvailable: boolean; +} + +const SidebarContext = React.createContext({} as SidebarContextData); + +export default SidebarContext; diff --git a/src/courseware/course/new-sidebar/SidebarContextProvider.jsx b/src/courseware/course/new-sidebar/SidebarContextProvider.tsx similarity index 95% rename from src/courseware/course/new-sidebar/SidebarContextProvider.jsx rename to src/courseware/course/new-sidebar/SidebarContextProvider.tsx index 36993886b1..74d2b7bb7a 100644 --- a/src/courseware/course/new-sidebar/SidebarContextProvider.jsx +++ b/src/courseware/course/new-sidebar/SidebarContextProvider.tsx @@ -1,7 +1,6 @@ import React, { useCallback, useEffect, useMemo, useState, } from 'react'; -import PropTypes from 'prop-types'; import isEmpty from 'lodash/isEmpty'; @@ -13,7 +12,13 @@ import { WIDGETS } from '../../../constants'; import SidebarContext from './SidebarContext'; import { SIDEBARS } from './sidebars'; -const SidebarProvider = ({ +interface Props { + courseId: string; + unitId: string; + children?: React.ReactNode; +} + +const SidebarProvider: React.FC = ({ courseId, unitId, children, @@ -122,14 +127,4 @@ const SidebarProvider = ({ ); }; -SidebarProvider.propTypes = { - courseId: PropTypes.string.isRequired, - unitId: PropTypes.string.isRequired, - children: PropTypes.node, -}; - -SidebarProvider.defaultProps = { - children: null, -}; - export default SidebarProvider; diff --git a/src/courseware/course/new-sidebar/SidebarTriggers.jsx b/src/courseware/course/new-sidebar/SidebarTriggers.tsx similarity index 100% rename from src/courseware/course/new-sidebar/SidebarTriggers.jsx rename to src/courseware/course/new-sidebar/SidebarTriggers.tsx diff --git a/src/courseware/course/new-sidebar/common/SidebarBase.jsx b/src/courseware/course/new-sidebar/common/SidebarBase.tsx similarity index 77% rename from src/courseware/course/new-sidebar/common/SidebarBase.jsx rename to src/courseware/course/new-sidebar/common/SidebarBase.tsx index cc606fe298..5438c9f5c0 100644 --- a/src/courseware/course/new-sidebar/common/SidebarBase.jsx +++ b/src/courseware/course/new-sidebar/common/SidebarBase.tsx @@ -1,5 +1,4 @@ import React, { useCallback, useContext } from 'react'; -import PropTypes from 'prop-types'; import classNames from 'classnames'; @@ -10,18 +9,30 @@ import { ArrowBackIos, Close } from '@openedx/paragon/icons'; import { useEventListener } from '../../../../generic/hooks'; import { WIDGETS } from '../../../../constants'; import messages from '../messages'; -import SidebarContext from '../SidebarContext'; +import SidebarContext, { type SidebarId } from '../SidebarContext'; -const SidebarBase = ({ - title, +interface Props { + title?: string; + ariaLabel: string; + sidebarId: SidebarId; + className?: string; + children: React.ReactNode; + showTitleBar?: boolean; + width?: string; + allowFullHeight?: boolean; + showBorder?: boolean; +} + +const SidebarBase: React.FC = ({ + title = '', ariaLabel, sidebarId, className, children, - showTitleBar, - width, - allowFullHeight, - showBorder, + showTitleBar = true, + width = '45rem', + allowFullHeight = false, + showBorder = true, }) => { const intl = useIntl(); const { @@ -58,8 +69,7 @@ const SidebarBase = ({ onClick={() => toggleSidebar(null)} onKeyDown={() => toggleSidebar(null)} role="button" - tabIndex="0" - alt={intl.formatMessage(messages.responsiveCloseSidebarTray)} + tabIndex={0} > @@ -90,25 +100,4 @@ const SidebarBase = ({ ); }; -SidebarBase.propTypes = { - title: PropTypes.string, - ariaLabel: PropTypes.string.isRequired, - sidebarId: PropTypes.string.isRequired, - className: PropTypes.string, - children: PropTypes.element.isRequired, - showTitleBar: PropTypes.bool, - width: PropTypes.string, - allowFullHeight: PropTypes.bool, - showBorder: PropTypes.bool, -}; - -SidebarBase.defaultProps = { - title: '', - width: '45rem', - allowFullHeight: false, - showTitleBar: true, - className: '', - showBorder: true, -}; - export default SidebarBase; diff --git a/src/courseware/course/new-sidebar/icons/RightSidebarFilled.jsx b/src/courseware/course/new-sidebar/icons/RightSidebarFilled.tsx similarity index 91% rename from src/courseware/course/new-sidebar/icons/RightSidebarFilled.jsx rename to src/courseware/course/new-sidebar/icons/RightSidebarFilled.tsx index d510f32139..be489c5988 100644 --- a/src/courseware/course/new-sidebar/icons/RightSidebarFilled.jsx +++ b/src/courseware/course/new-sidebar/icons/RightSidebarFilled.tsx @@ -1,5 +1,3 @@ -import * as React from 'react'; - const RightSidebarFilled = (props) => ( ( { excludeFetchSequence: false, }); axiosMock = new MockAdapter(getAuthenticatedHttpClient()); - const state = store.getState(); + const state = store.getState() as any; // TODO: remove 'any' once redux state gets types courseId = state.courseware.courseId; [unitId] = Object.keys(state.models.units); diff --git a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/discussions/DiscussionsWidget.jsx b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/discussions/DiscussionsWidget.tsx similarity index 100% rename from src/courseware/course/new-sidebar/sidebars/discussions-notifications/discussions/DiscussionsWidget.jsx rename to src/courseware/course/new-sidebar/sidebars/discussions-notifications/discussions/DiscussionsWidget.tsx diff --git a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/index.js b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/index.ts similarity index 100% rename from src/courseware/course/new-sidebar/sidebars/discussions-notifications/index.js rename to src/courseware/course/new-sidebar/sidebars/discussions-notifications/index.ts diff --git a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.jsx b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.tsx similarity index 85% rename from src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.jsx rename to src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.tsx index 6cfbb3cabd..23b437d2b7 100644 --- a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.jsx +++ b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.tsx @@ -14,7 +14,7 @@ import { import initializeStore from '../../../../../../store'; import { appendBrowserTimezoneToUrl, executeThunk } from '../../../../../../utils'; import { fetchCourse } from '../../../../../data'; -import SidebarContext from '../../../SidebarContext'; +import SidebarContext, { SidebarContextData } from '../../../SidebarContext'; import NotificationsWidget from './NotificationsWidget'; import setupDiscussionSidebar from '../../../../test-utils'; @@ -24,7 +24,7 @@ jest.mock('@edx/frontend-platform/analytics'); describe('NotificationsWidget', () => { let axiosMock; let store; - const ID = 'NEWSIDEBAR'; + const ID = 'DISCUSSIONS_NOTIFICATIONS'; const defaultMetadata = Factory.build('courseMetadata'); const courseId = defaultMetadata.id; let courseMetadataUrl = `${getConfig().LMS_BASE_URL}/api/courseware/course/${defaultMetadata.id}`; @@ -33,7 +33,7 @@ describe('NotificationsWidget', () => { const courseHomeMetadata = Factory.build('courseHomeMetadata'); const courseHomeMetadataUrl = appendBrowserTimezoneToUrl(`${getConfig().LMS_BASE_URL}/api/course_home/course_metadata/${courseId}`); - function setMetadata(attributes, options) { + function setMetadata(attributes, options = undefined) { const updatedCourseHomeMetadata = Factory.build('courseHomeMetadata', attributes, options); axiosMock.onGet(courseHomeMetadataUrl).reply(200, updatedCourseHomeMetadata); } @@ -85,7 +85,7 @@ describe('NotificationsWidget', () => { courseId, hideNotificationbar: false, isNotificationbarAvailable: true, - }} + } as SidebarContextData} > , @@ -94,14 +94,14 @@ describe('NotificationsWidget', () => { }); it('renders upgrade card', async () => { + const contextData: Partial = { + currentSidebar: ID, + courseId, + hideNotificationbar: false, + isNotificationbarAvailable: true, + }; await fetchAndRender( - + , ); @@ -116,14 +116,14 @@ describe('NotificationsWidget', () => { it('renders no notifications bar if no verified mode', async () => { setMetadata({ verified_mode: null }); + const contextData: Partial = { + currentSidebar: ID, + courseId, + hideNotificationbar: true, + isNotificationbarAvailable: false, + }; await fetchAndRender( - + , ); @@ -170,15 +170,15 @@ describe('NotificationsWidget', () => { it('marks notification as seen 3 seconds later', async () => { const onNotificationSeen = jest.fn(); + const contextData: Partial = { + currentSidebar: ID, + courseId, + onNotificationSeen, + hideNotificationbar: false, + isNotificationbarAvailable: true, + }; await fetchAndRender( - + , ); diff --git a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.jsx b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.tsx similarity index 97% rename from src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.jsx rename to src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.tsx index 7e7087ac5b..86fa54e728 100644 --- a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.jsx +++ b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.tsx @@ -65,6 +65,7 @@ const NotificationsWidget = () => { // After three seconds, update notificationSeen (to hide red dot) useEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-implied-eval setTimeout(onNotificationSeen, 3000); sendTrackEvent('edx.ui.course.upgrade.new_sidebar.notifications', notificationTrayEventProperties); }, []); @@ -94,7 +95,6 @@ const NotificationsWidget = () => { timeOffsetMillis={timeOffsetMillis} courseId={courseId} org={org} - upgradeNotificationCurrentState={upgradeNotificationCurrentState} setupgradeNotificationCurrentState={setUpgradeNotificationCurrentState} toggleSidebar={onToggleSidebar} /> diff --git a/src/courseware/course/new-sidebar/sidebars/index.js b/src/courseware/course/new-sidebar/sidebars/index.ts similarity index 93% rename from src/courseware/course/new-sidebar/sidebars/index.js rename to src/courseware/course/new-sidebar/sidebars/index.ts index d254ecc751..637a6e5ece 100644 --- a/src/courseware/course/new-sidebar/sidebars/index.js +++ b/src/courseware/course/new-sidebar/sidebars/index.ts @@ -6,8 +6,8 @@ export const SIDEBARS = { Sidebar: discussionsNotifications.Sidebar, Trigger: discussionsNotifications.Trigger, }, -}; +} as const; export const SIDEBAR_ORDER = [ discussionsNotifications.ID, -]; +] as const; diff --git a/src/courseware/course/sequence/Sequence.jsx b/src/courseware/course/sequence/Sequence.jsx index 9d7c0c4e7b..1a2a8f2d33 100644 --- a/src/courseware/course/sequence/Sequence.jsx +++ b/src/courseware/course/sequence/Sequence.jsx @@ -1,4 +1,4 @@ -/* eslint-disable no-use-before-define */ +/* eslint-disable @typescript-eslint/no-use-before-define */ import { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; diff --git a/src/courseware/course/sequence/content-lock/messages.js b/src/courseware/course/sequence/content-lock/messages.ts similarity index 100% rename from src/courseware/course/sequence/content-lock/messages.js rename to src/courseware/course/sequence/content-lock/messages.ts diff --git a/src/courseware/course/sequence/hidden-after-due/messages.js b/src/courseware/course/sequence/hidden-after-due/messages.ts similarity index 100% rename from src/courseware/course/sequence/hidden-after-due/messages.js rename to src/courseware/course/sequence/hidden-after-due/messages.ts diff --git a/src/courseware/course/sequence/honor-code/messages.js b/src/courseware/course/sequence/honor-code/messages.ts similarity index 100% rename from src/courseware/course/sequence/honor-code/messages.js rename to src/courseware/course/sequence/honor-code/messages.ts diff --git a/src/courseware/course/sequence/lock-paywall/messages.js b/src/courseware/course/sequence/lock-paywall/messages.ts similarity index 100% rename from src/courseware/course/sequence/lock-paywall/messages.js rename to src/courseware/course/sequence/lock-paywall/messages.ts diff --git a/src/courseware/course/sequence/messages.js b/src/courseware/course/sequence/messages.ts similarity index 100% rename from src/courseware/course/sequence/messages.js rename to src/courseware/course/sequence/messages.ts diff --git a/src/courseware/course/sequence/sequence-navigation/SequenceNavigation.jsx b/src/courseware/course/sequence/sequence-navigation/SequenceNavigation.jsx index 3b16312d62..38fd16bbc3 100644 --- a/src/courseware/course/sequence/sequence-navigation/SequenceNavigation.jsx +++ b/src/courseware/course/sequence/sequence-navigation/SequenceNavigation.jsx @@ -13,12 +13,12 @@ import { import { PluginSlot } from '@openedx/frontend-plugin-framework'; import { useSelector } from 'react-redux'; +import { LOADED } from '@src/constants'; import { GetCourseExitNavigation } from '../../course-exit'; import UnitButton from './UnitButton'; import SequenceNavigationTabs from './SequenceNavigationTabs'; import { useSequenceNavigationMetadata } from './hooks'; import { useModel } from '../../../../generic/model-store'; -import { LOADED } from '../../../data/slice'; import messages from './messages'; diff --git a/src/courseware/course/sequence/sequence-navigation/messages.js b/src/courseware/course/sequence/sequence-navigation/messages.ts similarity index 100% rename from src/courseware/course/sequence/sequence-navigation/messages.js rename to src/courseware/course/sequence/sequence-navigation/messages.ts diff --git a/src/courseware/course/share/messages.js b/src/courseware/course/share/messages.ts similarity index 100% rename from src/courseware/course/share/messages.js rename to src/courseware/course/share/messages.ts diff --git a/src/courseware/course/sidebar/sidebars/course-outline/CourseOutlineTray.jsx b/src/courseware/course/sidebar/sidebars/course-outline/CourseOutlineTray.jsx index f327f51a65..833562216a 100644 --- a/src/courseware/course/sidebar/sidebars/course-outline/CourseOutlineTray.jsx +++ b/src/courseware/course/sidebar/sidebars/course-outline/CourseOutlineTray.jsx @@ -9,7 +9,7 @@ import { } from '@openedx/paragon/icons'; import { useModel } from '@src/generic/model-store'; -import { LOADING, LOADED } from '@src/course-home/data/slice'; +import { LOADING, LOADED } from '@src/constants'; import PageLoading from '@src/generic/PageLoading'; import { getSequenceId, diff --git a/src/courseware/course/sidebar/sidebars/course-outline/messages.js b/src/courseware/course/sidebar/sidebars/course-outline/messages.ts similarity index 100% rename from src/courseware/course/sidebar/sidebars/course-outline/messages.js rename to src/courseware/course/sidebar/sidebars/course-outline/messages.ts diff --git a/src/courseware/course/sidebar/sidebars/discussions/messages.js b/src/courseware/course/sidebar/sidebars/discussions/messages.ts similarity index 100% rename from src/courseware/course/sidebar/sidebars/discussions/messages.js rename to src/courseware/course/sidebar/sidebars/discussions/messages.ts diff --git a/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx b/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx index de8ec204cb..c39d9d45e2 100644 --- a/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx +++ b/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx @@ -64,6 +64,7 @@ const NotificationTray = ({ intl }) => { }; // After three seconds, update notificationSeen (to hide red dot) useEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-implied-eval setTimeout(onNotificationSeen, 3000); sendTrackEvent('edx.ui.course.upgrade.old_sidebar.notifications', notificationTrayEventProperties); }, []); diff --git a/src/courseware/data/redux.test.js b/src/courseware/data/redux.test.js index a56a87d45d..2c8f5469a1 100644 --- a/src/courseware/data/redux.test.js +++ b/src/courseware/data/redux.test.js @@ -4,8 +4,8 @@ import MockAdapter from 'axios-mock-adapter'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import { getConfig } from '@edx/frontend-platform'; +import { FAILED, LOADING } from '@src/constants'; import * as thunks from './thunks'; -import { FAILED, LOADING } from './slice'; import { appendBrowserTimezoneToUrl, executeThunk } from '../../utils'; diff --git a/src/courseware/data/selectors.js b/src/courseware/data/selectors.js index b15c69b6cf..b042826b9c 100644 --- a/src/courseware/data/selectors.js +++ b/src/courseware/data/selectors.js @@ -1,4 +1,4 @@ -import { LOADED } from './slice'; +import { LOADED } from '@src/constants'; export function sequenceIdsSelector(state) { if (state.courseware.courseStatus !== LOADED) { diff --git a/src/courseware/data/slice.js b/src/courseware/data/slice.js index 7ab7b048b4..6178339832 100644 --- a/src/courseware/data/slice.js +++ b/src/courseware/data/slice.js @@ -1,10 +1,12 @@ /* eslint-disable no-param-reassign */ import { createSlice } from '@reduxjs/toolkit'; -export const LOADING = 'loading'; -export const LOADED = 'loaded'; -export const FAILED = 'failed'; -export const DENIED = 'denied'; +import { + LOADING, + LOADED, + FAILED, + DENIED, +} from '@src/constants'; const slice = createSlice({ name: 'courseware', diff --git a/src/courseware/messages.js b/src/courseware/messages.ts similarity index 100% rename from src/courseware/messages.js rename to src/courseware/messages.ts diff --git a/src/courseware/social-share/messages.js b/src/courseware/social-share/messages.ts similarity index 100% rename from src/courseware/social-share/messages.js rename to src/courseware/social-share/messages.ts diff --git a/src/frontend-platform.d.ts b/src/frontend-platform.d.ts new file mode 100644 index 0000000000..d9b2f7f91b --- /dev/null +++ b/src/frontend-platform.d.ts @@ -0,0 +1,41 @@ +// frontend-platform currently doesn't provide types... do it ourselves for i18n module at least. +// We can remove this in the future when we migrate to frontend-shell, or when frontend-platform gets types +// (whichever comes first). + +declare module '@edx/frontend-platform/i18n' { + // eslint-disable-next-line import/no-extraneous-dependencies + import { injectIntl as _injectIntl } from 'react-intl'; + /** @deprecated Use useIntl() hook instead. */ + export const injectIntl: typeof _injectIntl; + /** @deprecated Use useIntl() hook instead. */ + export const intlShape: any; + + // eslint-disable-next-line import/no-extraneous-dependencies + export { + createIntl, + FormattedDate, + FormattedTime, + FormattedRelativeTime, + FormattedNumber, + FormattedPlural, + FormattedMessage, + defineMessages, + IntlProvider, + useIntl, + } from 'react-intl'; + + // Other exports from the i18n module: + export const configure: any; + export const getPrimaryLanguageSubtag: (code: string) => string; + export const getLocale: (locale?: string) => string; + export const getMessages: any; + export const isRtl: (locale?: string) => boolean; + export const handleRtl: any; + export const mergeMessages: any; + export const LOCALE_CHANGED: any; + export const LOCALE_TOPIC: any; + export const getCountryList: any; + export const getCountryMessages: any; + export const getLanguageList: any; + export const getLanguageMessages: any; +} diff --git a/src/generic/CourseAccessErrorPage.jsx b/src/generic/CourseAccessErrorPage.jsx index 1178a3ed1c..ac6ab3f935 100644 --- a/src/generic/CourseAccessErrorPage.jsx +++ b/src/generic/CourseAccessErrorPage.jsx @@ -4,10 +4,10 @@ import { useParams, Navigate } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; import FooterSlot from '@openedx/frontend-slot-footer'; +import { LOADED, LOADING } from '@src/constants'; import useActiveEnterpriseAlert from '../alerts/active-enteprise-alert'; import { AlertList } from './user-messages'; import { fetchDiscussionTab } from '../course-home/data/thunks'; -import { LOADED, LOADING } from '../course-home/data/slice'; import PageLoading from './PageLoading'; import messages from '../tab-page/messages'; diff --git a/src/generic/messages.js b/src/generic/messages.ts similarity index 100% rename from src/generic/messages.js rename to src/generic/messages.ts diff --git a/src/generic/upgrade-button/messages.js b/src/generic/upgrade-button/messages.ts similarity index 100% rename from src/generic/upgrade-button/messages.js rename to src/generic/upgrade-button/messages.ts diff --git a/src/generic/upgrade-notification/UpgradeNotification.jsx b/src/generic/upgrade-notification/UpgradeNotification.jsx index e9d3b5dde9..861299dec8 100644 --- a/src/generic/upgrade-notification/UpgradeNotification.jsx +++ b/src/generic/upgrade-notification/UpgradeNotification.jsx @@ -1,9 +1,7 @@ import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { - useIntl, FormattedDate, FormattedMessage, injectIntl, -} from '@edx/frontend-platform/i18n'; +import { useIntl, FormattedDate, FormattedMessage } from '@edx/frontend-platform/i18n'; import { sendTrackEvent, sendTrackingLogEvent } from '@edx/frontend-platform/analytics'; import { Button, Icon, IconButton } from '@openedx/paragon'; import { Close } from '@openedx/paragon/icons'; @@ -561,4 +559,4 @@ UpgradeNotification.defaultProps = { toggleSidebar: null, }; -export default injectIntl(UpgradeNotification); +export default UpgradeNotification; diff --git a/src/instructor-toolbar/masquerade-widget/messages.js b/src/instructor-toolbar/masquerade-widget/messages.ts similarity index 100% rename from src/instructor-toolbar/masquerade-widget/messages.js rename to src/instructor-toolbar/masquerade-widget/messages.ts diff --git a/src/preferences-unsubscribe/index.jsx b/src/preferences-unsubscribe/index.jsx index af9ba379c5..63a96c718a 100644 --- a/src/preferences-unsubscribe/index.jsx +++ b/src/preferences-unsubscribe/index.jsx @@ -10,7 +10,7 @@ import { sendTrackEvent } from '@edx/frontend-platform/analytics'; import { logError } from '@edx/frontend-platform/logging'; import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n'; -import { LOADED, LOADING, FAILED } from '../constants'; +import { LOADED, LOADING, FAILED } from '@src/constants'; import PageLoading from '../generic/PageLoading'; import { unsubscribeNotificationPreferences } from './data/api'; import messages from './messages'; diff --git a/src/preferences-unsubscribe/messages.js b/src/preferences-unsubscribe/messages.ts similarity index 100% rename from src/preferences-unsubscribe/messages.js rename to src/preferences-unsubscribe/messages.ts diff --git a/src/product-tours/messages.js b/src/product-tours/messages.ts similarity index 100% rename from src/product-tours/messages.js rename to src/product-tours/messages.ts diff --git a/src/setupTest.js b/src/setupTest.js index a4cdba2df3..02abd12c02 100755 --- a/src/setupTest.js +++ b/src/setupTest.js @@ -193,10 +193,10 @@ export async function initializeTestStore(options = {}, overrideStore = true) { logUnhandledRequests(axiosMock); - // eslint-disable-next-line no-unused-expressions + // eslint-disable-next-line @typescript-eslint/no-unused-expressions !options.excludeFetchCourse && await executeThunk(fetchCourse(courseMetadata.id), store.dispatch); - // eslint-disable-next-line no-unused-expressions + // eslint-disable-next-line @typescript-eslint/no-unused-expressions !options.excludeFetchOutlineSidebar && await executeThunk( getCourseOutlineStructure(courseMetadata.id), store.dispatch, diff --git a/src/shared/effort-estimate/messages.js b/src/shared/effort-estimate/messages.ts similarity index 100% rename from src/shared/effort-estimate/messages.js rename to src/shared/effort-estimate/messages.ts diff --git a/src/shared/streak-celebration/StreakCelebrationModal.jsx b/src/shared/streak-celebration/StreakCelebrationModal.jsx index 31897b61b7..cd515dbec9 100644 --- a/src/shared/streak-celebration/StreakCelebrationModal.jsx +++ b/src/shared/streak-celebration/StreakCelebrationModal.jsx @@ -64,7 +64,7 @@ const StreakModal = ({ }) => { const { org, celebrations, username } = useModel('courseHomeMeta', courseId); const factoid = getRandomFactoid(intl, streakLengthToCelebrate); - // eslint-disable-next-line no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars const [randomFactoid, setRandomFactoid] = useState(factoid); // Don't change factoid on re-render // Open edX Folks: if you create a voucher with this code, the MFE will notice and show the discount diff --git a/src/shared/streak-celebration/messages.js b/src/shared/streak-celebration/messages.ts similarity index 100% rename from src/shared/streak-celebration/messages.js rename to src/shared/streak-celebration/messages.ts diff --git a/src/tab-page/messages.js b/src/tab-page/messages.ts similarity index 100% rename from src/tab-page/messages.js rename to src/tab-page/messages.ts diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index 86090965f3..0000000000 --- a/src/utils.js +++ /dev/null @@ -1,17 +0,0 @@ -// Helper, that is used to forcibly finalize all promises -// in thunk before running matcher against state. -export const executeThunk = async (thunk, dispatch, getState) => { - await thunk(dispatch, getState); - await new Promise(setImmediate); -}; - -// Utility function for appending the browser timezone to the url -// Can be used on the backend when the user timezone is not set in the user account -export const appendBrowserTimezoneToUrl = (url) => { - const browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone; - const urlObject = new URL(url); - if (browserTimezone) { - urlObject.searchParams.append('browser_timezone', browserTimezone); - } - return urlObject.href; -}; diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000000..5ea68509cd --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,23 @@ +/** + * Helper, that is used to forcibly finalize all promises + * in thunk before running matcher against state. + * + * TODO: move this to setupTest or testUtils - it's only used in tests. + */ +export const executeThunk = async (thunk, dispatch, getState = undefined) => { + await thunk(dispatch, getState); + await new Promise(setImmediate); +}; + +/** + * Utility function for appending the browser timezone to the url + * Can be used on the backend when the user timezone is not set in the user account + */ +export const appendBrowserTimezoneToUrl = (url: string) => { + const browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone; + const urlObject = new URL(url); + if (browserTimezone) { + urlObject.searchParams.append('browser_timezone', browserTimezone); + } + return urlObject.href; +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000..5c94e0e7a0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@edx/typescript-config", + "compilerOptions": { + "outDir": "dist", + "baseUrl": "./src", + "paths": { + "*": ["*"], + "@src/*": ["*"] + } + }, + "include": ["*.js", ".eslintrc.js", "src/**/*", "plugins/**/*"], + "exclude": ["dist", "node_modules"] +}