@openedx/frontend-app-learner-dashboard 2.0.0-alpha.2 → 2.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/containers/CoursesPanel/NoCoursesView/index.js +3 -3
- package/dist/containers/CoursesPanel/NoCoursesView/index.js.map +1 -1
- package/dist/data/services/lms/urls.d.ts +1 -0
- package/dist/data/services/lms/urls.js +12 -2
- package/dist/data/services/lms/urls.js.map +1 -1
- package/dist/testUtils.d.ts +2 -0
- package/dist/testUtils.js +22 -0
- package/dist/testUtils.js.map +1 -1
- package/dist/tracking/trackers/findCourses.d.ts +1 -1
- package/dist/tracking/trackers/findCourses.js +8 -1
- package/dist/tracking/trackers/findCourses.js.map +1 -1
- package/dist/widgets/LearnerDashboardHeader/DiscoverLinkMenuItem.js +1 -1
- package/dist/widgets/LearnerDashboardHeader/DiscoverLinkMenuItem.js.map +1 -1
- package/dist/widgets/LookingForChallengeWidget/index.js +4 -4
- package/dist/widgets/LookingForChallengeWidget/index.js.map +1 -1
- package/dist/widgets/LookingForChallengeWidget/track.d.ts +1 -1
- package/package.json +8 -4
package/dist/constants.d.ts
CHANGED
package/dist/constants.js
CHANGED
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,2CAA2C,CAAC;AACjE,MAAM,CAAC,MAAM,aAAa,GAAG,qCAAqC,CAAC","sourcesContent":["export const appId = 'org.openedx.frontend.app.learnerDashboard';\nexport const dashboardRole = 'org.openedx.frontend.role.dashboard';\n"]}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,2CAA2C,CAAC;AACjE,MAAM,CAAC,MAAM,aAAa,GAAG,qCAAqC,CAAC;AACnE,MAAM,CAAC,MAAM,WAAW,GAAG,mCAAmC,CAAC","sourcesContent":["export const appId = 'org.openedx.frontend.app.learnerDashboard';\nexport const dashboardRole = 'org.openedx.frontend.role.dashboard';\nexport const coursesRole = 'org.openedx.frontend.role.courses';\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { useIntl } from '@openedx/frontend-base';
|
|
3
|
+
import { getLinkProps, useIntl } from '@openedx/frontend-base';
|
|
4
4
|
import { Button, Image } from '@openedx/paragon';
|
|
5
5
|
import { Search } from '@openedx/paragon/icons';
|
|
6
|
-
import {
|
|
6
|
+
import { coursesUrl } from '../../../data/services/lms/urls';
|
|
7
7
|
import emptyCourseSVG from '../../../assets/empty-course.svg';
|
|
8
8
|
import { useInitializeLearnerHome } from '../../../data/hooks';
|
|
9
9
|
import messages from './messages';
|
|
@@ -13,7 +13,7 @@ export const NoCoursesView = () => {
|
|
|
13
13
|
const { formatMessage } = useIntl();
|
|
14
14
|
const { data: learnerData } = useInitializeLearnerHome();
|
|
15
15
|
const courseSearchUrl = ((_a = learnerData === null || learnerData === void 0 ? void 0 : learnerData.platformSettings) === null || _a === void 0 ? void 0 : _a.courseSearchUrl) || '';
|
|
16
|
-
return (_jsxs("div", { id: "no-courses-content-view", className: "d-flex align-items-center justify-content-center mb-4.5", children: [_jsx(Image, { src: emptyCourseSVG, alt: formatMessage(messages.bannerAlt) }), _jsx("h3", { className: "h1", children: formatMessage(messages.lookingForChallengePrompt) }), _jsx("p", { children: formatMessage(messages.exploreCoursesPrompt) }), _jsx(Button, { variant: "brand"
|
|
16
|
+
return (_jsxs("div", { id: "no-courses-content-view", className: "d-flex align-items-center justify-content-center mb-4.5", children: [_jsx(Image, { src: emptyCourseSVG, alt: formatMessage(messages.bannerAlt) }), _jsx("h3", { className: "h1", children: formatMessage(messages.lookingForChallengePrompt) }), _jsx("p", { children: formatMessage(messages.exploreCoursesPrompt) }), _jsx(Button, Object.assign({ variant: "brand" }, getLinkProps(coursesUrl(courseSearchUrl)), { iconBefore: Search, children: formatMessage(messages.exploreCoursesButton) }))] }));
|
|
17
17
|
};
|
|
18
18
|
export default NoCoursesView;
|
|
19
19
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/containers/CoursesPanel/NoCoursesView/index.jsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/containers/CoursesPanel/NoCoursesView/index.jsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,cAAc,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,cAAc,CAAC;AAEtB,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE;;IAChC,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,wBAAwB,EAAE,CAAC;IACzD,MAAM,eAAe,GAAG,CAAA,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,gBAAgB,0CAAE,eAAe,KAAI,EAAE,CAAC;IAC7E,OAAO,CACL,eACE,EAAE,EAAC,yBAAyB,EAC5B,SAAS,EAAC,yDAAyD,aAEnE,KAAC,KAAK,IAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAI,EACtE,aAAI,SAAS,EAAC,IAAI,YACf,aAAa,CAAC,QAAQ,CAAC,yBAAyB,CAAC,GAC/C,EACL,sBACG,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC,GAC3C,EACJ,KAAC,MAAM,kBACL,OAAO,EAAC,OAAO,IACX,YAAY,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,IAC7C,UAAU,EAAE,MAAM,YAEjB,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IACtC,IACL,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,aAAa,CAAC","sourcesContent":["import React from 'react';\nimport { getLinkProps, useIntl } from '@openedx/frontend-base';\nimport { Button, Image } from '@openedx/paragon';\nimport { Search } from '@openedx/paragon/icons';\nimport { coursesUrl } from '@src/data/services/lms/urls';\n\nimport emptyCourseSVG from '@src/assets/empty-course.svg';\nimport { useInitializeLearnerHome } from '@src/data/hooks';\n\nimport messages from './messages';\nimport './index.scss';\n\nexport const NoCoursesView = () => {\n const { formatMessage } = useIntl();\n const { data: learnerData } = useInitializeLearnerHome();\n const courseSearchUrl = learnerData?.platformSettings?.courseSearchUrl || '';\n return (\n <div\n id=\"no-courses-content-view\"\n className=\"d-flex align-items-center justify-content-center mb-4.5\"\n >\n <Image src={emptyCourseSVG} alt={formatMessage(messages.bannerAlt)} />\n <h3 className=\"h1\">\n {formatMessage(messages.lookingForChallengePrompt)}\n </h3>\n <p>\n {formatMessage(messages.exploreCoursesPrompt)}\n </p>\n <Button\n variant=\"brand\"\n {...getLinkProps(coursesUrl(courseSearchUrl))}\n iconBefore={Search}\n >\n {formatMessage(messages.exploreCoursesButton)}\n </Button>\n </div>\n );\n};\n\nexport default NoCoursesView;\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export function getApiUrl(): string;
|
|
2
2
|
export function updateUrl(base: any, url: any): any;
|
|
3
3
|
export function baseAppUrl(url: any): any;
|
|
4
|
+
export function coursesUrl(courseSearchUrl: any): any;
|
|
4
5
|
export function creditPurchaseUrl(courseId: any): string | null;
|
|
5
6
|
export function creditRequestUrl(providerId: any): string;
|
|
6
7
|
declare const _default: any;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { appId } from '../../../constants';
|
|
1
|
+
import { appId, coursesRole } from '../../../constants';
|
|
2
2
|
import { StrictDict } from '../../../utils';
|
|
3
|
-
import { getAppConfig, getSiteConfig } from '@openedx/frontend-base';
|
|
3
|
+
import { getAppConfig, getSiteConfig, resolveRouteByRole } from '@openedx/frontend-base';
|
|
4
4
|
const getBaseUrl = () => getSiteConfig().lmsBaseUrl;
|
|
5
5
|
export const getApiUrl = () => (`${getSiteConfig().lmsBaseUrl}/api`);
|
|
6
6
|
const getInitApiUrl = () => (`${getApiUrl()}/learner_home/init`);
|
|
@@ -13,6 +13,15 @@ export const updateUrl = (base, url) => ((url == null || url.startsWith('http://
|
|
|
13
13
|
export const baseAppUrl = (url) => updateUrl(getBaseUrl(), url);
|
|
14
14
|
// static view url
|
|
15
15
|
const programsUrl = () => baseAppUrl('/dashboard/programs');
|
|
16
|
+
/**
|
|
17
|
+
* Returns the URL for browsing courses: the courses route if an app in the running site
|
|
18
|
+
* provides one, so navigation stays within the SPA, or otherwise the course search URL the
|
|
19
|
+
* LMS reports (`courseSearchUrl`), made absolute.
|
|
20
|
+
*/
|
|
21
|
+
export const coursesUrl = (courseSearchUrl) => {
|
|
22
|
+
var _a, _b;
|
|
23
|
+
return ((_b = (_a = resolveRouteByRole(coursesRole)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : baseAppUrl(courseSearchUrl));
|
|
24
|
+
};
|
|
16
25
|
/**
|
|
17
26
|
* Returns the credit purchase URL for a course, or `null` when the site
|
|
18
27
|
* configures neither CREDIT_PURCHASE_URL nor ECOMMERCE_BASE_URL.
|
|
@@ -31,6 +40,7 @@ export default StrictDict({
|
|
|
31
40
|
getApiUrl,
|
|
32
41
|
baseAppUrl,
|
|
33
42
|
courseUnenroll,
|
|
43
|
+
coursesUrl,
|
|
34
44
|
creditPurchaseUrl,
|
|
35
45
|
creditRequestUrl,
|
|
36
46
|
entitlementEnrollment,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../../../../src/data/services/lms/urls.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../../../../src/data/services/lms/urls.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEzF,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,UAAU,CAAC;AAEpD,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,aAAa,EAAE,CAAC,UAAU,MAAM,CAAC,CAAC;AAErE,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,SAAS,EAAE,oBAAoB,CAAC,CAAC;AAEjE,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,GAAG,UAAU,EAAE,QAAQ,CAAC;AAC5C,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC,GAAG,UAAU,EAAE,oBAAoB,CAAC;AACjE,MAAM,mBAAmB,GAAG,GAAG,EAAE,CAAC,GAAG,SAAS,EAAE,wBAAwB,CAAC;AACzE,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,SAAS,EAAE,iCAAiC,IAAI,cAAc,CAAC;AAE1G,8CAA8C;AAC9C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,EAAE,CAAC,CAAC;AAE3I,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,GAAG,CAAC,CAAC;AAEhE,kBAAkB;AAClB,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC;AAE5D;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,eAAe,EAAE,EAAE;;IAAC,OAAA,CAC7C,MAAA,MAAA,kBAAkB,CAAC,WAAW,CAAC,0CAAE,GAAG,mCAAI,UAAU,CAAC,eAAe,CAAC,CACpE,CAAA;CAAA,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAQ,EAAE,EAAE;IAC5C,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAC/B,OAAO,GAAG,MAAM,CAAC,mBAAmB,IAAI,QAAQ,GAAG,CAAC;IACtD,CAAC;IACD,OAAO,MAAM,CAAC,kBAAkB;QAC9B,CAAC,CAAC,GAAG,MAAM,CAAC,kBAAkB,oBAAoB,QAAQ,GAAG;QAC7D,CAAC,CAAC,IAAI,CAAC;AACX,CAAC,CAAC;AACF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,GAAG,SAAS,EAAE,wBAAwB,UAAU,WAAW,CAAC;AAE5G,eAAe,UAAU,CAAC;IACxB,SAAS;IACT,UAAU;IACV,cAAc;IACd,UAAU;IACV,iBAAiB;IACjB,gBAAgB;IAChB,qBAAqB;IACrB,KAAK;IACL,aAAa;IACb,WAAW;IACX,mBAAmB;CACpB,CAAC,CAAC","sourcesContent":["import { appId, coursesRole } from '../../../constants';\nimport { StrictDict } from '../../../utils';\n\nimport { getAppConfig, getSiteConfig, resolveRouteByRole } from '@openedx/frontend-base';\n\nconst getBaseUrl = () => getSiteConfig().lmsBaseUrl;\n\nexport const getApiUrl = () => (`${getSiteConfig().lmsBaseUrl}/api`);\n\nconst getInitApiUrl = () => (`${getApiUrl()}/learner_home/init`);\n\nconst event = () => `${getBaseUrl()}/event`;\nconst courseUnenroll = () => `${getBaseUrl()}/change_enrollment`;\nconst updateEmailSettings = () => `${getApiUrl()}/change_email_settings`;\nconst entitlementEnrollment = (uuid) => `${getApiUrl()}/entitlements/v1/entitlements/${uuid}/enrollments`;\n\n// if url is null or absolute, return it as is\nexport const updateUrl = (base, url) => ((url == null || url.startsWith('http://') || url.startsWith('https://')) ? url : `${base}${url}`);\n\nexport const baseAppUrl = (url) => updateUrl(getBaseUrl(), url);\n\n// static view url\nconst programsUrl = () => baseAppUrl('/dashboard/programs');\n\n/**\n * Returns the URL for browsing courses: the courses route if an app in the running site\n * provides one, so navigation stays within the SPA, or otherwise the course search URL the\n * LMS reports (`courseSearchUrl`), made absolute.\n */\nexport const coursesUrl = (courseSearchUrl) => (\n resolveRouteByRole(coursesRole)?.url ?? baseAppUrl(courseSearchUrl)\n);\n\n/**\n * Returns the credit purchase URL for a course, or `null` when the site\n * configures neither CREDIT_PURCHASE_URL nor ECOMMERCE_BASE_URL.\n */\nexport const creditPurchaseUrl = (courseId) => {\n const config = getAppConfig(appId);\n if (config.CREDIT_PURCHASE_URL) {\n return `${config.CREDIT_PURCHASE_URL}/${courseId}/`;\n }\n return config.ECOMMERCE_BASE_URL\n ? `${config.ECOMMERCE_BASE_URL}/credit/checkout/${courseId}/`\n : null;\n};\nexport const creditRequestUrl = (providerId) => `${getApiUrl()}/credit/v1/providers/${providerId}/request/`;\n\nexport default StrictDict({\n getApiUrl,\n baseAppUrl,\n courseUnenroll,\n coursesUrl,\n creditPurchaseUrl,\n creditRequestUrl,\n entitlementEnrollment,\n event,\n getInitApiUrl,\n programsUrl,\n updateEmailSettings,\n});\n"]}
|
package/dist/testUtils.d.ts
CHANGED
package/dist/testUtils.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import react from 'react';
|
|
3
|
+
import { useLocation } from 'react-router-dom';
|
|
4
|
+
import { mergeSiteConfig } from '@openedx/frontend-base';
|
|
3
5
|
import { StrictDict } from './utils';
|
|
4
6
|
/**
|
|
5
7
|
* Mocked formatMessage provided by react-intl
|
|
@@ -180,4 +182,24 @@ export const mockLocation = (href) => {
|
|
|
180
182
|
global.window = Object.create(window);
|
|
181
183
|
global.window.location = { href };
|
|
182
184
|
};
|
|
185
|
+
/**
|
|
186
|
+
* Adds an app to the site config whose route at `path` provides `role`, so that
|
|
187
|
+
* `resolveRouteByRole(role)` finds it. Restore the previous site config afterwards with
|
|
188
|
+
* `setSiteConfig`.
|
|
189
|
+
*/
|
|
190
|
+
export const provideRoute = (role, path) => {
|
|
191
|
+
mergeSiteConfig({
|
|
192
|
+
apps: [{
|
|
193
|
+
appId: 'org.openedx.frontend.app.test',
|
|
194
|
+
routes: [{ path, handle: { roles: [role] } }],
|
|
195
|
+
}],
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Shows the current pathname, so a test can click a link and assert the client navigated.
|
|
200
|
+
*/
|
|
201
|
+
export const LocationDisplay = () => {
|
|
202
|
+
const { pathname } = useLocation();
|
|
203
|
+
return _jsx("div", { "data-testid": "location", children: pathname });
|
|
204
|
+
};
|
|
183
205
|
//# sourceMappingURL=testUtils.js.map
|
package/dist/testUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testUtils.js","sourceRoot":"","sources":["../src/testUtils.js"],"names":[],"mappings":"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","sourcesContent":["import react from 'react';\n\nimport { StrictDict } from '@src/utils';\n\n/**\n * Mocked formatMessage provided by react-intl\n */\nexport const formatMessage = (msg, values) => {\n let message = msg.defaultMessage;\n if (values === undefined) {\n return message;\n }\n // check if value is not a primitive type.\n if (Object.values(values).filter(value => Object(value) === value).length) {\n return <format-message-function {...{ message: msg, values }} />;\n }\n Object.keys(values).forEach((key) => {\n message = message.replaceAll(`{${key}}`, values[key]);\n });\n return message;\n};\n\n/**\n * Mock a single component, or a nested component so that its children render nicely\n * in snapshots.\n * @param {string} name - parent component name\n * @param {obj} contents - object of child components with intended component\n * render name.\n * @return {func} - mock component with nested children.\n *\n * usage:\n * mockNestedComponent('Card', { Body: 'Card.Body', Form: { Control: { Feedback: 'Form.Control.Feedback' }}... });\n * mockNestedComponent('IconButton', 'IconButton');\n */\nexport const mockNestedComponent = (name, contents) => {\n if (typeof contents === 'function') {\n return contents();\n }\n if (typeof contents !== 'object') {\n return contents;\n }\n const fn = () => name;\n Object.defineProperty(fn, 'name', { value: name });\n Object.keys(contents).forEach((nestedName) => {\n const value = contents[nestedName];\n fn[nestedName] = typeof value !== 'object'\n ? value\n : mockNestedComponent(`${name}.${nestedName}`, value);\n });\n return fn;\n};\n\n/**\n * Mock a module of components. nested components will be rendered nicely in snapshots.\n * @param {obj} mapping - component module mock config.\n * @return {obj} - module of flat and nested components that will render nicely in snapshots.\n * usage:\n * mockNestedComponents({\n * Card: { Body: 'Card.Body' },\n * IconButton: 'IconButton',\n * })\n */\nexport const mockNestedComponents = (mapping) => Object.entries(mapping).reduce(\n (obj, [name, value]) => ({\n ...obj,\n [name]: mockNestedComponent(name, value),\n }),\n {},\n);\n\n/**\n * Mock utility for working with useState in a hooks module.\n * Expects/requires an object containing the state object in order to ensure\n * the mock behavior works appropriately.\n *\n * Expected format:\n * hooks = { state: { <key>: (val) => React.createRef(val), ... } }\n *\n * Returns a utility for mocking useState and providing access to specific state values\n * and setState methods, as well as allowing per-test configuration of useState value returns.\n *\n * Example usage:\n * // hooks.js\n * import * as module from './hooks';\n * const state = {\n * isOpen: (val) => React.useState(val),\n * hasDoors: (val) => React.useState(val),\n * selected: (val) => React.useState(val),\n * };\n * ...\n * export const exampleHook = () => {\n * const [isOpen, setIsOpen] = module.state.isOpen(false);\n * if (!isOpen) { return null; }\n * return { isOpen, setIsOpen };\n * }\n * ...\n *\n * // hooks.test.js\n * import * as hooks from './hooks';\n * const state = new MockUseState(hooks)\n * ...\n * describe('state hooks', () => {\n * state.testGetter(state.keys.isOpen);\n * state.testGetter(state.keys.hasDoors);\n * state.testGetter(state.keys.selected);\n * });\n * describe('exampleHook', () => {\n * beforeEach(() => { state.mock(); });\n * it('returns null if isOpen is default value', () => {\n * expect(hooks.exampleHook()).toEqual(null);\n * });\n * it('returns isOpen and setIsOpen if isOpen is not null', () => {\n * state.mockVal(state.keys.isOpen, true);\n * expect(hooks.exampleHook()).toEqual({\n * isOpen: true,\n * setIsOpen: state.setState[state.keys.isOpen],\n * });\n * });\n * afterEach(() => { state.restore(); });\n * });\n *\n * @param {obj} hooks - hooks module containing a 'state' object\n */\nexport class MockUseState {\n constructor(hooks) {\n this.hooks = hooks;\n this.oldState = null;\n this.setState = {};\n this.stateVals = {};\n\n this.mock = this.mock.bind(this);\n this.restore = this.restore.bind(this);\n this.mockVal = this.mockVal.bind(this);\n this.testGetter = this.testGetter.bind(this);\n }\n\n /**\n * @return {object} - StrictDict of state object keys\n */\n get keys() {\n return StrictDict(Object.keys(this.hooks.state).reduce(\n (obj, key) => ({ ...obj, [key]: key }),\n {},\n ));\n }\n\n /**\n * Replace the hook module's state object with a mocked version, initialized to default values.\n */\n mock() {\n this.oldState = this.hooks.state;\n Object.keys(this.keys).forEach(key => {\n this.hooks.state[key] = jest.fn(val => {\n this.stateVals[key] = val;\n return [val, this.setState[key]];\n });\n });\n this.setState = Object.keys(this.keys).reduce(\n (obj, key) => ({\n ...obj,\n [key]: jest.fn(val => {\n this.hooks.state[key] = val;\n }),\n }),\n {},\n );\n }\n\n expectInitializedWith(key, value) {\n expect(this.hooks.state[key]).toHaveBeenCalledWith(value);\n }\n\n expectSetStateCalledWith(key, value) {\n expect(this.setState[key]).toHaveBeenCalledWith(value);\n }\n\n /**\n * Restore the hook module's state object to the actual code.\n */\n restore() {\n this.hooks.state = this.oldState;\n }\n\n /**\n * Mock the state getter associated with a single key to return a specific value one time.\n * @param {string} key - state key (from this.keys)\n * @param {any} val - new value to be returned by the useState call.\n */\n mockVal(key, val) {\n this.hooks.state[key].mockReturnValueOnce([val, this.setState[key]]);\n }\n\n testGetter(key) {\n test(`${key} state getter should return useState passthrough`, () => {\n const testValue = 'some value';\n const useState = (val) => ({ useState: val });\n jest.spyOn(react, 'useState').mockImplementationOnce(useState);\n expect(this.hooks.state[key](testValue)).toEqual(useState(testValue));\n });\n }\n\n get values() {\n return StrictDict({ ...this.hooks.state });\n }\n}\n\nexport const mockLocation = (href) => {\n delete global.window.location;\n global.window = Object.create(window);\n global.window.location = { href };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"testUtils.js","sourceRoot":"","sources":["../src/testUtils.js"],"names":[],"mappings":"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","sourcesContent":["import react from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { mergeSiteConfig } from '@openedx/frontend-base';\n\nimport { StrictDict } from '@src/utils';\n\n/**\n * Mocked formatMessage provided by react-intl\n */\nexport const formatMessage = (msg, values) => {\n let message = msg.defaultMessage;\n if (values === undefined) {\n return message;\n }\n // check if value is not a primitive type.\n if (Object.values(values).filter(value => Object(value) === value).length) {\n return <format-message-function {...{ message: msg, values }} />;\n }\n Object.keys(values).forEach((key) => {\n message = message.replaceAll(`{${key}}`, values[key]);\n });\n return message;\n};\n\n/**\n * Mock a single component, or a nested component so that its children render nicely\n * in snapshots.\n * @param {string} name - parent component name\n * @param {obj} contents - object of child components with intended component\n * render name.\n * @return {func} - mock component with nested children.\n *\n * usage:\n * mockNestedComponent('Card', { Body: 'Card.Body', Form: { Control: { Feedback: 'Form.Control.Feedback' }}... });\n * mockNestedComponent('IconButton', 'IconButton');\n */\nexport const mockNestedComponent = (name, contents) => {\n if (typeof contents === 'function') {\n return contents();\n }\n if (typeof contents !== 'object') {\n return contents;\n }\n const fn = () => name;\n Object.defineProperty(fn, 'name', { value: name });\n Object.keys(contents).forEach((nestedName) => {\n const value = contents[nestedName];\n fn[nestedName] = typeof value !== 'object'\n ? value\n : mockNestedComponent(`${name}.${nestedName}`, value);\n });\n return fn;\n};\n\n/**\n * Mock a module of components. nested components will be rendered nicely in snapshots.\n * @param {obj} mapping - component module mock config.\n * @return {obj} - module of flat and nested components that will render nicely in snapshots.\n * usage:\n * mockNestedComponents({\n * Card: { Body: 'Card.Body' },\n * IconButton: 'IconButton',\n * })\n */\nexport const mockNestedComponents = (mapping) => Object.entries(mapping).reduce(\n (obj, [name, value]) => ({\n ...obj,\n [name]: mockNestedComponent(name, value),\n }),\n {},\n);\n\n/**\n * Mock utility for working with useState in a hooks module.\n * Expects/requires an object containing the state object in order to ensure\n * the mock behavior works appropriately.\n *\n * Expected format:\n * hooks = { state: { <key>: (val) => React.createRef(val), ... } }\n *\n * Returns a utility for mocking useState and providing access to specific state values\n * and setState methods, as well as allowing per-test configuration of useState value returns.\n *\n * Example usage:\n * // hooks.js\n * import * as module from './hooks';\n * const state = {\n * isOpen: (val) => React.useState(val),\n * hasDoors: (val) => React.useState(val),\n * selected: (val) => React.useState(val),\n * };\n * ...\n * export const exampleHook = () => {\n * const [isOpen, setIsOpen] = module.state.isOpen(false);\n * if (!isOpen) { return null; }\n * return { isOpen, setIsOpen };\n * }\n * ...\n *\n * // hooks.test.js\n * import * as hooks from './hooks';\n * const state = new MockUseState(hooks)\n * ...\n * describe('state hooks', () => {\n * state.testGetter(state.keys.isOpen);\n * state.testGetter(state.keys.hasDoors);\n * state.testGetter(state.keys.selected);\n * });\n * describe('exampleHook', () => {\n * beforeEach(() => { state.mock(); });\n * it('returns null if isOpen is default value', () => {\n * expect(hooks.exampleHook()).toEqual(null);\n * });\n * it('returns isOpen and setIsOpen if isOpen is not null', () => {\n * state.mockVal(state.keys.isOpen, true);\n * expect(hooks.exampleHook()).toEqual({\n * isOpen: true,\n * setIsOpen: state.setState[state.keys.isOpen],\n * });\n * });\n * afterEach(() => { state.restore(); });\n * });\n *\n * @param {obj} hooks - hooks module containing a 'state' object\n */\nexport class MockUseState {\n constructor(hooks) {\n this.hooks = hooks;\n this.oldState = null;\n this.setState = {};\n this.stateVals = {};\n\n this.mock = this.mock.bind(this);\n this.restore = this.restore.bind(this);\n this.mockVal = this.mockVal.bind(this);\n this.testGetter = this.testGetter.bind(this);\n }\n\n /**\n * @return {object} - StrictDict of state object keys\n */\n get keys() {\n return StrictDict(Object.keys(this.hooks.state).reduce(\n (obj, key) => ({ ...obj, [key]: key }),\n {},\n ));\n }\n\n /**\n * Replace the hook module's state object with a mocked version, initialized to default values.\n */\n mock() {\n this.oldState = this.hooks.state;\n Object.keys(this.keys).forEach(key => {\n this.hooks.state[key] = jest.fn(val => {\n this.stateVals[key] = val;\n return [val, this.setState[key]];\n });\n });\n this.setState = Object.keys(this.keys).reduce(\n (obj, key) => ({\n ...obj,\n [key]: jest.fn(val => {\n this.hooks.state[key] = val;\n }),\n }),\n {},\n );\n }\n\n expectInitializedWith(key, value) {\n expect(this.hooks.state[key]).toHaveBeenCalledWith(value);\n }\n\n expectSetStateCalledWith(key, value) {\n expect(this.setState[key]).toHaveBeenCalledWith(value);\n }\n\n /**\n * Restore the hook module's state object to the actual code.\n */\n restore() {\n this.hooks.state = this.oldState;\n }\n\n /**\n * Mock the state getter associated with a single key to return a specific value one time.\n * @param {string} key - state key (from this.keys)\n * @param {any} val - new value to be returned by the useState call.\n */\n mockVal(key, val) {\n this.hooks.state[key].mockReturnValueOnce([val, this.setState[key]]);\n }\n\n testGetter(key) {\n test(`${key} state getter should return useState passthrough`, () => {\n const testValue = 'some value';\n const useState = (val) => ({ useState: val });\n jest.spyOn(react, 'useState').mockImplementationOnce(useState);\n expect(this.hooks.state[key](testValue)).toEqual(useState(testValue));\n });\n }\n\n get values() {\n return StrictDict({ ...this.hooks.state });\n }\n}\n\nexport const mockLocation = (href) => {\n delete global.window.location;\n global.window = Object.create(window);\n global.window.location = { href };\n};\n\n/**\n * Adds an app to the site config whose route at `path` provides `role`, so that\n * `resolveRouteByRole(role)` finds it. Restore the previous site config afterwards with\n * `setSiteConfig`.\n */\nexport const provideRoute = (role, path) => {\n mergeSiteConfig({\n apps: [{\n appId: 'org.openedx.frontend.app.test',\n routes: [{ path, handle: { roles: [role] } }],\n }],\n });\n};\n\n/**\n * Shows the current pathname, so a test can click a link and assert the client navigated.\n */\nexport const LocationDisplay = () => {\n const { pathname } = useLocation();\n return <div data-testid=\"location\">{pathname}</div>;\n};\n"]}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { isInternalUrl } from '@openedx/frontend-base';
|
|
1
2
|
import { createLinkTracker, createEventTracker } from '../../data/services/segment/utils';
|
|
2
3
|
import { categories, eventNames } from '../constants';
|
|
3
|
-
export const findCoursesClicked = (href, args = {}) =>
|
|
4
|
+
export const findCoursesClicked = (href, args = {}) => {
|
|
5
|
+
const tracker = createEventTracker(eventNames.findCoursesClicked, Object.assign({ pageName: 'learner_home', linkType: 'button', linkCategory: categories.searchButton }, args));
|
|
6
|
+
// A path in this site is followed by react-router in the client, so the event is just sent
|
|
7
|
+
// along the way. Anything else is a full page load, which createLinkTracker holds back until
|
|
8
|
+
// the event is on its way.
|
|
9
|
+
return isInternalUrl(href) ? tracker : createLinkTracker(tracker, href);
|
|
10
|
+
};
|
|
4
11
|
export default {
|
|
5
12
|
findCoursesClicked,
|
|
6
13
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findCourses.js","sourceRoot":"","sources":["../../../src/tracking/trackers/findCourses.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"findCourses.js","sourceRoot":"","sources":["../../../src/tracking/trackers/findCourses.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE;IACpD,MAAM,OAAO,GAAG,kBAAkB,CAAC,UAAU,CAAC,kBAAkB,kBAC9D,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,UAAU,CAAC,YAAY,IAClC,IAAI,EACP,CAAC;IACH,2FAA2F;IAC3F,8FAA8F;IAC9F,2BAA2B;IAC3B,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAC1E,CAAC,CAAC;AAEF,eAAe;IACb,kBAAkB;CACnB,CAAC","sourcesContent":["import { isInternalUrl } from '@openedx/frontend-base';\n\nimport { createLinkTracker, createEventTracker } from '../../data/services/segment/utils';\nimport { categories, eventNames } from '../constants';\n\nexport const findCoursesClicked = (href, args = {}) => {\n const tracker = createEventTracker(eventNames.findCoursesClicked, {\n pageName: 'learner_home',\n linkType: 'button',\n linkCategory: categories.searchButton,\n ...args,\n });\n // A path in this site is followed by react-router in the client, so the event is just sent\n // along the way. Anything else is a full page load, which createLinkTracker holds back until\n // the event is on its way.\n return isInternalUrl(href) ? tracker : createLinkTracker(tracker, href);\n};\n\nexport default {\n findCoursesClicked,\n};\n"]}
|
|
@@ -11,7 +11,7 @@ function DiscoverLink() {
|
|
|
11
11
|
export default function DiscoverLinkMenuItem({ variant = 'hyperlink' }) {
|
|
12
12
|
const { platformSettings } = useContext(GlobalDataContext);
|
|
13
13
|
const { courseSearchUrl } = platformSettings;
|
|
14
|
-
const url = urls.
|
|
14
|
+
const url = urls.coursesUrl(courseSearchUrl);
|
|
15
15
|
return (_jsx(LinkMenuItem, { label: _jsx(DiscoverLink, {}), url: url, variant: variant }));
|
|
16
16
|
}
|
|
17
17
|
//# sourceMappingURL=DiscoverLinkMenuItem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiscoverLinkMenuItem.js","sourceRoot":"","sources":["../../../src/widgets/LearnerDashboardHeader/DiscoverLinkMenuItem.jsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,iBAAiB,MAAM,uCAAuC,CAAC;AACtE,OAAO,IAAI,MAAM,8BAA8B,CAAC;AAChD,OAAO,QAAQ,MAAM,YAAY,CAAC;AAElC,SAAS,YAAY;IACnB,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IAEpC,OAAO,CACL,cAAK,SAAS,EAAC,QAAQ,YACrB,yBAAO,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAQ,GAC9C,CACP,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE;IACpE,MAAM,EAAE,gBAAgB,EAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAC3D,MAAM,EAAE,eAAe,EAAE,GAAG,gBAAgB,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IAE7C,OAAO,CACL,KAAC,YAAY,IACX,KAAK,EAAE,KAAC,YAAY,KAAG,EACvB,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,OAAO,GAChB,CACH,CAAC;AACJ,CAAC","sourcesContent":["import { useContext } from 'react';\nimport { LinkMenuItem, useIntl } from '@openedx/frontend-base';\n\nimport GlobalDataContext from '../../data/contexts/GlobalDataContext';\nimport urls from '../../data/services/lms/urls';\nimport messages from './messages';\n\nfunction DiscoverLink() {\n const { formatMessage } = useIntl();\n\n return (\n <div className=\"d-flex\">\n <span>{formatMessage(messages.discoverNew)}</span>\n </div>\n );\n}\n\nexport default function DiscoverLinkMenuItem({ variant = 'hyperlink' }) {\n const { platformSettings } = useContext(GlobalDataContext);\n const { courseSearchUrl } = platformSettings;\n const url = urls.
|
|
1
|
+
{"version":3,"file":"DiscoverLinkMenuItem.js","sourceRoot":"","sources":["../../../src/widgets/LearnerDashboardHeader/DiscoverLinkMenuItem.jsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,iBAAiB,MAAM,uCAAuC,CAAC;AACtE,OAAO,IAAI,MAAM,8BAA8B,CAAC;AAChD,OAAO,QAAQ,MAAM,YAAY,CAAC;AAElC,SAAS,YAAY;IACnB,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IAEpC,OAAO,CACL,cAAK,SAAS,EAAC,QAAQ,YACrB,yBAAO,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAQ,GAC9C,CACP,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE;IACpE,MAAM,EAAE,gBAAgB,EAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAC3D,MAAM,EAAE,eAAe,EAAE,GAAG,gBAAgB,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IAE7C,OAAO,CACL,KAAC,YAAY,IACX,KAAK,EAAE,KAAC,YAAY,KAAG,EACvB,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,OAAO,GAChB,CACH,CAAC;AACJ,CAAC","sourcesContent":["import { useContext } from 'react';\nimport { LinkMenuItem, useIntl } from '@openedx/frontend-base';\n\nimport GlobalDataContext from '../../data/contexts/GlobalDataContext';\nimport urls from '../../data/services/lms/urls';\nimport messages from './messages';\n\nfunction DiscoverLink() {\n const { formatMessage } = useIntl();\n\n return (\n <div className=\"d-flex\">\n <span>{formatMessage(messages.discoverNew)}</span>\n </div>\n );\n}\n\nexport default function DiscoverLinkMenuItem({ variant = 'hyperlink' }) {\n const { platformSettings } = useContext(GlobalDataContext);\n const { courseSearchUrl } = platformSettings;\n const url = urls.coursesUrl(courseSearchUrl);\n\n return (\n <LinkMenuItem\n label={<DiscoverLink />}\n url={url}\n variant={variant}\n />\n );\n}\n"]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useIntl } from '@openedx/frontend-base';
|
|
2
|
+
import { getLinkProps, useIntl } from '@openedx/frontend-base';
|
|
3
3
|
import { Card, Hyperlink, Icon } from '@openedx/paragon';
|
|
4
4
|
import { ArrowForward } from '@openedx/paragon/icons';
|
|
5
5
|
import { useInitializeLearnerHome } from '../../data/hooks';
|
|
6
6
|
import moreCoursesSVG from '../../assets/more-courses-sidewidget.svg';
|
|
7
|
-
import {
|
|
7
|
+
import { coursesUrl } from '../../data/services/lms/urls';
|
|
8
8
|
import { findCoursesWidgetClicked } from './track';
|
|
9
9
|
import messages from './messages';
|
|
10
10
|
import './index.scss';
|
|
@@ -14,8 +14,8 @@ export const LookingForChallengeWidget = () => {
|
|
|
14
14
|
const { formatMessage } = useIntl();
|
|
15
15
|
const { data: learnerData } = useInitializeLearnerHome();
|
|
16
16
|
const courseSearchUrl = ((_a = learnerData === null || learnerData === void 0 ? void 0 : learnerData.platformSettings) === null || _a === void 0 ? void 0 : _a.courseSearchUrl) || '';
|
|
17
|
-
const
|
|
18
|
-
return (_jsxs(Card, { orientation: "horizontal", id: "looking-for-challenge-widget", children: [_jsx(Card.ImageCap, { src: moreCoursesSVG, srcAlt: "course side widget" }), _jsxs(Card.Body, { className: "m-auto pr-2", children: [_jsx("h4", { children: formatMessage(messages.lookingForChallengePrompt) }), _jsx("h5", { children: _jsx(Hyperlink, { variant: "brand",
|
|
17
|
+
const url = coursesUrl(courseSearchUrl);
|
|
18
|
+
return (_jsxs(Card, { orientation: "horizontal", id: "looking-for-challenge-widget", children: [_jsx(Card.ImageCap, { src: moreCoursesSVG, srcAlt: "course side widget" }), _jsxs(Card.Body, { className: "m-auto pr-2", children: [_jsx("h4", { children: formatMessage(messages.lookingForChallengePrompt) }), _jsx("h5", { children: _jsx(Hyperlink, Object.assign({ variant: "brand" }, getLinkProps(url), { onClick: findCoursesWidgetClicked(url), className: "d-flex align-items-center", children: formatMessage(messages.findCoursesButton, { arrow: arrowIcon }) })) })] })] }));
|
|
19
19
|
};
|
|
20
20
|
LookingForChallengeWidget.propTypes = {};
|
|
21
21
|
export default LookingForChallengeWidget;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/widgets/LookingForChallengeWidget/index.jsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/widgets/LookingForChallengeWidget/index.jsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,cAAc,MAAM,0CAA0C,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,cAAc,CAAC;AAEtB,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAC,IAAI,IAAC,SAAS,EAAC,MAAM,EAAC,GAAG,EAAE,YAAY,GAAI,CAAC,CAAC;AAExE,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,EAAE;;IAC5C,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,wBAAwB,EAAE,CAAC;IACzD,MAAM,eAAe,GAAG,CAAA,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,gBAAgB,0CAAE,eAAe,KAAI,EAAE,CAAC;IAC7E,MAAM,GAAG,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC;IAExC,OAAO,CACL,MAAC,IAAI,IAAC,WAAW,EAAC,YAAY,EAAC,EAAE,EAAC,8BAA8B,aAC9D,KAAC,IAAI,CAAC,QAAQ,IACZ,GAAG,EAAE,cAAc,EACnB,MAAM,EAAC,oBAAoB,GAC3B,EACF,MAAC,IAAI,CAAC,IAAI,IAAC,SAAS,EAAC,aAAa,aAChC,uBACG,aAAa,CAAC,QAAQ,CAAC,yBAAyB,CAAC,GAC/C,EACL,uBACE,KAAC,SAAS,kBACR,OAAO,EAAC,OAAO,IACX,YAAY,CAAC,GAAG,CAAC,IACrB,OAAO,EAAE,wBAAwB,CAAC,GAAG,CAAC,EACtC,SAAS,EAAC,2BAA2B,YAEpC,aAAa,CAAC,QAAQ,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,IACtD,GACT,IACK,IACP,CACR,CAAC;AACJ,CAAC,CAAC;AAEF,yBAAyB,CAAC,SAAS,GAAG,EAAE,CAAC;AAEzC,eAAe,yBAAyB,CAAC","sourcesContent":["import { getLinkProps, useIntl } from '@openedx/frontend-base';\nimport { Card, Hyperlink, Icon } from '@openedx/paragon';\nimport { ArrowForward } from '@openedx/paragon/icons';\n\nimport { useInitializeLearnerHome } from '@src/data/hooks';\nimport moreCoursesSVG from '../../assets/more-courses-sidewidget.svg';\nimport { coursesUrl } from '../../data/services/lms/urls';\n\nimport { findCoursesWidgetClicked } from './track';\nimport messages from './messages';\nimport './index.scss';\n\nexport const arrowIcon = (<Icon className=\"mx-1\" src={ArrowForward} />);\n\nexport const LookingForChallengeWidget = () => {\n const { formatMessage } = useIntl();\n const { data: learnerData } = useInitializeLearnerHome();\n const courseSearchUrl = learnerData?.platformSettings?.courseSearchUrl || '';\n const url = coursesUrl(courseSearchUrl);\n\n return (\n <Card orientation=\"horizontal\" id=\"looking-for-challenge-widget\">\n <Card.ImageCap\n src={moreCoursesSVG}\n srcAlt=\"course side widget\"\n />\n <Card.Body className=\"m-auto pr-2\">\n <h4>\n {formatMessage(messages.lookingForChallengePrompt)}\n </h4>\n <h5>\n <Hyperlink\n variant=\"brand\"\n {...getLinkProps(url)}\n onClick={findCoursesWidgetClicked(url)}\n className=\"d-flex align-items-center\"\n >\n {formatMessage(messages.findCoursesButton, { arrow: arrowIcon })}\n </Hyperlink>\n </h5>\n </Card.Body>\n </Card>\n );\n};\n\nLookingForChallengeWidget.propTypes = {};\n\nexport default LookingForChallengeWidget;\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const linkNames: any;
|
|
2
|
-
export function findCoursesWidgetClicked(href: any): (e: any) => number;
|
|
2
|
+
export function findCoursesWidgetClicked(href: any): (() => void) | ((e: any) => number);
|
|
3
3
|
declare namespace _default {
|
|
4
4
|
export { linkNames };
|
|
5
5
|
export { findCoursesWidgetClicked };
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openedx/frontend-app-learner-dashboard",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.4",
|
|
4
|
+
"packageManager": "npm@11.12.1",
|
|
4
5
|
"description": "",
|
|
5
6
|
"repository": {
|
|
6
7
|
"type": "git",
|
|
@@ -70,6 +71,8 @@
|
|
|
70
71
|
},
|
|
71
72
|
"devDependencies": {
|
|
72
73
|
"@edx/browserslist-config": "^1.5.0",
|
|
74
|
+
"@openedx/frontend-base": "^2.0.0-alpha.15 || 0.0.0-dev",
|
|
75
|
+
"@openedx/paragon": "^23 || 0.0.0-dev",
|
|
73
76
|
"@testing-library/jest-dom": "^6.6.3",
|
|
74
77
|
"@testing-library/react": "^16.3.0",
|
|
75
78
|
"@testing-library/user-event": "^14.6.1",
|
|
@@ -82,11 +85,12 @@
|
|
|
82
85
|
"nodemon": "^3.1.14",
|
|
83
86
|
"react-dev-utils": "^12.0.0",
|
|
84
87
|
"tsc-alias": "^1.8.16",
|
|
85
|
-
"turbo": "^2.8.20"
|
|
88
|
+
"turbo": "^2.8.20",
|
|
89
|
+
"typescript": "^5.9.3"
|
|
86
90
|
},
|
|
87
91
|
"peerDependencies": {
|
|
88
|
-
"@openedx/frontend-base": "^2.0.0-alpha.
|
|
89
|
-
"@openedx/paragon": "^23",
|
|
92
|
+
"@openedx/frontend-base": "^2.0.0-alpha.15 || 0.0.0-dev",
|
|
93
|
+
"@openedx/paragon": "^23 || 0.0.0-dev",
|
|
90
94
|
"@tanstack/react-query": "^5",
|
|
91
95
|
"@types/react": "^18",
|
|
92
96
|
"@types/react-dom": "^18",
|