Compare commits

...

1381 Commits

Author SHA1 Message Date
dependabot[bot]
af8ef50a34 chore(deps): bump actions/upload-artifact from 4 to 6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 13:13:26 +00:00
edX requirements bot
9c5ac6ac5b chore: update browserslist DB (#1839)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-12-15 00:45:08 +00:00
edX requirements bot
f43ac7bcc3 chore: update browserslist DB (#1830)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-12-01 00:49:30 +00:00
Maniraja Raman
b282bc05df feat: update chat component to use PluginSlot and simplify logic (#1810) 2025-11-18 22:19:30 -05:00
edX requirements bot
d987aed861 chore: update browserslist DB (#1826)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-11-17 00:41:45 +00:00
Muhammad Labeeb
9ece337504 fix: remove proctortrack references (#1825)
Update all descriptions mentioning proctortrack with a generic message.

  https://github.com/openedx/edx-platform/issues/36329
2025-11-13 12:17:03 -05:00
edX requirements bot
d3235af879 chore: update browserslist DB (#1822)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-11-10 00:42:11 +00:00
kshitij.sobti
d0a8778015 feat: Add slots to add tab links for courses
Adds new slot that allow adding new links to course tabs.
2025-11-03 16:40:08 +05:30
edX requirements bot
f8381e7900 chore: update browserslist DB (#1818)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-11-03 00:42:13 +00:00
Jansen Kantor
1d5484ff1d fix: re-add removed import (#1815) 2025-10-28 11:12:33 -04:00
Muhammad Anas
52692dc662 refactor: shift grade summary calculation to backend and display "hidden grades" label in the grade table (#1797)
Refactors the grade summary logic to delegate all calculation responsibilities to the backend.
Previously, the frontend was performing grade summary computations using data fetched from the API. Now, the API itself provides the fully computed grade summary, simplifying the frontend and ensuring consistent results across clients.

Additionally, a "Hidden Grades" label has been added in the grade summary table to clearly indicate sections where grades are not visible to learners.

Finally, for visibility settings that depend on the due date, this PR adds a banner on the Progress page indicating that grades are not yet released, along with the relevant due date information.
2025-10-24 14:55:12 -03:00
Jansen Kantor
f91af211f6 feat: add plugin slot for content iframe error component (#1771)
* feat: add plugin slot for content iframe error component

* style: quality

* fix: copilot suggestions
2025-10-20 12:03:07 -04:00
edX requirements bot
7318fb3ef7 chore: update browserslist DB (#1808)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-10-20 00:41:43 +00:00
Michael Roytman
7233f08d3d feat: update version of frontend-lib-learning-assistant to 2.23.1 (#1807)
This commit installs version 2.23.1 of @edx/frontend-lib-learning-assistant.

This release fixes a bug where the Xpert Learning Assistant was only available to learners in the audit and credit modes.

See https://github.com/edx/frontend-lib-learning-assistant/releases/tag/v2.23.1.
2025-10-15 13:35:20 -04:00
edX requirements bot
d6d229f1c3 chore: update browserslist DB (#1799)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-10-13 00:40:36 +00:00
Muhammad Anas
47b9a436a6 chore: bump frontend-component-header to v8.x.x (#1791)
* chore: bump frontend-component-header to v6.6.x

* chore: bump frontend-component-header to ^8.0.0
2025-10-08 09:48:07 -04:00
renovate[bot]
e556d5b74c chore(deps): update dependency @edx/frontend-component-header to v6.4.2 (#1804)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-07 19:17:29 +00:00
renovate[bot]
694d95a816 chore(deps): update dependency @edx/frontend-component-footer to v14.9.2 (#1803)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-07 16:13:33 +00:00
PKulkoRaccoonGang
e83813da8e build: Upgrade to node 24 and update package-lock.json 2025-10-06 11:54:57 -04:00
edX requirements bot
a54a1b8c3c chore: update browserslist DB (#1795)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-09-29 00:39:45 +00:00
Feanil Patel
d3188efbcc build: remove unused @edx/reactifex package
Remove @edx/reactifex package from devDependencies as it is no longer
needed. Translation extraction functionality has been verified to work
correctly without this dependency.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-26 13:09:24 -04:00
edX requirements bot
33f737579a chore: update browserslist DB (#1793)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-09-22 00:41:28 +00:00
Agrendalath
870263001e fix: ensure iframe visibility tracking is triggered on load
The previous implementation had a race condition that sometimes prevented
XBlocks from being marked as viewed. Users had to scroll or resize the window
to trigger visibility tracking instead of having it happen once content loads.
2025-09-18 16:49:07 +05:30
Peter Kulko
af50d5a6ed test: Add Node 24 to CI matrix (#1752) 2025-09-16 10:55:28 -04:00
Samuel Allan
7fccf7794c fix: update frontend-build to fix install issues
Earlier versions of @openedx/frontend-build used on older version of
'sharp', which caused intermittent installation issues. The version of
'sharp' was updated in @openedx/frontend-build to fix these issues, so
the frontend-build version can be updated here, to fix the issues in
this project too. See
https://github.com/openedx/frontend-build/issues/664 and
https://github.com/openedx/frontend-build/pull/665 for more information.

The frontend-build dependency was updated by:

```
npm install --package-lock-only @openedx/frontend-build
```

Private-ref: https://tasks.opencraft.com/browse/BB-9953
2025-09-12 14:21:20 -03:00
edX requirements bot
c760bc479b chore: update browserslist DB (#1788)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-09-08 00:40:25 +00:00
edX requirements bot
d5140a6bf0 chore: update browserslist DB (#1784)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-09-01 00:46:51 +00:00
Isaac Lee
9bf5d01c41 chore: update learning assistant plugin 2.23.0 (#1781) 2025-08-25 12:54:13 -04:00
edX requirements bot
f3334085d7 chore: update browserslist DB (#1783)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-08-25 00:41:09 +00:00
dependabot[bot]
4840fff44b chore(deps): bump actions/download-artifact from 4 to 5 (#1779)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-21 14:21:56 -07:00
Muhammad Adeel Tajamul
579bd0365b feat: updated notification preferences unsubscribe flow (#1778) 2025-08-21 14:09:28 -04:00
abdullahwaheed
2b4a9661a5 chore: update browserslist DB 2025-08-18 06:14:24 +05:30
dependabot[bot]
a6e4e28e58 chore(deps): bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 14:33:52 -04:00
dependabot[bot]
e6f7588ccd chore(deps): bump js-toml from 1.0.1 to 1.0.2
Bumps [js-toml](https://github.com/sunnyadn/js-toml) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/sunnyadn/js-toml/releases)
- [Commits](https://github.com/sunnyadn/js-toml/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: js-toml
  dependency-version: 1.0.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-06 16:44:33 +05:30
Muhammad Anas
db29e314c3 feat: customize proctoring review requirements link using externalLinkUrlOverrides (#1775) 2025-08-04 10:36:44 -04:00
Diana Olarte
e9121f9261 feat: display the certificate available date if available in progress tab 2025-08-01 16:21:36 +05:30
Nawfal Ahmed
9cbc2276d6 feat: use discount info endpoint for streak discount information (#1763)
* feat: use discount info endpoint for streak discount information

* feat: pass course run key to discount code info call

* feat: move changes behind a flag

* fix: use async IIFE inside useEffect

* fix: fix line length

* fix: remove default value in dev

* fix: improve coverage by adding conditional test based on env value

* refactor: move logic inside function

* refactor: move functions to utils

* fix: ignore merge config
2025-07-31 14:53:18 -04:00
Maniraja Raman
4c8aa7c80c feat: add FEATURE_ENABLE_CHAT_V2_ENDPOINT to environment files and update library version (#1768) 2025-07-29 16:48:07 -04:00
Diana Villalvazo
68926334a1 test: transform snapshot into rtl test 1/2 (#1756)
* test: remove snapshots and use rtl tests

* test: improve coverage on search results test
2025-07-29 10:13:07 -04:00
Diana Villalvazo
56a73eee15 test: transform snapshot into rtl test 2/2 (#1757)
* test: remove snapshots and use rtl tests

* test: add expected result on map search
2025-07-29 10:03:07 -04:00
Jacobo Dominguez
bf95916063 docs: add comprehensive readme documentation for plugin slots (#1770) 2025-07-28 14:10:49 -04:00
Diana Villalvazo
48270c35dd chore: remove react-unit-test-utils package (#1758) 2025-07-28 14:02:55 -04:00
Diana Villalvazo
33d7d669d9 test: deprecate react-unit-test-utils 1/2 (#1750) 2025-07-28 12:48:53 -04:00
Diana Villalvazo
a75c89cd14 test: deprecate react-test-utils 2/2 (#1751) 2025-07-28 12:12:32 -04:00
Ihor Romaniuk
06902d8ae8 feat: remove waffle flags for managing course outline sidebar (#1713)
* feat: remove waffle flags for managing course outline sidebar

* fix: flag and tests

* fix: product-tours tests

* fix: remove default content for SequenceNavigationSlot and update tests

* fix: remove default content for CourseBreadcrumbsSlot

* fix: update plugin-slots version and documentation

* revert: update plugin-slots version

* fix: update tests
2025-07-21 14:57:43 -04:00
edX requirements bot
e4134641e6 chore: update browserslist DB (#1755)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-07-07 00:44:46 +00:00
edX requirements bot
77fcc83efd chore: update browserslist DB (#1744)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-06-30 00:43:50 +00:00
Farhaan Bukhsh
b0505352be fix: Fixes the auto_advance feature for video XBlock
The commit adds eventlistener which picks up the autoAdvance message and
triggers the next sequence. This has the same effect of clicking the
next button.

Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
2025-06-24 19:22:33 +05:30
Brian Smith
ddbc2124ef feat!: add design tokens support (#1737)
BREAKING CHANGE: Pre-design-tokens theming is no longer supported.

Co-authored-by: Diana Olarte <diana.olarte@edunext.co>
2025-06-18 12:07:01 -04:00
renovate[bot]
462e75f6a6 fix(deps): update dependency @edx/frontend-platform to v8.4.0 (#1739)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-18 14:03:53 +00:00
renovate[bot]
bc4c8c2dec fix(deps): update dependency @edx/frontend-component-footer to v14.9.0 (#1736)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-18 05:29:53 +00:00
renovate[bot]
ecd5164806 fix(deps): update dependency @openedx/frontend-build to v14.6.1 (#1700)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-18 01:03:51 +00:00
edX requirements bot
44d952bef7 chore: update browserslist DB (#1734)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-06-16 00:42:49 +00:00
sundasnoreen12
7eddc918bb fix: fixed right panel closing issue (#1732)
* fix: fixed right panel closing issue

* fix: fixed status of notificationTrayStatus in session storage

* test: added test cases to close or open notification tray
2025-06-13 10:33:14 -04:00
edX requirements bot
f28528e813 chore: update browserslist DB (#1730)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-06-09 00:43:43 +00:00
wgu-jesse-stewart
ab3f5fd7bc fix: ensure full-height layout (#1724)
When content within a sequence was shorter than the height of the browser viewport, the `.sequence-container > .outline-sidebar-wrapper` element does not expand appropriately.  This caused the course outline sidebar to be partially or completely hidden from view.
2025-06-06 15:55:15 -03:00
ayesha waris
73eaf61261 revert: "temp: reverse stack order of discussions and upsell in sidebar (#1705)" (#1712)
This reverts commit 2ce833341b.
2025-06-05 13:25:22 -04:00
KristinAoki
db9663b664 feat: add start:with-theme command 2025-06-05 19:47:23 +05:30
jacobo-dominguez-wgu
7edac93752 fix: removing '-1 +' from media queries (#1727) 2025-06-04 16:27:04 -07:00
Javier Ontiveros
d1dede568e feat: hide sidebar on screen resize (#1720)
Adds an event handler on the window resize to check if the sidebar isOpen and the size of the viewport is smaller than the sidebar display to hide the sidebar and prevent it from blocking the course view.
2025-06-04 16:22:01 -03:00
Javier Ontiveros
31b02d777f feat: disable completion item icons on flag (#1714)
* feat: base modifications to disable completion checks when flag enabled

* chore: started updating tests

* chore: udpated tests

* chore: added missing negative test

---------

Co-authored-by: Adolfo R. Brandes <adolfo@axim.org>
2025-06-04 15:33:12 -03:00
dependabot[bot]
67bb54a028 chore(deps): bump tar-fs
Bumps  and [tar-fs](https://github.com/mafintosh/tar-fs). These dependencies needed to be updated together.

Updates `tar-fs` from 2.1.2 to 3.0.9
- [Commits](https://github.com/mafintosh/tar-fs/compare/v2.1.2...v3.0.9)

Updates `tar-fs` from 3.0.8 to 3.0.9
- [Commits](https://github.com/mafintosh/tar-fs/compare/v2.1.2...v3.0.9)

---
updated-dependencies:
- dependency-name: tar-fs
  dependency-version: 3.0.9
  dependency-type: indirect
- dependency-name: tar-fs
  dependency-version: 3.0.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-04 20:32:27 +05:30
jacobo-dominguez-wgu
847d4e5ce6 fix: center and align previous and next buttons (#1718)
* fix: prev and next buttons were not propertly centered and aligned

* fix: removing flex-basis property for navigation buttons
2025-06-04 10:22:45 -03:00
edX requirements bot
b89cdb4a69 chore: update browserslist DB (#1723)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-06-02 00:42:51 +00:00
Maria Grimaldi
a1d0afff6c refactor: move file to corresponding folder 2025-05-30 08:33:47 -04:00
Maria Grimaldi
1714f285b0 chore: add workflow to pull release testing issues into the BTR board
Add GH workflow that includes issues into the BTR board after the issue
is labeled with `release testing`.  Also add label needs triage for
bug triaging issues.
2025-05-30 08:18:57 -04:00
Jorg Are
03cda5326a chore: add id to verified-upgrade-deadline link (#1719) 2025-05-29 15:33:51 -04:00
Ihor Romaniuk
a71152b008 feat: move sequence navigation to plugin slot (#1716) 2025-05-29 12:05:00 -04:00
wgu-jesse-stewart
d14c2a9ffd fix: sidebar not showing sections on pending courses (#1679) 2025-05-27 13:47:21 -04:00
Jorg Are
b6c29df0a0 chore: add identifiers to some upgrade links/buttons (#1686) 2025-05-21 08:45:19 -04:00
ayesha waris
2ce833341b temp: reverse stack order of discussions and upsell in sidebar (#1705)
Co-authored-by: Ayesha Waris <ayesha.waris@192.168.10.27>
2025-05-19 11:45:32 -04:00
renovate[bot]
ff57a6b217 fix(deps): update dependency @edx/frontend-platform to v8.3.7 (#1710)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 13:58:38 +00:00
edX requirements bot
dc6ee749be chore: update browserslist DB (#1709)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-05-19 00:42:52 +00:00
renovate[bot]
236fb57023 fix(deps): update dependency @edx/frontend-platform to v8.3.6 (#1707)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 16:38:56 +00:00
Nathan Sprenkle
d3d2f75c12 chore: re-add query-string dependency (#1703)
Several of our plugins still rely on this, though it should be removed ASAP
2025-05-12 10:36:48 -04:00
edX requirements bot
8e9306d35a chore: update browserslist DB (#1704)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-05-12 00:42:14 +00:00
Jansen Kantor
b1ee8a3713 feat: add course end dashboard plugin slots (#1658)
* feat: add additional course end plugin slots

* fix: bring plugin slot names in line with new naming scheme

* refactor: change plugin files to tsx,remove propTypes

* fixup! refactor: change plugin files to tsx,remove propTypes

* fixup! fixup! refactor: change plugin files to tsx,remove propTypes

* fixup! fixup! fixup! refactor: change plugin files to tsx,remove propTypes

* fix: accidentally committed test code

* fix: plugin-slot fixes

* chore: add ENTERPRISE_LEARNER_PORTAL_URL env var
2025-05-08 14:23:41 -04:00
renovate[bot]
73406fbb31 fix(deps): update dependency @edx/openedx-atlas to ^0.7.0 (#1699)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-06 02:39:17 +00:00
renovate[bot]
f4ae1c51ff fix(deps): update dependency @edx/frontend-component-footer to v14.7.1 (#1698)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 22:27:28 +00:00
renovate[bot]
7ef3892027 fix(deps): update dependency @edx/frontend-platform to v8.3.5 (#1697)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 17:04:09 +00:00
Braden MacDonald
1484bc50f7 refactor: replace query-string pkg, remove unused <ShareButton> (#1676) 2025-05-05 09:56:09 -07:00
edX requirements bot
6b197aad27 chore: update browserslist DB (#1696)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-05-05 00:42:17 +00:00
Maxim Beder
1412bfe209 feat: update certificate icons
Old certificates icons contained edX trademark logos, which were not
suitable for the open source repos. Replaced with icons that contain
Open edX logos.
2025-04-30 10:27:27 -03:00
Brian Smith
e8d3bd7c24 fix(docs): correct ProgressCertificateStatusSlot README title (#1689) 2025-04-25 13:37:58 -04:00
Brian Smith
511091055b fix(docs): correct CourseRecommendationsSlot README title (#1688) 2025-04-25 13:37:02 -04:00
Brian Smith
24c9437e91 feat: import FooterSlot from component package instead of slot package (#1682) 2025-04-24 12:32:45 -04:00
Brian Smith
fb6f110732 feat: standardize slot ids (#1685) 2025-04-24 07:27:23 -04:00
renovate[bot]
1656b73a31 fix(deps): update dependency @edx/frontend-component-header to v6.4.0 (#1684)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 20:19:28 +00:00
edX requirements bot
81671ad328 chore: update browserslist DB (#1681)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-04-21 00:41:04 +00:00
Ivo Branco
4cc716b20c chore(deps): update dependency @openedx/frontend-build (#1677)
This will extract more messages to be translated.
2025-04-16 15:36:46 -04:00
Braden MacDonald
756fbbac83 chore: remove 'patch-package' and its unused frontend-build patch 2025-04-15 11:56:18 -07:00
KristinAoki
903fe28ff6 refactor: change to useIntl 2025-04-15 10:45:26 -07:00
Adolfo R. Brandes
14c662dc53 feat: removes Upgrade Notification as default content
As a follow-up to
https://github.com/openedx/frontend-app-learning/pull/1368, remove the
UpgradeNotification component from the sidebar's default content.
2025-04-14 16:50:55 -03:00
Adolfo R. Brandes
af432eab27 chore: remove extraneous config file 2025-04-14 15:28:43 -03:00
edX requirements bot
dde640df33 chore: update browserslist DB (#1673)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-04-14 00:41:29 +00:00
KristinAoki
b827db800d fix: lint errors 2025-04-10 11:14:16 -04:00
KristinAoki
5b7f76b43d fix: breadcrumb preview link 2025-04-10 11:14:16 -04:00
KristinAoki
cf4bea3604 fix: unit link in preview mode 2025-04-10 11:14:16 -04:00
Feanil Patel
85e6e9266d feat: Drop canShowUpgradeSock course data.
DEPR: https://github.com/openedx/edx-platform/issues/36429

This piece of data is not being used anywhere but was still being
consumed so just drop the data so that the backend can be updated to no
longer provide the data.

The backend API is being updated in https://github.com/openedx/edx-platform/pull/36436
2025-04-09 10:13:24 -04:00
Brian Smith
360af1f0e9 feat: upgrade to react 18 (#1663) 2025-04-07 14:58:51 -04:00
edX requirements bot
26f4a90976 chore: update browserslist DB (#1670)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-04-07 00:39:51 +00:00
renovate[bot]
0d45c78ace fix(deps): update dependency @edx/frontend-platform to v8.3.4 (#1623)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-03 14:27:08 +00:00
renovate[bot]
c18214dc41 fix(deps): update dependency @openedx/paragon to v22.17.0 (#1666)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-03 07:34:37 +00:00
renovate[bot]
54611c1b4d fix(deps): update dependency @openedx/frontend-build to v14.4.2 (#1665)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-03 03:19:56 +00:00
renovate[bot]
7ca4b71ff7 fix(deps): update dependency @edx/frontend-lib-learning-assistant to v2.21.0 (#1664)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 22:52:12 +00:00
renovate[bot]
63a7ff83cf fix(deps): update dependency @edx/frontend-component-footer to v14.4.0 (#1662)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 19:16:07 +00:00
renovate[bot]
8ecaa018da fix(deps): update dependency @edx/react-unit-test-utils to v3.1.0 (#1652)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 13:56:25 +00:00
renovate[bot]
64ca156095 fix(deps): update dependency @openedx/frontend-slot-footer to v1.1.1 (#1661)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 13:56:12 +00:00
Brian Smith
c06f2c37ab chore(deps): update @openedx dependencies to versions that support React 18 (#1656) 2025-04-02 09:49:49 -04:00
Sarina Canelake
d5a092b220 Update edx.rtd.io links to docs.openedx.org (#1654)
* docs: Update edx.rtd links to their new homes

* docs: Update README to not prescribe a version of Node
2025-03-26 17:43:44 +05:30
Kristin Aoki
81b621195e fix: button hover background color (#1653)
This PR updates the hover background for the top navigation buttons that are shown when the left side navigation is enabled. The hover background is updated to match the hover background of other existing IconButton components, see DiscussionNotificationTrigger.jsx, on the page.
2025-03-25 17:03:29 +00:00
renovate[bot]
226c4cc1d7 fix(deps): update dependency @edx/frontend-lib-special-exams to v3.4.0 (#1651)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 01:51:16 +00:00
renovate[bot]
7f6a59b701 fix(deps): update dependency @openedx/paragon to v22.16.1 (#1650)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 23:57:56 +00:00
renovate[bot]
7ea0bd175b fix(deps): update dependency @openedx/frontend-build to v14.3.3 (#1648)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 19:56:42 +00:00
Kristin Aoki
dae1d63e23 feat: update unit title plugin (#1643)
This PR updates the unit title plugin to include all the elements that are part of the unit title, which includes the unit title, bookmark button, and navigation buttons (if left sidebar navigation is enabled).
2025-03-24 11:46:02 -04:00
edX requirements bot
6ab0deb7b7 chore: update browserslist DB (#1646)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-03-24 00:39:25 +00:00
Michael Roytman
e5f04d92b9 fix: useExamAccess hook does not make call to fetchExamAccessToken after isExam changes (#1644)
This commit fixes a bug that prevents the fetchExamAccessToken hook in the useExamAccess hook from running. This occurs when the value of isExam returned by the useIsExam hook changes from false to true. Because the dependency array of the useEffect hook within the useExamAccess hook was ['id'], the useEffect hook would not rerun on changes to isExam. The fix is to add isExam to the dependency array.
2025-03-20 15:01:40 -04:00
Kristin Aoki
f39a50e7dc feat: add section outline plugin (#1632)
This PR adds a plugin slot for the section list in the outline tab. This plugin can be used to add custom content before the list or add extra content to the titles for sections and subsections. To accomplish this, some of the smaller components inside Section and SequenceLink have been extrapolated into their own components so that they can be easily imported for use in plugins.
2025-03-18 16:51:16 -04:00
Kristin Aoki
72724bcafb fix: use sentence casing (#1640)
* fix: use sentence casing

* fix: failing tests
2025-03-18 15:28:59 -04:00
Kristin Aoki
964abbe0c3 fix: right sidebar icon behavior (#1636)
When using the right new-sidebar with the left sidebar navigation, the icon for the right sidebar changed whenever the left sidebar was open. The icon change is supposed to indicate to users that the right sidebar is open. It is confusing to users when the left sidebar navigation is open and the right sidebar icon is filled instead of outlined.
2025-03-17 09:31:23 -04:00
edX requirements bot
96d20e20e6 chore: update browserslist DB (#1638)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-03-17 00:39:37 +00:00
Kristin Aoki
a56fd7d0e1 feat: change blocked icon to lock icon (#1619)
* feat: replace blocked icon with locked

* refactor: replace injectIntl with useIntl

* revert: temporary test change

* fix: failing test

* fix: wording of message description

* fix: lingering lint error

* fix: missing message variable
2025-03-12 15:43:27 -04:00
Rodrigo Martin
679caa61f3 feat: Update link styling (#1631) 2025-03-11 12:06:28 -03:00
edX requirements bot
420060967b chore: update browserslist DB (#1630)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-03-10 00:32:49 +00:00
Michael Roytman
91d3762513 feat: update version of frontend-lib-learning-assistant to 2.19.2 (#1629)
This commit installs version 2.19.2 of @edx/frontend-lib-learning-assistant.

This release commit fixes a bug where the days remaining banner appears after an audit trial learner sends their first message. In this case, the days remaining is not displayed until the call to the chat summary endpoint completes. This commit adds a loading spinner to the banner that appears while that call is in progress.

See https://github.com/edx/frontend-lib-learning-assistant/releases/tag/v2.19.2.
2025-03-07 11:01:21 -05:00
Marcos Rigoli
2e3ed087d1 fix: Updated a11y on Courseware Search results. (#1620) 2025-03-06 15:24:35 -03:00
Rodrigo Martin
d76d4db097 feat: remove align-items-center from unit title main header (#1628) 2025-03-06 12:52:12 -03:00
renovate[bot]
04b314d157 fix(deps): update dependency @openedx/paragon to v22.16.0 (#1626)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-06 05:43:15 +00:00
renovate[bot]
1db4848d1a fix(deps): update dependency @openedx/frontend-slot-footer to v1.1.0 (#1625)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-06 02:18:14 +00:00
renovate[bot]
8f294781d2 fix(deps): update dependency @openedx/frontend-plugin-framework to v1.5.0 (#1624)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-05 22:06:50 +00:00
renovate[bot]
d6908abb13 chore(deps): update dependency @testing-library/user-event to v14.6.1 2025-03-05 14:00:48 -08:00
Braden MacDonald
96d3d0da7e chore: remove husky 2025-03-05 16:39:59 -03:00
renovate[bot]
14cc32fcf6 fix(deps): update dependency @openedx/frontend-build to v14.3.2 (#1616)
* fix(deps): update dependency @openedx/frontend-build to v14.3.2

* fix: 'unitId' PropType is defined but prop is never used

* fix: bump maximum allowed bundle size for now :/

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-03-05 18:04:37 +00:00
Jansen Kantor
0ac127e4c9 feat: add plugin slot for course end course recommendations (#1618) 2025-03-04 15:12:53 -05:00
Rodrigo Martin
06e5fb5a44 feat: Update previous and next unit navigation buttons design (#1617)
* feat: Update previous and next unit navigation buttons design

* feat: add unit test

* feat: move unit navigation to be inline with unit title
2025-03-04 11:05:39 -03:00
Agrendalath
2235737490 feat: close sidebar on mobile after selecting a unit 2025-03-03 13:28:59 -08:00
edX requirements bot
fca32ae872 chore: update browserslist DB (#1567)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-03-03 10:16:40 -08:00
Braden MacDonald
ae04e5b366 fix: remove husky internal files that should never have been committed 2025-02-28 10:18:31 -08:00
Marcos Rigoli
db3f1b9cb0 feat: Search a11y updated behavior. (#1614)
* feat: Updated accesibility on courseware search modal

* chore: Updated i18n to use useIntl() hook and dialog behavior updates

* feat: Added close when clicking on the modal backdrop

* chore: Swapped remove listeners with an AbortController

* fix: Fixed tests

* chore: Rolled back unintended husky script change
2025-02-28 10:12:39 -05:00
renovate[bot]
ec360bc545 fix(deps): update dependency @edx/frontend-platform to v8.2.1 (#1615)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-28 14:44:43 +00:00
renovate[bot]
6c5220b4d7 fix(deps): update dependency @edx/frontend-lib-special-exams to v3.3.0 (#1613)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-28 10:38:07 +00:00
renovate[bot]
f433118a8d fix(deps): update dependency @edx/browserslist-config to v1.5.0 (#1612)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-28 06:41:56 +00:00
renovate[bot]
e798331855 fix(deps): update dependency @edx/frontend-component-header to v5.8.3 (#1609)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-28 00:54:24 +00:00
renovate[bot]
adb5796ff6 fix(deps): update dependency sass-loader to v16.0.5 (#1610)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-28 00:53:56 +00:00
renovate[bot]
9958638a86 fix(deps): update dependency @reduxjs/toolkit to v1.9.7 2025-02-27 16:47:57 -08:00
renovate[bot]
b8e844eba6 fix(deps): update dependency sass to v1.85.1 2025-02-27 16:43:20 -08:00
Varsha Menon
da633ffbd9 feat: upgrade learning assistant frontend to 2.19.1 optimizely bug fix (#1607) 2025-02-27 10:15:04 -05:00
Rodrigo Martin
46889c2aba feat(AU-2375): Update breadcrumbs and outline navigation bar UI (#1582)
* feat: extend CourseOutlineSidebarTriggerSlot props

* feat: Remove courseId from CourseOutlineSidebarTriggerPlugin props

* feat: update useContextId to use courseware data along with coursehome

* feat: extend useCourseOutlineSidebar values with sequenceStatus
2025-02-27 11:24:05 -03:00
Kristin Aoki
3cbbb0272b fix: update outline sidebar hooks for plugins (#1586)
* fix: update outline sidebar hooks for plugins

* docs: explain UnitLinkWrapper
2025-02-21 14:49:52 -05:00
Michael Roytman
911c7658f5 feat: update version of frontend-lib-special-exams library from 3.2.0 to 3.2.1 (#1591)
This commit updates the version of the frontend-lib-special-exams library from 3.2.0 to 3.2.1. The full changelog is available here: openedx/frontend-lib-special-exams@3.2.0...3.2.1: https://github.com/openedx/frontend-lib-special-exams/compare/v3.2.0...v3.2.1.

The changes in this new version are summarized below.
* Update exam message for submitted proctored exams with more accurate language.
2025-02-21 11:28:07 -05:00
Varsha Menon
b54d1e467e Revert "chore: upgrade frontend lib learning assistant version (#1590)" (#1592)
This reverts commit e34d18d727.
2025-02-21 10:38:28 -05:00
Varsha Menon
e34d18d727 chore: upgrade frontend lib learning assistant version (#1590) 2025-02-19 12:18:51 -05:00
Kyle McCormick
6949e5708f chore: make sure links point to MFE not legacy (#1589)
now that the legacy profile and account pages have been removed, we need to make sure that all of the links point to the MFE URLs; we were relying on the legacy applications to do redirection before.

FIXES: APER-3884
FIXES: openedx/public-engineering#71

Co-authored-by: Deborah Kaplan <deborahgu@users.noreply.github.com>
2025-02-18 08:59:15 -08:00
Stanislav
eef6b1efe2 fix: Ugly appearance of the Start/Resume Course button at the top of the course outline (#1585) 2025-02-14 18:17:21 -08:00
Kristin Aoki
9dc45e192d fix: accessibility issues on outline and unit pages (#1580)
This PR fixes the following accessibility issues:

1. Header used for screenreader only text
2. Element focus when expanding and dismissing welcome message
3. Bookmark button using wrong ARIA attributing while processing bookmark status
2025-01-31 14:18:28 -05:00
Marcos Rigoli
bd9c97c269 fix: Unify Xpert audit trial eligibility between backend and frontend (#1581)
* fix: Refactored Chat to be easier to read

* chore: Fixed comment typo
2025-01-30 16:35:39 -03:00
Alison Langston
c70fb138f0 feat: update proctoring info panel api call (#1579) 2025-01-29 15:00:13 -05:00
Kristin Aoki
8823cfaa0a feat: update next unit button plugin for left sidebar navigation usage (#1578)
* feat: move unit next button slot to plugins folder

* feat: update unit navigation at top to use next unit plugin

* fix: remove 2u plugin specific code
2025-01-28 13:01:18 -05:00
salmannawaz
7865fadec2 chore: update catalog-info file and remove openedx.yaml (#1575) 2025-01-24 09:39:36 -05:00
Marcos Rigoli
5be1620f1d fix: Updated learning assistant to v2.14.2 (#1577) 2025-01-21 17:17:38 -03:00
Kshitij Sobti
d5a6a59d07 feat: Add plugin slots for progress page components (#1496) 2025-01-16 12:56:07 -05:00
Braden MacDonald
826f1382dd * fix(deps): update @openedx/paragon to v22.13.0, fix minor TypeScript warning (#1572)
* fix(deps): update dependency @openedx/paragon to v22.13.0

* fix: update use of useWindowSize() to reflect accurate data types

* chore: allow slightly larger bundle size for new paragon :/

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 10:09:17 -08:00
Awais Ansari
5e5fdeba44 fix: updated notifiations preferences url (#1573) 2025-01-10 17:13:15 +05:00
dependabot[bot]
01369eb00d chore(deps): bump cross-spawn from 7.0.3 to 7.0.6
Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6.
- [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6)

---
updated-dependencies:
- dependency-name: cross-spawn
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-08 17:25:18 -08:00
renovate[bot]
4bb4bb7a88 fix(deps): update dependency @edx/browserslist-config to v1.4.0 (#1570)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-08 00:40:32 +00:00
renovate[bot]
1d154f46c1 fix(deps): update dependency @edx/frontend-platform to v8.1.5 (#1568)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-06 22:58:18 +00:00
renovate[bot]
420db8133f chore(deps): update dependency jest-when to v3.7.0 2025-01-06 14:53:06 -08:00
Kristin Aoki
1ffc93dc6d feat: update grade summary to show floating point grades (#1558)
This PR resolves the bug that shows assignment's weighted grades that do not sum to the correct total grade. When a learner's weighted grades round down to the nearest whole number, but the summation of the weighted grades will round to a higher percent than the pre-rounded summation. To clarify this for users, the assignment's weighted grade will now show 2 decimal points, matching the legacy display found in the grade graph. To further clarify the difference, a tooltip was added to show the learner the raw weighted grade and the rounded weighted grade.
2025-01-06 15:12:40 -05:00
Marcos Rigoli
346e15abd4 feat: Updated frontend-lib-learning-assistant to v2.14.1 (#1559) 2025-01-03 13:00:10 -03:00
renovate[bot]
4726c23bc3 fix(deps): update dependency sass-loader to v16.0.4 (#1565)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-03 02:01:20 +00:00
renovate[bot]
cbbb417894 fix(deps): update dependency @openedx/frontend-slot-footer to v1.0.7 (#1564)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 22:50:50 +00:00
renovate[bot]
c57f28ad40 fix(deps): update dependency @openedx/frontend-build to v14.2.2 (#1563)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 18:25:52 +00:00
renovate[bot]
310fb84517 fix(deps): update dependency @edx/frontend-platform to v8.1.4 (#1562)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 16:06:10 +00:00
renovate[bot]
623f6946e5 fix(deps): update dependency @edx/frontend-component-header to v5.8.2 (#1561)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 15:54:37 +00:00
renovate[bot]
cf124877e8 chore(deps): update dependency eslint-import-resolver-webpack to v0.13.10 (#1560)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 14:40:47 +00:00
renovate[bot]
0456ad9318 fix(deps): update dependency husky to v9 (#1545)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 11:34:18 -03:00
edX requirements bot
7be87b0f83 chore: update browserslist DB (#1555)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-01-02 11:33:07 -03:00
Rodrigo Martin
cbe5b28762 fix(AU-2174): Fix left sidebar throwing 404 (#1556) 2024-12-20 13:09:10 -03:00
Abdur Rahman Asad
4a80532b8d fix: update iframe feature policy
This is needed to fix Xblock video play button not working in Chrome for youtube videos due to iframe security policy.
2024-12-18 09:38:00 -08:00
Marcos Rigoli
e505f78cfb feat: Updated frontend-lib-learning-assistant to v2.13.0 (#1557) 2024-12-18 12:50:19 -03:00
dependabot[bot]
3811f5f9d5 chore(deps): bump nanoid from 3.3.7 to 3.3.8
Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.7 to 3.3.8.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.3.7...3.3.8)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 11:17:29 -08:00
Varsha Menon
8a20b908c7 feat: upgrade learning assistant (#1553) 2024-12-16 10:09:34 -05:00
Kristin Aoki
8a6fa937ea feat: add progress certificate status plugin slot (#1551) 2024-12-11 13:24:33 +01:00
Alison Langston
dafdcad2b4 feat: update gating for chat component (#1550)
* feat: update gating for chat component

* fix: add gating for access expiration

* chore: upgrade learning assistant version
2024-12-09 16:21:40 -05:00
dependabot[bot]
cd56ffaf9d chore(deps): bump path-to-regexp and express
Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `path-to-regexp` from 0.1.10 to 0.1.12
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md)
- [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.10...v0.1.12)

Updates `express` from 4.21.1 to 4.21.2
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.2/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.21.1...4.21.2)

---
updated-dependencies:
- dependency-name: path-to-regexp
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-09 12:06:31 -08:00
edX requirements bot
c11cb85d78 chore: update browserslist DB (#1548)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-12-09 10:04:40 -08:00
Farhaan Bukhsh
b09bcbd3ae Revert PR #1519 "fix: only one in-course experience sidebar can be open..."
(and "fix: add test in CourseOutlineTray")
This reverts commit 020e7fb42 and 038b05ba
2024-12-04 11:06:35 -08:00
Braden MacDonald
4a925f9c11 refactor: convert masquerade UI widgets to Function Components + TypeScript (#1513)
* refactor: convert masquerade UI widgets to TypeScript

* test: improve test coverage

* chore: upgrade @testing-library/user-event to v14

* test: improve test coverage

* test: improve test coverage
2024-12-04 22:33:06 +05:30
Brian Smith
f5b6243c61 feat: wrap existing sidebars in frontend-plugin-framework PluginSlots (#1543) 2024-12-04 10:24:03 -05:00
dependabot[bot]
98c670afe7 chore(deps): bump http-proxy-middleware from 2.0.6 to 2.0.7
Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.6 to 2.0.7.
- [Release notes](https://github.com/chimurai/http-proxy-middleware/releases)
- [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.7/CHANGELOG.md)
- [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.6...v2.0.7)

---
updated-dependencies:
- dependency-name: http-proxy-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-02 09:34:26 -08:00
jciasenza
038b05ba6c fix: add test in CourseOutlineTray 2024-11-30 20:57:59 +05:30
jciasenza
020e7fb42c fix: only one in-course experience sidebar can be open at a time failing 2024-11-30 20:57:59 +05:30
Demid
ead98538b9 feat: hide studio button for limited staff (#1436) 2024-11-29 00:36:05 +05:30
renovate[bot]
90ef6ace5c fix(deps): update dependency @openedx/frontend-plugin-framework to v1.4.1 (#1544)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-26 22:50:10 +00:00
renovate[bot]
e0196f2a2a fix(deps): update dependency copy-webpack-plugin to v12 2024-11-26 14:41:49 -08:00
edX requirements bot
b7befcff7e chore: update browserslist DB (#1541)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-11-25 10:38:56 -08:00
Varsha Menon
642031bf87 feat: upgrade learning assistant (#1542) 2024-11-25 12:02:51 -05:00
Brian Smith
f778f27647 feat: update to header with new FPF pluginProps (#1524) 2024-11-22 15:20:58 -05:00
renovate[bot]
b3bce8713c chore(deps): update dependency @pact-foundation/pact to v13.2.0 2024-11-21 13:59:06 -08:00
renovate[bot]
dacb30c73e chore(deps): update actions/checkout action to v4 2024-11-21 09:37:10 -08:00
renovate[bot]
81a4deeec0 fix(deps): update dependency @openedx/paragon to v22.10.0 (#1536)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-21 05:14:05 +00:00
renovate[bot]
9a1b05a1a4 fix(deps): update dependency @openedx/frontend-plugin-framework to v1.4.0 (#1535)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-21 00:55:38 +00:00
renovate[bot]
b9e1fb0d2b fix(deps): update dependency @edx/frontend-lib-special-exams to v3.2.0 (#1534)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 22:04:03 +00:00
renovate[bot]
ebd0f8816c fix(deps): update dependency @edx/frontend-lib-learning-assistant to v2.5.0 (#1533)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 20:47:48 +00:00
renovate[bot]
d749429361 fix(deps): update dependency @edx/frontend-component-header to v5.8.0 (#1532)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 17:12:33 +00:00
renovate[bot]
19b8df35ae chore(deps): update dependency axios-mock-adapter to v2.1.0 2024-11-20 09:06:54 -08:00
renovate[bot]
e468d2087b fix(deps): update dependency sass-loader to v16.0.3 (#1530)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 11:23:37 +00:00
renovate[bot]
42e0ac86d7 fix(deps): update dependency @openedx/frontend-slot-footer to v1.0.6 (#1529)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 08:36:02 +00:00
renovate[bot]
ea5cf37fd8 fix(deps): update dependency @edx/frontend-platform to v8.1.2 (#1528)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 03:33:02 +00:00
renovate[bot]
e4cdec7389 chore(deps): update dependency @pact-foundation/pact to v13.1.5 (#1527)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 00:14:12 +00:00
renovate[bot]
8aafc6b8bd fix(deps): update dependency redux to v4.2.1 2024-11-19 16:08:56 -08:00
dependabot[bot]
913c8e4086 chore(deps): bump codecov/codecov-action from 4 to 5
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-18 11:27:30 -08:00
Nathan Sprenkle
c221770213 chore: bump frontend-build to 14.2.0 (#1522) 2024-11-18 14:02:51 -05:00
Nathan Sprenkle
4fe40c264f feat: add configurable robots meta tag (#1520) 2024-11-18 12:47:52 -05:00
Marcos Rigoli
c20c7677a3 chore: Updated @edx/frontend-lib-learning-assistant to v2.4.1 (#1518) 2024-11-14 15:22:23 -03:00
Kristin Aoki
2ff8c3949e fix: update skip nav destination (#1516) 2024-11-12 16:18:09 -05:00
edX requirements bot
4a5c43d365 chore: update browserslist DB (#1515)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-11-12 12:32:57 -08:00
Kristin Aoki
4da37f369b feat: add page not found route (#1514)
* feat: add page not found route

* feat: add logging

* feat: add tests
2024-11-12 09:05:24 -05:00
edX requirements bot
0effb32318 chore: update browserslist DB (#1511)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-11-04 12:26:21 -08:00
Roman Edirisinghe
6813872dd3 fix: corrects typo in IFRAME_FEATURE_POLICY 2024-11-04 09:47:37 -08:00
Kristin Aoki
e337a367d1 fix: xblock error mfe unit preview (#1508)
* feat: add functionality to see unit draft preview

* fix: course redirect unit to sequnce unit redirect

* fix: not showing preview when masquerading

* feat: in preview fetch draft branch of sequence metadata
2024-11-01 13:22:24 -04:00
Bilal Qamar
65343470e1 test: Remove support for Node 18 (#1454)
* test: Remove support for Node 18

* chore: update code coverage artifact naming
2024-10-31 15:35:17 -04:00
Navin Karkera
e69114a839 feat: option to show/hide ungraded assignment in progress page (#1380)
* feat: option to show/hide ungraded assignment in progress page

test: add tests for show ungraded toggle

feat: update score label in progress page based on grading

refactor: update score label text and add tooltip

refactor: move label tooltip near header as normal text

refactor: update problem score label Graded scores

* refactor: move config check to utils
2024-10-31 15:48:24 +05:30
Alison Langston
2d63a14c2e feat: update courseware search api name (#1507) 2024-10-30 08:52:54 -04:00
Juan Carlos Iasenza (Aulasneo)
2d1f893a40 fix: untranslatable strings in Instructor Toolbar #1193 (#1505) 2024-10-29 14:34:08 -07:00
edX requirements bot
64f92deeb1 chore: update browserslist DB (#1506)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-10-28 11:28:11 -07:00
Kristin Aoki
d47433ee83 feat: add functionality to see unit draft preview (#1501)
* feat: add functionality to see unit draft preview

* feat: add tests for course link redirects

* fix: course redirect unit to sequnce unit redirect

* fix: test coverage
2024-10-28 10:31:17 -04:00
Brian Smith
6f1159617e feat: add frontend-plugin-framework header slot (#1504) 2024-10-23 11:45:57 -04:00
Brian Smith
8cc6b8cdde feat(deps): update header to 5.6.0 (#1502) 2024-10-22 19:19:47 -04:00
edX requirements bot
048488fb25 chore: update browserslist DB (#1499)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-10-21 11:08:06 -07:00
edX requirements bot
2a58ad2477 chore: update browserslist DB (#1497)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-10-15 10:46:25 -07:00
Mubbshar Anwar
798c51b4e7 fix: pass extra prop to plugin slot (#1494)
passing model as a prop to plugin slot for dynamic model selection
SONIC-717
2024-10-11 14:40:10 +05:00
Braden MacDonald
9a83d67d78 refactor: Enable TypeScript support in this repo (#1459) 2024-10-07 10:23:24 -07:00
edX requirements bot
356b183c5c chore: update browserslist DB (#1495)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-10-07 10:16:08 -07:00
Braden MacDonald
d64a4e448b chore(deps): bump sass to v1.79 and sass-loader to v16 (#1490) 2024-10-03 14:36:01 -07:00
Piotr Surowiec
860b3f9952 fix: send XBlock visibility status to the LMS (#1491) 2024-10-01 20:38:19 +05:30
edX requirements bot
4418c5422f chore: update browserslist DB (#1493)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-09-30 00:36:11 +00:00
dependabot[bot]
372c9de1db chore(deps): bump micromatch from 4.0.5 to 4.0.8 (#1469)
Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8.
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 12:14:18 -07:00
dependabot[bot]
65adaf18d4 build(deps): bump webpack from 5.89.0 to 5.94.0 (#1468)
Bumps [webpack](https://github.com/webpack/webpack) from 5.89.0 to 5.94.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.89.0...v5.94.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 19:11:35 +00:00
renovate[bot]
ed77465282 chore(deps): update dependency joi to v17.13.3 (#1474) 2024-09-23 12:04:09 -07:00
edX requirements bot
f5f6747ecb chore: update browserslist DB (#1489)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-09-23 11:42:30 -07:00
Ishan Masdekar
fbe16483ac fix: corrects navigation if the student does not pass the entrance exam (#1429) 2024-09-23 11:41:52 -07:00
Piotr Surowiec
e4a0105042 fix: increase subsection grades rounding precision (#1397)
We used two decimal digits to match the experience from the edx-platform.
However, https://github.com/openedx/edx-platform/pull/27788 increased
the precision to reduce the impact of double rounding.
2024-09-23 11:39:15 -07:00
Kaustav Banerjee
1d19ae0e7b fix: masquerade dropdown not showing current selection (#1434)
* feat: remove child components from state and use data instead

* fix: change active selection based on user input

* test: add test cases
2024-09-23 11:32:41 -07:00
Navin Karkera
b9d11982e3 feat: support jumping to specific xblock id (#1427)
Adds ability to pass `jumpToId` query param to iframe url as id hash to
be used by browser to scroll to the correct xblock
2024-09-20 10:34:56 -07:00
Braden MacDonald
73590f1ccd fix: upload codecov report as a separate workflow step (#1476) 2024-09-20 10:21:33 -07:00
Braden MacDonald
f8d35bf45d docs: Update README to explain how to run this using Tutor (#1472) 2024-09-19 09:55:48 -07:00
Braden MacDonald
2038bad822 feat: use bundlewatch to monitor bundle size (#1479) 2024-09-19 16:15:15 +00:00
Braden MacDonald
6c11947397 fix: sass deprecation warning in GradeBar.scss (#1473) 2024-09-19 09:06:11 -07:00
renovate[bot]
26565cd89c chore(deps): update dependency axios-mock-adapter to v2 (#1484)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-17 11:28:34 -07:00
edX requirements bot
3a203e8351 chore: update browserslist DB (#1487)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-09-16 09:48:48 -07:00
Kristin Aoki
500e4abcb9 Revert "fix: show studio button if user has access (#1452)" (#1486)
This reverts commit 82b27e59cc.
2024-09-13 13:39:10 -04:00
renovate[bot]
d78851bb5b chore(deps): update dependency @pact-foundation/pact to v13 (#1478)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-12 22:12:41 +00:00
renovate[bot]
8c9a43d02b chore(deps): update actions/checkout action to v4 (#1477)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-12 15:06:53 -07:00
renovate[bot]
13c7c1de89 fix(deps): update dependency classnames to v2.5.1 (#1464)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-12 13:55:42 -07:00
renovate[bot]
ba44b28cec fix(deps): update dependency @openedx/paragon to v22.8.1 2024-09-12 19:18:16 +00:00
renovate[bot]
79affe0629 chore(deps): update dependency axios-mock-adapter to v1.22.0 (#1037)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-12 19:10:17 +00:00
edX requirements bot
d0ec7e3fb2 chore: enable github action auto update in dependabot.yml (#1451) 2024-09-12 11:48:37 -07:00
renovate[bot]
3f8b8077a9 chore(deps): update dependency @testing-library/jest-dom to v5.17.0 (#1362)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-12 11:47:07 -07:00
renovate[bot]
290f17d76d fix(deps): update dependency @openedx/frontend-plugin-framework to v1.3.0 2024-09-12 18:46:31 +00:00
renovate[bot]
64a1149550 fix(deps): update dependency @edx/frontend-platform to v8.1.1 2024-09-12 18:46:16 +00:00
edX requirements bot
e907ade40a chore: update browserslist DB (#1447)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-09-12 11:38:51 -07:00
renovate[bot]
68a7bf5527 fix(deps): update dependency @openedx/frontend-slot-footer to v1.0.5 2024-09-12 16:21:21 +00:00
renovate[bot]
db75ea28e4 fix(deps): update dependency @edx/openedx-atlas to v0.6.2 2024-09-12 16:20:58 +00:00
Braden MacDonald
ba4bdfe6af fix: remove unneeded deps, put build deps into 'dependencies' not dev (#1456) 2024-09-12 09:14:56 -07:00
Jorg Are
b63508db97 feat: Add a plugin slot for the content iframe loader (#1453) 2024-09-11 14:11:08 +01:00
Kristin Aoki
82b27e59cc fix: show studio button if user has access (#1452) 2024-09-09 09:11:56 -04:00
Bilal Qamar
ec8b5c5d6e build: Upgrade to Node 20 (#1443)
* feat: updated node to v20

* fix: updated/resolved failing test

* refactor: updated package-lock along with validate & lockfile version workflows

* refactor: removed unnecesary eslint ignore & updated ProductTours test
2024-09-06 12:23:07 -04:00
Bilal Qamar
dc1e9cd2e8 test: Add Node 20 to CI matrix (#1445)
* test: Add Node 20 to CI matrix

* refactor: removed eslint disable

* refactor: updated validate workflow continue-on-error node version
2024-09-03 12:20:36 -04:00
Muhammad Adeel Tajamul
a681333a08 feat: added UI for one click unsubscribe flow (#1444)
* feat: added UI for one click unsubscribe flow

---------

Co-authored-by: Awais Ansari <awais.ansari63@gmail.com>
2024-08-19 14:15:15 +05:00
renovate[bot]
7cbbc720d1 chore(deps): update dependency @openedx/frontend-build to v14.1.0 2024-08-15 03:10:59 +00:00
renovate[bot]
863a838e6e fix(deps): update dependency @openedx/frontend-slot-footer to v1.0.3 2024-08-15 00:29:50 +00:00
renovate[bot]
5b046e828a fix(deps): update dependency @openedx/frontend-plugin-framework to v1.2.3 2024-08-14 22:00:05 +00:00
renovate[bot]
a8f72c5e75 fix(deps): update dependency @edx/openedx-atlas to v0.6.1 2024-08-14 20:28:08 +00:00
renovate[bot]
bb6c678904 fix(deps): update dependency @edx/frontend-component-header to v5.3.4 2024-08-14 15:27:41 +00:00
Bilal Qamar
71c2a31531 feat: updated frontend-build & frontend-platform major versions (#1391)
* feat: platform & react-unit-test-utils major version update, updated jest to v29

* feat: updated frontend-build to v14 along with respective edx packages

* refactor: bumped package versions, updated snapshots for failing tests

* fix: code refactors to resolve failing tests

* refactor: added code comment in jest config
2024-08-14 11:20:27 -04:00
Braden MacDonald
99a44dda37 docs: transfer maintainership from 2U Aurora to volunteers (Braden + Farhaan) 2024-08-08 08:27:24 -04:00
Marcos Rigoli
5ae86465cc fix: Optimizely initialization refactor for Xpert (#1432) 2024-08-06 14:01:12 -03:00
Marcos Rigoli
6e9c105eb9 fix: Updated learning assistant version (#1431) 2024-08-05 10:10:16 -04:00
sundasnoreen12
26199fa954 fix: reset initialsidebar after shouldDisplaySidebarOpen (#1428)
* fix: reset initialsidebar after shouldDisplaySidebarOpen

* fix: fixed issue due to localstorage sidebar value when shifting from old to new one
2024-08-02 15:22:18 +05:00
Arunmozhi
3a542766d7 fix: remove redundant form-control in masquerade user input 2024-08-01 11:18:57 -04:00
sundasnoreen12
bbe03dc46f fix: fixed overflow issue of stacked bar on mobile (#1425)
* fix: fixed overflow issue of stacked bar on mobile

* refactor: instead of ismobileview i used shouldDisplayFullScreen
2024-07-30 13:53:12 +05:00
Ihor Romaniuk
167d51b596 fix: iframe height for discussions sidebar (#1393)
* fix: iframe height for discussions sidebar

* fix: increase adaptation brakepoint
2024-07-26 10:57:40 -04:00
sundasnoreen12
7efe8f5cc3 chore: make sidebar less intrusive for mobile (#1423)
* chore: make sidebar less intrusive for mobile

* fix: fixed first time view issue

* refactor: refactor code
2024-07-24 14:59:53 +05:00
Alison Langston
263fe6d1a2 chore: upgrade la library version (#1424) 2024-07-23 08:57:54 -04:00
Marcos Rigoli
76f98d5bb2 feat: Added experiments to Learning Assistant (#1421) 2024-07-19 12:33:13 -03:00
Zachary Hancock
e0386fe40b fix: update exams lib (#1422) 2024-07-19 10:56:13 -04:00
Kristin Aoki
7d99677acd feat: plugin slot to show non course content on next button click (#1412) 2024-07-17 21:05:43 -06:00
Marcos Rigoli
29bc2d9e17 chore: Revert Learning Assistant upgrade due to a bug (#1420) 2024-07-15 11:49:39 -03:00
Marcos Rigoli
27f3e79508 chore: Update learning assistant lib (#1419) 2024-07-15 11:10:55 -03:00
Zachary Hancock
ed74bee760 chore: update exams lib (#1418) 2024-07-11 14:30:03 -04:00
Emad Rad
c7a81fe07a chore: README updated
- code blocks added.
- heading issues fixed.
- small typos fixed.
2024-06-28 09:09:39 -04:00
Zachary Hancock
d880aac569 chore: update learning assistant lib (#1411) 2024-06-24 09:04:08 -04:00
Rodrigo Martin
072d608c64 feat(AU-2073): Trigger track event when iframe fails on load (#1407)
* feat(AU-2073): Trigger track event when iframe fails on load

* feat: fix tests

* fix: remove courseId from event
2024-06-04 16:48:21 -03:00
Ihor Romaniuk
9437142bc8 fix: optimize scroll position observer after video fullscreen exit (#1371) 2024-05-30 14:15:15 -03:00
Ihor Romaniuk
58c8ec5777 feat: [FC-0056] courseware sidebar enhancement (#1386)
- Display section and sequence progress
- Add tracking event to the unit button
- Hide the horizontal unit navigation with enabled sidebar navigation
2024-05-30 13:26:59 -03:00
Ahtisham Shahid
07357b9f10 feat: added role attrs in sidebar tracking event (#1399) 2024-05-30 12:06:21 +05:00
sundasnoreen12
1264b4245c fix: fixed width issue of incontext sidebar (#1395) 2024-05-27 13:43:31 +05:00
Zachary Hancock
e3ecee18e3 style: use brand style for search button border (#1394) 2024-05-23 13:08:48 -04:00
Varsha Menon
c3d96622e8 feat: update courseware search button (#1382) 2024-05-23 11:27:10 -04:00
Jorg Are
e577efbd27 feat: add unit title to pluginslot (#1383) 2024-05-21 17:20:51 +01:00
Rodrigo Martin
df361236d0 feat(AU-2006): Show loading state when translating unit block (#1389) 2024-05-17 13:48:23 -03:00
Brian Smith
e656f5445c feat!: organize plugin slots as components, add footer slot (#1381)
BREAKING CHANGE: slot ids have been changed for consistency
* `sequence_container_plugin` -> `sequence_container_slot`
* `unit_title_plugin` -> `unit_title_slot`
2024-05-17 12:09:47 -03:00
Zachary Hancock
f124c0d491 fix: incorrectly named plugin slots (#1388) 2024-05-16 10:24:27 -04:00
Leangseu Kim
cc041ba348 chore: lock test util to version 2.0.0 2024-05-15 15:42:24 -04:00
Leangseu Kim
257c9dcd7f chore: make sidebar less intrusive for mobile (#1377)
* chore: fix incorrect fetch result

* chore: make sidebar less intrusive for mobile

* chore: linting
2024-05-14 11:22:55 -04:00
Marcos Rigoli
1857b86c7e feat: Notification Plugin Slots (#1368)
* feat: add plugin slot for fbe lock paywall (#1347)

* feat: Added PluginSlot wrapping UpgradeNotification components (#1366)

* chore: Updated PluginSlot mock to support children and test ids

* chore: Updated mocked PluginSlot

* chore: Added unit test for MockedPluginSlot

* fix: Updated slot name ids

* feat: Added Plugin Slot wrapping UpgradeNotification in NotificationTray (#1367)

* fix: Removed PluginSlot prop scoping for UpgradeNotification (#1369)

* feat: generic sidebar notification plugin (#1379)

* feat: make notification plugin api generic

* feat: include new sidebar and tests

* feat: tweak sidebar toggle

* style: fix extra space from merge

* feat: rename plugin slots

---------

Co-authored-by: Alison Langston <46360176+alangsto@users.noreply.github.com>
Co-authored-by: Zachary Hancock <zhancock@edx.org>
2024-05-13 16:59:20 -04:00
Ihor Romaniuk
1c3610e9af feat: [FC-0056] create course outline sidebar (#1375) 2024-05-07 13:02:06 -03:00
Awais Ansari
796bbef10b fix: removed new sidebar view tickiness (#1376) 2024-04-30 19:09:17 +05:00
sundasnoreen12
799e57f970 fix: fixed width issues of old and new sidebar (#1374)
Co-authored-by: Awais Ansari <79941147+awais-ansari@users.noreply.github.com>
2024-04-30 17:40:23 +05:00
Awais Ansari
cf3a91dde0 feat: added course level isNewDiscussionSidebarViewEnabled flag to control sidebar view switching (#1373)
* feat: added course level isNewDiscussionSidebarViewEnabled flag

* test: fixed notification widget test cases
2024-04-29 16:14:08 +05:00
Leangseu Kim
72381a783b chore: remove UnitTranslationPlugin (#1352)
* chore: remove UnitTranslationPlugin

* chore: add plugin slot for sequence
2024-04-22 12:14:33 -04:00
sundasnoreen12
75f56ea4bd fix: fixed flicker issue of navbar width (#1364)
* fix: fixed fliker issue of navbar  width

* refactor: added hook function

* refactor: placed discussion and notification constant on common place

* refactor: moved to constant

* refactor: fixed variable rename
2024-04-18 15:27:16 +05:00
Rodrigo Martin
a418ba6adb feat(AU-1894): send track event when requesting translation (#1360)
* feat(AU-1894): send track event when requesting translation

* feat: add source != target language condition
2024-04-17 15:42:51 -03:00
sundasnoreen12
2da930f819 fix: fixed expended view unit bar issue (#1356)
* fix: fixed expended view unit bar issue

* refactor: removed expanded width
2024-04-17 12:29:45 +05:00
renovate[bot]
a2c38112fb chore(deps): update dependency @openedx/frontend-build to v13.1.4 2024-04-16 18:01:10 +00:00
Alison Langston
36535d188d feat: upgrade special exams (#1357) 2024-04-16 12:55:53 -04:00
renovate[bot]
79f49032e3 fix(deps): update dependency @edx/frontend-lib-special-exams to v3.0.1 2024-04-16 16:09:21 +00:00
renovate[bot]
9b3b123e45 fix(deps): update dependency @edx/frontend-component-footer to v13.0.5 2024-04-16 16:08:42 +00:00
sundasnoreen12
98436b4605 fix: fixed zindex and width issue (#1346) 2024-04-15 19:15:42 +00:00
Leangseu Kim
7652fa46d1 Lk/translation only for verified (#1355)
* chore: update verified mode logic

* chore: add is staff logic

* chore: add test
2024-04-15 11:57:20 -03:00
Leangseu Kim
2347ce88cd chore: update translation tour modal title 2024-04-15 09:40:22 -04:00
Leangseu Kim
78e5c57bd3 chore: fix translation for verified student only logic 2024-04-15 09:40:22 -04:00
Leangseu Kim
108636761c chore: fix codecov action error 2024-04-12 11:28:23 -04:00
Leangseu Kim
5f56828bda chore: patch frontend-build deployment 2024-04-12 11:28:23 -04:00
Rodrigo Martin
23e522e893 feat(AU-1949): Restrict WCT to verified track learners only (#1345)
* feat(AU-1949): Restrict WCT to verified track learners only

* fix: use jest-when

* fix: clean tests
2024-04-08 11:16:08 -03:00
sundasnoreen12
9423a889ba fix: fixed units overflow issue (#1343)
* fix: fixed units overflow issue

* refactor: refactor code for desktop and xl screen

* refactor: fixed refactor issue
2024-04-05 01:33:07 +05:00
Isaac Lee
85b95adb9f fix: modal iframe height to 100% (#1341) 2024-04-02 13:14:05 -04:00
ABBOUD Moncef
d4e7b416b1 fix: course update iframe (#1204) 2024-03-29 16:12:23 -04:00
renovate[bot]
0cb369af2b fix(deps): update dependency @openedx/paragon to v22.2.1 2024-03-27 20:57:21 +00:00
renovate[bot]
c908d3a3dd fix(deps): update dependency @edx/frontend-platform to v7.1.3 2024-03-27 17:48:28 +00:00
renovate[bot]
895a3b6b9f chore(deps): update dependency @openedx/frontend-build to v13.0.30 2024-03-27 17:47:25 +00:00
Leangseu Kim
36b3c36379 feat: whole course translations (#1330)
* feat: add language selection

chore: update tests so we have less error message

test: update test

* test: update tests

* chore: remove duplicate translation

* chore: lint for console

* chore: remove comments

* chore: make sure the affect url frame refresh after the language selection change

* chore: add whole_course_translation and language to courseware meta (#1305)

* feat: Add feedback widget UI mock

Add unit tests

Fix snapshot

Clean Sequence component logEvent calls

Clean unit test

Put feedback widget behind whole course translation flag

Fix useFeedbackWidget test

* chore: add src and dest translation

* feat: first iteration of plugin translation

chore: update plugin instruction

* feat: Connect FeedbackWidget with backend services (#1325)

Connect FeedbackWidget with backend services

Move feedback widget to unit translation plugin

* feat: Add authentication to WCT feedback endpoints (#1329)

* chore: add fetch config and move feedback widget for the plugin

chore: rewrite and test the api request

chore: rebase

chore: update translation feedback

chore: test

chore: add more tests

* chore: rebase

* chore: update requested change

* chore: update package

* chore: upgrade frontend-lib-special-exams and frontend-lib-learning-assistant

* chore: update tests

* chore: remove unneeded package

* chore: update example config

* chore: add source-map-loader

* fix: feedback widget render error after submit feedback (#1335)

* fix: feedback widget render error after submit feedback

* fix: widget logic

---------

Co-authored-by: Rodrigo Martin <rodrigom_94@hotmail.com>
2024-03-27 13:39:36 -04:00
Isaac Lee
3917262492 fix: bump exams ver to fix exam timer (#1331) 2024-03-21 15:57:22 -04:00
Alison Langston
7ad120c4d5 feat: upgrade learning assistant version (#1327) 2024-03-18 15:33:38 -04:00
Samir Sabri
94d20833aa feat!: remove Transifex calls for OEP-58 2024-03-18 15:01:23 -04:00
Isaac Lee
4698b11ab9 fix: rollback exams lib to unblock pipeline (#1324) 2024-03-14 14:31:40 -04:00
Awais Ansari
e46d4cc54d feat: add tracking event in upgrade notifications tray (#1323) 2024-03-14 20:52:19 +05:00
Ihor Romaniuk
92d8f637c0 fix: sequence container width and responsive for sequence navigation block (#1219) 2024-03-13 13:29:34 -03:00
Eugene Dyudyunov
c3b786c771 fix: correct rtl for handouts (#1289) 2024-03-13 12:58:56 -03:00
Isaac Lee
00aab61551 chore: update exams lib (#1321) 2024-03-13 10:14:15 -04:00
Ihor Romaniuk
b547ada1a5 fix: RTL for the upgrade notification list (#1220) 2024-03-11 12:31:36 -04:00
Ihor Romaniuk
b7159590d3 fix: wrong text-color class and text contrast on dates page (#1223) 2024-03-11 12:31:27 -04:00
Marcos Rigoli
a2d7f704a6 fix: Updated search modal to match Bootstrap's z-index. (#1318) 2024-03-11 11:44:42 -03:00
Maria Grimaldi
bca3aaccf5 feat: use navigation sequence metadata to disable navigation components (#1273)
Use navigation_disabled sequence metadata based on Hide From TOC
block field, so the student cannot navigate to another sequences in
the course outline.
https://openedx.atlassian.net/wiki/spaces/OEPM/pages/3853975595/Feature+Enhancement+Proposal+Hide+Sections+from+course+outline
2024-03-08 10:51:31 -03:00
Marcos Rigoli
3b46df6d03 fix: Updated exams UI to fix timer (#1317) 2024-03-07 15:48:20 -03:00
Bryann Valderrama
7c8e26d213 feat: show hide from toc
Show message in course outline when Hide From TOC is enabled
https://openedx.atlassian.net/wiki/spaces/OEPM/pages/3853975595/Feature+Enhancement+Proposal+Hide+Sections+from+course+outline
2024-03-06 09:42:19 -03:00
Jeremy Ristau
b1c2c1f7b3 chore: create catalog-info.yaml (#1315)
* chore: create catalog-info.yaml

* chore: update catalog-info.yaml
2024-03-05 09:25:08 -05:00
Emad Rad
4797425a21 docs: broken readme fixed (#1264) 2024-03-03 07:50:01 -05:00
Alison Langston
54bb72b60c feat: update chat visibility (#1310) 2024-03-01 08:17:27 -05:00
renovate[bot]
a91ef116f1 fix(deps): update dependency @edx/frontend-platform to v5.6.1 2024-02-29 00:51:21 +00:00
renovate[bot]
80634c6188 fix(deps): update dependency @edx/frontend-component-header to v4.11.1 2024-02-28 21:46:24 +00:00
renovate[bot]
ec1bad25a7 fix(deps): update dependency @edx/frontend-component-footer to v12.7.1 2024-02-28 21:24:08 +00:00
renovate[bot]
b2980f02a0 fix(deps): update dependency @edx/react-unit-test-utils to v1.7.1 2024-02-28 19:24:33 +00:00
renovate[bot]
9d38e9dc93 chore(deps): update dependency @openedx/frontend-build to v13.0.28 2024-02-28 16:52:17 +00:00
Mashal Malik
c28991d6e0 refactor: replace @edx/paragon and @edx/frontend-build (#1261)
Co-authored-by: mashal-m <mashal.malik@arbisoft.com>
Co-authored-by: Bilal Qamar <59555732+BilalQamar95@users.noreply.github.com>
2024-02-28 13:42:44 -03:00
Alison Langston
ff7366d42a feat: refactor date visibility (#1298) 2024-02-22 15:25:37 -05:00
Alison Langston
6def66677a feat: update chat visibility (#1297) 2024-02-22 11:46:48 -05:00
Alison Langston
8335dec0de feat: upgrade learning assistant version (#1295) 2024-02-21 09:31:08 -05:00
Varsha Menon
992ab4887b feat: show chat for desktop only (#1286) 2024-02-20 14:37:57 -05:00
Alison Langston
5d2aa5e60a feat: update learning assistant version (#1294) 2024-02-20 13:59:48 -05:00
sundasnoreen12
9dd79ca77e fix: fixed empty section issue (#1292)
* fix: fixed empty section issue

* refactor: added checks to hide view
2024-02-15 15:56:04 +05:00
Muhammad Adeel Tajamul
9bfa0d06b6 feat: stick discussion sidebar to top (#1290) 2024-02-15 06:43:32 +05:00
Alison Langston
c6d4bb3b45 feat: update exams and learning-assistant versions (#1291) 2024-02-13 10:29:49 -05:00
Alison Langston
db1fc7782c feat: gate visibility of chat component by active attempt (#1282) 2024-02-12 09:17:32 -05:00
Marcos Rigoli
efd57c326e CoursewareSearch - Show filters if needed only (#1287)
* fix: CoursewareSearch - Show filters if needed only

* fix: Refactored CoursewareSearch filtering logic

* chore: Fixed unit tests for CoursewareResultsFilter

* chore: Added CoursewareSearch hooks coverage
2024-02-09 12:50:42 -03:00
Muhammad Abdullah Waheed
a18ed8ed6c feat: babel-plugin-react-intl to babel-plugin-formatjs migration (#1200) 2024-02-08 14:58:48 -05:00
mashal-m
a340381738 refactor: update lock file version 2024-02-08 14:10:30 -05:00
Michael Roytman
170cbe1da0 Refactor use of frontend-lib-special-exams public API to use hooks. (#1284)
* feat: refactor use of frontend-lib-special-exams public API to hooks

This commit refactors the use of the frontend-lib-special-exams public API to use hooks.

This commit also imports the root reducer from the frontend-lib-special-exams library. This root reducer is used for the specialExams slice when configuring the store for this application.

* feat: update special exams version

* feat: update snapshots

---------

Co-authored-by: Alie Langston <alangsto@wellesley.edu>
2024-02-08 13:58:19 -05:00
Michael Roytman
174de4bc1b feat: update version of frontend-lib-learning-assistant to 1.21.0 (#1285)
This commit installs version 1.21.0 of @edx/frontend-lib-learning-assistant. This commit also refactors the Chat tests to assert on whether the Xpert component is rendered by the Chat component, not whether Xpert actually renders. This is because Xpert now has its own logic to determine whether to render.

This release uses a new GET endpoint published on the Learning Assistant backend to determine whether the Learning Assistant feature is enabled. If the features is not enabled, the Learning Assistant is not rendered, and vice-versa.
2024-02-07 15:39:23 -05:00
alangsto
55e2332b00 feat: remove audit access to learning assistant chat (#1280)
* feat: remove audit access to la

* feat: remove audit access to la
2024-01-29 17:08:17 -05:00
Omar Al-Ithawi
25d746b7c8 feat: tutor-mfe compatiblilty for atlas pull (#1279)
- install atlas
 - remove `--filter` to pull all languages by default
 - use ATLAS_OPTIONS to allow custom `--filter`
 - include frontend-lib-special-exams in `atlas pull`
2024-01-29 12:40:36 -05:00
alangsto
e790e2636f feat: upgrade learning assistant to latest version (#1278) 2024-01-24 15:08:30 -05:00
alangsto
c428222125 Revert "feat: update learning-assistant version" (#1277) 2024-01-24 10:17:21 -05:00
alangsto
58365ba18e feat: update learning-assistant version (#1276) 2024-01-24 09:33:38 -05:00
Troy Sankey
ab87167052 fix: ignore failed outline API call when learner has no access
If the learner doesn't even have access to the course (e.g. because the
course starts in the future), don't worry about a 404 fetching the
course outline since we're not planning to use it anyway.

ENT-8078
2024-01-22 12:49:08 -08:00
sundasnoreen12
4928f505bd test: added test cases for new sidebar (#1267)
* test: added test cases for new sidebar

* test: added factory for verified user

* refactor: updated description for notification widget
2024-01-11 15:54:25 +05:00
alangsto
59a68afa5d feat: gate chat visibility by course end date (#1270) 2024-01-10 09:10:15 -05:00
Zachary Hancock
486faa5744 chore: update exams lib (#1268) 2024-01-08 13:56:01 -05:00
sundasnoreen12
023f5ac254 feat: added implementation for new sidebar (#1260)
* feat: added implementation for new sidebar

* test: fixed test cases

* refactor: fixed naming convention and combine useeffects

* refactor: improved sidebar UI and renamed sidebar flag

* refactor: remove additional states

* refactor: fixed UI and logic related issue

* refactor: simplified condition

* refactor: toggle sidebar action

* refactor: fixed toggle issues

* refactor: back arrow component

* refactor: changed useeffect position

---------

Co-authored-by: Awais Ansari <awais.ansari63@gmail.com>
2024-01-08 13:40:21 +05:00
Michael Roytman
4dc4725ba1 feat: pass unitId as a prop through to Xpert component (#1256)
This commit modifies the Course component to pass the unitId prop, which presents the unit usage key in which the Xpert is being rendered, to the Chat component. The Chat component passes this unit ID as a prop to the Xpert component.
2024-01-05 09:08:55 -05:00
Michael Roytman
600f5b4dff feat: add technical support URL in the LTI-based provider proctored exam download instructions (#1258)
This commit changes the installed version of the frontend-lib-special-exams module from 2.25.0 to 2.26.0.

This release adds support for displaying a technical support URL for LTI-based providers on the download instructions interstitial of proctored exams. The download instructions will display a technical support URL when it is returned from the proctoring settings backend endpoint. If the technical support URL is not available, then the technical support email and technical support phone number will be used instead.
2023-12-20 15:18:25 -05:00
German
06d79ce16d fix: prevent error when there are no results for a given filter (#1257) 2023-12-19 13:00:14 -03:00
German
b3a06fd07e feat: update filter naming on courseware search modal (#1255)
Update names to be one of the folow:
1. All Content
2. Text
3. Video
4. Section
5. Other
2023-12-18 17:01:02 -03:00
Zachary Hancock
684ac495f5 feat: update exams library (#1254) 2023-12-15 16:03:26 -05:00
Troy Sankey
79575330c9 feat: Add redirect to enterprise learner dashboard (#1251)
When a learner tries to load the B2C course page for a course that
starts in the future (error_code="course_not_started"), normally the
learning MFE automatically redirects to the B2C dashboard.  This change
supports an alternate error_code "course_not_started_enterprise_learner"
to trigger an alternative redirect to the B2B (enterprise) learner
dashboard.

This does two main things:

1. When the course metadata API response indicates
   course_access.error_code = "course_not_started_enterprise_learner"
   then redirect to "/redirect/enterprise-learner-dashboard".
2. When the top-level router matches path "/redirect/enterprise-learner-dashboard"
   then redirec to to the value of config `ENTERPRISE_LEARNER_PORTAL_URL`.

ENT-8078
2023-12-15 07:45:36 -05:00
Marcos
2bf326fc67 UI search UI a11y changes (#1253)
* fix: Updated UI a11y changes in Courseware Search

* feat: Removed result count for search

* fix: Added new line at the end of course-tabs-navigation.scss
2023-12-15 09:23:34 -03:00
German
e004ead21d bug: fix errors messages when results are empty (#1252)
https://2u-internal.atlassian.net/browse/KBK-80
2023-12-12 16:59:25 -03:00
German
4d723335bf feat: use state params to keep query and filter while searching (#1249)
* feat: use state params to keep query and filter while searching

* feat: Minor factors renaming methods

* feat: fix tests

* feat: Only change url when hit search button

* feat: fix tests
2023-12-11 10:45:13 -03:00
mashal-m
d065c23e32 refactor: add @openedx in renovate automate configuration 2023-12-05 14:18:41 -05:00
alangsto
83c600737b feat: remove segment event (#1250) 2023-12-05 11:47:36 -05:00
alangsto
a30dccd3cf feat: upgrade frontend-lib-learning-assistant version (#1248) 2023-12-05 09:26:01 -05:00
Ben Warzeski
4e1346716b feat: allow plugin.modal to open a fullscreen modal (#1243) 2023-12-04 13:18:59 -05:00
Marcos
5906576c6e Add test coverage for Courseware Search components (WIP) (#1242)
* chore: 100% coverage on CoursewareSearchResults.jsx

* chore: Added test coverage for all CoursewareSearch components

* chore: Minor fixes on Courseware Search components
2023-12-04 12:39:07 -03:00
renovate[bot]
d7cffcd414 fix(deps): update dependency @edx/brand to v1.2.3 2023-12-04 11:34:23 +00:00
renovate[bot]
cf49d92951 chore(deps): update dependency rosie to v2.1.1 2023-12-04 07:05:38 +00:00
Leangseu Kim
2fd5e92d2d chore: fix typo for modal event 2023-11-29 15:26:48 -05:00
leangseu-edx
bce25c462a chore: update sidebar logic (#1236)
* fix: make side bar notification behave correctly

---------

Co-authored-by: Awais Ansari <awais.ansari63@gmail.com>
2023-11-22 11:46:34 -05:00
Ben Warzeski
fe773d1700 feat: forward modal-close event to children on modal close (#1238)
* feat: forward modal-close event to children on modal close

* fix: update tests
2023-11-21 14:38:46 -05:00
leangseu-edx
748e73d128 revert: notification made forum click rate drop (#1237) 2023-11-17 15:30:51 -05:00
Leangseu Kim
c38d69f9db chore: update test 2023-11-09 14:19:28 -05:00
Leangseu Kim
18103bcf54 chore: make notification display by default 2023-11-09 14:19:28 -05:00
German
9698c4d4de fix: maxScore can be null (#1235) 2023-11-09 14:47:25 -03:00
Marcos
a70a26f2e5 Endpoint usage implementation for Courseware Search (WIP) (#1232)
* feat: Endpoint usage implementation for Courseware Search

Co-authored-by: Simon Chen <schen@edx.org>

* chore: Added tests and error case

* fix: remove console log

* fix: update tests

* fix: update tests

* fix: update variables

---------

Co-authored-by: Simon Chen <schen@edx.org>
Co-authored-by: German <germanolle@gmail.com>
2023-11-09 13:13:59 -03:00
Leangseu Kim
308f03cf3a chore: make notification trigger default to open for audit user 2023-11-08 15:54:09 -05:00
Stanislav
9a0cdc06c9 fix: Fix dropdown menu in breadcrumbs (#1190)
Co-authored-by: Stanislav Lunyachek <lunyachek@MacBook-Pro-M1.local>
2023-11-08 13:35:29 -05:00
Mashal Malik
a64f0e0406 refactor: updated README file to reflect template changes (#1230) 2023-10-31 19:12:30 +05:00
Alex
ce24a58c99 feat: Add courseware search results filter container (#1225) 2023-10-27 09:34:29 -05:00
Marcos
c257048d29 feat: Added CoursewareSearchResults UI component (#1224)
* feat: Added CoursewareSearchResults UI component

* fix: Added conditional for undefined case instead of null

* fix: Updated code to avoid mutation
2023-10-27 10:57:02 -03:00
David Nuon
7c9211073f Add CoursewareSearchForm component (#1214)
* feat: Add CoursewareSearchBar component

* fix: lint

* fix: Clarified component names and i18n description

* test: Add more tests

* fix: lint

* fix: Made props in CoursewareSearchForm optional
2023-10-24 13:32:26 -07:00
alangsto
040f1cb55b feat: upgrade learning assistant version (#1217) 2023-10-23 15:54:48 -04:00
Feanil Patel
00e7680c20 chore: Update to the new version of brand-openedx in the new scope. (#1216)
Part of https://github.com/openedx/axim-engineering/issues/23

This updates the `@edx/brand` alias to point to the `brand-openedx` package at
the `openedx` scope. This does not impact imports because this package is used
via an alias.
2023-10-20 13:21:00 -04:00
Marcos
cbb419c256 Added Courseware Search container popover UI (#1212)
* feat: Added Courseware Search container popover

* chore: Added unit tests for CoursewareSearch and CoursewareSearchToggle

* chore: Updated unit test for CourseTabsNavigation

* chore: Partial coverage on Courseware Search Hooks

* chore: Finished Courseware Search Hooks unit testing

* fix: Fixed an overlook that caused a conditional hook

* fix: Reduced bounce timeout on scroll/resize to 100ms

* chore: Updated snapshots

* chore: Moved @testing-library/react-hooks dep to DEV

* chore: Minor adjustments on unit tests

* chore: Fixed test issue
2023-10-20 11:33:41 -03:00
alangsto
12205de132 feat: upgrade learning assistant version (#1215) 2023-10-20 10:07:18 -04:00
Marcos
62465ec956 feat: added waffle flag state for Courseware Search (#1199) 2023-10-12 19:06:00 +00:00
Syed Ali Abbas Zaidi
165097d061 chore: bump frontend-platform (#1209) 2023-10-12 18:42:22 +05:00
Zachary Hancock
570cdb4b2a fix: exams lib bug patch (#1205) 2023-10-11 14:09:01 -04:00
Rafay
391ea08b20 fix: make progress graph respect course settings (#1194) 2023-10-11 11:28:10 -04:00
renovate[bot]
5604def491 chore(deps): update dependency @edx/frontend-build to v12.9.17 2023-10-04 21:51:00 +00:00
Syed Ali Abbas Zaidi
b788b969c3 feat: upgrade react router to v6 (#1128)
* feat: upgrade react router to v6

* fix: all test cases affected by react router upgrade

* refactor: fix navigations

* fix: test cases affectewd due to lib-special-exams

* refactor: improve code coverage
2023-10-04 17:34:53 -04:00
Zachary Hancock
b7a3d5640a fix: special exams version fix (#1196) 2023-09-27 13:12:20 -04:00
Zachary Hancock
3a21d8c807 feat: update exams library (#1188) 2023-09-25 13:46:29 -04:00
alangsto
81442bebe9 feat: update learning assistant version (#1195) 2023-09-21 14:44:58 -04:00
alangsto
168ed1e184 feat: upgrade learning assistant version (#1187) 2023-09-18 13:27:57 -04:00
Ben Warzeski
c8e32c3f46 feat: allow override of plugin.modal height (#1184) 2023-09-15 10:12:47 -04:00
Bilal Qamar
51dd90741b feat: update react & react-dom to v17 (#1127)
* feat: update react & react-dom to v17

* build: update paragon version

* refactor: updated edx packages

* refactor: updated react-unit-test-utils

* build: update lock file

* build: update lock file

* build: update lock file

* build: update lock file

* refactor: bumped frontend-lib-learning-assistant version

---------

Co-authored-by: mashal-m <mashal.malik@arbisoft.com>
2023-09-11 10:53:32 -04:00
Michael Roytman
f58d6d6d25 feat: add Segment event for rendering Xpert and bump frontend-lib-learning-assistant version (#1182)
In order to diagnose low usage rates, we're temporarily adding Segment events for rendering the chat and for closing the call-to-action message. This will help us determine whether Xpert is being successfully rendered and whether Xpert is being ignored by tracking whether learners close the call-to-action message at a high rate.

At a minimum, we expect to remove the Segment event for rendering the Xpert, because this will be a very noisy Segment event. We plan to leave it in for a few days just to accumulate data. We will evaluate whether to keep the call-to-action dismissal Segment event based on the data.

This commit adds the Segment event for rendering the Xpert. This commit also installs version 1.11.1 of frontend-lib-learning-assistant, which introduces a Segment event for for closing the call-to-action message.
2023-09-08 16:11:41 -04:00
alangsto
81a49bd755 feat: grant audit learners access (#1180) 2023-09-07 13:47:04 -04:00
Pierre Mailhot
2ae033160f fix: alert.start.long and alert.start.calendar (#1173)
They are currently using end, but since we are in the course-start-alert file it should be start instead.
2023-09-07 11:18:35 -04:00
alangsto
32bd3190a6 fix: prevent content tools from displaying over chat sidebar (#1179) 2023-08-31 17:09:16 -04:00
Artur Gaspar
645ac2cb5f fix: toggle notes visibility button state correctly (#1170) 2023-08-31 10:36:53 -04:00
Michael Roytman
ee80b24cba feat: install new version of frontend-lib-learning-assistant to conditionally render toggle elements (#1178)
This commit installs version 1.9.3 of @edx/frontend-lib-learning-assistant, which includes a UI tweak to conditionally render the Xpert toggle button and action message (call-to-action) only when the Xpert sidebar is closed.
2023-08-30 11:53:23 -04:00
alangsto
ee1d816cc8 feat: update frontend-lib-learning-assistant (#1177) 2023-08-30 08:48:22 -04:00
alangsto
e8ac2ffc7e feat: update frontend-lib-learning-assistant (#1176) 2023-08-29 17:01:38 -04:00
alangsto
62d3e95cc8 feat: update learning assistant version (#1175) 2023-08-29 15:47:02 -04:00
Michael Roytman
ce6771d7cc feat: install new version of frontend-lib-learning-assistant to add UI tweaks (#1174)
This commit installs version 1.8.0 of @edx/frontend-lib-learning-assistant, which includes a various UI tweaks.
2023-08-29 14:08:39 -04:00
alangsto
1dcde821b4 feat: upgrade learning assistant library (#1172) 2023-08-28 13:38:19 -04:00
Michael Roytman
694e3ed6d5 feat: install new version of frontend-lib-learning-assistant and add Privacy Policy URL to config (#1171)
This commit installs version 1.6.0 of @edx/frontend-lib-learning-assistant, which includes a new user disclosure feature. This commit also includes the Privacy Policy URL to the frontend-app-learning config, because the Xpert learning assistant uses this config value in the disclosure.
2023-08-28 10:44:27 -04:00
alangsto
ba843622c2 feat: update version of the learning assistant frontend (#1168) 2023-08-24 14:19:19 -04:00
Michael Roytman
2d29827e6b feat: install Xpert chatbot from frontend-lib-learning-assistant (#1166)
This commit installs the Xpert chatbot feature from the frontend-lib-learning-assistant repository into the frontend-lib-learning application.

This component is rendered by the Course component. The component is only rendered when a few conditions are satisfied.
2023-08-23 09:14:14 -04:00
sundasnoreen12
2b9b3db5d3 refactor: refactor code by creating 1 instance of header instead of 3 (#1164)
* refactor: refactor code by creating single instance of header instead of 3

* refactor: refactor courseStatus comparsion code

---------

Co-authored-by: SundasNoreen <sundas.noreen@arbisoft.com>
2023-08-23 14:46:47 +05:00
Awais Ansari
2e90e214b4 fix: should not fetch courseTopics for lti provider (#1165)
* fix: should not fetch courseTopics for lti provider

* refactor: fetch course topics when provider is edx
2023-08-22 12:44:31 +05:00
alangsto
ea2d7ed839 feat: add config value for chat response url (#1163) 2023-08-18 08:52:25 -04:00
Mohamed Akram
5ee61904d5 fix: make nav buttons use links for accessibility (#1137) 2023-08-14 13:18:55 -04:00
Zachary Hancock
6232b0cb98 Revert "Revert "feat: update special exams lib (#1152)" (#1154)" (#1161)
This reverts commit 1871e491a7.

The original PR was reverted due to it's deploy coinciding with the app breaking. Turns out it was not the root cause.
2023-08-10 10:30:22 -04:00
Zachary Hancock
09542338a2 feat: rebuild package lock (#1160)
* feat: rebuild package lock

* feat: update paragon

* test: fix axios/jest incompatibility
2023-08-09 13:29:59 -04:00
renovate[bot]
c3d345e642 chore(deps): update dependency @edx/reactifex to v2.2.0 2023-08-09 04:24:16 +00:00
renovate[bot]
ec2bf60345 chore(deps): update dependency @edx/browserslist-config to v1.2.0 2023-08-09 00:02:00 +00:00
Zachary Hancock
b0c71e5291 fix: error when navigating exam units (#1157)
* fix: incorrect usage of useEffect callback caused intermittent react errors
2023-08-08 17:34:05 -04:00
renovate[bot]
dcd6847254 fix(deps): update dependency reselect to v4.1.8 2023-08-08 18:41:06 +00:00
renovate[bot]
d2df9241c3 chore(deps): update dependency @edx/frontend-build to v12.9.4 2023-08-08 15:56:08 +00:00
Zachary Hancock
1871e491a7 Revert "feat: update special exams lib (#1152)" (#1154)
This reverts commit 0c49658314.
2023-08-08 11:23:12 -04:00
renovate[bot]
03543c0af1 fix(deps): update dependency js-cookie to v3.0.5 2023-08-08 14:33:17 +00:00
Zachary Hancock
0c49658314 feat: update special exams lib (#1152) 2023-08-08 09:04:58 -04:00
Demid
2a1173584e fix: make iframe wrapper take all vieport width (#1094) 2023-07-31 12:21:56 -04:00
Omar Al-Ithawi
398330fa07 feat: include paragon in atlas pull (#1145)
This pull request is part of the [FC-0012 project](https://openedx.atlassian.net/l/cp/XGS0iCcQ) which is sparked by the [Translation Infrastructure update OEP-58](https://open-edx-proposals.readthedocs.io/en/latest/architectural-decisions/oep-0058-arch-translations-management.html#specification).
2023-07-25 11:21:54 -04:00
renovate[bot]
f92fc8c3a5 fix(deps): update dependency @popperjs/core to v2.11.8 2023-07-25 14:01:38 +00:00
renovate[bot]
5e072949d6 chore(deps): update dependency @edx/frontend-build to v12.9.3 2023-07-25 11:25:32 +00:00
Rebecca Graber
2d132f114c feat: upgrade pact (#1141)
Upgrade pact to 11
2023-07-17 12:47:29 -04:00
alangsto
c73ef26d8e feat: add segment event for lti modal launch (#1140) 2023-07-13 13:56:25 -04:00
ayesha waris
97ca7fe6aa fix: sidebar state remains open for all users (#1139) 2023-07-13 15:30:16 +05:00
Ben Warzeski
e95a59c6c8 fix: modal hook name for unit iframe modal signal (#1138) 2023-07-10 15:26:56 -04:00
Peter Kulko
5f9c441cd2 fix: added Paragon translations (#1136) 2023-07-10 14:25:56 -04:00
Ben Warzeski
2e641ac6c9 Bw/unit splitup (#1134)
* refactor: break Unit component into smaller unit-tested parts

* feat: save scroll position on video fullscreen exit

* chore: remove swap file
2023-07-10 10:29:56 -04:00
alangsto
22937918ab feat: add component to iframe LTI launch (#1135) 2023-07-06 14:57:39 -04:00
ihor-romaniuk
714f5d452c fix: save scroll position on exit from video xblock fullscreen mode 2023-07-06 08:43:01 -04:00
ayesha waris
8ac9745261 fix: modifies sidebar state such that it remains open (#1131)
* fix: modifies sidebar state such that it remains open

* refactor: removed localstorage for discussions sideba
2023-06-27 14:05:46 +05:00
Zachary Hancock
340580cb41 chore: update exams lib (#1130) 2023-06-22 09:19:43 -04:00
Leangseu Kim
5a99ca5c91 fix: breadcrumb jump nav styling 2023-06-08 09:19:45 -04:00
Ben Warzeski
9943df49e4 feat: allow clipboard write to xblock iframes (#1117) 2023-06-06 10:09:33 -04:00
Jenkins
855474d406 chore(i18n): update translations 2023-06-04 17:09:52 -04:00
Ghassan Maslamani
a78496a3f6 fix: sync LMS_BASE_URL for bookmark API if changed
This change makes it possible to use the latest  LMS_BASE_API
  if it was changed because of dynamic config API, which is the
  default case of tutor.

  This changes closes openedx/wg-build-test-release/issues/270

   Fixes that are simlar to this
  - gradebook openedx/frontend-app-gradebook/pull/290
  - course authoring openedx/frontend-app-course-authoring/pull/389
2023-05-31 15:11:34 +01:00
Jansen Kantor
79b65dadca fix: gracefully handle 403 responses in tab loading (#1111) 2023-05-24 11:38:40 -04:00
Bilal Qamar
fc8f5d43e8 feat: upgraded to node v18, added .nvmrc and updated workflows (#1084)
* feat: upgraded to node v18, added .nvmrc and updated workflows

* refactor: updated packages

* refactor: updated packages

* refactor: updated packages

* fix: add workaround in json file

* build: remove jestEnv line from json

* refactor: updated packages

* refactor: updated packages

* refactor: updated packages

* refactor: updated packages

* refactor: updated packages

* refactor: updated packages

* fix: add workaround in json file

* build: remove jestEnv line from json

* refactor: updated packages

* refactor: updated packages

* refactor: updated packages

* refactor: updated packages

* refactor: updated packages

* refactor: updated jest & fixed failing tests

* refactor: updated lmsPact failing test cases

* refactor: updated frontend-build version

* Merge branch master of github.com:edx/frontend-app-learning into bilalqamar95/node-v18-upgrade

---------

Co-authored-by: mashal-m <mashal.malik@arbisoft.com>
2023-05-23 18:39:34 +05:00
Zachary Hancock
6232f40a74 feat: update special-exams-lib (#1113) 2023-05-16 15:08:46 -04:00
David Joy
bc0ff1ce65 chore: bumping frontend-platform version to get userId logging
frontend-platform has a new feature to include the userId (if it exists) when logging an error to the logging service.  We want that.
2023-05-16 09:44:29 -04:00
David Joy
5997b29cee fix: logging an error when unit iframe fails to load
Right now we log nothing to the logging service when a unit iframe fails to load.  The ErrorPage that’s shown isn’t using the ErrorBoundary, so we had no indication that something went wrong.  This solves the problem closer to the source where the error originates.
2023-05-16 09:44:29 -04:00
Omar Al-Ithawi
d2de0632cd feat: add experimental atlas to pull_translations (#1093)
This is an experimental off-by-defualt feature for moving the translation files ouside the repos.

Run `OPENEDX_ATLAS_PULL=true make translations` to use atlas to pull translations instead of transifex.

Refs: FC-12 OEP-58
2023-05-09 10:03:42 -04:00
Zachary Hancock
922cc2187a fix: update exams lib to fix download click bug (#1110) 2023-05-09 09:23:40 -04:00
Sagirov Eugeniy
d9539796b5 chore: update frontend-platform version to v4.2.0 2023-05-02 14:34:30 -03:00
alangsto
e0acb501eb chore: upgrade frontend-lib-special-exams version (#1107) 2023-04-26 08:52:03 -04:00
Asad Ali
a03ffe2724 fix: fix links under contenttools (#1096) 2023-04-26 13:42:16 +05:00
Jenkins
cbdf7ce064 chore(i18n): update translations 2023-04-23 17:09:46 -04:00
Zachary Hancock
7184e85b2b feat: update exams library (#1103) 2023-04-21 12:09:29 -04:00
Emad Rad
b5321d01e4 feat: Persian Language added to messages (#989)
feat: fa_IR added to transifex_langs

feat: Persian translations added

Co-authored-by: Leangseu Kim <lkim@edx.org>
Co-authored-by: leangseu-edx <83240113+leangseu-edx@users.noreply.github.com>
2023-04-18 14:03:06 -04:00
Yoiber
6c8ab1a4c9 chore(i18n): add more languages (#1063)
* chore(i18n): add more languages

* chore(i18n): Pylint fixed
2023-04-18 12:41:30 -04:00
Varsha
01f9d8f50b feat: fetch exam access token (#1083)
* feat: fetch exam access token

* build: update frontend lib special exams version
2023-04-17 14:59:05 -04:00
Zachary Hancock
764befd4bd feat: exams svc should not be enabled by default (#1100) 2023-04-12 10:36:21 -04:00
Zachary Hancock
7317c9424a feat: update special-exams lib (#1098) 2023-04-10 09:46:21 -04:00
alangsto
d897663b73 feat: upgrade special exams version and add required config values (#1097) 2023-04-06 09:55:06 -04:00
Muhammad Adeel Tajamul
2e4eb158f2 feat: added url param to open discussion sidebar (#1092) 2023-04-04 13:33:35 +05:00
Jenkins
35b229bd1b chore(i18n): update translations 2023-04-02 17:09:43 -04:00
Muhammad Adeel Tajamul
4ebd569792 feat: added open/close state of discussion sidebar in local storage (#1086) 2023-03-28 15:39:00 +05:00
lunyachek
52235ebc1c feat: create component to decode params 2023-03-27 14:54:42 -04:00
Jenkins
aa380e8619 chore(i18n): update translations 2023-03-26 17:09:41 -04:00
lunyachek
4cf0c7f4d7 feat: Add border for active tab in course navigation at Live page 2023-03-22 10:36:33 -04:00
alangsto
743650a99e chore: pin frontend lib special exams version (#1088) 2023-03-17 13:35:26 -04:00
Muhammad Adeel Tajamul
39d89bee9e fix: discussion sidebar loads very slow (#1081) 2023-03-13 05:40:23 +05:00
Jenkins
a601e431b2 chore(i18n): update translations 2023-03-12 17:09:40 -04:00
Muhammad Adeel Tajamul
7519bbe28e fix: copy link for discussion sidebar not working in chrome (#1079) 2023-03-10 06:01:24 +05:00
alangsto
4b90dcbfc3 feat: update special exams version (#1080) 2023-03-09 10:45:47 -05:00
Zachary Hancock
54cb52cb6d feat: update special-exams library (#1078) 2023-03-08 15:14:39 -05:00
renovate[bot]
6dbd3f49dd fix(deps): update dependency @edx/paragon to v20.28.4 2023-03-01 11:25:35 +00:00
renovate[bot]
678502bb40 fix(deps): update dependency @edx/brand to v1.2.0 2023-03-01 07:19:50 +00:00
renovate[bot]
bf77fc7ca1 fix(deps): update dependency query-string to v7.1.3 2023-03-01 02:08:11 +00:00
renovate[bot]
421a9a5d2b fix(deps): update dependency @edx/frontend-lib-special-exams to v2.2.1 2023-02-28 22:45:58 +00:00
Feanil Patel
dfe44cae56 build: Updating a missing workflow file add-depr-ticket-to-depr-board.yml.
The .github/workflows/add-depr-ticket-to-depr-board.yml workflow is missing or needs an update to stay in
sync with the current standard for this workflow as defined in the
`.github` repo of the `openedx` GitHub org.
2023-02-28 10:37:18 -05:00
Feanil Patel
a88571dae8 build: Creating a missing workflow file add-remove-label-on-comment.yml.
The .github/workflows/add-remove-label-on-comment.yml workflow is missing or needs an update to stay in
sync with the current standard for this workflow as defined in the
`.github` repo of the `openedx` GitHub org.
2023-02-28 10:37:18 -05:00
Feanil Patel
a4ea334692 build: Creating a missing workflow file self-assign-issue.yml.
The .github/workflows/self-assign-issue.yml workflow is missing or needs an update to stay in
sync with the current standard for this workflow as defined in the
`.github` repo of the `openedx` GitHub org.
2023-02-28 10:37:18 -05:00
Adam Stankiewicz
97a1cb4ffc chore: upgrade @edx/frontend-platform to v3.4.1 (#1071)
* chore: upgrade @edx/frontend-platform to v3.4.0
* chore: upgrade to frontend-platform v3.4.1
2023-02-28 09:18:28 -05:00
Jenkins
5166bfe056 chore(i18n): update translations 2023-02-26 16:09:40 -05:00
Varsha
33e3765b19 build: add exams url to envs (#1066) 2023-02-22 11:40:24 -05:00
Jenkins
a13e7d7389 chore(i18n): update translations 2023-02-19 16:09:38 -05:00
Isaac Lee
a4ea1b54a4 fix: exams with no due date now display exam type (#1064)
* fix: exams with no due date now display exam type
2023-02-16 15:16:19 -05:00
Eugene Dyudyunov
cd430ebb5d fix: first section celebration
Fix the first section celebration modal showing logic.

On Nutmeg+ it's shown only after the page reload or after going directly
to the second section from the course home. Going through the course
with the Next/Previous buttons has no effect (which worked on Maple).

Notes:
- the weekly goal has the same showing logic, but I assume that is
correct behavior so no changes are added for it in this commit.
- showing a celebration modal for the first section completion when
going directly to the first unit of the second section seems to be a bug
(reproduces on Maple too)
2023-02-14 16:54:40 -05:00
Jenkins
630d44a8cc chore(i18n): update translations 2023-02-12 16:09:38 -05:00
Jenkins
894e16ddf0 chore(i18n): update translations 2023-02-05 16:09:37 -05:00
Muhammad Abdullah Waheed
263c486330 chore: Automate Browserslist DB Update (#987)
* feat: added cron github action to auto update brwoserlist DB periodically

* refactor: used a shared script to update broswerslist DB, create PR and automerge it
2023-01-31 17:41:10 +05:00
Bilal Qamar
b3d33667d4 Updated frontend-build to v12 (#962)
* feat: rebase previous frontend-build upgrade

* chore: make welcome message to default to empty
2023-01-30 12:20:07 -05:00
Jenkins
b500546e8d chore(i18n): update translations 2023-01-29 16:09:37 -05:00
leangseu-edx
cb9e0aa52f feat: copy static to dist folder for prod (#1057)
* feat: copy static to dist folder for prod

* chore: update webpack.prod.config.js

Co-authored-by: Ben Warzeski <bwarzeski@edx.org>

Co-authored-by: Ben Warzeski <bwarzeski@edx.org>
2023-01-25 14:29:00 -05:00
Leangseu Kim
69ff5463b3 fix: update iframe static stylesheet 2023-01-25 10:08:44 -05:00
ihor-romaniuk
3b4561e142 fix: fix alignment in the streak celebration modal 2023-01-24 11:47:43 -05:00
Jenkins
cf3b3a27bc chore(i18n): update translations 2023-01-22 16:09:35 -05:00
Ben Warzeski
3bb7aa06bc Bw/share by unit (#1050)
* fix: disable share feature on component unmount

* fix: share only on set units

* fix: share only on set units

* fix: typo
2023-01-20 11:33:38 -05:00
Ben Warzeski
4cea9e582b Bw/share by unit (#1049)
* fix: disable share feature on component unmount

* fix: share only on set units

* fix: share only on set units
2023-01-20 11:02:37 -05:00
Ben Warzeski
0c74bb5106 fix: disable share feature on component unmount (#1048)
* fix: disable share feature on component unmount

* chore: make sure useEffect run only once

Co-authored-by: Leangseu Kim <lkim@edx.org>
2023-01-20 09:07:18 -05:00
Jansen Kantor
b082f3ed19 feat: remove mmp2p (#1042)
* feat: remove mmp2p experiment folder

* feat: remove AccessExpirationAlertMMP2P

* feat: remove imports references and conditionals for mmp2p
2023-01-19 15:35:01 -05:00
leangseu-edx
5d477cebb2 fix: update social sharing icon and title (#1046)
* fix: update social sharing icon and title

* chore: remove twitter icon
2023-01-18 10:29:09 -05:00
Leangseu Kim
851e49f8fb chore: install react share and implement social share demo 2023-01-17 09:17:40 -05:00
Jansen Kantor
09436dd175 test: each.it indentation (#1043) 2023-01-12 16:00:06 -05:00
Awais Ansari
53c8e01c28 fix: hide discussions sidebar and trigger icon when unit does not exist or enableInContext is false. (#1039)
* fix: removed nonCourseWare topics from topics

* fix: hide discussions sidebar and trigger icon when enableInContext is false
2023-01-09 14:29:42 +05:00
Leangseu Kim
ed2d816bbe fix: upgrade discount space 2023-01-03 12:54:22 -05:00
Awais Ansari
7c067299fb refactor: rename inContext param to inContextSidebar (#1022) 2022-12-30 17:04:33 +05:00
Mehak Nasir
4ee1570bfa fix: sidebar length is fixed (#1023) 2022-12-28 13:34:17 +05:00
Leangseu Kim
91c548847b fix: upgrade paragon to remedy the pipeline fix 2022-12-23 11:15:17 -05:00
renovate[bot]
49440ffb45 chore(deps): update dependency @edx/reactifex to v2.1.1 2022-12-23 11:54:31 +00:00
renovate[bot]
6752447d94 chore(deps): update dependency @edx/browserslist-config to v1.1.1 2022-12-23 05:25:42 +00:00
renovate[bot]
75c6aadb09 fix(deps): update dependency util to v0.12.5 2022-12-23 05:14:37 +00:00
renovate[bot]
9eceb355f6 fix(deps): update dependency reselect to v4.1.7 2022-12-23 05:02:03 +00:00
renovate[bot]
df7786388c fix(deps): update dependency regenerator-runtime to v0.13.11 2022-12-23 04:51:29 +00:00
renovate[bot]
361de31e22 fix(deps): update dependency react-share to v4.4.1 2022-12-23 04:40:17 +00:00
renovate[bot]
9e040ec8f1 fix(deps): update dependency react-redux to v7.2.9 2022-12-22 22:25:46 +00:00
renovate[bot]
8db8aeed71 fix(deps): update dependency classnames to v2.3.2 2022-12-22 22:15:18 +00:00
renovate[bot]
04471e550b fix(deps): update dependency @popperjs/core to v2.11.6 2022-12-22 22:04:21 +00:00
renovate[bot]
925ee97a76 fix(deps): update dependency @edx/frontend-lib-special-exams to v2.1.2 2022-12-22 21:54:00 +00:00
renovate[bot]
65086af173 chore(deps): update dependency @testing-library/jest-dom to v5.16.5 2022-12-22 21:42:53 +00:00
Adam Stankiewicz
33923d9a69 chore: upgrade @edx/frontend-build from v9 -> v12 (#1017)
* chore: ignore eslint issues during frontend-build v9 -> v12 upgrade

* chore: add comment to .eslintrc.js file

* chore: update frontend-build

* chore: update test and remove a few unit tests

Co-authored-by: Leangseu Kim <lkim@edx.org>
2022-12-22 13:44:02 -05:00
leangseu-edx
080d31e934 Revert "fix: update transifex flag for tx cli 1.4.0"
This reverts commit f8a1147571.
2022-12-20 16:06:36 -05:00
Leangseu Kim
f3c80ed39b fix: text in goal modal 2022-12-20 15:03:08 -05:00
Leangseu Kim
1ca4eda08a chore: fix fo format relative time 2022-12-19 11:10:34 -05:00
Jenkins
6193c2d1b3 chore(i18n): update translations 2022-12-18 16:04:31 -05:00
leangseu-edx
f8a1147571 fix: update transifex flag for tx cli 1.4.0 2022-12-14 11:40:24 -05:00
Ghassan Maslamani
edba1600dc fix: fix tabs urls on progress tab
This fix does fixes the url links by getting them from the state
 simliar to how tabs navigation gets them.

 This would allow it work for PUBLIC_PATH is not '/', i.e. in
 tutor.

  This was reported in openedx/build-test-release-wg/issues/222
2022-12-07 17:55:15 +00:00
Jenkins
9a07ad1501 chore(i18n): update translations 2022-12-04 16:04:31 -05:00
Awais Ansari
b343ca7a74 Revert "Revert "fix: remove minHeight from in-context discussion sidebar (#1002)" (#1003)" (#1007)
This reverts commit ba06fd7c98.
2022-12-01 14:17:18 +05:00
Abdullah Waheed
b6d272e99d feat: added new translations in Makefile and updated all the translations 2022-11-30 13:31:18 +00:00
Mubbshar Anwar
0fbb53ae86 fix: update event name (#1004)
update segment event name

VAN-1168
2022-11-23 11:24:20 +05:00
Awais Ansari
ba06fd7c98 Revert "fix: remove minHeight from in-context discussion sidebar (#1002)" (#1003)
This reverts commit 9396fbd9d4.
2022-11-18 18:22:35 +05:00
Awais Ansari
9396fbd9d4 fix: remove minHeight from in-context discussion sidebar (#1002) 2022-11-17 20:59:50 +05:00
Abderraouf Mehdi Bouhali
57d880de70 fix(rtl): mirror new user tour modal background
Mirrors the background image used in the new user tour modal
as it obstructs the readability of the modal title when in RTL
2022-11-07 16:04:17 +00:00
Abderraouf Mehdi Bouhali
bfad5cf684 fix(rtl): use backslash to write fractions (grades) 2022-11-07 16:03:56 +00:00
Jenkins
b0378e1331 chore(i18n): update translations 2022-11-06 16:04:22 -05:00
Andrew Shultz
19d06d60be fix: display onboarding expired after expiration (#997)
Currently expiring soon is displayed 28 days before expiration
and forever afterwards. Adds an actual expired state for after.

Also clarifies the expring soon message which assumed other course,
that was not necessarily true.

Also updates the take action lines when you do not have valid
onboarding to make sure they appear for everything not currently valid
or in process, and updates the submitted process lines to not appear
for expired statuses.
2022-11-03 09:26:42 -04:00
Zachary Hancock
df91fef82e feat: update special exams lib (#992) 2022-10-31 11:49:24 -04:00
Jenkins
7e53ddb685 chore(i18n): update translations 2022-10-30 17:09:24 -04:00
Diana Olarte
be72e36a3a feat: allow runtime configuration (#955)
Allows frontend-app-learning to be configured at
runtime using the LMS's new MFE Configuration API.

Part of openedx/frontend-wg#103
2022-10-27 10:01:43 -04:00
Abderraouf Mehdi Bouhali
fa5cf8f204 fix(rtl): force (%) symbol to follow text direction 2022-10-26 10:31:53 -03:00
Jenkins
759d154e13 chore(i18n): update translations 2022-10-19 05:08:31 -04:00
Abderraouf Mehdi Bouhali
7c4200e9d3 fix(rtl): mirror position of grade rectangles in grade bar (#980)
Translates the rectangles for current and passing
grades when to appear on the right when in RTL.
2022-10-14 12:49:37 -04:00
Kshitij Sobti
e5e73e40ba feat: update discussion sidebar url to allow grouping by subsection (#968)
To enable grouping by subsection in the discussions MFE, this PR updates
the embed URL to the one that supports grouping.

ref: https://github.com/openedx/frontend-app-discussions/pull/281
2022-10-12 17:57:42 +05:00
Muhammad Abdullah Waheed
1892edaade refactor: updated renovate config to auto update minor and patch versions of edx dependencies (#963) 2022-09-28 10:47:31 -04:00
Sarina Canelake
381be9a26b Fix github url strings (org edx -> openedx) (#971)
* fix: fix github url strings (org edx -> openedx)

* fix: update path to .github workflows to read from openedx org
2022-09-14 10:01:48 -04:00
Shafqat Farhan
b3841ef446 feat: [VAN-1081] - Set weekly goal and start course events via query param (#972) 2022-09-13 11:00:09 +05:00
Jenkins
5a897e4ea1 chore(i18n): update translations 2022-09-11 17:07:42 -04:00
Hammad Ahmad Waqas
96ceab8b2f fix: Redirecting to MFE home page instead of access-denied page to save redirection (#970) 2022-09-07 15:39:12 +05:00
Hammad Ahmad Waqas
f9806d0759 feat: added support to check if active enterprise is same as EnterpriseCourseEnrollment object (#967) 2022-09-07 11:39:03 +05:00
edx-semantic-release
a7b584c566 chore(i18n): update translations 2022-08-07 17:03:35 -04:00
Shafqat Farhan
193a184142 feat: [VAN-1000] - Set weekly goal through welcome email via query param (#956) 2022-07-26 09:07:55 +05:00
Hammad Ahmad Waqas
3e76f7ac78 feat: Added support to redirect to DSC if required. (#958) 2022-07-25 13:14:41 +05:00
Maman Khan
36062ff3a6 fix: removed derpreciated codecov package (#953) 2022-06-20 08:10:46 +05:00
ruzniaievdm
6257cb4b58 refactor: Replace PDF course certificate view code (#946)
Co-authored-by: ruzniaievdm <ruzniaievdm@gmail.com>
2022-06-13 09:15:09 -04:00
edx-semantic-release
792d9eb758 chore(i18n): update translations 2022-06-12 17:04:27 -04:00
edx-semantic-release
cd84a15891 chore(i18n): update translations 2022-06-03 13:57:12 -04:00
Diana Catalina Olarte
cafb881a61 fix: show site name instead of edX 2022-05-18 12:23:43 +01:00
edX requirements bot
fd94da0a43 feat: Add package-lock file version check (#941) 2022-05-06 15:53:47 +05:00
edx-semantic-release
1e41547b3e chore(i18n): update translations 2022-04-24 17:04:22 -04:00
Renovate Bot
bf2f123367 fix(deps): update dependency @edx/paragon to v19.18.3 2022-04-21 19:06:04 +00:00
Renovate Bot
0211ecf45e fix(deps): update dependency core-js to v3.22.2 2022-04-21 16:49:25 +00:00
renovate[bot]
36ac129267 fix(deps): update dependency @edx/paragon to v19.18.0 (#926)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-21 12:32:06 -04:00
renovate[bot]
20d4c35d83 fix(deps): update dependency core-js to v3.22.0 (#927)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-21 12:30:10 -04:00
Michael Terry
bbff8e719e fix: remove support for the legacy courseware pages
Access to learners for these pages has been removed, so we don't
need to keep any support for it around. Simplifies some code paths.
2022-04-21 08:50:53 -04:00
edx-semantic-release
5461c08169 chore(i18n): update translations 2022-04-17 17:09:11 -04:00
Michael Terry
ee88a12d8f fix: assume that dates & outline legacy tabs don't exist
They've both been removed from the LMS now. It would be harmless
to keep support for them in place, but it's pointless because
any redirects to the LMS will just come right back to us.

AA-799
2022-04-15 12:26:47 -04:00
Muhammad Adeel Tajamul
9b316bd859 feat: added live tab (#923)
Co-authored-by: adeel.tajamul <adeel.tajamul@arbisoft.com>
2022-04-14 10:04:26 +05:00
Renovate Bot
7e7eb83596 fix(deps): update dependency @edx/paragon to v19.15.1 2022-04-13 22:08:11 +00:00
Thomas Tracy
aaa367780d fix: [MICROBA-1769] Cert status before course end (#918)
* fix: [MICROBA-1769] Cert status before course end

Right now, learners who are nonpassing are able to view information
about thier certificates early at the course end screen and progress
pages. This is because we show messaging around the nonpassing state in
some cases before a course ends and certificates are available. This can
also lead to cases where grades are not finalized and students who may
be passing see a scary nonpassing message instead.

This change makes it so during the course exit, a student who finishes a
course before the course is over will see the celebration screen
regardless of passing status. Once the course is over (or if
certificates are available immediately), and they are
still not passing, they will see the nonpassing messaging. The same
change was made for the certificate status alert in the progress tab.
2022-04-13 10:14:00 -04:00
Kshitij Sobti
6d42ee9c6f feat: add discussions tab [BD-38] [TNL-9743] (#879)
* feat: add discussions tab

Adds code to load the discussions MFE in an iframe in the tab so the user isn't redirected to the LMS.

Adds code for the discussions tab, making it dynamically resize based on contents using a postMessage API.

* feat: update path based on user navigation inside discussions MFE

The discussions MFE will send path change events via the postMessage API so that the learning MFE path can be kept in sync. This will allow reloading a page without having the iframe revert to same path each time.
2022-04-13 19:01:29 +05:00
Renovate Bot
41047f4c88 fix(deps): update dependency @edx/paragon to v19.15.0 2022-04-12 09:55:15 -04:00
Renovate Bot
d83551c809 chore(deps): update dependency @testing-library/react to v12.1.5 2022-04-11 23:37:47 +00:00
Renovate Bot
7c3088901d fix(deps): update dependency @edx/frontend-component-footer to v10.2.4 2022-04-11 17:27:50 +00:00
Renovate Bot
518c9ef6c2 chore(deps): update dependency @edx/reactifex to v2 2022-04-11 10:17:28 -04:00
Michael Terry
ae97efaf2b fix: add back es-check & fsevents for now to fix build
A previous commit (7f37575) dropped es-check, which dropped
fsevents, which caused our build system (which is still using
npm@6) to fail with an error like `Unsupported platform for
fsevents` when trying to install fsevents through a dependency
(e.g. when installing npm aliases).

I am reintroducing all the package-lock changes from that commit
to get back fsevents in a state where that error does not occur.

I think a longer-term fix would be to instead upgrade our build
system to node16 / npm6. But this is an easy fix for now to unblock
the builds.
2022-04-11 09:46:10 -04:00
edx-semantic-release
361a099ed1 chore(i18n): update translations 2022-04-10 17:08:59 -04:00
Adam Stankiewicz
7f3757539a build: use shared browserslist config and remove is-es5 check 2022-04-08 16:30:25 -04:00
Michael Terry
44f5132e2a fix: downgrade react and upgrade some other deps to align
Now that we are using node 16, peer dependencies are much more
strict about aligning between all of our dependencies.

This PR downgrades react from 17 to 16 (no changes) and upgrades
paragon and frontend-lib-special-exams to all be on the same
page about what peer dependency ranges are valid.
2022-04-08 16:00:29 -04:00
Renovate Bot
53b19c9be3 chore(deps): update codecov/codecov-action action to v3 2022-04-07 15:24:08 -04:00
edX requirements bot
abc374b60a chore!: Dropped support for Node 12 2022-04-07 15:15:04 -04:00
Muhammad Soban Javed
af837fcac8 fix: run npm i with npm 8 to update lock file version (#915) 2022-04-06 16:41:04 +05:00
Renovate Bot
e328e3d597 chore(deps): update dependency @testing-library/jest-dom to v5.16.4 2022-04-05 18:39:33 +00:00
Renovate Bot
559160213d fix(deps): update dependency @popperjs/core to v2.11.5 2022-04-05 14:53:55 +00:00
Renovate Bot
878a4616f3 fix(deps): update dependency react-redux to v7.2.8 2022-04-04 16:02:20 +00:00
Renovate Bot
3028d79597 fix(deps): update dependency @edx/frontend-component-header to v2.4.6 2022-04-04 15:44:31 +00:00
alangsto
aa0de7663c chore: upgrade special exams lib version (#906) 2022-04-04 06:41:51 -07:00
edx-semantic-release
acd91a1c31 chore(i18n): update translations 2022-04-04 07:10:20 -04:00
Usama Sadiq
b32817b3dd build: update transifex pull translations command (#903) 2022-04-04 16:04:32 +05:00
Thomas Tracy
8b32e5892f chore: [MICROBA-1780] missing copy edit (#902)
We missed a copy edit from the previous PR made for this ticket. Also
changing the id to something more relevant to the message.
2022-04-01 14:28:58 -04:00
Thomas Tracy
76cf85f3d7 chore: [MICROBA-1780] Copy edits (#901)
A partner was not happy with messaging for a course whose
students were in the "earned-not-available" state. This aims to make the
messaging more clear.
2022-04-01 12:43:05 -04:00
Renovate Bot
7d86c501a7 fix(deps): update dependency react-redux to v7.2.7 2022-03-31 22:18:26 +00:00
Renovate Bot
eeee32c100 fix(deps): update dependency @reduxjs/toolkit to v1.8.1 2022-03-31 22:02:34 +00:00
Renovate Bot
95d88a054e fix(deps): update dependency @edx/frontend-platform to v1.15.6 2022-03-31 21:43:23 +00:00
edX requirements bot
550b15a16c fix: transifex migration to new client 2022-03-31 13:33:29 -04:00
Renovate Bot
715393d6ad chore(deps): update dependency @edx/reactifex to v1.1.0 2022-03-31 11:34:28 -04:00
Renovate Bot
19b4241020 fix(deps): update dependency @edx/paragon to v19.13.6 2022-03-31 09:34:02 -04:00
Renovate Bot
09bd5bd748 chore(deps): update dependency ansi-regex to 3.0.1 [security] 2022-03-31 09:32:44 -04:00
Renovate Bot
89771cb56b chore(deps): update dependency @edx/frontend-build to v9.1.4 2022-03-31 02:23:12 +00:00
Michael Terry
3353ee2f9d fix(deps): update dependency @edx/paragon to v19.13.1 2022-03-28 11:30:08 -04:00
Renovate Bot
7c1821382c fix(deps): update dependency @reduxjs/toolkit to v1.8.0 2022-03-28 11:12:22 -04:00
Ghassan Maslamani
b444d677b7 fix: import i18n messages from header for learning to consume
It just makes the learning consume the i18n of the header, as
  otherwise the learning would show the deafult messages of the
  header.
2022-03-28 10:55:44 -04:00
dependabot[bot]
7178f28838 chore(deps): bump minimist from 1.2.5 to 1.2.6
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 10:44:40 -04:00
Renovate Bot
b07f22193c chore(deps): update dependency ansi-regex to 4.1.1 [security] 2022-03-28 10:43:42 -04:00
Renovate Bot
c6eba42120 chore(deps): update dependency @testing-library/jest-dom to v5.16.3 2022-03-28 09:27:16 -04:00
Michael Terry
7bb2266790 fix: stop stripping most inaccessible sequences from navigation
I had previously made a "fix" to strip all inaccessible sequences
from the learning sequence outline hierarachy, as a way to filter
out unreleased sequences. See commit d1f19a9.

But that was too big a hammer and stripped a lot of released-but-
inaccessible sequences too (e.g. prerequisites).

So now, we adopt a more nuanced approach and explicitly just filter
out sequences that are both inaccessible AND unreleased.

AA-1219
2022-03-28 09:16:05 -04:00
edX Transifex Bot
0a70f9b64e chore(i18n): update translations 2022-03-27 17:08:29 -04:00
Renovate Bot
cfe4432c6b fix(deps): update dependency @edx/frontend-component-footer to v10.2.2 2022-03-24 13:47:25 +00:00
Chris Deery
f7219b4f5d fix: [AA-1219] Crash when locked content rendered without unit ID (#878)
Allows SequenceNavigation to complete rendering even if unitId is not provided.
2022-03-22 17:35:45 -04:00
Renovate Bot
14a19b2794 fix(deps): update dependency @edx/frontend-platform to v1.15.5 2022-03-21 20:21:41 +00:00
edX Transifex Bot
8a9767cdd3 chore(i18n): update translations 2022-03-20 17:08:15 -04:00
Chris Deery
3cba1bbac4 fix: [AA-1207] Remove redundant API fields (#873)
Remove redundant fields from courseware API. These are all found in courseHome: 

- number
- org
- originalUserIsStaff
- isStaff
- verifiedMode
- isMasquerading (virtual field from isStaff and originalUserIsStaff)
2022-03-18 09:20:31 -04:00
Chris Deery
9436770620 fix: improve Guard for Iframe resize (#875)
Fix line that was causing JS errors when it was called in a context without a valid document.
2022-03-17 14:47:19 -04:00
Renovate Bot
d03dd34009 fix(deps): update dependency @fortawesome/react-fontawesome to v0.1.18 2022-03-16 20:57:50 +00:00
Renovate Bot
9cdacde4dc chore(deps): update dependency @pact-foundation/pact to v9.17.3 2022-03-16 15:54:09 +00:00
Renovate Bot
a22ac3a776 fix(deps): update dependency @edx/frontend-platform to v1.15.3 2022-03-14 21:29:02 +00:00
Michael Terry
7e19af44da fix: trust the course grade the LMS gives us for progress page
Rather than recompute it ourselves. Now that the backend is fixed
to consider only visible grades for the course grade, we don't need
to try to work around its logic (which is more accurate/consistent
in general).

AA-1217
2022-03-14 13:04:06 -04:00
Dillon Dumesnil
57c3f3080e feat: AA-1205: Enable Entrance Exam support for Learning MFE (#840)
Adds an alert to the courseware if the section is an Entrance Exam. Also
adds a listener to reload the page upon receiving a message from the LMS
indicating the user has now passed the exam.

Commit also contains misc. clean up for i18n messages switching to variable names.
2022-03-14 08:09:15 -07:00
Renovate Bot
385635f5d1 fix(deps): update dependency @popperjs/core to v2.11.4 2022-03-14 11:59:19 +00:00
edX Transifex Bot
a7f763cd2a chore(i18n): update translations 2022-03-13 17:08:02 -04:00
Renovate Bot
c7c9c19771 fix(deps): update dependency @popperjs/core to v2.11.3 2022-03-12 15:29:22 +00:00
julianajlk
1d3a779ef1 feat: Add past expiration messaging for UpgradeNotification (#853)
REV-2500
2022-03-11 10:37:30 -05:00
julianajlk
4f1a50ec24 feat: Add Value Prop past expiration messaging for gated content (#836)
REV-2500
2022-03-11 09:58:44 -05:00
Chris Deery
72d18dc4f9 fix: [AA-1207] unify source of tabs (#861)
Courseware and courseHome both provide tabs to the mfe.
This PR unifies the calls so that tab descriptions are only fetched from courseHome metadata

Remove jest-chain dependencies to make test errors more usable.
2022-03-10 13:29:30 -05:00
Renovate Bot
2197ec0c21 fix(deps): update dependency @edx/paragon to v19.7.0 2022-03-10 09:28:37 -05:00
Renovate Bot
069ac9c234 chore(deps): update dependency @testing-library/react to v12.1.4 2022-03-10 09:00:20 -05:00
Renovate Bot
3edf349969 fix(deps): update dependency @edx/frontend-platform to v1.15.2 2022-03-08 17:41:52 +00:00
Michael Terry
a2516e9fcc fix: avoid a race condition with redux data on course exit page
I would sometimes see a case where we were trying to access
recommendations data before it was defined.
2022-03-07 15:03:03 -05:00
Renovate Bot
554806e9ce chore(deps): update actions/setup-node action to v3 2022-03-07 14:18:38 -05:00
Renovate Bot
ed13128fc4 fix(deps): update dependency prop-types to v15.8.1 2022-03-07 13:40:23 -05:00
Renovate Bot
373a2d88fc fix(deps): update dependency @edx/frontend-component-header to v2.4.5 2022-03-07 13:40:07 -05:00
Renovate Bot
bcd54a4f4b fix(deps): update font awesome 2022-03-07 13:39:44 -05:00
Renovate Bot
c4cb0e5ac2 chore(deps): update actions/checkout action to v3 2022-03-07 13:39:26 -05:00
Renovate Bot
c77d518d04 fix(deps): update dependency core-js to v3.21.1 2022-03-07 13:39:12 -05:00
Renovate Bot
703250c3d2 fix(deps): update dependency @edx/frontend-component-footer to v10.2.1 2022-03-07 16:52:26 +00:00
Michael Terry
35ec314505 chore: drop unused frontend-enterprise-utils dependency 2022-03-07 11:35:50 -05:00
Michael Terry
9fc7951576 fix: downgrade frontend-build to fix our builds
For a still-unknown reason, 9.1.2 breaks our builds in GoCD.
While that investigation continues, let's drop down to a known
working version.
2022-03-07 11:35:50 -05:00
Michael Terry
4ed350c9c6 chore: update testing-library/react to latest 12.x
Also, drop our specific testing-library/dom dependency. We can
get it transitively though testing-library/react, and they are
coupled closely enough that we don't want them out of lockstep
anyway.

Thus, this commit also updates testing-library/dom to 8.x,
because that's what testing-library/react 12.x needs.
2022-03-07 11:35:50 -05:00
Michael Terry
ebed27529c fix: adjust timer test to work again 2022-03-07 11:35:50 -05:00
Michael Terry
24ced5dc63 chore: update testing-library/dom version and clean dev deps
Get on the latest 7.x release and remove some unused dev deps:
- enzyme
- enzyme-adapter-react-17
- glob
2022-03-07 11:35:50 -05:00
Kshitij Sobti
f004d0ab3c feat: Sidebar refactor and add support for discussions sidebar. (#762)
squash!: remove unnecessary styling and migrate to bootstrap and other review feedback
2022-03-07 18:56:05 +05:00
edX Transifex Bot
1bbcc6d052 chore(i18n): update translations 2022-03-06 16:07:49 -05:00
Renovate Bot
3d122e0fb9 chore(deps): update dependency @wojtekmaj/enzyme-adapter-react-17 to v0.6.6 2022-03-04 00:08:49 +00:00
Renovate Bot
685d2d5593 chore(deps): update dependency @pact-foundation/pact to v9.17.2 2022-03-03 21:38:21 +00:00
Michael Terry
97bd45cfa8 chore: update frontend-build, paragon, header, and footer
A collection of edx-owned npm updates. These required an actual
code change of using our own svg rather than directly loading an
svg from paragon, because paragon has its own svgo config that
can potentially conflict with our version of svgo - as it does
when we update frontend-build.

And with the latest versions of frontend-build, we can now use
the latest versions of paragon.

Header and footer updates thrown in for free.
2022-03-03 16:20:05 -05:00
Chris Deery
55dac2696e fix: [AA-1206] resolve access APIs (#838)
* fix: [AA-1206] resolve access APIs

As part of eliminating redundant fields course_access was removed from
 the Courseware metadata API. There are some differences between the
 two APIs - courseware returned an error if the course had flags
 preventing it from being loaded in the MFE, and courseHome had a
 second field, can_load_courseware, that returned a boolean.

 This fix unifies the handling of the access fields to behave consistently.
2022-03-03 16:12:14 -05:00
Michael Terry
4586f8a6ad chore: update frontend-platform to 1.15.1
The bot PRs to do this stalled out, so I'm doing it manually.
2022-03-03 12:38:55 -05:00
Renovate Bot
88bc1f6956 fix(deps): update dependency @popperjs/core to v2.11.2 2022-03-03 12:08:06 -05:00
Jawayria
4f2f17beb3 fix: update workflow 2022-03-03 11:27:11 -05:00
edX requirements bot
8114750796 build: Added support for node v16 2022-03-03 11:27:11 -05:00
Michael Terry
7b945a9fce fix: guard access to a react ref before using it
This was causing some errors ever since we started using the ref
in an event handler - I'm not entirely sure why the ref stops
being valid, unless it's a lifecycle thing. But anyway, this
seems to stop the error in testing.
2022-03-03 11:09:49 -05:00
Michael Terry
48aad3951a fix: resize course handout iframe as contents change
This can happen if a handout has e.g. expanding list elements.

AA-1215
2022-03-01 13:05:35 -05:00
Michael Terry
dcf8da2279 chore: update transifex scripts to api v3
Transifex is sunsetting anything below v3 later this year. Let's
get ahead of our scripts unexpectedly failing.

- Switch 'reactifex' dev dep to our maintained fork at
  '@edx/reactifex' (it has an older released version number,
  but it's still maintained unlike the original)
- Update Makefile commands for new v3 transifex API
2022-02-28 12:49:35 -05:00
Michael Terry
d8e1124a4c chore: update to paragon 19.3.0
No change on our end, this is just to get us as up-to-date as
possible.

This is the latest version of paragon we probably want to use as
long as we still claim to support IE11 via browserlist. We start
getting warnings about grid-auto-rows not being supported in IE11
beginning in paragon 19.4.0 with its new SelectableBox component.

To update our browerlist to drop IE11, we'll need to update our
node version. Which is in progress elsewhere. But for this series
of commits, I've gotten as far as I can / want to with paragon.
2022-02-28 11:19:19 -05:00
Michael Terry
e9f0a658d6 chore: update to paragon 19.1.0
Replace our custom Tour component with the drop-in ProductTour
replacement in paragon.
2022-02-28 11:19:19 -05:00
Michael Terry
7049445969 chore: update to paragon 19.0.0
Adapt to the big <Card> redesign.

Also, as part of 19.0.0, the shadow variables in paragon got
marked as !default, letting the theme override them. This would
normally be fine and good. But the edx.org theme has a dramatically
larger shadow set. And a lot of our cards and card-like components
were designed with a smaller shadow in mind. So I added a new
raised-card custom css class to keep as many cards looking the same.

Notably, I cannot fix the data tables on the Progress tab. So those
might have a larger shadow with this change, but that's unavoidable
and presumably the intent of the edx.org theme authors.
2022-02-28 11:19:19 -05:00
Michael Terry
f17a635e9d chore: update to paragon 17.1.2
Adapt to secret <Spinner> API breakage (they stopped rendering
children, instead requiring a screenReaderText prop).
2022-02-28 11:19:19 -05:00
Michael Terry
cc8ee33dcd chore: update to paragon 17.0.0
- Drop our custom breakpoints (identical to paragon's)
- Drop our custom useWindowSize (and adapt to paragon's version
  not providing a size initially at component mount)
- Drop our dependency on react-responsive
- Drop our dependency on react-break
2022-02-28 11:19:19 -05:00
Ghassan Maslamani
c25ec8f1ae feat: add descriptions for i18n messages (#815)
It fixes: openedx/frontend-wg/issues/74
2022-02-28 09:10:57 -05:00
Sarina Canelake
8325851813 build: add DEPR workflow automation 2022-02-24 16:05:03 -05:00
edX Transifex Bot
a66d2cf524 chore(i18n): update translations 2022-02-20 16:07:24 -05:00
renovate[bot]
628ede3ccc chore(deps): update dependency follow-redirects to 1.14.8 [security] (#800)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-17 16:33:23 -05:00
Michael Terry
c0c51a3028 fix: remove custom newrelic snippet in favor of new frontend-build one (#832) 2022-02-17 16:12:59 -05:00
Simon Chen
947e5e3cb2 fix: deny proctored exam access to audit and honor enrollment tracks (#831)
We need to allow both Timed exams and non-exam types content to be rendered

Co-authored-by: Simon Chen <schen@edX-C02FW0GUML85.local>
2022-02-17 16:10:32 -05:00
renovate[bot]
93baa10141 chore(deps): update dependency node-fetch to 2.6.7 [security] (#821)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-17 15:49:19 -05:00
renovate[bot]
c02bf1eeed chore(deps): update dependency @testing-library/jest-dom to v5.16.2 (#760)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-17 15:47:13 -05:00
renovate[bot]
b4c90ab506 chore(deps): update dependency jest to v27.5.1 (#756)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-17 15:46:24 -05:00
renovate[bot]
e20bed64fb fix(deps): update dependency @edx/paragon to v16.24.0 (#748)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-17 15:45:35 -05:00
Dillon Dumesnil
8285d42b7e fix: AA-1194: Update the breadcrumb link (#829)
Before, for sections, it would link you to the chapter which would
cause a JS error since the sequence endpoint expects sequentials.
This updates to now link to the first subsection within a section when
you hit the section breadcrumb
2022-02-17 12:45:13 -08:00
Simon Chen
74484b7847 fix: revert "fix: deny proctored exam access to audit and honor enrollment tracks (#828)" (#830)
This reverts commit 45d5141769.

Co-authored-by: Simon Chen <schen@edX-C02FW0GUML85.local>
2022-02-17 14:58:21 -05:00
Simon Chen
45d5141769 fix: deny proctored exam access to audit and honor enrollment tracks (#828)
Co-authored-by: Simon Chen <schen@edx-c02fw0guml85.lan>
2022-02-17 14:11:51 -05:00
Michael Terry
3c52eb2e8d feat: stop calling course blocks rest API and assume LS exists (#803)
- Assume that Learning Sequences is available (waffle has been
  removed)
- Stop calling course blocks API, which provided mostly duplicated
  information now.
- Refactor a bit to avoid needing to globally know which units
  exist in sequences. That is now provided just-in-time for only
  the current sequence.
- Add /first and /last URLs that you can use instead of unit IDs
  in URL paths, in service of the above point.

AA-1040
AA-1153
2022-02-17 14:10:24 -05:00
Ghassan Maslamani
616027df86 fix: rewrite calcualtor tips to reflect the supported features (#825)
Fixes #820
  - Removing constants that are no longer supported
  - Removing suffixes that are no longer supported
2022-02-17 11:24:00 -05:00
Kyle McCormick
93790464f8 build: move pact dependency to devDependencies (#823)
Pact is a testing library. It is not used in to run the
Learning MFE application. Therefore, it belongs in the
devDependencies section of package.json, not the
dependencies section.
2022-02-16 09:05:25 -05:00
Chris Deery
c2cb5744a1 fix: [AA-1195] update dependencies for security warnings (#826)
fix: [AA-1195] fix dependency security alerts

Update frontend-build dependency to 9.0.6

Update es-check to 6.2.1
2022-02-15 13:02:19 -05:00
dependabot[bot]
5d62cb2f46 chore(deps): bump nanoid from 3.1.30 to 3.2.0 (#809)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.30 to 3.2.0.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.30...3.2.0)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-15 10:43:35 -05:00
dependabot[bot]
0f11fd6245 chore(deps): bump node-fetch from 2.6.1 to 2.6.7 (#817)
Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.1 to 2.6.7.
- [Release notes](https://github.com/node-fetch/node-fetch/releases)
- [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.1...v2.6.7)

---
updated-dependencies:
- dependency-name: node-fetch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-15 10:41:53 -05:00
dependabot[bot]
2d6e4063ed chore(deps): bump follow-redirects from 1.14.1 to 1.14.8 (#824)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.1 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.1...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-15 10:38:18 -05:00
Bianca Severino
7b6f5ccf86 chore: bump frontend-lib-special-exams to 1.15.3 (#822) 2022-02-14 09:57:08 -05:00
Bianca Severino
61f0ce2023 chore: bump frontend-lib-special-exams to 1.15.2 (#814) 2022-02-08 11:11:02 -05:00
Chris Deery
5706adde4d fix: [AA-1018] api cleanup
revert missing slice from Tabpage call
2022-02-07 11:40:35 -05:00
Chris Deery
ec1c3da725 fix: [AA-1018] api cleanup
Fix error when moving from courseHome to courseware.
2022-02-04 11:48:58 -05:00
Chris Deery
64b0c03d30 fix: [AA-1018] api cleanup
couple of minor fixes from reviews
2022-01-31 11:20:17 -05:00
Chris Deery
3b33aacb3d fix: [AA-1018] api cleanup
Back off change to fetchCourse in courseware/thunks.js
2022-01-31 11:20:17 -05:00
Chris Deery
f907c588c9 fix: [AA-1018] api cleanup
refactor - don't need to synchronize courseHomeMeta and coursewareMeta manually
2022-01-31 11:20:17 -05:00
Chris Deery
99cf1f9f06 fix: [AA-1018] api cleanup
refactor - remove 'slice' prom from TabContainer.jsx
2022-01-31 11:20:17 -05:00
Chris Deery
7f016e55aa fix: [AA-1018] api cleanup
Implement review feedback.
Clean up tests
2022-01-31 11:20:17 -05:00
Chris Deery
f0f8027de4 fix: [AA-1018] api cleanup
Remove extraneous logging statement
2022-01-31 11:20:17 -05:00
Chris Deery
fd3d0f9391 fix: [AA-1018] api cleanup
Remove debugging code
2022-01-31 11:20:17 -05:00
Chris Deery
3fe5bb1733 fix: [AA-1018] api refactor
This is the first step toward clearing out the redundant metadata from the
coursewareMetadata and getting it from a common source - the courseHomeMetadata.

remove username from coursewareMetadata
Remove courseAccess from coursewareMetadata.

Fix all unit tests
Modify classes that use metadataModel to use courseHomeMetadata for common data.
metadataModel still exists as a mechanism to distinguish if a component is under
courseware or courseHome, and it will be renamed or removed in a later refactor.
2022-01-31 11:20:05 -05:00
edX Transifex Bot
6db421eade chore(i18n): update translations 2022-01-23 16:06:37 -05:00
Dillon Dumesnil
b9d1bf0624 feat: AA-1138: Adds in Weekly Goal Celebration Modal (#797)
The logic to show the modal is controlled by the backend.
Displays the modal only in courseware the first time the learner
hits their weekly learning goal. After viewing the goal, the
database row is updated to not show the modal again.

Also updates first section celebration to use the StandardModal
component as the Modal component has been deprecated.
2022-01-18 06:11:36 -08:00
edX Transifex Bot
2789c7415b chore(i18n): update translations 2022-01-16 16:06:24 -05:00
Carla Duarte
8484d98e26 fix: RTL bug on progress tab (#804) 2022-01-14 15:09:11 -05:00
Carla Duarte
b346b741d5 fix: removing overflow-x scroll from checkpoint (#802) 2022-01-14 12:18:36 -05:00
Ihor Romaniuk
eedaa9f2e9 fix: add support for legacy theme static for the LmsHtmlFragment (#785)
Enables an alternative configuration to match the legacy styles. No-op by default.
2022-01-14 11:11:05 -05:00
Zachary Hancock
f2f0cb6008 chore: update special exams lib (#798) 2022-01-13 14:51:51 -05:00
Ihor Romaniuk
b61057f2df feat: add rtl support (#783)
* feat: add rtl support for chart on progress tab

* feat: change 'div' to semantic 'main' tag

* fix: revert changing div to main tag
2022-01-12 09:40:58 -05:00
Carla Duarte
2d46bacdc7 fix: update Tour components and product tour behavior (#794) 2022-01-11 13:50:12 -05:00
Chris Deery
4655b344a7 feat: [AA-922] remove deprecated goals feature (#789)
* fix: [AA-922] remove deprecated goals feature

While the new Weekly Learning Goals were being rolled out, the previous goal setting feature still existed behind a waffle flag.
The Weekly Learning Goals now become the one and only learning goal feature. It is managed behind the course_experience.enable_course_goals flag

- Remove original Goals panel and related components

- Remove references to weeklyLearningGoalEnabled Waffle flag
2022-01-10 13:38:57 -05:00
Michael Terry
41207e953e feat: show error page when xblock fails to render (#795)
AA-1175
2022-01-10 13:33:30 -05:00
Matthew Piatetsky
16a6eeab24 fix: add aria radiogroup role to goals widget (#792) 2022-01-07 14:04:53 -05:00
Michael Terry
907892e7bb fix: don't log errors when we ask for sequence metadata for units (#790) 2022-01-04 15:07:48 -05:00
Zachary Hancock
f5d1b1c897 chore: update special exams library (#788) 2022-01-04 12:32:18 -05:00
edX Transifex Bot
5854afa987 chore(i18n): update translations 2022-01-02 16:10:59 -05:00
edX Transifex Bot
2aa2e42595 chore(i18n): update translations 2021-12-26 16:10:47 -05:00
Chris Deery
edf9e58d6d fix: [AA-1076] show grade override notice (#773)
* fix: [AA-1076] show grade override notice

- Progress page indicates if a grade has been overridden
- add unit test
2021-12-21 14:07:44 -05:00
Michael Terry
d344b501ab fix: add back missing message translation string (#784)
It was accidentally removed when we switched to the external
header (frontend-component-header), but the string is still
actually used.
2021-12-21 13:53:11 -05:00
julianajlk
2bf4f2a0b5 feat: Add NotificationTray persistence by course (#772)
REV-2424
2021-12-21 13:50:07 -05:00
Arslan
de49e8b271 fix: Use Link from router to fix path based routing issue 2021-12-21 12:53:37 +00:00
Michael Terry
fb21f88c02 fix: when LS is enabled, don't re-connect units and sequences (#782)
Learning Sequences (LS) don't need to edit unit blocks at all.
It's not their data and the stitching code didn't have all the
safety guards that the course block normalizer does in api.js.

This fixes an issue with degenerate course layouts (like problems
as direct children of sequences) when LS is enabled. It was trying
to stitch units and sequences together but failing to account for
unitIds that aren't actual units.

Which is technically still supported by the platform, though not
possible in Studio. We could try to do something smarter here, but
that's not LS's job - it should just trust that the unit data is
correctly normalized already. That unit loading code will
eventually move to the sequence metadata anyway (ideally) and LS
won't touch units at all.

AA-1162
2021-12-20 16:55:21 -05:00
Michael Terry
1044d2afc6 feat: use learning sequences even when masquerading (#774)
The backend recently grew support for it, so we can use it
directly instead of falling back to course blocks in that case.

AA-1151
2021-12-20 13:19:38 -05:00
Carla Duarte
aaf2856573 fix: round grades on progress tab (#778) 2021-12-20 09:03:30 -05:00
Asad Iqbal
1546c62e7f feat: Removed course header stuff (#715) 2021-12-20 08:57:05 -05:00
edX Transifex Bot
b8875f3cda chore(i18n): update translations 2021-12-19 16:10:41 -05:00
Carla Duarte
febc0cae0b fix: course breadcrumb styling (#776) 2021-12-16 13:54:32 -05:00
Carla Duarte
cc0c3c24d9 fix: remove launch tour from header (#775) 2021-12-16 12:03:40 -05:00
Carla Duarte
2fa4a837b1 feat: new user course home tour (AA-1027) (#750) 2021-12-14 12:53:10 -05:00
Dillon Dumesnil
32e299e13b feat: AA-1121: Add in eventing for Goals (#770) 2021-12-09 09:11:21 -08:00
Renovate Bot
f92d2e2ecd fix(deps): update dependency @edx/frontend-platform to v1.14.3 2021-12-08 23:28:08 +00:00
Bianca Severino
fffc48b41a chore: update frontend-lib-special-exams to 1.14.1 (#765) 2021-12-08 10:22:10 -05:00
Renovate Bot
0cc2dcdbc5 fix(deps): update dependency @edx/frontend-platform to v1.14.2 2021-12-08 13:09:15 +00:00
Dillon Dumesnil
e9ca92a359 fix: AA-1107: Update styling for goal unsubscribe page (#763) 2021-12-07 11:53:42 -08:00
Renovate Bot
439965847a fix(deps): update dependency core-js to v3.19.3 2021-12-06 09:52:29 +00:00
Simon Chen
436c05487a fix: Only dismiss the modal when masquerading as specific learner (#759)
if the user is masquerading as a specific learner, then dismiss the modal and do not post back and save the Honor Code signature

Co-authored-by: Simon Chen <schen@edX-C02FW0GUML85.local>
2021-12-02 10:08:49 -05:00
Michael Terry
fba300bc5c fix: avoid trying to open a unit as a sequence (#752)
Make sure to always include the sequence ID when changing the URL
from the jump nav dropdown. We got the correct place eventually
anyway, but this avoids some API requests that we know will fail.

AA-1111
2021-12-01 12:28:10 -08:00
julianajlk
8c43de9fc0 feat: Update notification feature to be course specific (#742)
REV-2360
2021-11-30 09:25:14 -05:00
Phillip Shiu
c2b46d50a8 refactor: [REV-2388] remove "non-profit" MM-P2P language (#758) 2021-11-30 09:03:58 -05:00
Renovate Bot
e2ce54dea8 fix(deps): update dependency core-js to v3.19.2 2021-11-29 21:10:12 +00:00
Renovate Bot
af45d899e3 fix(deps): update dependency reselect to v4.1.5 2021-11-25 00:05:33 +00:00
Renovate Bot
15a4ea42b2 chore(deps): update dependency @testing-library/jest-dom to v5.15.1 2021-11-23 16:12:04 +00:00
Renovate Bot
555dddf8de fix(deps): update dependency @edx/frontend-platform to v1.14.1 2021-11-22 13:32:11 +00:00
renovate[bot]
b03e0fd904 chore(deps): update dependency es-check to v6.1.1 (#725)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-19 09:39:52 -05:00
renovate[bot]
a0c2e86a95 fix(deps): update dependency reselect to v4.1.4 (#709)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-19 09:08:15 -05:00
renovate[bot]
39682badef chore(deps): pin dependencies (#735)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-19 09:04:27 -05:00
renovate[bot]
45afc3fbee fix(deps): update dependency @pact-foundation/pact to v9.17.0 (#747)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-19 09:03:56 -05:00
renovate[bot]
15d20dd693 fix(deps): update dependency @edx/paragon to v16.18.0 (#692)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-19 09:03:27 -05:00
renovate[bot]
2d77ad7125 fix(deps): update dependency core-js to v3.19.1 (#705)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 16:52:43 -05:00
renovate[bot]
33df4d2b7f chore(deps): update dependency @testing-library/user-event to v13.5.0 (#690)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 16:51:25 -05:00
renovate[bot]
09b16976fd chore(deps): update dependency jest to v27.3.1 (#691)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 16:50:35 -05:00
renovate[bot]
1b430f99fe chore(deps): update dependency @edx/frontend-build to v8.1.6 (#707)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 16:49:42 -05:00
renovate[bot]
982f849f41 fix(deps): update dependency @edx/frontend-platform to v1.14.0 (#713)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 16:46:51 -05:00
renovate[bot]
6ec3a4cb5a chore(deps): update dependency @testing-library/jest-dom to v5.15.0 (#722)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 16:46:17 -05:00
renovate[bot]
4d29b202b1 chore(deps): update dependency ansi-regex to 5.0.1 [security] (#736)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 16:45:15 -05:00
renovate[bot]
99ee1da598 chore(deps): update dependency path-parse to 1.0.7 [security] (#737)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 16:44:53 -05:00
renovate[bot]
b896a64853 chore(deps): update dependency tmpl to 1.0.5 [security] (#738)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 16:44:10 -05:00
edX Transifex Bot
94ab6d016e chore(i18n): update translations 2021-11-15 02:09:44 +05:00
Michael Terry
41006f5cbf feat: bump New Relic script to v1211 (#743)
From v1209. No notable changes, but just getting up to date.
2021-11-09 13:05:25 -05:00
Chris Deery
9c2c1427e1 fix: [AA-1087] defer goals widget for proctoring (#727)
fix: [AA-1087] defer goals widget for proctoring

- pause showing goals widget while proctor info panel awaits callback.

- Implement tests to check that goals show up when
  proctoring does not

- small refactoring of LearningGoalButton to eliminate test warnings
2021-11-09 10:22:20 -05:00
Bianca Severino
c19f21d257 fix: pass integrity signature flag to exam wrapper (#739) 2021-11-08 13:36:45 -05:00
edX Transifex Bot
1d98de1e0c chore(i18n): update translations 2021-11-08 02:09:30 +05:00
Dillon Dumesnil
64eb268cb0 feat: AA-1020: Add Credit Information to Progress tab (#726)
This is to match what the old Progress tab would show so we
can enable this for all credit courses as well
2021-11-05 11:08:29 -07:00
Carla Duarte
f7428db3c3 feat: product tour components (#695) 2021-11-05 07:57:15 -06:00
Renovate Bot
7986db7027 fix(deps): update dependency @edx/frontend-enterprise-utils to v1.1.1 2021-11-03 09:12:44 +00:00
edX Transifex Bot
7704a8a5d7 chore(i18n): update translations 2021-11-03 00:22:22 +05:00
Phillip Shiu
d88f83311c refactor: [REV-2262] create generic bullets to reuse in all upsell messaging (#723) 2021-11-02 12:42:15 -04:00
Carla Duarte
6f0a69b838 fix: update goal styling (#721) 2021-11-02 09:22:43 -06:00
Chris Deery
7ed1be1960 fix: [AA-1044] add missing h2 for screenreaders (#720)
* fix: [AA-1044] add missing h2 for screenreaders

- Add placeholder h2 tag with message indicating reserve for future use
- internationalize placeholder text
2021-11-01 13:31:19 -04:00
alangsto
663559f8c7 chore: update special exams lib (#718) 2021-11-01 10:24:59 -04:00
edX Transifex Bot
4a56673377 chore(i18n): update translations 2021-11-01 02:09:48 +05:00
Michael Terry
d1f19a9dc4 fix: skip inaccessible learning sequence data (#716)
When normalizing learning sequences, skip inaccessible sequences
and also skip sections with only inaccessible sequences.

This both imitates the legacy course block behavior and also
avoids a failure when merging course block data with LS data
when they disagree about which sequences exist.
2021-10-29 10:53:50 -04:00
Renovate Bot
8a3722a723 fix(deps): update dependency redux to v4.1.2 2021-10-28 10:36:03 +00:00
Chris Deery
4abf6ebdce fix: [AA-1078] weekly learning goals a11y nav (#711)
- Add radio role and aria-checked to button to enable screen reader use
2021-10-27 16:55:41 -04:00
Chris Deery
d1013802ba fix: [AA-1078] a11y and styling for weekly goals (#710)
* fix: [AA-1078] weekly learning goals fine tune

- Fix a11y issues with buttons
- Replace media query with algorithmic approach for determining button layout
- Misc styling fixes
2021-10-27 10:48:14 -04:00
Renovate Bot
581e8c4769 fix(deps): update dependency react-redux to v7.2.6 2021-10-25 21:16:21 +00:00
Michael Terry
ea5c7f516a fix: Revert "fix: disable the call to ecommerce for now (#701)" (#706)
This reverts commit f93519f675.

The original fix may have been working after all and a bogus
test by me using a staff account made me think the discount was
not being offered. Reverting the emergency fix and going to test
the original fix again.
2021-10-25 10:24:23 -04:00
edX Transifex Bot
ce7cef0c6b chore(i18n): update translations 2021-10-25 02:09:35 +05:00
Renovate Bot
45a823e6c7 fix(deps): update dependency @pact-foundation/pact to v9.16.5 2021-10-24 18:08:04 +00:00
David Joy
0b8cf06c29 fix: set modal-lti max-width to be important (#702) 2021-10-21 17:51:27 -04:00
Michael Terry
f93519f675 fix: disable the call to ecommerce for now (#701)
It doesn't seem to be working - instead never calling ecommerce and
always showing the normal non-discount version of the streak modal.

Going to investigate later, but this is just a quick shutoff for
now.
2021-10-21 16:46:10 -04:00
Michael Terry
c39b3ae4c5 fix: don't show 3-day streak discount if it won't provide a discount (#658)
Also, this will pull the actual discount percent from ecommerce,
instead of hardcoding it.

AA-1012
2021-10-21 12:50:14 -04:00
Renovate Bot
c3ea12225d chore(deps): update dependency husky to v7.0.4 2021-10-21 05:26:12 +00:00
Renovate Bot
f914d83510 chore(deps): update dependency @edx/frontend-build to v8.0.6 2021-10-20 16:13:31 +00:00
Matthew Piatetsky
67ea30a45a fix: ensure we don't update goals while users are masquerading (#697) 2021-10-20 10:20:01 -04:00
Phillip Shiu
eabbb440f0 Revert "refactor: create generic bullets to reuse in all upsell messaging (#689)" (#696)
This reverts commit 8735f219e9.
2021-10-20 09:47:39 -04:00
Phillip Shiu
8735f219e9 refactor: create generic bullets to reuse in all upsell messaging (#689)
REV-2262
2021-10-20 07:49:05 -04:00
Chris Deery
c2414ce1ba fix: [AA-906] WeeklyLearningGoals (#694)
Fix incorrect message for returning students
2021-10-19 15:30:04 -04:00
Michael Terry
e6fee7b5b9 fix: catch and redirect URLs with spaces in them (#693)
In an attempt to debug some odd LMS errors (which would happen if
you loaded an MFE page with spaces instead of plus signs), this
commit notices page requests with spaces in the course key and
switches it out for plus signs, logging the incident.
2021-10-19 11:39:06 -04:00
Chris Deery
d8f3c7441e feat: [AA-906] UI for WeeklyLearningGoals (#664)
* feat: [AA-906] UI for WeeklyLearningGoals

Add component to OutlineTab for selecting Weekly Learning Goals
Move start button to before course outline, and put in card with Call to action.
Unit tests
Implement temporary a11y feedback
add react-responsive as a dependency

Everything except for the start/resume button move is behind a waffle flag: course_goals.number_of_days_goals
2021-10-19 10:37:22 -04:00
Renovate Bot
765bf2089c fix(deps): update dependency @fortawesome/react-fontawesome to v0.1.16 2021-10-19 04:14:24 +00:00
Renovate Bot
10fce146fd chore(deps): update dependency @edx/frontend-build to v8.0.5 2021-10-19 04:00:57 +00:00
edX Transifex Bot
b274cb5137 chore(i18n): update translations 2021-10-18 02:10:27 +05:00
Albert (AJ) St. Aubin
a6e539dad2 feat: update the text for unearned certificates
[MICROBA-1536]
2021-10-15 15:38:14 -04:00
renovate[bot]
83fa3f78bc fix(deps): update dependency @edx/paragon to v16.14.9 (#683)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-15 09:08:25 -04:00
renovate[bot]
1e4f3ec151 chore(deps): update dependency @testing-library/user-event to v13.4.1 (#684)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-15 09:08:08 -04:00
renovate[bot]
1ac806b7dd fix(deps): update dependency js-cookie to v3 (#596)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Michael Terry <mterry@edx.org>
2021-10-14 15:57:03 -04:00
renovate[bot]
1d08618be9 fix(deps): update dependency core-js to v3.18.3 (#627)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-14 15:40:12 -04:00
renovate[bot]
b90a54759c chore(deps): update dependency jest to v27.2.5 (#619)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-14 15:29:41 -04:00
renovate[bot]
a1ef37ca0b fix(deps): update dependency react-router-dom to v5.3.0 (#629)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-14 15:27:39 -04:00
renovate[bot]
d178913e4b chore(deps): update dependency glob to v7.2.0 (#649)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-14 15:26:30 -04:00
renovate[bot]
9f2ce9d152 chore(deps): update dependency @testing-library/user-event to v13.3.0 (#679)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-14 15:25:22 -04:00
renovate[bot]
d6722ca271 fix(deps): update dependency @edx/paragon to v16.14.7 (#644)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-14 15:21:27 -04:00
renovate[bot]
aa2004434e fix(deps): update dependency @edx/frontend-enterprise-utils to v1.1.0 (#682)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-14 15:18:56 -04:00
Renovate Bot
921f3eef06 fix(deps): update dependency @pact-foundation/pact to v9.16.4 2021-10-11 00:04:09 +00:00
edX Transifex Bot
8337fc79be chore(i18n): update translations 2021-10-11 02:10:22 +05:00
connorhaugh
2230173da8 feat: rollout jump nav to course staff (#672)
As per https://openedx.atlassian.net/browse/TNL-7107 we need to rollout jumpnav to course staff.
2021-10-08 09:33:15 -04:00
Thomas Tracy
09072f318b fix: Fix redirect loop (#676)
MICROBA-1523
2021-10-07 16:35:08 -04:00
Michael Terry
1f7cb2cc28 fix: move NewRelic testing script even higher (#675)
Per their docs, this really should be the first script. And we were
hitting some cloudflare scripts being inserted ahead of us. This
might fix that.
2021-10-07 14:44:32 -04:00
Ned Batchelder
c6ad7c51d3 build: use the organization commitlint check 2021-10-07 13:51:59 -04:00
Andrew Shultz
20d4de09d7 fix: upgrade the frontend-lib-special-exams library to v1.13.3 (#674)
prevents confusing exam errors in non-exam situations

MST-905
2021-10-07 11:35:18 -04:00
Matthew Piatetsky
5aa857f1de fix: Unsubscribe audit users from goal remindners on the course exit page (#671)
This reverts commit 20390d1e33.
2021-10-07 09:14:48 -04:00
Thomas Tracy
3fcc0d87c9 [feat] Add notices redirect to learning MFE (#667)
* [feat] MICROBA-1523 Add notices redirect to learning MFE

To support the notices plugin on platform, this adds a redirect to the
course home page. If a user lands on that page and has not acknowledged
a notice, the user will be redirected to notice instead of the course
home.
2021-10-06 14:25:05 -04:00
Bianca Severino
0bc7faaa56 fix: prevent integrity signature creation while masquerading (#665) 2021-10-06 11:26:04 -04:00
connorhaugh
0889b17e85 fix: course home button error. (#669)
In order to finish off TNL-7107 I needed to meet the acceptance criteria: When learners or educators select a section dropdown item they are taken to the first subsection within that section that is not completed by default. If all subsections are completed they should be taken to the first(subsection) in that section.

This reimagining of Jumpnav does that by lazy loading in the menuItem's destinations and routing the user using React-Router.
2021-10-06 11:14:24 -04:00
connorhaugh
f57f39a787 Revert "Feat lazy load jump nav destinations (#663)" (#670)
This reverts commit dd6a499cfc.
2021-10-05 16:55:58 -04:00
Matthew Piatetsky
20390d1e33 Revert "feat: Unsubscribe audit users from goal remindners on the course exit page (#660)" (#668)
This reverts commit 55b3396acd.
2021-10-05 14:26:05 -04:00
Matthew Piatetsky
55b3396acd feat: Unsubscribe audit users from goal remindners on the course exit page (#660) 2021-10-05 11:18:36 -04:00
Renovate Bot
dae0c8931c fix(deps): update dependency @reduxjs/toolkit to v1.6.2 2021-10-05 03:55:38 +00:00
connorhaugh
dd6a499cfc Feat lazy load jump nav destinations (#663)
In order to finish off TNL-7107 I needed to meet the acceptance criteria: When learners or educators select a section dropdown item they are taken to the first subsection within that section that is not completed by default. If all subsections are completed they should be taken to the first(subsection) in that section.

This reimagining of Jumpnav does that by lazy loading in the menuItem's destinations and routing the user using React-Router.
2021-10-04 08:58:37 -04:00
Renovate Bot
0c006e28de fix(deps): update dependency @pact-foundation/pact to v9.16.3 2021-10-01 12:33:15 +00:00
Renovate Bot
bdba0d2c3c fix(deps): update dependency @pact-foundation/pact to v9.16.2 2021-10-01 02:58:12 +00:00
julianajlk
965a299f6c fix: UpgradeNotification bullet point padding override (#659) 2021-09-29 13:08:53 -04:00
julianajlk
7cfeaab330 fix: Value Prop miscellaneous styling fixes (#657)
REV-2188
2021-09-29 10:15:57 -04:00
edX Transifex Bot
76e3173fc4 chore(i18n): update translations 2021-09-28 21:11:36 +05:00
connorhaugh
e1d3b91dca fix: make breadcrumbs limiting accessible to audit (#655) 2021-09-28 09:23:42 -04:00
julianajlk
0592c40496 Fix lockpaywall container display issue on mobile (#654)
REV-2357
2021-09-27 09:24:49 -04:00
Michael Terry
175a40d9fa fix: correct some escaping on the new relic agent string (#653) 2021-09-24 10:53:02 -04:00
Michael Terry
192a58ab51 fix: hardcode the newrelic agent, to load it earlier (#652)
This is a test, before making a more proper fix in frontend-build.
But I'd like to confirm this fixes some issues we've seen with
newrelic metrics.

AA-1015
2021-09-24 10:09:17 -04:00
Simon Chen
7215db6682 fix: Upgrade the frontend-lib-special-exams library to v1.13.2 (#650)
The special exam timer synced with backend to show accurate count down timer

Co-authored-by: Simon Chen <schen@edx-c02fw0guml85.lan>
2021-09-23 11:13:32 -04:00
Bianca Severino
cb29902152 fix: remove special exam and proctoring flags (#648) 2021-09-22 09:11:55 -04:00
connorhaugh
2932d98976 feat: breadcrumb rolloutout flag + analytics (#647)
As an addendum to https://openedx.atlassian.net/browse/TNL-7107, we want to hide rollout behind a frontend feature flag added in https://github.com/edx/edx-internal/pull/5489. We also want to report these events to the events api with name `edx.ui.lms.jump_nav.selected`. Doummentation to add this event is listed at the following PR: https://github.com/edx/edx-documentation/pull/1982
2021-09-21 15:39:52 -04:00
connorhaugh
8c0e98ad4f feat: Breadcrumb Jump Navigation STAGE ONLY (#641)
Enable faster movement through the course content for learners and course instructors familiar with their course structure using jump navigation selectors in dropdown menus that augment our existing breadcrumbs in the learner sequence experience. When learners/instructors click on sections or subsections these menus are revealed and can be selected to jump to this part of the course.

Implemented using paragon's Selectmenu component, and data from the learning_sequences API.

Note: as the L_S api does not yet have completion data, we are holding off on accepting the completion ACs.

Smoke testing and QA testing will be required, as this feature is prominent in the learner experience. 

The feature is presently only rolled out on stage, but will FF to roll out to instructors on test soon.
2021-09-17 15:39:06 -04:00
Renovate Bot
8b9dfd2f08 fix(deps): update dependency @edx/frontend-platform to v1.12.7 2021-09-17 16:50:13 +00:00
Zainab Amir
e0a81d6cc9 feat: add learner type to course homepage (#643) 2021-09-17 11:19:25 +05:00
Renovate Bot
9cdaa64f64 fix(deps): update dependency @edx/paragon to v16.13.3 2021-09-14 22:30:51 +00:00
Michael Terry
54d96cc162 fix: stop logging course-blocks 403 responses as errors (#637)
They are benign and normal for logged out users. Instead, log them
as info messages, so we can still track them if we need to.

AA-1011
2021-09-13 15:31:43 -04:00
Renovate Bot
3da1fb6581 fix(deps): update dependency @edx/frontend-platform to v1.12.6 2021-09-13 10:43:43 +00:00
edX Transifex Bot
268e8b0b40 chore(i18n): update translations 2021-09-13 02:10:28 +05:00
Renovate Bot
d93cb70966 fix(deps): update dependency @edx/paragon to v16.13.2 2021-09-10 19:16:41 +00:00
Michael Terry
90d6ea8137 feat: notify the user if a sequence is hidden because of due date (#636)
Normally, these sequences are skipped. But if the user manually
goes to the section, they should be notified why they can't access
it. That can easily happen if they bookmarked the page or something.

AA-1000
2021-09-10 11:13:48 -04:00
David Ormsbee
73302d72cb doc: ADR for "Direction of Courseware APIs"
Describing the removal of calls to Course Blocks API for courseware
rendering, how those responsibilities would be split, and the motivation
for doing so. TNL-7326
2021-09-09 12:50:25 -04:00
renovate[bot]
666d9e6b38 fix(deps): update dependency @edx/paragon to v16.13.1 (#620)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-09 12:04:53 -04:00
Carla Duarte
fcc0cceb8d fix: update progress grade table styling (AA-934) (#635) 2021-09-09 10:07:35 -04:00
Carla Duarte
597ecb7b4e fix: update SubsectionTitleCell styling (AA-934) (#633) 2021-09-08 10:48:55 -04:00
Renovate Bot
5ec0fec0ff fix(deps): update dependency @pact-foundation/pact to v9.16.1 2021-09-08 13:45:01 +00:00
Renovate Bot
74c75af34d fix(deps): update dependency @edx/frontend-platform to v1.12.5 2021-09-06 11:28:17 +00:00
edX Transifex Bot
9a1966a034 fix(i18n): update translations 2021-09-06 02:05:39 +05:00
Renovate Bot
1868606ee8 fix(deps): update dependency react-redux to v7.2.5 2021-09-04 20:58:27 +00:00
Carla Duarte
70e2aa0203 feat: add page banner to masquerade (AA-877) (#606) 2021-09-03 09:47:39 -04:00
Michael Roytman
bdfbbc0b75 feat: Display "Onboarding Past Due" message in onboarding button if onboarding is past due (#472)
[MST-746](https://openedx.atlassian.net/browse/MST-746)

The ProctoringInfoPanel displays information in a learner's course outline about the state of the learner's onboarding. It displays a link to navigate the learner to the onboarding exam if it is available. If the onboarding exam is not yet released, it displays information about the release date. This code changes adds an "Onboarding Past Due" message to the link if the onboarding is past due, as determined by a call to the LMS onboarding endpoint.
2021-09-01 16:32:00 -04:00
Chris Deery
fda9ab6bce Feat: [AA-950] Streak discount productization (#623)
- Remove Jira tag from StreakCelebrationCouponEnabled prop
- Remove "experiment" from streak discount vars
- Cleaned up warning in unit test
- Added mock function for closeStreakCelebration
- Set End Date to 2 weeks from current date
- Updated unit tests
- Fixed naming issues
- Added official coupon code
- Cast isStreakCelebrationOpen to boolean

Co-authored-by: cdeery <cdeery@edx.edu>
2021-09-01 12:21:43 -04:00
Zachary Hancock
04cc668e9b chore: update special-exams-lib (#625) 2021-08-31 11:09:52 -04:00
alangsto
c91e5d5f58 chore: update frontend-lib-special-exams version (#624) 2021-08-30 16:44:50 -04:00
Renovate Bot
22ca88c981 fix(deps): update dependency core-js to v3.16.4 2021-08-29 17:06:50 +00:00
Renovate Bot
ffd03cb1de fix(deps): update reactrouter monorepo to v5.2.1 2021-08-28 01:50:24 +00:00
edX Transifex Bot
8cfe4bc099 fix(i18n): update translations 2021-08-27 00:49:52 +05:00
Phillip Shiu
191ef9c7b9 fix: add accent to e in resumé (#616)
Fixes: REV-2214
2021-08-26 13:02:05 -04:00
Renovate Bot
ac0813816f fix(deps): update dependency @edx/paragon to v16.9.1 2021-08-26 13:14:15 +00:00
Diane Kaplan
a614145e6d REV-2297: add NotificationTray red dot functionality, so learner notices new prompt 2021-08-25 13:08:23 -04:00
Renovate Bot
ca9a000fd2 chore(deps): update dependency husky to v7.0.2 2021-08-25 03:12:11 +00:00
Renovate Bot
9e2b2ec541 fix(deps): update dependency core-js to v3.16.3 2021-08-24 21:57:17 +00:00
Michael Terry
8552329739 feat: add a new course goal unsubscribe landing page (#612)
URL format: /goal-unsubscribe/<uuid-token>

This is designed to be used in the new course goals feature, where
emails will be sent to learners and those emails will include a
link to this landing page, as an unsubscribe link.

Also, update calls to the LMS course home API to not include the
/v1/ fragment anymore, as we're moving to an unversioned API.

AA-907
2021-08-24 16:10:04 -04:00
Bianca Severino
90fc5f0024 fix: pass originalUserIsStaff to SequenceExamWrapper (#610)
Pass this value to determine whether the user is staff
masquerading as a learner.
2021-08-24 13:01:41 -04:00
Renovate Bot
d3c44f3984 fix(deps): update dependency @edx/frontend-lib-special-exams to v1.12.1 2021-08-24 15:04:16 +00:00
Awais Ansari
a607fe4574 fix: media query max-width effect on course content pages (#600) 2021-08-24 15:08:30 +05:00
Diane Kaplan
2d5e1caae7 feat: cleanup tracking code for obsolete upsell link (#531)
Co-authored-by: Diane Kaplan <dkaplan@edx.org>
See: https://openedx.atlassian.net/browse/REV-2305
2021-08-23 15:26:08 -04:00
Ali Akbar
5087353e88 test: add pact tests for courseware and course-home (#598) 2021-08-23 20:02:31 +05:00
edX Transifex Bot
2171c28825 fix(i18n): update translations 2021-08-23 02:05:31 +05:00
Renovate Bot
adde6e3470 chore(deps): update dependency @edx/frontend-build to v8.0.4 2021-08-20 19:55:35 +00:00
Robert Raposa
0d015be97e build: git ignore local environment overrides (#580)
Git ignore for .env.private to enable local environment
overrides as detailed by frontend-build. See:
https://github.com/edx/frontend-build#override-default-envdevelopment-environment-variables-with-envprivate
2021-08-20 09:13:35 -04:00
Renovate Bot
dfbdcee163 chore(deps): update dependency @edx/frontend-build to v8.0.3 2021-08-19 23:16:57 +00:00
renovate[bot]
3ad7b9e95d fix(deps): update dependency @edx/frontend-platform to v1.12.4 (#605)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Michael Terry <mterry@edx.org>
2021-08-19 11:32:23 -04:00
renovate[bot]
aedee4f847 fix(deps): update dependency @edx/paragon to v16.9.0 (#604)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-19 11:03:10 -04:00
renovate[bot]
6878ef9fe1 fix(deps): update dependency @edx/frontend-enterprise-utils to v1 (#602)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-19 11:02:37 -04:00
Renovate Bot
04dc5a26ec chore(deps): update dependency @edx/frontend-build to v8.0.1 2021-08-18 01:54:46 +00:00
Renovate Bot
33348eabbd fix(deps): update dependency core-js to v3.16.2 2021-08-17 17:10:28 +00:00
edX Transifex Bot
c5a383dfdb fix(i18n): update translations 2021-08-16 02:10:23 +05:00
renovate[bot]
1177c6e2e2 chore(deps): update dependency axios-mock-adapter to v1.20.0 (#597)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-13 08:56:56 -04:00
renovate[bot]
d6fdf1512f chore(deps): update dependency es-check to v6 (#595)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 16:10:22 -04:00
renovate[bot]
936885707d chore(deps): update dependency @testing-library/user-event to v13 (#594)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 16:09:28 -04:00
renovate[bot]
71db431b97 chore(deps): update dependency @edx/frontend-build to v8 (#590)
* chore(deps): update dependency @edx/frontend-build to v8

* fix: install the util package, webpack5 no longer polyfills it

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Michael Terry <mterry@edx.org>
2021-08-12 14:54:55 -04:00
Adam Stankiewicz
b741525bfc fix: replace frontend-enterprise with frontend-enterprise-utils (#593) 2021-08-12 14:42:27 -04:00
renovate[bot]
0394118608 chore(deps): update codecov/codecov-action action to v2 (#589)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 14:14:48 -04:00
renovate[bot]
c6df8cdbb5 fix(deps): update dependency @reduxjs/toolkit to v1.6.1 (#156)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 13:15:21 -04:00
renovate[bot]
1fbd9d4645 fix(deps): update dependency core-js to v3.16.1 (#269)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 13:02:48 -04:00
renovate[bot]
42a3f6b244 fix(deps): update dependency react-helmet to v6.1.0 (#130)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 12:57:40 -04:00
renovate[bot]
6ca4c99c0d fix(deps): update dependency redux to v4.1.1 (#522)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 12:54:56 -04:00
renovate[bot]
5deac01615 fix(deps): pin dependency @pact-foundation/pact to 9.16.0 (#583)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 12:53:01 -04:00
renovate[bot]
1160353ab9 fix(deps): update dependency @edx/paragon to v16.7.0 (#588)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 12:52:43 -04:00
renovate[bot]
ca8cfda9b9 fix(deps): update dependency truncate-html to v1.0.4 (#587)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 12:45:02 -04:00
renovate[bot]
3d9cb20e33 fix(deps): update dependency react-share to v4.4.0 (#216)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 11:52:20 -04:00
renovate[bot]
37f32fddf2 chore(deps): update dependency husky to v7 (#523)
* chore(deps): update dependency husky to v7

* fix: migrate config from husky4 to husky7

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Michael Terry <mterry@edx.org>
2021-08-12 11:52:11 -04:00
Renovate Bot
b5689a7997 fix(deps): update dependency regenerator-runtime to v0.13.9 2021-08-12 15:46:30 +00:00
renovate[bot]
c88ea31c20 fix(deps): update dependency @edx/frontend-component-footer to v10.1.6 (#585)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 11:20:55 -04:00
renovate[bot]
9de77c282d chore(deps): update dependency codecov to v3.8.3 (#584)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 11:20:33 -04:00
renovate[bot]
1b995d2510 fix(deps): update react monorepo to v17 (#255)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 11:20:09 -04:00
renovate[bot]
66300caf30 chore(deps): update dependency @edx/frontend-build to v5.6.14 (#330)
* chore(deps): update dependency @edx/frontend-build to v5.6.14

* fix: avoid circular dependency to keep eslint happy

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Michael Terry <mterry@edx.org>
2021-08-12 11:20:02 -04:00
Robert Raposa
29391f7741 build: update frontend-platform to 1.12.3 (#582)
* build: update frontend-platform to 1.12.1

* build: update frontend-platform to 1.12.3
2021-08-12 11:03:39 -04:00
renovate[bot]
15782609c3 chore(deps): update dependency @testing-library/user-event to v12.8.3 (#160)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 10:55:42 -04:00
renovate[bot]
f2fc950678 chore(deps): update actions/setup-node action to v2 (#314)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 10:49:22 -04:00
renovate[bot]
42445d884f fix(deps): update react monorepo to v16.14.0 (#244)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 10:28:30 -04:00
renovate[bot]
a5ea7431fc chore(deps): update dependency rosie to v2.1.0 (#454)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 10:25:19 -04:00
renovate[bot]
df29cd0f9a fix(deps): update font awesome (#154)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 10:24:40 -04:00
renovate[bot]
4898487a82 chore(deps): update dependency @testing-library/jest-dom to v5.14.1 (#158)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 10:19:27 -04:00
renovate[bot]
6588153e4c chore(deps): update dependency jest to v27 (#163)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 10:12:19 -04:00
renovate[bot]
a568c5f2fc chore(deps): update dependency axios-mock-adapter to v1.19.0 (#260)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 10:06:31 -04:00
renovate[bot]
054afc0475 fix(deps): pin dependency lodash.camelcase to 4.3.0 (#520)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 10:05:10 -04:00
renovate[bot]
58e8de2c22 chore(deps): update dependency es-check to v5.2.4 (#361)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 10:03:30 -04:00
renovate[bot]
2b00cecd19 fix(deps): update dependency classnames to v2.3.1 (#518)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 10:02:31 -04:00
Ali Akbar
58f1634c63 test: add consumer pact tests for courseware (#510) 2021-08-10 14:57:24 +05:00
edX Transifex Bot
2092a5d8d1 fix(i18n): update translations 2021-08-09 02:05:23 +05:00
Michael Terry
1308d1e90b docs: explain the learning MFE specific environment variables (#578)
This adds some links to the docs for general MFE instructions,
plus documents the learning MFE specific ones.

Also fixes the README badge links.
2021-08-06 10:15:06 -04:00
Matt Tuchfarber
3b4dcfefaf fix: ignore grade for allowlist certs (#577)
Allowlist certs were hidden on the progress view because the grade
wasn't passing. This gives "downloadable" certs preference over the
grade.
2021-08-05 16:07:54 -04:00
Zachary Hancock
d4a4cd24ec feat: staff may review exam content without attempt (#576) 2021-08-04 13:50:44 -04:00
Dillon Dumesnil
149ca245fd style: Update subsection title to be greyed out if unavailable (#574)
AA-932
2021-08-03 05:36:32 -07:00
Emma
56ea6d46d4 fix: dfferentiate upsell link eventing between in_course and course_home 2021-08-02 10:40:03 -04:00
Thomas Tracy
d12e93d80a [feat] MB-1192: Add not passing, course ended status to certificate status alert (#548)
[feat] Add not passing, course ended status to certificate status alert on the outline tab
2021-08-02 10:10:08 -04:00
Chris Deery
63c86701de fix: Swap the prev and next icons in rtl (#571)
Right To Left (RTL) languages need to reverse the
direction of the icons in navigation.
This fix corrects the arrows in UnitNavigation.jsx,
which were missed in the previous checkin.

Fixes: AA-891

Co-authored-by: cdeery <cdeery@edx.edu>
2021-08-02 10:01:54 -04:00
edX Transifex Bot
b99910357b fix(i18n): update translations 2021-08-02 02:05:24 +05:00
Michael Terry
b4bedfe3f0 fix: re-enable access error redirects for course home (#570)
These redirects are already in place for the courseware, and will
redirect to the outline page, or the dashboard, or wherever, based
on the type of access error (unenrolled, access expired, survey
needed, etc).

This commit stops the course home tabs from paying attention to the
401 error messages coming from the backend - course_access in the
metadata API handles that now.

This commit also changes our useModel hook to more gracefully handle
not being able to find the model - it is a valid case we want to
allow (still will cause problems if you actually try to use the data,
but will at least provide an object you can inspect).
2021-07-30 14:20:42 -04:00
Brian Mesick
8c41e182a2 feat: Remove upgrade sock from course pages (#556)
REV-2220: The upgrade sock is being removed from the remaining course pages in favor of the new Value Prop work.
2021-07-30 12:55:09 -04:00
David Ormsbee
fae2396977 refactor: Begin transition to Learning Sequences API
For performance and long term simplification reasons, we want to take
the work currently done by the Course Blocks API and split it up between
the Learning Sequences API (course outline) and Sequence Metadata API
(details about the Units in a Sequence). This will also make it easier
to later support different kinds of Sequences, where we might not know
all the details about it at the time we load the course-wide outline
data.

This starts moving over the responsibility for the high level outline
and metadata to Learning Sequences. It requires that the waffle flag
"learning_sequences.use_for_outlines" be active in the LMS. If that flag
is not active, the Learning Sequences API call will return a 403 error,
and this code will fall back to the older behavior.

Some data could not be shifted over yet. Namely:

* Sequence legacy URL is not currently output by the Learning Sequences
  API. This is simple to add, but I don't know if there's any point in
  adding it now that the Courseware MFE is functional for timed exams.
* Unit metadata was not completely shifted over to the Sequence Metadata
  API because doing so would cause blocking requests and would cause a
  noticeable performance regression. This should not be moved over until
  the Sequence Metadata API can be made more performant.
* Effort Estimation currently relies on content introspection of the
  underlying content in a way that the Learning Sequences API does not
  support.

This is the last of a handful of PRs in support of TNL-8330.
2021-07-29 12:04:36 -04:00
Chris Deery
276f2a516a fix: Swap the prev and next icons in rtl (#566)
Right To Left (RTL) languages need to reverse the
direction of the icons in navigation.

Fixes: AA-891

Co-authored-by: cdeery <cdeery@edx.edu>
2021-07-29 11:39:58 -04:00
Michael Terry
01ba277425 fix: adjust syntax of a translation, so transifex will accept it (#568) 2021-07-29 08:56:43 -04:00
Saad Yousaf
64f374855b fix: remove focus state for Navigation tab items. (#567)
Co-authored-by: SaadYousaf <saadyousaf@A006-00314.local>
2021-07-28 21:37:15 +05:00
Carla Duarte
a8348e1568 feat: updating alerts to use Paragon Alert over custom (AA-914) (#557) 2021-07-28 09:39:31 -04:00
Viktor Rusakov
6a3ad1d659 chore: update special exams library version (#564) 2021-07-28 07:22:12 -04:00
Saad Yousaf
2f0933be6e fix: update container-fluid to container-xl class to match legacy experience. (#530)
Co-authored-by: SaadYousaf <saadyousaf@A006-00314.local>
2021-07-28 02:01:26 +05:00
Saad Yousaf
4be3b8a56f fix: update Navigation tab items styling to match design. (#536)
Co-authored-by: SaadYousaf <saadyousaf@A006-00314.local>
2021-07-28 01:28:50 +05:00
Matthew Piatetsky
2075a0b3dd fix: grey out problem scores when a learner does not have access, instead of when a learner does have access (#565) 2021-07-27 11:52:51 -04:00
Michael Terry
52750ef769 fix: temporarily disable course-home denied redirects (#563)
They caused a regression when not logged in or enrolled. Will
hopefully re-enable after developing a fix.
2021-07-27 11:46:38 -04:00
Matthew Piatetsky
e2b00d6684 [AA-933] fix: address issues with progress page fbe exception UI (#561)
* fix: address issues with progress page fbe exception UI

* address comments
2021-07-27 10:59:23 -04:00
Michael Terry
6003865840 fix: remove unused portions of effort estimate experiment (#560)
We are sticking with the sequence version, and abandoning the section
version. This commit also marks the strings for translation, as it
is a real feature now, not just an experiment.

AA-659
2021-07-27 09:46:02 -04:00
Zachary Hancock
30a487ec13 chore: upgrade special-exams library (#562) 2021-07-27 09:26:47 -04:00
Michael Terry
c667e29492 fix: handle course access errors in Course Home side of things too (#558)
The courseware was properly reading the access errors and
redirecting the user as appropriate (like to the dashboard or
whatever).

This requires a backend change to push the error along.
2021-07-26 16:33:59 -04:00
edX Transifex Bot
be4375dd7c fix(i18n): update translations 2021-07-26 02:05:37 +05:00
Dillon Dumesnil
a4d651a77a fix: AA-912: If the URL is not provided, only show display name (#554)
In https://github.com/edx/edx-platform/pull/28233, the logic was updated
to only return a URL if the content was still accessible to the learner.
This handles the case of the URL being null
2021-07-22 07:17:59 -07:00
Diane Kaplan
3703e8d81d feat: add upsell events for progress tab upsell links (#532) 2021-07-22 09:05:16 -04:00
julianajlk
c5e480456a fix: LockPaywall content gating layout issue (#549)
REV-2307
2021-07-21 10:22:05 -04:00
Emma
d57dd66dd2 add edxwelcome code info to unhappy path 2021-07-21 10:19:04 -04:00
Matthew Piatetsky
377f780e85 feat: handle FBE Exception cases on new progress page (#539) 2021-07-20 12:20:53 -04:00
Carla Duarte
057b431818 fix: problem score styling (#546) 2021-07-19 13:47:59 -04:00
edX Transifex Bot
e4a883e335 fix(i18n): update translations 2021-07-19 02:05:25 +05:00
Carla Duarte
984926d97c fix: progress score margin (#545) 2021-07-15 15:28:35 -04:00
Viktor Rusakov
9f81897fd2 feat: update onboarding link on the course home page (#542) 2021-07-15 15:10:17 -04:00
Carla Duarte
270c177a83 feat: add problem scores to progress tab (AA-875) (#538) 2021-07-15 13:47:51 -04:00
Albert (AJ) St. Aubin
915f521976 fix: Corrected status message with incorrect mention of email 2021-07-15 10:27:45 -04:00
Thomas Tracy
903d8d4cfb [feat] MB-1299 Add tracking to cert alert buttons (#541)
* [feat] Add tracking to cert alert buttons
2021-07-14 14:02:53 -04:00
julianajlk
f2f4f5f3a5 Fix bug that was applying the CSS to other active classes (#543) 2021-07-14 12:25:32 -04:00
Diane Kaplan
28d359e715 feat: remove first purchase discount banner from courseware (REV-2132) 2021-07-14 11:44:23 -04:00
julianajlk
d93df0e06f feat: remove value_prop_cookie to show the Notification feature in courseware (#524)
Part 4 of REV-2130
2021-07-14 10:47:32 -04:00
Albert (AJ) St. Aubin
86a4cf9af7 feat: Added the Request Certificate Alert
[MICROBA-678]

When a certificate is in a unexpected state (i.e. notpassing with a
passing grade) this alert will allow the user to attempt to resolve the
issue on their own. It will run the code that checks the certificates
status. It requires that the course is configured to allow users to
Request Certificates though.
2021-07-13 10:52:28 -04:00
Thomas Tracy
e423dddb03 [fix] Add href to dates link on coming soon alert (#535) 2021-07-12 13:33:34 -04:00
Sagirov Evgeniy
f21dad95b5 feat: [BD-26] Timer bar on non-sequence pages (#502)
* feat: Timer bar on non-sequence pages

* chore: Update frontend-lib-special-exams version.

Co-authored-by: Viktor Rusakov <vrusakov66@gmail.com>
Co-authored-by: Igor Degtiarov <igor.degtiarov@raccoongang.com>
2021-07-12 11:12:43 -04:00
Saad Yousaf
9978ddf418 fix: change styling of More button to stay consistent with other navigation items. (#528)
Co-authored-by: SaadYousaf <saadyousaf@A006-00314.local>
2021-07-12 18:15:27 +05:00
edX Transifex Bot
d2a8d870af fix(i18n): update translations 2021-07-12 02:05:26 +05:00
Thomas Tracy
3ef4daecce feat: Add Scheduled content alert
Adds a new alert to the outline page that informs the learner of content
coming soon to the course.
2021-07-08 15:47:12 -04:00
Matthew Piatetsky
d2573a16b1 feat: add user id parameter to progress page (#505) 2021-07-08 12:17:43 -04:00
Albert (AJ) St. Aubin
e7c0ebdfe3 Revert "feat: Add Scheduled content alert"
This reverts commit 83151d291c.
2021-07-07 10:39:15 -04:00
renovate[bot]
1ad2cf73bf fix(deps): update dependency @edx/frontend-lib-special-exams to v1.8.3 (#501)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-07 09:26:12 -04:00
edX Transifex Bot
d60d782e5a fix(i18n): update translations 2021-07-07 03:11:53 +05:00
Thomas Tracy
83151d291c feat: Add Scheduled content alert
Adds a new alert to the outline page that informs the learner of content
coming soon to the course.
2021-07-06 16:08:55 -04:00
Viktor Rusakov
ed55920f99 refactor: place all logic regarding special exam redirect into single function (#521) 2021-07-06 13:02:29 -04:00
julianajlk
4f1c8a4671 refactor: rename Value Prop related notification components (#516)
Part 3 of REV-2130
2021-07-06 12:43:49 -04:00
edX Transifex Bot
0878bf9f13 fix(i18n): update translations 2021-07-05 02:09:17 +05:00
Zachary Hancock
21f3875dae chore: update special exams lib (#517) 2021-07-02 13:29:30 -04:00
Carla Duarte
d4dc75c5a0 feat: updating shift dates banners (#512) 2021-07-02 10:11:49 -04:00
julianajlk
8a1151e8c5 feat: add Value Prop upgrade notification to Courseware (#511)
Part 2 of REV-2130
2021-07-02 10:11:41 -04:00
julianajlk
5e925c93da Move UpgradeCard to generic directory to be accessible in courseware (#514)
Part 1 of REV-2130, Value Prop work
2021-07-02 09:29:48 -04:00
Jansen Kantor
43033ddc91 move mmp2p useModel call and use outline model (#509) 2021-06-30 09:07:59 -04:00
Kristin Aoki
cf08fa5eb9 fix: Autoscroll moves element to center of page
This PR fixes the anchor tag's position on the page when autoscrolling
is used. Previously, the scroll would move the element to the center of
the page. Now the scroll moves the element to the top of the page. The
only case where the element will not be at the top of the page is when
the element is too close to the bottom of the page and there is not
enough page remaining to force the element to the top.
2021-06-29 09:05:04 -04:00
Thomas Tracy
37ce01c00a Ttracy/microba 1192 early with info display behavior (#497)
* [feat] Add ID verification Alert to course home

if a user has a verified seat, but is in the unverified certificate
status state, the certificateStatusAlert will now show a message letting
the learner know they need to verify in order to earn a certificate.

This does not remove the message about the verification deadline in the
right sidebar of the course home.
2021-06-28 12:20:06 -04:00
David Ormsbee
9edac2519a fix: remove sequences we shouldn't see by using learning_sequences
Removes sequences we shouldn't see by using the Learning Sequences API
(TNL-8377). Depends on https://github.com/edx/edx-platform/pull/27955

It works by adding a call to the Learning Sequences API and (if that
endpoint is enabled, i.e. returns 200 for this user+course), uses the
results of that endpoint to remove sequences from the Course Blocks API
call. Learning Sequences knows how to do things like bubble up the
content group settings of units to sequences for the case where all
units have the same restrictions and the user would see an empty
sequence.
2021-06-28 11:41:56 -04:00
Bianca Severino
f9fbc1eb49 fix: add missing check for graded units (#508)
This fixes a bug where if the learner needs an integrity signature, but
the unit is not graded, neither the honor code panel nor the unit
content would display.
2021-06-28 10:12:58 -04:00
edX Transifex Bot
5c68c1d554 fix(i18n): update translations 2021-06-28 02:09:03 +05:00
Zachary Hancock
4180a2e7a0 chore: update special exams library (#503) 2021-06-24 13:10:51 -04:00
Brian Mesick
554e63d653 feat: Remove upsell banner on course home (#499)
REV-2233: The upsell banner now duplicates the sidebar banner. Removing it in favor of the new implementation on course home, but keeping the masquerade message that shows instructors when a learner lost access to the course.
2021-06-24 12:46:57 -04:00
Kristin Aoki
c9f299eada fix: Autoscroll on page when using jump_to_id
This PR adds a URL hash check to useEffect. Previously the anchor tags
that use jump_to_id would remain at the top of the page. As a result,
users would have to manually scroll to the target location or just read
the full page. Now when the page has a URL hash, it will send the hash
to the listener in the iframe. Using the message listener, it receives
an object with offset in the event.data and the page will scroll to the
location provided by offset. This change will impact the Learner in the
New Experience view.
2021-06-23 12:57:47 -04:00
Carla Duarte
d1bb46eef3 AA-815: ui and a11y progress tab fixes (#494) 2021-06-23 09:42:12 -04:00
Renovate Bot
492c573f56 fix(deps): update dependency @edx/frontend-component-footer to v10.1.5 2021-06-23 08:03:06 +00:00
Brian Mesick
0c55863a3d Revert "feat: Remove upsell banner on course home (#493)" (#498)
This reverts commit fbd9d858e4.
2021-06-22 10:37:11 -04:00
Brian Mesick
fbd9d858e4 feat: Remove upsell banner on course home (#493)
REV-2233: The upsell banner now duplicates the sidebar banner. Removing it in favor of the new implementation on course home, but keeping the masquerade message that shows instructors when a learner lost access to the course.
2021-06-22 10:01:57 -04:00
Rebecca Graber
7b0429f472 feat: make course recommendations a part of the course celebration (#486) 2021-06-21 13:18:35 -04:00
Brian Mesick
56decd8ed0 feat: Remove course sock from OutlineTab. (#495)
REV-2122: As part of the Value Prop implementation, we are removing the course sock from Course Home
2021-06-21 12:55:11 -04:00
Matthew Piatetsky
3155055276 feat: change color of start/resume course button (#496) 2021-06-21 10:58:03 -04:00
Albert (AJ) St. Aubin
1b84930a84 feature: Added notification and link to get to a users PDF cert.
This feature will allow users with downloadable PDF certificates to see
the certificate status alert and then access their certificate on the
Course Outline page. This should only show once a learner has earned a
certificate and that certificate is available.
2021-06-17 07:33:33 -04:00
Michael Terry
99185a9b8a fix: guard against courseGoals being undefined (#489)
No idea why this would happen honestly - it looks always defined
from the backend, and api.js doesn't transorm it. But we are seeing
JS errors related to it. So trying this as a first pass.

AA-848
2021-06-15 13:13:38 -04:00
Carla Duarte
e9c3a6bc5e fix: update assignment policy logic (#483) 2021-06-14 11:22:57 -04:00
Sagirov Evgeniy
5a30cddd32 feat: Added 'allow_proctoring_opt_out' attribute for SequenceMetadata API. (#485) 2021-06-14 10:44:37 -04:00
Ihor Romaniuk
432cb669f5 feat: add temporary flag for enabling/disabling proctored exams (#464) 2021-06-14 10:42:53 -04:00
Matthew Piatetsky
26e1eb64c5 fix: ensure clicking the bookmarks button doesn't break the unitHasLoaded property (#481) 2021-06-14 09:36:15 -04:00
edX Transifex Bot
30e0e3b8f4 fix(i18n): update translations 2021-06-14 02:08:38 +05:00
Carla Duarte
46e459aaf3 fix: update progress tab assignment policy logic (#482) 2021-06-11 12:05:40 -04:00
Carla Duarte
6949fa8201 fix: updating progress tab to better respect showGrades field (#480) 2021-06-11 09:42:06 -04:00
Albert (AJ) St. Aubin
fab2da4586 feature: Improve the Certificate Alerts in the outline to support new
statuses

[MICROBA-678]

These changes refactor the CertificateAvailableAlert and add new
features to it to support more status alerts for certificates. It
attempts to do so in an iterative manner so that new/updated alerts can
be included over time.
2021-06-10 13:03:12 -04:00
Kristin Aoki
6a402c50ea fix: Scroll page when html anchor tag clicked
This PR adds a listener check to messages. Previously the anchor tags that were set to scroll on the page to another element would open the link outside of the iframe and redirect the parent page. As a result, users would have to have to click the back arrow to navigate back to the course and continue the unit. Now when the listener receives an object with offset in the event.data, the page will scroll to the location provided by offset. The offset is only received when a user clicks on an anchor tag in the unit iframe that focuses on another element on the page. This change will impact the Learner.

Jira issue: TNL-8312
2021-06-09 13:18:46 -04:00
Zachary Hancock
bfeb8c70c0 fix: pin special exams library (#479) 2021-06-09 11:09:05 -04:00
David Ormsbee
cf61c7a747 fix: display Unit titles as <h1> (TNL-8387)
Unit titles were being written to the page as <h2> because the old
courseware experience reserved <h1> for wrapping the header logo link.
We've since determined that this is not a best practice, and the new
courseware MFE in this repo no longer uses a <h1> for that purpose, but
the Unit title was never promoted from <h2> to <h1> until this commit.

Course teams have traditionally been permitted to use <h3>-<h6> in their
content. Making this change does mean that there will now be a gap with
some content, where we skip from <h1> to <h3>. For the short term, we
are NOT recommending course teams use <h2>, until we have a better
chance to evaluate whether that heading should remain reserved for
platform-level use.
2021-06-07 13:49:58 -04:00
Adeel Ehsan
a003059c8f Account activation pop up added: (#474)
VAN-435
2021-06-07 10:33:59 +05:00
Adeel Ehsan
854010ba52 Revert "Account activation pop up added: (#425)" (#473)
This reverts commit 07b82b1d87.
2021-06-05 01:14:52 +05:00
Adeel Ehsan
07b82b1d87 Account activation pop up added: (#425)
VAN-435
2021-06-04 20:13:12 +05:00
Bianca Severino
5c204ad0f9 feat: add honor code component (#465)
This component blocks access to graded units when
the user is required to sign the integrity agreement for
the course. Once signed, it will not appear for the course
again.
2021-06-04 09:06:32 -04:00
Matthew Piatetsky
5bfca28450 feat: update streak discount coupon expiration date (#471) 2021-06-02 17:12:56 -04:00
Carla Duarte
a36da4cd84 AA-807: progress tab eventing (#470) 2021-06-02 14:31:13 -04:00
Diane Kaplan
f08a23ecf9 feat: remove first purchase discount banner from course home (REV-2253) 2021-06-01 09:12:28 -04:00
edX Transifex Bot
3432b0c73b fix(i18n): update translations 2021-05-29 02:00:46 +05:00
edX Transifex Bot
c1c3d5c68f fix(i18n): update translations 2021-05-29 00:03:12 +05:00
julianajlk
2a52534442 fix: gated content banner discount display (#466)
REV-2232
2021-05-28 13:38:49 -04:00
Carla Duarte
519cf27c4e AA-813: fix progress tab related links (#461) 2021-05-26 12:01:18 -04:00
Carla Duarte
9d07f26f13 AA-807: upgrade deadline passed on progress tab (#463) 2021-05-26 12:01:12 -04:00
Albert (AJ) St. Aubin
fdfb60bee8 feat: Updating the messages for certificate availability.
[MICROBA-678]
2021-05-26 07:23:48 -04:00
Dillon Dumesnil
75c9e93241 refactor: Update the defaults for our .env files (#459)
Nulls can provide undesired behavior so we want to switch to empty strings
2021-05-24 09:08:48 -07:00
Vladas Tamoshaitis
a5ba5655b6 feet: [BD-26] Add support for special exams (#435)
* feat: add packages dir to .gitignore

* Investigate exam redirect (#2)

* feat: remove exam redirect

* feat: take control over exam instructions

* refactor: use fedx code structure

* fix: remove debug logging, remove redirect check

Co-authored-by: Vladas Tamoshaitis <vladas.tamoshaitis@raccoongang.com>

* Add state and reducer for check microfrontend_special_exams waffle flag (#4)

* feat: add state and reducer for check microfrontend_special_exams waffle flag

* fix: rename special exams enabled flag

* fix: rename reducer for setting special exams enabled flag

* refactor: timer feature

* feat(tests): extend tests + fix failing ones, fix quality

* fix: revert removing package lock file

Co-authored-by: Vladas Tamoshaitis <vladas.tamoshaitis@raccoongang.com>

* fix: naming of waffle flag helpers to reflect relation with mfe

* fix: change naming of the waffle flag

* fix: revert remove package lock file

* feat: switch to @edx npm package

* fix: Remove redundant references from .gitignore

* fix: add is_mfe_special_exams_enabled to courseMetadata.factory.js

* fix: fix tests for 'Sequence' content wrapped in 'SequenceExamWrapper'

Co-authored-by: Sagirov Eugeniy <sagirov19@gmail.com>
Co-authored-by: Vladas Tamoshaitis <vladas.tamoshaitis@raccoongang.com>
Co-authored-by: Sagirov Evgeniy <34642612+UvgenGen@users.noreply.github.com>
Co-authored-by: Igor Degtiarov <igor.degtiarov@raccoongang.com>
2021-05-24 08:44:01 -04:00
edX Transifex Bot
46056a0c53 fix(i18n): update translations 2021-05-24 02:08:01 +05:00
Carla Duarte
05b2439ff6 AA-816: update grade summary calculations (#456) 2021-05-19 15:44:49 -04:00
Carla Duarte
663bf7562b AA-814: course grade footer fix (#455) 2021-05-19 13:44:28 -04:00
Renovate Bot
58e29d81be fix(deps): update dependency react-redux to v7.2.4 2021-05-17 20:40:00 +00:00
Renovate Bot
027eeb8a49 chore(deps): update dependency glob to v7.1.7 2021-05-17 20:05:07 +00:00
Renovate Bot
e6a4bcd833 chore(deps): update dependency codecov to v3.8.2 2021-05-17 19:09:59 +00:00
Julia Eskew
1da461e2de feat: Support classifying certain errors as ignored errors in an MFE. (#447)
Ignored errors are sent to New Relic as page actions instead of JS errors,
allowing those errors to still be tracked as occurring but without causing
unnecessary alerts.

Ignored errors are configured per-MFE, *not* globally.

Bump the frontend-platform version to 1.10.2.

Add IGNORED_ERROR_REGEX variable for use in development. The actual
production value will be read from the YAML in edx-internal.

TNL-7924
2021-05-17 13:43:01 -04:00
Matthew Piatetsky
3c07cab8c2 [AA-746] fix: add hour/minute to assignment due dates and update dates timeline with branding styles (#450)
* fix: add hour/minute to assignment due dates and update dates timeline with branding styles

* update badge styles
2021-05-17 12:39:34 -04:00
Carla Duarte
110088688a fix: grade range bug (#449) 2021-05-17 09:23:49 -04:00
Matthew Piatetsky
d8243d6ea8 fix: remove currency symbol to avoid double currency symbol with some upgrade buttons (#448) 2021-05-14 09:48:50 -04:00
Carla Duarte
b1fdbcccf3 AA-790: progress tab handle unenrolled/unauthenticated users (#445) 2021-05-13 15:07:19 -04:00
edX Transifex Bot
00205d4b1f fix(i18n): update translations 2021-05-12 22:29:14 +05:00
julianajlk
6100f3ac2e fix: i18n translations for UpgradeCard (#442)
REV-2126 Value Prop
2021-05-12 09:50:08 -04:00
Matthew Piatetsky
6fa6de4543 fix: don't throw an error when there is no verified mode (#444)
AA-759
2021-05-11 16:16:41 -04:00
Matthew Piatetsky
d0bcb19754 feat: Set up streak celebration discount experiment (#431)
As part of this work, the streak celebration has been migrated from a Paragon Modal to a Modal Dialog
AA-759
2021-05-11 14:06:03 -04:00
Carla Duarte
0f69ed5502 AA-792: Progress tab UI fixes (#443) 2021-05-10 16:43:38 -04:00
edX Transifex Bot
039d761a27 fix(i18n): update translations 2021-05-10 02:07:36 +05:00
Diane Kaplan
e2dd081d44 fix checkmark bullets to vertically align with text (#440)
Co-authored-by: Diane Kaplan <dkaplan@edx.org>
2021-05-07 12:37:38 -04:00
Emma Green
7e75671618 add important so that it overrides other style 2021-05-07 10:48:23 -04:00
Emma Green
5ca10042c8 fix checkmark bullets to line up with text 2021-05-07 10:09:57 -04:00
alangsto
64979ecaf0 fix: Remove confusing language on proctoring info panel (#437)
MST-700. Remove language that says learners with a verified onboarding can take exams. This created confusion for learners who did not realize they must also complete IDV before taking a proctored exam.
2021-05-06 15:33:55 -04:00
Ben Holt
0175c4cf27 Guarded for undefined headers in getOutlineTabData 2021-05-06 12:32:16 -04:00
Emma Green
531f6d96ae more stuffs 2021-05-06 12:32:16 -04:00
Emma Green
997be712f1 add time offset 2021-05-06 12:32:16 -04:00
Emma Green
7e5dacf68d static expiration box 2021-05-06 12:32:16 -04:00
alangsto
73fa56d401 fix: update border color for approved in another course status (#436) 2021-05-06 10:25:56 -04:00
Michael Terry
e46977f50d fix: use new xblock handler URLs for sequence blocks (#423)
They've changed to proper new-style handlers, so the URL also
changed. This will let us get the fix for green checkmarks showing
up as audit users pass FBE units, even though those units aren't
actually complete.

AA-409
2021-05-06 09:38:57 -04:00
Awais Jibran
28e1f6f65a Fix height issue in safari (#434) 2021-05-05 23:10:42 +05:00
Julia Eskew
6c257271bb feat: Deny course staff visibility of legacy courseware. (#427)
Currently, course staff can always view their courses
in the Legacy courseware experience.

With this change, course staff will *not* be able
to view their courses if the New (MFE) courseware
experience has been enabled for them.

This does not affect global staff, and it does not
affect courses that are still running in the Legacy
experience.

Adds a new parameter returned by the course metadata API
used by the courseware MFE to determine if the button to
show legacy experience should be displayed or not.

TNL-8203
2021-05-04 13:57:00 -04:00
Carla Duarte
36f567c834 fix: accurately represent pass/fail grade range (#433) 2021-05-04 11:51:44 -04:00
Carla Duarte
c6627a0854 fix: remove sr-only scss mixin from unit nav buttons (#432) 2021-05-04 09:16:49 -04:00
Carla Duarte
608db6d423 AA-723: scss fixes (#430) 2021-05-03 14:25:56 -04:00
Carla Duarte
72168b56f8 AA-723: progress tab locked content experience (#426) 2021-05-03 13:11:22 -04:00
edX Transifex Bot
5af20067b8 fix(i18n): update translations 2021-05-03 20:05:51 +05:00
edX Transifex Bot
c8ae544c8b fix(i18n): update translations 2021-05-03 02:07:36 +05:00
julianajlk
28fddc5550 feat: Add Sidebar and SidebarNotificationButton components for Value Prop (#414)
REV-2125
2021-04-29 11:36:55 -04:00
Matthew Piatetsky
ef635b2a9b feat: Add certificate status component to the new progress page (#415)
Much of the logic is copied from the course exit certificate states.
AA-719
2021-04-29 09:39:07 -04:00
Matthew Piatetsky
ce69d57dc8 fix: add back events for course home and courseware sock upgrade button (#424)
AA-728
2021-04-28 12:20:08 -04:00
Dillon Dumesnil
43aa6291c3 fix: AA-663: Update header text for CourseCompletion (#421)
If the marketing url is not set, we shouldn't have a message
about sharing.
2021-04-26 07:53:54 -07:00
Carla Duarte
e9f63674ca AA-721: Course grade bar (#413) 2021-04-26 10:05:14 -04:00
Saad Yousaf
41b97ba638 fix: center content by fixing the container-fluid class (#419)
Co-authored-by: SaadYousaf <saadyousaf@A006-00314.local>
2021-04-24 02:36:47 +05:00
Dillon Dumesnil
8a7c61b64a feat: Switch to default values for 12 vs 24 hour time. (#420)
Our current version on react-intl doesn't support hourCycle
anyway and after speaking to product, we feel comfortable with
letting it default based on locale.
2021-04-22 12:04:13 -07:00
Dillon Dumesnil
34dbcb7ea6 fix: AA-738: Switch our use of FormattedTime to use hourCycle (#418)
We had a bug reported where learners were seeing a due date like
March 24, 24:59 instead of March 25, 00:59. This is a bug that only
shows up in Chrome. The hour12 flag overrides the hourCycle flag so
we are just going to swap the two. h23 means a 24 hour format ranging
from 0-23 (there also exists a h24 option which goes from 1-24).

See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
for any additional details on the options.
2021-04-21 12:15:13 -07:00
Kyle McCormick
ca8122686b fix: allow media access through unit iframe (#412)
Set the `allow` attribute of the unit iframe to allow
access to camera, MIDI, location, and encrpyted media.

Access to these features was implicitly allowed in older
browser versions. However, in the current versions of
at least Chromium and Firefox, iframed content must be
explicitly granted the ability to request media access.

This fixes a bug where content requiring microphone
access did not work in the Learning MFE.

TNL-7675
2021-04-21 14:30:02 -04:00
edX Transifex Bot
4472541008 fix(i18n): update translations 2021-04-16 10:18:04 -04:00
Diane Kaplan
e5c8dad319 [REV-2127] feat: update gated content lock screen to Value Prop designs (#394) 2021-04-16 08:54:03 -04:00
stvn
3e82152ae7 Merge PR #233 renovate/codecov-3.x
* Commits:
  chore(deps): update dependency codecov to v3.8.1
2021-04-14 08:21:38 -07:00
Renovate Bot
4d2bd81bf0 chore(deps): update dependency codecov to v3.8.1 2021-04-13 15:06:26 +00:00
Carla Duarte
aca45fb26e AA-720: Progress Tab Course Completion chart (#407) 2021-04-13 10:08:13 -04:00
edX Transifex Bot
d13bb04648 fix(i18n): update translations 2021-04-11 17:06:50 -04:00
Bianca Severino
8dc7593780 fix: pass username into proctoring info panel (#406)
Pass a username into the proctoring info panel, allowing staff
to view a specific learner's onboarding status while masquerading.
2021-04-09 12:55:48 -04:00
Kyle McCormick
88005ea5d2 refactor!: clean up unused references to lms_web_url (#409)
Before edx-platform version 19ba691,
only `lms_web_url` was exposed from the course
blocks API. Now that the API also exposes
`legacy_web_url`, we can stop falling back
to `lms_web_url` when `legacy_web_url` is
absent.

TNL-7796
2021-04-09 10:36:04 -04:00
Emma Green
e86f4a88cc small changes to the way the price is displayed on the course home page to pave the way for the expiration box 2021-04-07 12:02:48 -04:00
Kyle McCormick
cf58ff3d3f feat: Use legacy_web_url to redirect to legacy courseware (#404)
As part of making the new courseware experience the
default for staff, the LMS /jump_to/ links that are
exposed by the Course Blocks API via the `lms_web_url`
field will soon direct users to whichever experience
is active to them (instead of always directing to
the legacy experience & relying on the learner
redirect).

Because of this, the MFE can no longer rely on
`lms_web_url` to land a staff user to the legacy
experience. However, the aformentioned change
will also introduce a `legacy_web_url` field
to the API, which we *can* use for this purpose.

TNL-7796
2021-04-07 09:21:07 -04:00
edX Transifex Bot
32ac3632d0 fix(i18n): update translations 2021-04-04 17:06:51 -04:00
Diane Kaplan
6abf8531bb feat: ahead of value prop designs, update text to prep translations (REV-2127)
Co-authored-by: Diane Kaplan <dkaplan@edx.org>
2021-04-01 10:35:19 -04:00
Kyle McCormick
353964e75c feat: handle courseware paths more liberally (#395)
Valid courseware URLs currently include:
* /course/:courseId
* /course/:courseId/:sequenceId
* /course/:courseId/:sequenceId/:unitId

In this commit we add support for:
* /course/:courseId/:sectionId
* /course/:courseId/:sectionId/:unitId
* /course/:courseId/:unitId

All URL forms still redirect to:
  /course/:courseId/:sequenceId/:unitId

See ADR #8 for more context.

All changes:
* refactor: allow courseBlocks factory to build multiple sections
* refactor: make CoursewareContainer tests less brittle & stateful
* feat: handle courseware paths more liberally
* refactor: reorder, rename, & comment redirection functions

TNL-7796
2021-04-01 09:10:00 -04:00
Carla Duarte
6a376b20c7 AA-722: Progress Tab (#391) 2021-03-31 15:00:14 -04:00
Ben Warzeski
162f0ceeb5 Mmp2p 3 (#402)
* [MM-P2P] move access and meta logic to initialization and store in state

* move model access to thunk action
2021-03-31 10:43:38 -04:00
Ben Warzeski
9dcb91af9e mmp2p: handle missing verified-mode info after upgrade deadline (#401) 2021-03-30 11:18:49 -04:00
Kyle McCormick
4d1ed0f357 refactor: de-dupe factories between courseware and course-home (#400) 2021-03-29 16:05:51 -04:00
edX Transifex Bot
d94c7ad003 fix(i18n): update translations 2021-03-28 17:06:42 -04:00
Zachary Hancock
edef36becb update other course approved messaging (#398) 2021-03-26 13:33:37 -04:00
Matthew Piatetsky
29a13f729a fix: remove extra x in first section celebration modal (#397)
x icon that was added to paragon as part of the streak celebration modal is redundant with the x added to only the first section celebration modal
AA-713
2021-03-22 10:00:27 -04:00
edX Transifex Bot
6a6bddc5c8 fix(i18n): update translations 2021-03-21 17:06:30 -04:00
Carla Duarte
b12f184d18 AA-712: upsell link click tracking (#393)
* AA-712: course_home_audit_access_expires and in_course_audit_access_expires

* AA-712: course_home_welcome and in_course_welcome

* AA-712: course_home_dates

* AA-712: course_home_course_tools

* AA-712: course_home_upgrade_shift_dates and dates_upgrade

* AA-712: fixing up PR comments
2021-03-19 12:36:36 -04:00
Carla Duarte
45a68973b7 AA-711: implement upsell click events (#392) 2021-03-16 16:10:47 -04:00
Ben Holt
ab98cca421 Cleaned up all references to REV-1512's value prop experiment (#379)
Cleaned up all references to REV-1512's value prop experiment [REV-2123]
2021-03-15 14:31:21 -04:00
edX Transifex Bot
413b189293 fix(i18n): update translations 2021-03-14 17:06:28 -04:00
Matthew Carter
774b7bb1fc Set flyover visability default to true (#388) 2021-03-12 14:44:38 -05:00
Matthew Carter
ff93d7f4d4 Update language for last date to upgrade (#386) 2021-03-12 10:01:45 -05:00
Carla Duarte
e3d9ff9ed3 AA-213: Redirect progress tab to legacy (#384) 2021-03-11 15:46:37 -05:00
Ben Warzeski
6e2294e279 MMP2P G2 Activation (2nd try) (#382)
* upgrade paragon

* mmp2p experiment code

* mmp2p courseware triggers

* mmp2p course-home triggers

* mmp2p load styles

* mmp2p - add missed locator docstrings

* mmp2p test fixes

* add lazy loading for image-bearing components

* mmp2p experiment README

* mmp2p add lazy loading for sidecard

* generalize prices for currency options

* mmp2p fix flyover mobile args

* mmp2p fix lock paywall border display

* mmp2 - add safety-rail around verifiedmode access
2021-03-11 11:13:38 -05:00
Rebecca Graber
c17beeb908 WS-1740 logging, copy, style changes (#383) 2021-03-11 09:39:05 -05:00
Ben Warzeski
5c65627582 Revert "MM-P2P G2 Activation (#380)" (#381)
This reverts commit 8c0cafafa1.
2021-03-10 18:55:34 -05:00
Ben Warzeski
8c0cafafa1 MM-P2P G2 Activation (#380)
* upgrade paragon

* mmp2p experiment code

* mmp2p courseware triggers

* mmp2p course-home triggers

* mmp2p load styles

* mmp2p - add missed locator docstrings

* mmp2p test fixes

* add lazy loading for image-bearing components

* mmp2p experiment README

* mmp2p add lazy loading for sidecard

* generalize prices for currency options

* mmp2p fix flyover mobile args

* mmp2p fix lock paywall border display
2021-03-10 16:40:53 -05:00
Rebecca Graber
3450570d7e WS-1740 add course recommendations to celebration page (experiment) (#376)
* WS-1740 add course recommendations to celebration page (experiment)
2021-03-08 10:07:08 -05:00
edX Transifex Bot
c650283446 fix(i18n): update translations 2021-03-07 16:06:19 -05:00
Zachary Hancock
28773ce4c2 onboarding panel exam release date (#375)
* disable onboarding link for unreleased exam
2021-03-02 13:04:20 -05:00
Bianca Severino
e4b1d8088a Add "other course approved" and "expiring soon" states to proctoring info panel (#373) 2021-03-02 09:11:12 -05:00
edX Transifex Bot
1dc0669bae fix(i18n): update translations 2021-02-28 16:06:42 -05:00
Carla Duarte
58eb9fe23c AA-651: fix dates tab undefined property (#372) 2021-02-26 15:59:49 -05:00
Carla Duarte
38617c827e AA-684: sequence link to legacy or MFE (#371) 2021-02-26 12:00:10 -05:00
Matthew Piatetsky
a9939a1b5e fix three day streak bug with incorrect variable (#370) 2021-02-25 12:05:33 -05:00
Matthew Piatetsky
2525805aac feat: Create three day streak celebration (#354)
Show learners a celebratory modal if they visit the learning mfe for 3 days in a row. Call edx-platform API to determine if they should see the celebration.
AA-304
2021-02-22 14:34:28 -05:00
Ben Warzeski
26a7b3b0de tie p2p action only to targetted date-summary entry if there are multiple (#367) 2021-02-22 13:48:43 -05:00
Ben Warzeski
4bbc29591c fix conditional for injecting experiment method (#366) 2021-02-22 12:33:27 -05:00
Carla Duarte
49bfc65a03 fix null course goal object bug (#365) 2021-02-18 12:17:32 -05:00
Michael Terry
d017c3194e feat: Show effort estimation if the backend provides it (#357)
AA-614
2021-02-16 14:36:05 -05:00
Ben Warzeski
a2ccedcecd [MM-P2P] optimizely experiment overrides for course_home (#364)
* alert override

* course home date overrides

* add undefined check for experiment hook

* inject intl rather than passing
2021-02-16 12:01:04 -05:00
Renovate Bot
3a7c455bb3 fix(deps): update font awesome 2021-02-08 22:05:08 +00:00
Renovate Bot
19087417b4 fix(deps): update dependency @edx/frontend-platform to v1.8.4 2021-02-08 21:17:06 +00:00
Renovate Bot
05c6878644 fix(deps): update dependency @edx/frontend-component-footer to v10.1.4 2021-02-08 20:09:56 +00:00
Matthew Piatetsky
7e2f495f52 Use contains_content_type_gated_content attribute, rather than the graded attribute, to determine if the content type gating paywall should be displayed. (#349)
The issue was that items with the graded attribute are not always going to be paywalled by content type gating.
AA-613
2021-02-05 12:29:08 -05:00
Dillon Dumesnil
50e649daa3 AA-491: Update MFE with analytics event (#351)
These already exist in the legacy view. This is just porting them
over into the MFEs
2021-02-02 05:39:27 -08:00
Dillon Dumesnil
629382f719 AA-492: Add event data for consumption in the backend (#355) 2021-02-01 09:46:21 -08:00
edX Transifex Bot
8835a9cd6a fix(i18n): update translations 2021-01-31 16:05:18 -05:00
Simon Chen
3e2eebdd9b MST-621 (#353)
The text in the onboarding panel for submitted state is confusing. This PR updated the text so learners understood the wait
2021-01-28 11:54:05 -05:00
Carla Duarte
acd2cc3222 AA-638: course completion bug (#352) 2021-01-27 13:59:06 -05:00
Michael Terry
9ef3787d4b AA-410: Make sure alerts are cleaned up after being added (#324) 2021-01-25 12:41:32 -05:00
Carla Duarte
47fd6bfe18 AA-512: underline links within iframes (#347) 2021-01-25 11:11:14 -05:00
edX Transifex Bot
984010a8ec fix(i18n): update translations 2021-01-24 16:04:53 -05:00
Michael Terry
58543a34b3 Separate courses redux model into courseHomeMeta and coursewareMeta (#348) 2021-01-22 15:28:16 -05:00
alangsto
293dc9f4c3 Updated broken links (#346)
updated tests

added test
2021-01-21 14:54:18 -05:00
alangsto
68c8d31dd1 added component for proctoring panel (#345)
added 404 test

updated for feedback

updated test
2021-01-21 12:15:56 -05:00
Carla Duarte
96ef87886f AA-361: shift dates banner tests (#344) 2021-01-19 17:09:29 -05:00
Carla Duarte
48e3f43062 AA-598: canEnroll loop bug fix (#343) 2021-01-11 16:53:22 -05:00
Carla Duarte
d74557d681 AA-481: Course home outline UI fixes (#341) 2021-01-11 15:30:49 -05:00
edX Transifex Bot
0e18e0908a fix(i18n): update translations 2021-01-10 16:05:20 -05:00
Carla Duarte
958c13ca93 AA-465: Various a11y fixes (#340) 2021-01-07 12:11:28 -05:00
Carla Duarte
26de2cebeb AA-545: Add course in progress CourseExit variant (#334) 2021-01-06 15:10:29 -05:00
Matthew Piatetsky
bd8496a5e2 move flyover button toggle within frontend-app-learning (#339) 2021-01-06 12:31:00 -05:00
Matthew Piatetsky
aa56239f54 add empty div to fix bug with moving flyover toggle 2021-01-06 11:45:00 -05:00
Emma Green
a0b85111eb change the flyover icon underline to 2px from UX feedback 2021-01-06 10:04:22 -05:00
Dillon Dumesnil
07b252ecc6 AA-501: Send query param to recheck access to xblocks for render (#335) 2021-01-06 06:49:25 -08:00
David Joy
92b364e0f8 Upgrading frontend-platform to latest. (#336) 2021-01-05 16:14:34 -05:00
Emma Green
9247eb3098 fix grammer for value prop experiment for gated upsell 2021-01-04 11:50:09 -05:00
Emma Green
9e0f5d7e22 add black underline when value prop flyover is open 2021-01-04 11:50:09 -05:00
edX Transifex Bot
db4b4d18cc fix(i18n): update translations 2020-12-27 16:04:43 -05:00
julianajlk
92a464b2da Update REV-1512 experiment gated content (#329)
REV-1512
2020-12-22 10:08:00 -05:00
Matthew Piatetsky
7fed8db02a fix button interactivity (#328) 2020-12-21 13:01:47 -05:00
Matthew Piatetsky
8161f4d9a0 fix x button interactivity (#327) 2020-12-21 12:13:27 -05:00
Ben Holt
c6661e71b1 Add span for mobile return text and standardize on notifications title for localization (#325) 2020-12-21 11:02:39 -05:00
edX Transifex Bot
6dc7ff761a fix(i18n): update translations 2020-12-20 16:04:36 -05:00
Matthew Piatetsky
de4a7d9f34 Update business logic for the flyover per UX feedback (#316) 2020-12-17 12:51:19 -05:00
Ben Holt
5f239583fd Extract flyover component and make a version for mobile (#315) 2020-12-17 11:34:17 -05:00
Renovate Bot
aff49aa8a9 fix(deps): update dependency @edx/frontend-component-footer to v10.1.1 2020-12-17 16:24:06 +00:00
David Joy
6e10bffd40 fix: bumping frontend-build version to 5.5.5 (#319) 2020-12-17 11:22:34 -05:00
Michael Terry
37a4dcce18 AA-449: Show discounted price in upgrade buttons & course exit (#311)
If an offer is active for the user, show the discounted price (and
a struck-out original price) on upgrade buttons in the course sock
and outline sidebar.

Also show the discount code and price in the course exit upgrade
screen.
2020-12-17 10:18:57 -05:00
renovate[bot]
c16da21602 chore(deps): update dependency @edx/frontend-build to v5.5.4 (#317)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-12-17 10:16:33 -05:00
renovate[bot]
55ea84f9a6 fix(deps): pin dependencies (#215)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-12-17 10:09:05 -05:00
Carla Duarte
4341a828db AA-131: Landing page for anonymous or un-enrolled users (#281) 2020-12-16 15:50:17 -05:00
Matthew Piatetsky
255e36baa8 [REV-1517] Add Notification header and X to hide the flyover (#313)
* Add back classes to first purchase offer banner that are used in the REV-1512 optimizely test

* Add notification header with an X to hide the flyover box
2020-12-16 12:35:05 -05:00
Renovate Bot
2fc4c8c153 chore(deps): update dependency @edx/frontend-build to v5.5.3 2020-12-15 23:50:16 +00:00
Matthew Piatetsky
79f5c7fcf4 Add back classes to first purchase offer banner that are used in the REV-1512 optimizely test (#309) 2020-12-15 14:59:56 -05:00
Carla Duarte
743621ff51 Dates tab badge fix (#310) 2020-12-15 12:06:53 -05:00
Carla Duarte
9272498c9e AA-417: Update cert images (#308) 2020-12-15 10:24:27 -05:00
Michael Terry
e89aef78b5 TNL-7185: Stop using dangerouslySetInnerHTML in alerts (#306)
Render offer and access-expiration alerts ourselves from newly
passed in backend data, rather than from provided HTML blobs.
2020-12-14 16:09:49 -05:00
edX Transifex Bot
3d41c56a0a fix(i18n): update translations 2020-12-13 16:04:55 -05:00
JJ
e4060b7481 [REV-1521] Add new lock paywall component for the Value Prop experiment (#293)
Add a new lock paywall component to be shown as part of the Purchase squad's Value Prop Optimizely experiment.
2020-12-11 11:31:07 -05:00
Renovate Bot
4e92053151 Update dependency @edx/frontend-build to v5.5.2 2020-12-10 22:33:33 +00:00
Michael Terry
38700499d4 AA-450: add catalog search link to bottom of course exit (#299) 2020-12-10 11:16:35 -05:00
Matthew Piatetsky
0e3fc032ab Add flyover box and button to toggle it for the REV1512 experiment (#291)
This part would be trickier to do in optimizely so adding it in react
REV-1512
2020-12-10 11:04:05 -05:00
Dillon Dumesnil
a604e0be10 AA-503: Course Celebration view for users in verification pending state (#301)
Learners were having questions when we would continue showing them the
'Verify Now' button if they had a submitted a verification attempt
already.
2020-12-09 14:37:23 -05:00
Carla Duarte
264f36b89e AA-504: Dates tab rebrand fix (#303) 2020-12-09 14:36:39 -05:00
stvn
2319a7dfb0 Merge PR #302 kill/travis
* Commits:
  Remove Travis-CI integration
2020-12-09 10:54:31 -08:00
stvn
6549e2b8a2 Remove Travis-CI integration
This is admittedly the much abridged version, but...
Due to changes at Travis-CI that lead to prohibitively slow build/wait
times, we (edx) decided to switch CI/validation provider to Github
Actions [1].

While we had originally intended to keep the integration available,
following Travis-CI's drop in available open-source credits, it no
longer appears to be a viable option for the community.

As such, and given our already present vendor lock-in at Github,
we recommend using Github Actions for CI/validation in this repo.

However, for those not hosting in the Github ecosystem, you can
configure your testrunner to run `make validate.ci`, for the same
effect; the Github Action is just a wrapper for this call.

- [0] Fixes: TNL-7784
- [1] #276
2020-12-09 10:44:32 -08:00
David Joy
ddfc88dad6 Miscellaneous rebranding fixes (#300)
* Rebranding course license

- Fixing horizontal padding
- Setting color to gray 500
- Removing unnecessary a:hover color
- Removing unneeded CSS classes (sequence-footer, course-license, and license-text)
- Removing unnecessary spans

* Removing all usages of theme-color.

* Removing underline from “Help” button in header

* Use outline-primary for user menu button in header.

* Revert text-decoration-none on Help link

This is unnecessary now - it’s fixed at the brand level.

* Rebranding breadcrumbs to be primary-500.

* Set styling for Unit title to h3.

* Setting bookmark button color to primary-500

* Aligning current selection line to be inside dropdown, not outside.

* Adjusting sequence dropdown colors

Gray 700 for non-active units, primary 500 for active unit icon.

* Remove custom btn-outline-light config

We no longer use it in this MFE and the color palette in paragon/the brand has changed anyway.

* Let the stylesheet breathe!
2020-12-08 17:13:23 -05:00
stvn
e1e3d4992d Merge PR #298 fix/codecov
* Commits:
  Run coverage via Github Action
2020-12-08 10:09:57 -08:00
David Joy
43b0f2fbf0 Darken sequence nav buttons so they don’t appear disabled (#297) 2020-12-08 12:47:48 -05:00
stvn
64ff72faa9 Run coverage via Github Action
Note: I tried directly invoking `codecov`, but it "couldn't tell" that
it was running in a GA/CI container, so I've opted for using the GA
codecov integration, which does work as expected.
2020-12-08 09:31:27 -08:00
stvn
cc0af77e2f Merge PR #276 add/github-workflow
* Commits:
  Add Github workflow for CI tests
  Use common CI test target via Travis
  Consolidate CI test scripts in Makefile
2020-12-08 08:55:29 -08:00
stvn
7086bdc9ab Add Github workflow for CI tests 2020-12-08 08:48:56 -08:00
stvn
e627fd6f27 Use common CI test target via Travis 2020-12-08 08:47:31 -08:00
stvn
2ba9440966 Consolidate CI test scripts in Makefile 2020-12-08 08:46:57 -08:00
David Joy
cd51206462 Fixes tab color, according to rebrand UX feedback (#296) 2020-12-08 11:13:12 -05:00
Michael Terry
0cb97db7eb AA-383: add outline sidebar upgrade card (#289)
Also adds the course sock to the outline page.
2020-12-08 10:58:57 -05:00
Renovate Bot
421b438569 fix(deps): update dependency @fortawesome/react-fontawesome to v0.1.13 2020-12-08 00:29:54 +00:00
Renovate Bot
1d40baf4cd chore(deps): update dependency es-check to v5.1.4 2020-12-07 23:36:14 +00:00
David Joy
3c5fb46a4d Update MFE to use the new “brand-openedx” repository. (#283)
* Update MFE to use the new “brand-openedx” repository.

This will allow the MFE to be re-branded by overriding this default implementation.  More detail here:

https://github.com/edx/brand-openedx

* Removing unused frontend-component-header module.

This app doesn’t use frontend-component-header.  That it was a dependency is confusing and led me to believe I needed to wait for its rebrand to continue - not so.  Removing the unused dependency.

* Adding quick comment describing the structure of gated_content

* Fixing course exit styling

* Changing LinkedIn icon

* fix: fix Instructor toolbar button styling

* Bumping footer, platform, and paragon versions.

* Using configured logo and favicon.

Co-authored-by: Carla Duarte <cduarte@edx.org>
2020-12-07 17:50:06 -05:00
Michael Terry
5f06d726f7 AA-478: correctly refresh outline data when refreshing dates (#292) 2020-12-07 14:09:44 -05:00
Michael Terry
bcd69f5836 AA-463: move welcome message below banners on outline tab (#290) 2020-12-07 09:51:30 -05:00
Michael Terry
654fd4c35c AA-483: Fix some course exit segment event calls to work again (#288) 2020-12-04 10:33:45 -05:00
Michael Terry
b98a87c1f5 AA-476: Send org_key with tracking events (#286)
Also convert the course tool click event from accidentally being
a segment event into a log event, like it is on the LMS.
2020-12-03 12:44:52 -05:00
Zainab Amir
0d29082793 Add suppression to username in header (#287) 2020-12-03 15:39:16 +05:00
Dillon Dumesnil
2d56bc5953 AA-448: UI fixes (#285)
LinkedIn button size and single column for view grades button in mobile
2020-12-02 04:59:16 -08:00
David Joy
1bfe3f4436 Use prereqSectionName for the name of the prereq section. (#284)
Surprise, surprise.

Not sure how this wasn’t correct.  The bug results in the content lock UI showing the name of the current section rather than the prerequisite when describing… the prerequisite.
2020-12-01 10:04:59 -05:00
edX Transifex Bot
3f9f40800a fix(i18n): update translations 2020-11-22 16:04:56 -05:00
Renovate Bot
a1c7969477 fix(deps): update dependency @edx/frontend-component-header to v2.0.6 2020-11-19 20:24:49 +00:00
renovate[bot]
53cf637938 chore(deps): update dependency @edx/frontend-build to v5.4.0 (#247)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-11-19 13:13:22 -05:00
stvn
329bcba31c Merge PR #275 add/event/tracking-logs
* Commits:
  Submit events to the tracking logs, not just Segment
2020-11-17 12:46:26 -08:00
stvn
122cef6053 Submit events to the tracking logs, not just Segment
Due to an unfortunate naming choice, we apparently had _not_ been
sending navigation events to the tracking logs' `/track` backend, but
just to the Segment.io tracking backend.

Note: There are still other portions of this repo _outside_ the learning
sequence (Course Tools, Celebration, etc.) that only send to Segment and
not the tracking logs, though maybe this is by design, those being "new"
events?
2020-11-17 11:05:14 -08:00
Carla Duarte
a8a8cf5862 AA-199: Program Completion in CourseExit page (#271) 2020-11-16 15:03:45 -05:00
edX Transifex Bot
74149c2c54 fix(i18n): update translations 2020-11-15 16:04:56 -05:00
Michael Terry
15975fdd78 AA-356: add more config overrides for branding (#270)
Remove some edX-specific branding / links (like support URLs) in
favor of values from configuration.

Images (sample certificates) are still branded for now. We can get
them later.
2020-11-10 10:24:33 -05:00
David Joy
99f0a4a208 fix: make LTI modals full-screen (#268)
Fixes TNL-7410

This causes LTI modals in courseware to take up the whole screen.  It does this by creating a new “dialogClassName” value that we then use to override the default heights/widths of the Bootstrap modal.

We also remove the title of the iframe, which just takes up space and detracts from the LTI content.
2020-11-03 16:04:41 -05:00
edX Transifex Bot
4f9cd060be fix(i18n): update translations 2020-11-01 16:04:56 -05:00
Michael Terry
cd1d3dd379 AA-402: send segment events for course-exit (#265)
Specifically, a "I visited this page" event, with information on
which variant was seen. And "I clicked this button" events, for
our various calls to action.
2020-10-29 09:55:14 -04:00
Renovate Bot
b08f3d7b45 chore(deps): update dependency es-check to v5.1.2 2020-10-28 01:24:55 +00:00
Carla Duarte
1531f3e912 AA-390: Add Social Share icons to Course Exit (#259) 2020-10-27 14:58:35 -04:00
Michael Terry
6f415544be AA-197: Handle non-cert learners that can upgrade (#263)
Tell them about verified certificates and link to ecommerce.

Also fixes AA-376 by handling the no-verified-mode-to-upgrade-to
case.
2020-10-27 11:28:52 -04:00
Renovate Bot
4eb52a592d fix(deps): update dependency react-redux to v7.2.2 2020-10-27 00:35:14 +00:00
Renovate Bot
b4823b90e7 fix(deps): update dependency @fortawesome/react-fontawesome to v0.1.12 2020-10-26 15:20:56 +00:00
edX Transifex Bot
5602c0a3b3 fix(i18n): update translations 2020-10-25 17:04:55 -04:00
Dillon Dumesnil
e0e53f24f1 AA-397: Course Exit Tests (#257)
This also renames the CourseExit url from /course/{course_id}/course-exit
to /course/{course_id}/course-end for better UX.
2020-10-23 10:01:42 -07:00
Renovate Bot
9d8c687e4d fix(deps): update dependency @edx/paragon to v12.0.5 2020-10-23 15:50:47 +00:00
Michael Terry
aeb6a3ebb4 Revert "Revert "AA-403: use PageRoute, not Route (#252)" (#253)" (#254)
This reverts commit e2aa00b16d.
2020-10-20 15:20:10 -04:00
Michael Terry
e2aa00b16d Revert "AA-403: use PageRoute, not Route (#252)" (#253)
This reverts commit ac711d5f3d.
2020-10-20 15:06:05 -04:00
Michael Terry
ac711d5f3d AA-403: use PageRoute, not Route (#252)
This way we get frontend-platform's automatic segment page tracking.
2020-10-20 14:38:19 -04:00
Dillon Dumesnil
9d8b5d21b5 AA-385: Add LinkedIn Add to Profile Button to Course Celebrate (#249) 2020-10-20 07:30:18 -07:00
Michael Terry
15ae6d4981 AA-362: Add tests for outline tab alerts (#250) 2020-10-20 10:03:30 -04:00
Carla Duarte
f063495cbb AA-381: Fix shorten welcome message bug (#251) 2020-10-19 16:31:05 -04:00
Michael Terry
c5821faee8 AA-377: Add non-passing course exit screen (#246)
- Adds a non-passing cert learner course exit screen
- Moves all the logic about what course-exit mode we're in into
  a utility method in the course-exit folder
- Moves all the logic about how the 'Next' button should read into
  a utility method in the course-exit folder
2020-10-19 11:00:44 -04:00
edX Transifex Bot
f83a6e574c fix(i18n): update translations 2020-10-18 17:04:55 -04:00
Renovate Bot
03661ccf4b fix(deps): update dependency @edx/frontend-platform to v1.5.4 2020-10-15 22:24:59 +00:00
Carla Duarte
2d5af74b1b AA-357: Add reset dates banner to outline tab (#243) 2020-10-15 13:44:04 -04:00
Carla Duarte
ae8141c1a8 AA-388: CourseCelebration UI improvements (#242) 2020-10-15 10:37:53 -04:00
Carla Duarte
e9cf5e58de AA-388: CourseExitPage UI improvements (#237) 2020-10-14 10:34:55 -04:00
David Joy
1950fe56bd TNL-7299 - Hide sequences that are time limited (special exams) (#241)
If a sequence has its isTimeLimited flag set, then show a spinner instead of the sequence content.  The CoursewareContainer, meanwhile, will be attempting to redirect to the legacy experience.

This prevents a situation where we temporarily show proctored/special exam content to users before their exam starts.
2020-10-14 10:11:14 -04:00
Renovate Bot
94cacb14e7 chore(deps): update dependency @edx/frontend-build to v5.2.7 2020-10-10 16:04:46 +00:00
Renovate Bot
a8dea78e24 chore(deps): update dependency @edx/frontend-build to v5.2.6 2020-10-10 15:17:05 +00:00
Renovate Bot
8adcfb040a fix(deps): update dependency @edx/paragon to v12.0.4 2020-10-07 18:05:43 +00:00
David Joy
4f396737e4 Fixes TNL-7613 and TNL-7614 (#236)
The course blocks API accepts a value of ‘special_exam_info’ in its requested_fields parameter.  This value is necessary to include special exam sequences for non-staff users.  Special exams include timed, proctored, and practice proctored exams.
2020-10-06 17:17:29 -04:00
Dillon Dumesnil
36f8dd81cd Quick fix to add slice to other routes using TabContainer (#235) 2020-10-06 11:57:18 -07:00
Dillon Dumesnil
f6aebc7d29 AA-389: Updating Routing for CourseExit Page (#234)
The CourseExit page uses the TabContainer because it seems to be a better solution
than adding it into the paths for the CoursewareContainer, despite the CoursewareContainer
already doing the correct fetch. The reason for this is because within the
CoursewareContainer, it would still be necessary to check for the /course-exit path (due
to the CoursewareContainer trying to greedily match sequenceId (read: it will try and
look up 'course-exit' as a sequence)). That effectively defeats the purpose of using the
routing in the first place so instead, we place it in a TabContainer.

The InstructorToolbar didMount logic became necessary once we had a page (CourseExit) that does a redirect on a quick exit.
As a result, it unmouunts the InstructorToolbar (which will be remounted by the new component),
but the InstructorToolbar's MasqueradeWidget has an outgoing request. Since it is unmounted
during that time, it raises an error about a potential memory leak. By stopping the render
when the InstructorToolbar is unmounted, we avoid the memory leak.
2020-10-06 10:42:48 -07:00
Renovate Bot
8a63aef3f0 fix(deps): update dependency @fortawesome/fontawesome-svg-core to v1.2.32 2020-10-05 20:07:48 +00:00
edX Transifex Bot
4be37ceb14 fix(i18n): update translations 2020-10-04 17:09:55 -04:00
Carla Duarte
d123fe6229 AA-363: Tests for Outline Tab and Widgets (#222) 2020-10-02 16:48:42 -04:00
Nick
2f738fdba4 AA-196 course celebration cert (#197)
* AA-196 course celebration cert

* AA-196: Course Celebration for passing Verified Learners

Co-authored-by: Dillon Dumesnil <ddumesnil@edx.org>

Note: This PR is being merged in somewhat incomplete as we decided to split off the work into a couple of other tickets. For example, the UI styling is not complete and I plan to also take another look at the routing. These code paths are not in use yet as the `courseExitPageIsActive` will always be False.
2020-10-02 07:27:59 -07:00
Michael Terry
d52aa3246e Revert "Revert "AA-291: Add Optimizely (#219)" (#227)" (#229)
This reverts commit 42715d3de2.
2020-10-01 10:38:09 -04:00
stvn
e6e5258e5b Merge PR #228 log/unexpected-course-block
* Commits:
  Log "Section ... has child block" as info, not error
  Log "Unexpected course block type" as info, not error
2020-09-30 14:59:53 -07:00
stvn
753925ba99 Log "Section ... has child block" as info, not error 2020-09-30 14:03:01 -07:00
stvn
684be8c0cf Log "Unexpected course block type" as info, not error 2020-09-30 13:36:22 -07:00
Michael Terry
42715d3de2 Revert "AA-291: Add Optimizely (#219)" (#227)
This reverts commit f91abd319f.
2020-09-29 16:05:13 -04:00
Renovate Bot
4d21633462 fix(deps): update dependency @fortawesome/fontawesome-svg-core to v1.2.31 2020-09-29 17:16:25 +00:00
Carla Duarte
f91abd319f AA-291: Add Optimizely (#219) 2020-09-29 11:19:22 -04:00
Renovate Bot
43be11c636 fix(deps): update dependency @edx/paragon to v12.0.1 2020-09-28 20:15:39 +00:00
edX Transifex Bot
72df79b9b8 fix(i18n): update translations 2020-09-27 17:04:45 -04:00
Michael Terry
6f331ea6d5 AA-253: handle the backend giving less data (#223)
Specifically, no outline tree or no course tools
2020-09-25 16:50:30 -04:00
Renovate Bot
d137d5682d chore(deps): update dependency @edx/frontend-build to v5.2.3 2020-09-25 14:39:48 +00:00
Renovate Bot
ea9f5254b7 fix(deps): update dependency @edx/frontend-platform to v1.5.3 2020-09-23 03:24:13 +00:00
Renovate Bot
577a19e35c chore(deps): update dependency es-check to v5.1.1 2020-09-22 06:31:10 +00:00
edX Transifex Bot
f58d405b3b fix(i18n): update translations 2020-09-20 17:04:33 -04:00
David Joy
927d424d33 Agrendalath/bb 2599 low priority tests (#214)
* [TNL-7269] WIP low priority tests

* [TNL-7269] Add low priority tests

* [TNL-7269] Fix failing EnrollmentAlert tests

* [TNL-7269] Address review comments

* Fixing test errors on rebase with master.

Co-authored-by: Agrendalath <piotr@surowiec.it>
2020-09-18 09:27:41 -04:00
Kyle McCormick
25e5d39a72 Refer to 'Existing experience' as 'Legacy experience' (#213) 2020-09-17 13:50:57 -04:00
Michael Terry
d8ed3d6bf8 AA-265: Add more tests for the dates tab (#207)
* Prepare some initial test refactoring

- Expand test data for course home metadata
- Don't test courseware metadata in course-home redux tests

This is Dillon's work.

* AA-265: Add more tests for the dates tab

Add an ADR to talk about how we want to test in this repo.

And refactor the fake dates tab data used for debugging to also be
used for tests.
2020-09-17 11:01:33 -04:00
Carla Duarte
c5a43524a1 AA-368: Expand course outline section that contains resume block (#212) 2020-09-16 13:46:06 -04:00
Alex Dusenbery
adfc2d568b fix: bump frontend-enterprise to 4.2.3 2020-09-16 10:03:21 -04:00
Carla Duarte
4c6797c631 AA-128: Course Home UI/UX improvements (#208) 2020-09-16 09:29:58 -04:00
edX Transifex Bot
e2710f6ed3 fix(i18n): update translations 2020-09-13 17:05:12 -04:00
Jeff LaJoie
1b859f4ab6 ENT-3181: Enables custom branding for enterprise customers in logo and user menu 2020-09-11 09:15:39 -04:00
Dillon Dumesnil
f44ce4c311 AA-320: Adding in UTM parameters to sharing links (#204) 2020-09-10 08:14:30 -07:00
edX Transifex Bot
d8dbbaa7a2 fix(i18n): update translations 2020-09-06 17:04:58 -04:00
Michael Terry
ddc85f2fd3 AA-306: Update twitter hashtag for celebrations (#201)
It's now #myedxjourney instead of #mooc.

Also, fixed the wording of the email share option.
2020-09-03 11:17:42 -04:00
Michael Terry
9cbe0b7c8b AA-126: Update outline tab to be a little closer to LMS (#198)
- Changed it to use its own normalizeBlocks call (and stop sharing
  with courseware)
- Add green checkmarks for complete blocks
- Added icons, descriptions, and due dates for subsections
- Updated look of subsections to match LMS a bit more
2020-08-31 16:44:30 -04:00
Carla Duarte
c83389e7c5 AA-125: quick fix (#199) 2020-08-31 13:50:20 -04:00
Carla Duarte
37d56b4197 AA-125: Course Goals in Course Home Outline Tab (#190) 2020-08-31 09:58:34 -04:00
Renovate Bot
01f69e2273 fix(deps): update dependency @edx/paragon to v10.1.1 2020-08-27 21:21:46 +00:00
Michael Terry
c5ada7e974 AA-326: hide dates banner if the upgrade link is null (#195)
This will prevent a pointless & broken button when the upgrade
deadline has passed for the course.
2020-08-25 09:04:06 -04:00
edX Transifex Bot
450d1c1861 fix(i18n): update translations 2020-08-23 17:04:33 -04:00
David Joy
aa10b3f600 Use ‘modal-lg’ for LTI modals. Update Paragon. (#193)
The new version of Paragon includes a “dialogClassName” property on Modal which lets us set the modal width to ‘modal-lg’ or ‘modal-sm’ - we’re using the former here.
2020-08-21 16:28:02 -04:00
Michael Terry
b65bd0ff44 AA-305: Update Masquerade Widget UI (#188)
* AA-305: Update Masquerade Widget UI

This will start showing the user being masqueraded as in the Toolbar
and will show any error messages next to the Toolbar as well.

* Further masquerade widget fixes

Co-authored-by: Dillon Dumesnil <ddumesnil@edx.org>
2020-08-21 12:49:12 -04:00
David Joy
86d28136de Paragon 10: Updating Dropdown and Button usages. (#187)
* Updating Dropdown and Button.

* Fixing broken tests and test warnings.

* Remove comment block.

* Using variant=“link” on the Tabs Dropdown.Toggle.

* Fixing some merge conflicts.
2020-08-20 13:46:44 -04:00
Alex Dusenbery
707fcc2aa1 feat: ent-3273 | Don't show order history in dropdown if user is associated with a subscription
Update frontend-enterprise dependency to 4.2.2
2020-08-20 11:31:52 -04:00
Kyle McCormick
caabf6a54c Prepend dev BASE_URL with http:// to fix login redirects (#189) 2020-08-20 08:35:16 -04:00
Dave St.Germain
d910d09e00 Allow units to create a modal in the parent window (#184)
This is used by LTI blocks configured to launch in a modal window. Instead of opening a modal in our unit iframe, the component will send a message to the parent window (the courseware mfe) requesting it to open its own modal, containing a URL to launch the LTI tool.
2020-08-19 13:08:13 -04:00
edX Transifex Bot
de53ed9258 fix(i18n): update translations 2020-08-16 17:08:26 -04:00
daphneli-chen
81188ae30f AA-274: Created credit requirements banner (#168)
Co-authored-by: Daphne Li-Chen <dli-chen@edx.org>
2020-08-14 16:50:10 -04:00
stvn
f5d361661f Merge PR #183 add/kill-switch
* Commits:
  Implement kill-switch for non-staff users
2020-08-13 14:28:30 -07:00
David Joy
c298bc1dbf Implement kill-switch for non-staff users
to redirect to the current unit’s lmsWebUrl if the MFE is disabled

If we receive an error_code of 'microfrontend_disabled',
go to the equivalent unit in the LMS experience.

Fixes: TNL-7362
Co-authored-by: stvn <stvn@mit.edu>
2020-08-12 17:26:30 -07:00
Kyle McCormick
0ad80a63cf Fix lint warnings; require 0 warnings for Travis build (#181) 2020-08-12 17:16:28 -04:00
Kyle McCormick
bc76adf8eb Wrap all alert payloads in useMemo to avoid infinite re-rendering (#182)
* Wrap all alert payloads in useMemo to avoid infinite re-rendering

This manifested in production as a browser freeze for any
user who saw the 15%-off-to-upgrade message.

TNL-7400

* fixup! meant to say identity, not equality
2020-08-12 17:12:31 -04:00
David Joy
cc7142e5c1 Fix checkBlockCompletion parameters
We were assuming a prop named unitId existed in CoursewareContainer - it doesn’t.  unitId is not in redux.  What we do have, is the unitId in the route params - what we refer to as routeUnitId.  If we use this instead of the non-existent unitId, then life is good.

I wrote a test (that breaks!) prior to implementing the fix.  The fix satisfies the test. 🎉
2020-08-12 16:01:12 -04:00
Dillon Dumesnil
a975b8ae70 Format may not be defined. Provide a default and only add to URL if it exists (#178) 2020-08-12 09:49:21 -07:00
Renovate Bot
3b34a87391 Pin dependency @edx/paragon to 9.1.1 2020-08-12 12:38:20 -04:00
Nick
453f56c7c8 AA-287 cta events (#177) 2020-08-12 11:48:46 -04:00
Dillon Dumesnil
a131a9f9fb Add format into iframe request to populate context (#174)
The format is used with the due date in the vertical to show
text like "Homework due ___"
2020-08-11 08:32:24 -07:00
Carla Duarte
d5f9af1954 AA-129: Resume Course button (#133) 2020-08-11 11:08:29 -04:00
Carla Duarte
a44d2633a1 AA-255: Dates Tab Tooltip for ORA (#173) 2020-08-10 09:37:01 -04:00
edX Transifex Bot
de2a46eb93 fix(i18n): update translations 2020-08-09 17:08:11 -04:00
Nick
9a315aa29d AA-264 mfe courseware reset dates (#165)
- add toast display after successful reset of dates via banner.
2020-08-06 15:20:53 -04:00
stvn
ad74b2295b Merge PR #106 add/masquerade-username
* Commits:
  Add "masquerade as specific student" support
2020-08-06 12:06:47 -07:00
stvn
c8961d3777 Add "masquerade as specific student" support 2020-08-06 09:07:53 -07:00
Dillon Dumesnil
c7c401e385 AA-275: Persist if the original user was staff for Instructor Toolbar (#167)
We want to be able to know if both the original user is a Staff user
as well as if the user being masqueraded as is staff. This updates
to accept both of these fields
2020-08-06 08:58:47 -07:00
Michael Terry
9e0f192ae7 AA-278 & AA-279: Add offer and course expired alerts to outline (#164)
* AA-278: Add offer alert to outline

It was previously only used in the courseware. But to match the
LMS, we also want to show it on the outline tab.

* AA-279: Add course expired alert to outline

It was previously only used in the courseware. But to match the
LMS, we also want to show it on the outline tab.
2020-08-06 09:49:37 -04:00
daphneli-chen
4667535c0c AA-211: Created certificate banner and studio link (#134)
Co-authored-by: Daphne Li-Chen <dli-chen@edx.org>
2020-08-05 10:26:34 -04:00
Renovate Bot
a1646c5793 Update dependency regenerator-runtime to v0.13.7 2020-08-04 06:58:42 +00:00
Renovate Bot
0e6f64081d Update dependency react-share to v4.2.1 2020-08-04 04:38:41 +00:00
Renovate Bot
8e4f0535a7 Update dependency react-redux to v7.2.1 2020-08-04 03:20:10 +00:00
Renovate Bot
6f14f01dc2 Update dependency codecov to v3.7.2 2020-08-04 01:42:40 +00:00
Renovate Bot
6233f16812 Update dependency @testing-library/user-event to v12.0.17 2020-08-04 00:10:16 +00:00
Renovate Bot
a60480ec52 Update dependency @fortawesome/fontawesome-svg-core to v1.2.30 2020-08-03 22:15:38 +00:00
Renovate Bot
eba9d9a44d Update dependency @edx/frontend-platform to v1.5.2 2020-08-03 20:30:07 +00:00
Renovate Bot
8cd3d6501f Update dependency @edx/frontend-component-footer to v10.0.11 2020-08-03 19:52:06 +00:00
dependabot[bot]
76fc6d64f2 Bump codecov from 3.7.0 to 3.7.1
Bumps [codecov](https://github.com/codecov/codecov-node) from 3.7.0 to 3.7.1.
- [Release notes](https://github.com/codecov/codecov-node/releases)
- [Commits](https://github.com/codecov/codecov-node/compare/v3.7.0...v3.7.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-08-03 14:40:37 -04:00
Michael Terry
314b82d0b2 AA-276: Add course start alert in outline (#146)
Also move a few of the outline alerts into the course home
source folder.
2020-08-03 13:39:25 -04:00
Michael Terry
e17b66851e AA-277: Add certificate available alert on outline (#144) 2020-08-03 13:04:47 -04:00
Renovate Bot
9accacd019 chore(deps): update dependency @testing-library/dom to v7.16.3 2020-08-03 16:23:38 +00:00
Renovate Bot
a9cec0102b chore(deps): pin dependencies 2020-08-03 10:16:24 -04:00
Michael Terry
e4d6d37c4e AA-124: Show course end alert (#135)
This is a parity-with-LMS change, to bring their warning about
the course ending within a couple weeks to the MFE.
2020-08-03 09:53:40 -04:00
edX Transifex Bot
7ad501d73b fix(i18n): update translations 2020-08-02 17:07:56 -04:00
David Joy
f1d43b18d6 Tweak CoursewareContainer tests to get them working again.
This is effectively fixing merge conflicts between:

https://github.com/edx/frontend-app-learning/pull/128

and:

https://github.com/edx/frontend-app-learning/pull/97
2020-07-31 16:02:38 -04:00
Agrendalath
d408986682 [TNL-7268] Fix tests after rebase 2020-07-31 16:02:38 -04:00
Agrendalath
8d7fbb5bd8 [TNL-7268] refactor tests to use factories 2020-07-31 16:02:38 -04:00
Agrendalath
7c046870e3 [TNL-7268] Remove icon mock
As we're not using snapshots, we will not need this anymore.
2020-07-31 16:02:38 -04:00
Agrendalath
0c5fd44d13 [TNL-7268] Fix tests after rebase 2020-07-31 16:02:38 -04:00
Agrendalath
f3d23abe84 [TNL-7268] Fix imports, ignore implicit exports for tests 2020-07-31 16:02:38 -04:00
Agrendalath
6a44d018d8 [TNL-7268] Remove unused dependency 2020-07-31 16:02:38 -04:00
Agrendalath
3362047bcc [TNL-7268] Replace snapshots with specific assertions 2020-07-31 16:02:38 -04:00
Agrendalath
c1bf77efa4 [TNL-7268] Fix tests after rebase 2020-07-31 16:02:38 -04:00
Agrendalath
e6443ae3bd [TNL-7268] Address the review comments 2020-07-31 16:02:38 -04:00
Agrendalath
6f7ec81197 [TNL-7268] Fix tests and dependencies after rebase 2020-07-31 16:02:38 -04:00
Agrendalath
8719fad091 [TNL-7268] Add high priority tests 2020-07-31 16:02:38 -04:00
Agrendalath
ec7f532bc9 [TNL-7268] WIP: Add high priority tests 2020-07-31 16:02:38 -04:00
Dillon Dumesnil
0c8389e244 AA-280: Add assignment type to dates tab display (#137) 2020-07-31 12:09:47 -07:00
Michael Terry
cd8f3072e2 AA-124: Refactor enrollment alerts (#126)
- Place them only on the Outline page
- Support a few cases where enrollment isn't actually allowed
2020-07-30 12:51:17 -04:00
David Joy
b048ca8187 Fixes saving unit position and unit redirection bugs (#128)
* Bumping axios-mock-adapter version

Thought there was a feature in 1.18.2 that I needed - turns out the feature hasn’t been released yet.  Still fine to bump the dependency, though.

* Hiding some warnings about console logging.

* Fixes bugs in CoursewareContainer

Fixes a few bugs in the courseware container:

- Position was not being saved because we weren’t reading “saveUnitPosition” correctly.
- We weren’t calling checkContentRedirect with the right arguments - it was using a non-existent unitId instead of the routeUnitId, meaning we would redirect to the active unit even if a unit was specified in the URL.

Adds tests in CoursewareContainer for various URL and data states.

Now explicitly tests:
- Exam redirects
- The resume block method when it has, and doesn’t have, a block to resume.
- The content redirect when a unit isn’t present on the URL (uses sequence.position)
- Loading a specific unit (not the first of a sequence!) by URL.

Updated some of the factories to be more flexible/allow multiple units.
2020-07-29 14:24:39 -04:00
daphneli-chen
71482f1ec7 AA-205: created chapters and subsections containing progress (#109)
Co-authored-by: Daphne Li-Chen <dli-chen@edx.org>
2020-07-28 12:53:49 -04:00
Nick
7a108728c0 AA-214 social buttons (#127)
- social sharing buttons for linkedin and email
2020-07-28 12:00:26 -04:00
Michael Terry
d7f41fd02a Enable handouts on outline page (#125) 2020-07-27 10:01:18 -04:00
edX Transifex Bot
0e7bccef0b fix(i18n): update translations 2020-07-26 17:07:31 -04:00
Michael Terry
5ac49610da Re-enable the celebration modal (#123)
It got accidentally disabled during a refactor.

Also, try a little harder to make sure it doesn't re-appear during
the same browsing session.
2020-07-24 13:02:50 -04:00
Carla Duarte
175675da55 AA-127: Fix outline tab redirect URL (#122)
Co-authored-by: Carla Duarte <cduarte@edx.org>
2020-07-23 16:01:46 -04:00
Nick
f715fd5ed6 AA-123 welcome message (#121) 2020-07-23 12:28:56 -04:00
Carla Duarte
cdab8959ca AA-218: Course Tool Analytics (#118)
Tracking analytics for onClick events in the Course Tool widget.
Extra: Fixed intl error in the Course Dates widget.

Co-authored-by: Carla Duarte <cduarte@edx.org>
2020-07-23 10:40:52 -04:00
David Joy
be0ee18519 fix: Use reselect’s defaultMemoize instead of lodash.memoize (#120)
* fix: Use reselect’s defaultMemoize instead of lodash.memoize

Lodash memoize doesn’t examine all parameters when deciding to memoize, apparently, meaning it doesn’t re-call the function if any parameter except the first changes.

More here: https://dev.to/nioufe/you-should-not-use-lodash-for-memoization-3441

* Fixing test setup.  Improper use of sequenceMetadata factory!

Two problems:

One, we weren’t properly passing the courseId into our sequenceMetadata factories, so it was differing than the one defined in courseMetadata.  This didn’t manifest until now because we weren’t using the one from sequenceMetadata until this memoization fix!

Two, I’d updated the options for sequenceMetadata to have a “unitBlocks” option, but didn’t update all the usages of the old “unitBlock” option.  This meant it was manually creating its own unit instead of inheriting the one from courseBlocks, resulting in a different ID.
2020-07-22 10:19:53 -04:00
David Joy
c96cd87967 Change CoursewareContainer into a class component. (#115)
I find it much more legible this way.

Some thoughts… as part of refactoring it, I made some of the redux selectors more formal, and made use of reselect more thoroughly. this resulted in a reduction in re-renders from 16 to 12 on your average page load. It’s also a bit more verbose, accounting for some of the increased line count.

I hadn’t tried it before, but found the memoize method of comparing previous props/state to current props/state to be very, very nice. Much easier than manually comparing props, and much clearer to me than using react hooks’ dependency arrays.

The lack of dependency arrays feels really freeing in general to me. They’ve been such a source of hard-to-track-down bugs, and the hooks linter does not always suggest the right solution for what belongs in and out of the array.

Function names are nice. We had a ton of custom hooks in there so that we could put names to otherwise anonymous bits of functionality.

Also note: this component has a test suite. It passed without any changes. 🥳
2020-07-21 09:31:12 -04:00
Calen Pennington
854020dd67 Fix test failures due to changed snapshots, and add representative data for extra_info 2020-07-20 15:45:49 -04:00
Calen Pennington
d320c6b5bc Include assignment extraInfo on dates page 2020-07-20 14:01:02 -04:00
Carla Duarte
81c6b401fd AA-230: Dates Tab MFE styling (#111)
Co-authored-by: Carla Duarte <cduarte@edx.org>
2020-07-20 13:39:56 -04:00
Michael Terry
16bd20e0e8 AA-121: Support showing handouts in the course outline (#112)
And add translation support for the outline.
2020-07-20 09:24:26 -04:00
edX Transifex Bot
23ea255674 fix(i18n): update translations 2020-07-19 17:07:19 -04:00
edX Transifex Bot
dec5340bf3 fix(i18n): update translations 2020-07-17 15:23:15 -04:00
Patrick Cockwell
086b5d8986 TNL-7303 Add Course License details (#103) 2020-07-17 13:26:21 -04:00
David Joy
b940901400 fix: Use activeUnitIndex instead of position, and remove the latter (#110)
We were inconsistently using “position” - a 1-indexed value - in JS arrays which are 0-indexed.  We had an existing, normalized property called “activeUnitIndex” which we now use everywhere instead.  The value is modified back to 1-indexed before being returned to the server.
2020-07-16 10:14:18 -04:00
David Joy
afb4b77250 CoursewareContainer tests. (#108)
* Adding testing-library dependencies, and bumping frontend-build to be compatible with them.

* Adding a function to initialize the redux store

We need to use it in a few places.  Seems worth not-repeating, since they can easily get out of sync.  In general, tests should only test the parts of the store they care about, as well.

* Adding function to initialize a mock application.

Ultimately I’d like to move this to frontend-platform as an alternative to ‘initialize’ for tests.  ‘initialize’ is an async function which complicates matters.

* Using more explicit assertions for courseware reducer fields.

This removes the need for the snapshot file, and ensures our test is more resilient to unrelated changes in the store.

Also added a few more stages of assertions to some of the tests, showing that they have the right values over time.

* Adding a helper to build a simple course blocks response.

We can use this in the courseware data tests, and shortly in the tests for CoursewareContainer.

* Modifying sequenceMetadata factory to allow multiple units.

This will help us test sequence navigation’s behavior more fully by having multiple units in a sequence.

* A little linting and cleanup.

* Adding first round of tests for CoursewareContainer.

Tests loading, sequence navigation/unit rendering, and ‘denied’ states.

Subsequent tests will add tests for handlers.
2020-07-15 10:27:48 -04:00
Carla Duarte
bc30b20b0d AA-221: Pull in has_ended variable for dates banner logic (#107)
Co-authored-by: Carla Duarte <cduarte@edx.org>
2020-07-14 15:58:48 -04:00
Bill Currie
3e14b17271 [BD-29] [TNL-7288] Fix front-end behavior when the course has no sections or no subsections in the first section (#98)
* Do not redirect when the sequenceId is not valid

That is, if firstSequenceId is null or undefined. This prevents the url
becoming bogus but does cause the course contents display to become stuck
with the loading message.

* Detect invalid sequence when loading

If the course has no sections or the first section has no sub-sections,
then sequence will be null. Before the redirection fix, this would cause an
error, but after, the sequenceStatus never leaves the loading state. Thus,
if still loading and the sequence is null, return the no.content message.

* Check sequenceId instead of sequence

From David Joy:

During initial page load, I expect there's a period of time before the
course blocks API and the sequence metadata API come back where the
sequenceStatus is loading but the sequence is still false, meaning that
we'll see a flash of this 'no content' messaging for a moment before the
data comes in.

If we instead check whether sequenceId is null here, that may give us a
more accurate condition. The sequenceId in redux is only populated when we
begin to request a sequence (fetchSequence thunk). If we have no sequence
ID in the URL route, then fetchSequence never happens and the sequenceId in
redux stays null.

* Fix up some additional errors Piotr found

This fixes errors caused by deleting units or subsections.

* Move test for unit validity to SequenceContent
2020-07-14 15:21:33 -04:00
Kyle McCormick
c0d0895630 Do not assume HTML blocks are units (#105)
After further conversation, we decide that
we shouldn't just treat HTML blocks as units.
We've been making the assumption that Verticals
occupy the Unit-level, and we shouldn't break that
assumption for this specific case.

Reverts part of e04f588d1f.
However, the error handling changes remain.
2020-07-10 09:05:04 -04:00
Michael Terry
c2f4ba3ad0 AA-195: Don't show schedule banner if no schedule (#100)
In some cases (user schedule is close to or past the course end),
we don't actually have dates for a course, even if we would normally
have them.

When that happens, let's not show a banner saying we made a
schedule for the learner.
2020-07-09 16:10:49 -04:00
Demid
eac9bf9c92 [BD-29] [TNL-7266] Learning MFE data integration tests (#95)
* Add test for fetchCourse

* Add tests for fetchDatesTab, fetchOutlineTab, fetchSequence and resetDeadlines

* Implement fetch tabs tests

* Add fail test case for fetchSequence

* Add success test for fetchSequence

* Add test for resetDeadlines

* Update test group name

* Add empty tests for courseware and bookmarks

* Fix wrong field in saveSequencePosition thunk

* Add tests for courseware data layer

* Temporary commit

* Split tests after rebase

* Revert "Fix wrong field in saveSequencePosition thunk"

This reverts commit 4394d363c58ad929f81e587ce4da2241528494b5.

* Fix test for position

* Move executeThunk into utils

* Add test for all reducers

* Add expect statements for logs

* Remove redundant snapshot tests and add some specific checks

* Polishing

* Remove redundant checks

* Fix bug in normalizer and update test

* Upgrade @edx/frontend-platform dependency

* Utilize MockAuthService instead of manual auth package mocking

* Update tests after breaking changes in master

* Remove redundant snapshot check
2020-07-09 10:39:37 -04:00
David Joy
5332be8e65 Update README.rst 2020-07-09 10:28:57 -04:00
Kyle McCormick
e04f588d1f Treat html-type XBlocks as units (#104)
Fixes bug where courses with html-type XBlocks as children
of sequences would ignore those children instead of treating them
as units. This caused the app to later just give up and redirect
to the course home in the old experience.

Also, handle that scenario where we have sections/sequences
with children of unexpected block types more gracefully by
logging an error instead of crashing.

TNL-7305
2020-07-09 10:22:30 -04:00
daphneli-chen
fe013f57c5 AA-203: Created progress page and receiving username, email, and enrollment status (#96)
Co-authored-by: Daphne Li-Chen <dli-chen@edx.org>
2020-07-08 16:00:25 -04:00
David Joy
7df50264cf Update 0004-model-store.md (#101)
Explaining the rationale for model-store in a bit more detail.
2020-07-02 13:24:25 -04:00
David Joy
73c74119f0 Organizationing (#102)
* Moving model-store into “generic” sub-directory.

Also adding a README.md to explain what belongs in “generic”

* Moving user-messages into “generic” sub-directory.

* Moving PageLoading into “generic” sub-directory.

* Moving “tabs” module into “generic” sub-directory.

* Moving InstructorToolbar and MasqueradeWidget up to instructor-toolbar.

The masquerade widget is a sub-module of instructor-toolbar.

* Co-locating celebration APIs with celebration utils.

Also adding an ADR about thunk/API naming conventions and making some other areas of the code adhere to it.

* Moving courseware data (thunks, api) into the courseware module.

Note that cousre-home/data/api still uses normalizeBlocks - this should be fixed so it’s not reaching across.  Maybe we pull that particular API up top.

This PR includes a few TODOs for things I saw, as well as a tiny bit of whitespace cleanup.
2020-07-02 13:11:50 -04:00
Carla Duarte
a6edc9132f AA-186: Refactoring to separate Course Home logic from Courseware (#93)
- Pulled Course Home specific components into `course-home`
- Created a courseHome reducer (and all necessary data files - api, thunks, slice)
- Removed Course Home logic from Courseware's data files (api, thunks, slice, etc.)
- Renamed Outline Tab URL to end in `/home` rather than `/outline` again (per Product)

Co-authored-by: Carla Duarte <cduarte@edx.org>
2020-06-25 10:26:47 -04:00
Patrick Cockwell
8b34f8c792 TNL-7126 BD-29 Visual Updates to Learning Sequence (#88)
* BB-2569: Use faVideo instead of faFilm for video units; Set page title based on section, sequence, and course titles

* Add CourseLicense component with styling

* Reorder the pageTitleBreadCrumbs that are used for setting the page title

* Revert "Add CourseLicense component with styling"

This reverts commit 8d154998de.

* Fix package-lock.json so that only new changes for react-helmet are included
2020-06-23 16:09:12 -04:00
daphneli-chen
534b9b205f AA-122: Created Dates Widget on course home page (#82)
Including upcoming dates and a link to dates tab. Gives user ability to
look at any important upcoming dates for their course and to navigate
to upcoming assignments.

Co-authored-by: Daphne Li-Chen <daphneli-chen@MacBook-Pro.local>
2020-06-23 14:05:18 -04:00
Michael Terry
1471abe7dd dates: fix missing Today entry if it would be last entry (#94) 2020-06-23 09:39:54 -04:00
Michael Terry
d55c8b134c Don't show verified-only badge on Today (#92)
If the Today date entry on the dates tab doesn't have any items,
we were showing the Verified Only badge. This fixes that mistake.
2020-06-22 14:37:03 -04:00
Michael Terry
6c052a2661 Avoid redundant paragon sass import (#91)
Move all scss imports into the main index.scss. This will let them
all know about existing sass variables and avoid duplicate imports.
2020-06-22 11:24:15 -04:00
Michael Terry
ac47454b14 Don't show celebration modal too much (#89)
Make sure we only show it for the first unit of a sequence.
2020-06-19 14:29:13 -04:00
stvn
a18adc4112 Merge PR #71 add/masquerade
* Commits:
  Show audit content lock when masquerading
  Create masquerade widget component
2020-06-19 09:59:38 -07:00
Michael Terry
6cdd075243 AA-137: Add first-section celebration (#78)
When a learner completes their first section in a course, throw up
a modal that celebrates that fact and encourages them to share
progress.
2020-06-18 09:27:11 -04:00
David Joy
eb8c97ee86 fix: Ensure lmsWebUrl is loaded in useExamRedirect (#87)
The sequence.lmsWebUrl variable is loaded as part of the course blocks API.  The status of that API’s request is stored in courseStatus.

The useEffect hook in useExamRedirect didn’t ensure that courseStatus was equal to “loaded”.  This meant that if the sequence loaded first, it might attempt to redirect to sequence.lmsWebUrl even though that variable is still undefined.

When global.location.assign() is given `undefined` as a value, it tacks it onto the end of the URL and calls it a day.  After that, we’ve got a badly formed URL.
2020-06-17 14:07:14 -04:00
stvn
24051232af Show audit content lock when masquerading 2020-06-16 23:59:30 -07:00
stvn
dee5128448 Create masquerade widget component
on the Staff Instructor Toolbar
2020-06-16 23:59:30 -07:00
Nick
5ffc1bc599 Add logging back to the coursemetadata call (#86) 2020-06-16 14:42:18 -04:00
Nick
bf0d3b1565 AA-133 mfe dates banner fix (#85)
- mfe dates banner along with fixing previously reverted
  PR by adding back in original coursemetadata call.

This reverts commit 8df4654cf1.
2020-06-16 13:11:50 -04:00
Nick
8df4654cf1 Revert "AA-133 mfe dates banner (#79)" (#84)
This reverts commit 973f3d68aa.
2020-06-16 10:14:30 -04:00
Nick
973f3d68aa AA-133 mfe dates banner (#79)
- dates banner on dates tab
2020-06-16 09:55:04 -04:00
Carla Duarte
b51809fa50 Quick fix: Corrected Outline Tab redirect URL (#83)
Co-authored-by: Carla Duarte <cduarte@edx.org>
2020-06-15 17:54:16 -04:00
Carla Duarte
253836fa9f AA-181: Outline Tab Refactor (#80)
- Updated the Outline Tab to fetch course blocks from the Outline API.
- Changed naming conventions to more accurately portray the tab naming scheme
(ex. Outline Tab, Dates Tab, etc.)
- Removed logic from `fetchCourses` that was specific to the Outline Tab
2020-06-15 15:19:13 -04:00
David Joy
65173e9f93 fix: remove conditions for an infinite React hooks loop (#81)
The useAlert hook was being given a new payload object every time it was called, defeating any memoization happening inside.

It was also re-calling it’s useEffect hook when alertId changed, which it was changing itself. That’s a no-no.
2020-06-10 17:08:07 -04:00
David Joy
a8d01c423d Miscellaneous small refactorings (#74)
* Normalizing “courseInfo” back into “course”

Splitting it out denormalizes the data and introduces potential data inconsistencies.

* Name component JSX files with the name of the component.

* Normalizing some module exports/naming.

* Moving alerts into a sub-directory.

* DRYing up alert hook creation into reusable useAlert hook.

* Adding some comments about ‘courses’ hydration.
2020-06-02 14:15:12 -04:00
Carla Duarte
025f37cd21 AA-120: Course Tools Widget (#73)
Co-authored-by: Carla Duarte <cduarte@edx.org>
2020-06-02 13:41:23 -04:00
Michael Terry
964bde180a Further UI tweaks to the Dates tab (#76)
Allow for per-item badges if not all items in a given day match
for the badge. And some minor spacing changes.
2020-06-01 09:45:35 -04:00
Nick
209a64c29b AA-117 mfe dates tab waffle flag (#75)
- redirect back to platform dates tab if waffle flags are not
  enable for the mfe dates tab
2020-05-29 13:48:23 -04:00
Michael Terry
bdb1afe990 Finish up basic dates tab support (#70)
- Drop mock data, call real API instead
- Call course metadata API for general info, not the dates API
- Mark text as translatable
- Add badges and timeline dots, group same-day items

AA-116
2020-05-26 13:15:36 -04:00
Michael Terry
7487d8d32f Add basic dates tab (#62)
This is not the final visuals for the dates tab, but an in-progress
page to base further work on.

AA-116
2020-05-26 13:07:24 -04:00
698 changed files with 65439 additions and 22047 deletions

71
.env
View File

@@ -1,18 +1,55 @@
# See README.rst for explanations of these.
# If you add a new learning MFE-specific variable, please note it there!
NODE_ENV='production'
ACCESS_TOKEN_COOKIE_NAME=null
BASE_URL=null
CREDENTIALS_BASE_URL=null
CSRF_TOKEN_API_PATH=null
ECOMMERCE_BASE_URL=null
INSIGHTS_BASE_URL=
LANGUAGE_PREFERENCE_COOKIE_NAME=null
LMS_BASE_URL=null
LOGIN_URL=null
LOGOUT_URL=null
MARKETING_SITE_BASE_URL=null
ORDER_HISTORY_URL=null
REFRESH_ACCESS_TOKEN_ENDPOINT=null
SEGMENT_KEY=null
SITE_NAME=null
STUDIO_BASE_URL=
USER_INFO_COOKIE_NAME=null
ACCESS_TOKEN_COOKIE_NAME=''
APP_ID='learning'
BASE_URL=''
CONTACT_URL=''
CREDENTIALS_BASE_URL=''
CREDIT_HELP_LINK_URL=''
CSRF_TOKEN_API_PATH=''
DISCOVERY_API_BASE_URL=''
DISCUSSIONS_MFE_BASE_URL=''
DISCOUNT_CODE_INFO_URL=''
ECOMMERCE_BASE_URL=''
ENABLE_JUMPNAV='true'
ENABLE_NOTICES=''
ENTERPRISE_LEARNER_PORTAL_HOSTNAME=''
ENTERPRISE_LEARNER_PORTAL_URL=''
EXAMS_BASE_URL=''
FAVICON_URL=''
IGNORED_ERROR_REGEX=''
INSIGHTS_BASE_URL=''
LANGUAGE_PREFERENCE_COOKIE_NAME=''
LMS_BASE_URL=''
LOGIN_URL=''
LOGOUT_URL=''
LOGO_URL=''
LOGO_TRADEMARK_URL=''
LOGO_WHITE_URL=''
LEGACY_THEME_NAME=''
MARKETING_SITE_BASE_URL=''
ORDER_HISTORY_URL=''
PROCTORED_EXAM_FAQ_URL=''
PROCTORED_EXAM_RULES_URL=''
REFRESH_ACCESS_TOKEN_ENDPOINT=''
SEARCH_CATALOG_URL=''
SEGMENT_KEY=''
SESSION_COOKIE_DOMAIN=''
SITE_NAME=''
SOCIAL_UTM_MILESTONE_CAMPAIGN=''
STUDIO_BASE_URL=''
SUPPORT_URL=''
SUPPORT_URL_CALCULATOR_MATH=''
SUPPORT_URL_ID_VERIFICATION=''
SUPPORT_URL_VERIFIED_CERTIFICATE=''
TERMS_OF_SERVICE_URL=''
TWITTER_HASHTAG=''
TWITTER_URL=''
USER_INFO_COOKIE_NAME=''
OPTIMIZELY_FULL_STACK_SDK_KEY=''
SHOW_UNGRADED_ASSIGNMENT_PROGRESS=''
# Fallback in local style files
PARAGON_THEME_URLS={}

View File

@@ -1,18 +1,57 @@
# See README.rst for explanations of these.
# If you add a new learning MFE-specific variable, please note it there!
NODE_ENV='development'
ACCESS_TOKEN_COOKIE_NAME='edx-jwt-cookie-header-payload'
BASE_URL='localhost:2000'
APP_ID='learning'
BASE_URL='http://localhost:2000'
CONTACT_URL='http://localhost:18000/contact'
CREDENTIALS_BASE_URL='http://localhost:18150'
CREDIT_HELP_LINK_URL='https://help.edx.org/edxlearner/s/article/Can-I-receive-college-credit-or-credit-hours-for-my-course'
CSRF_TOKEN_API_PATH='/csrf/api/v1/token'
DISCOVERY_API_BASE_URL='http://localhost:18381'
DISCUSSIONS_MFE_BASE_URL='http://localhost:2002'
DISCOUNT_CODE_INFO_URL=''
ECOMMERCE_BASE_URL='http://localhost:18130'
ENABLE_JUMPNAV='true'
ENABLE_NOTICES=''
ENTERPRISE_LEARNER_PORTAL_HOSTNAME='localhost:8734'
ENTERPRISE_LEARNER_PORTAL_URL='http://localhost:8734'
EXAMS_BASE_URL=''
FAVICON_URL=https://edx-cdn.org/v3/default/favicon.ico
IGNORED_ERROR_REGEX=''
LANGUAGE_PREFERENCE_COOKIE_NAME='openedx-language-preference'
LMS_BASE_URL='http://localhost:18000'
LOGIN_URL='http://localhost:18000/login'
LOGOUT_URL='http://localhost:18000/logout'
LOGO_URL=https://edx-cdn.org/v3/default/logo.svg
LOGO_TRADEMARK_URL=https://edx-cdn.org/v3/default/logo-trademark.svg
LOGO_WHITE_URL=https://edx-cdn.org/v3/default/logo-white.svg
LEGACY_THEME_NAME=''
MARKETING_SITE_BASE_URL='http://localhost:18000'
ORDER_HISTORY_URL='localhost:1996/orders'
ORDER_HISTORY_URL='http://localhost:1996/orders'
PORT=2000
PROCTORED_EXAM_FAQ_URL=''
PROCTORED_EXAM_RULES_URL=''
REFRESH_ACCESS_TOKEN_ENDPOINT='http://localhost:18000/login_refresh'
SEGMENT_KEY=null
SEARCH_CATALOG_URL='http://localhost:18000/courses'
SEGMENT_KEY=''
SITE_NAME='edX'
SOCIAL_UTM_MILESTONE_CAMPAIGN='edxmilestone'
STUDIO_BASE_URL='http://localhost:18010'
SUPPORT_URL='https://support.edx.org'
SUPPORT_URL_CALCULATOR_MATH='https://support.edx.org/hc/en-us/articles/360000038428-Entering-math-expressions-in-assignments-or-the-calculator'
SUPPORT_URL_ID_VERIFICATION='https://support.edx.org/hc/en-us/articles/206503858-How-do-I-verify-my-identity'
SUPPORT_URL_VERIFIED_CERTIFICATE='https://support.edx.org/hc/en-us/articles/206502008-What-is-a-verified-certificate'
TERMS_OF_SERVICE_URL='https://www.edx.org/edx-terms-service'
TWITTER_HASHTAG='myedxjourney'
TWITTER_URL='https://twitter.com/edXOnline'
USER_INFO_COOKIE_NAME='edx-user-info'
SESSION_COOKIE_DOMAIN='localhost'
CHAT_RESPONSE_URL='http://localhost:18000/api/learning_assistant/v1/course_id'
PRIVACY_POLICY_URL='http://localhost:18000/privacy'
OPTIMIZELY_FULL_STACK_SDK_KEY=''
SHOW_UNGRADED_ASSIGNMENT_PROGRESS=''
# Fallback in local style files
PARAGON_THEME_URLS={}

View File

@@ -1,18 +1,54 @@
# See README.rst for explanations of these.
# If you add a new learning MFE-specific variable, please note it there!
NODE_ENV='test'
ACCESS_TOKEN_COOKIE_NAME='edx-jwt-cookie-header-payload'
BASE_URL='localhost:2000'
APP_ID='learning'
BASE_URL='http://localhost:2000'
CONTACT_URL='http://localhost:18000/contact'
CREDENTIALS_BASE_URL='http://localhost:18150'
CREDIT_HELP_LINK_URL='https://help.edx.org/edxlearner/s/article/Can-I-receive-college-credit-or-credit-hours-for-my-course'
CSRF_TOKEN_API_PATH='/csrf/api/v1/token'
DISCOVERY_API_BASE_URL='http://localhost:18381'
DISCUSSIONS_MFE_BASE_URL='http://localhost:2002'
DISCOUNT_CODE_INFO_URL=''
ECOMMERCE_BASE_URL='http://localhost:18130'
ENABLE_JUMPNAV='true'
ENABLE_NOTICES=''
ENTERPRISE_LEARNER_PORTAL_HOSTNAME='localhost:8734'
ENTERPRISE_LEARNER_PORTAL_URL='http://localhost:8734'
EXAMS_BASE_URL='http://localhost:18740'
FAVICON_URL=https://edx-cdn.org/v3/default/favicon.ico
IGNORED_ERROR_REGEX=''
LANGUAGE_PREFERENCE_COOKIE_NAME='openedx-language-preference'
LMS_BASE_URL='http://localhost:18000'
LOGIN_URL='http://localhost:18000/login'
LOGOUT_URL='http://localhost:18000/logout'
LOGO_URL=https://edx-cdn.org/v3/default/logo.svg
LOGO_TRADEMARK_URL=https://edx-cdn.org/v3/default/logo-trademark.svg
LOGO_WHITE_URL=https://edx-cdn.org/v3/default/logo-white.svg
LEGACY_THEME_NAME=''
MARKETING_SITE_BASE_URL='http://localhost:18000'
ORDER_HISTORY_URL='localhost:1996/orders'
ORDER_HISTORY_URL='http://localhost:1996/orders'
PORT=2000
PROCTORED_EXAM_FAQ_URL=''
PROCTORED_EXAM_RULES_URL=''
REFRESH_ACCESS_TOKEN_ENDPOINT='http://localhost:18000/login_refresh'
SEGMENT_KEY=null
SEARCH_CATALOG_URL='http://localhost:18000/courses'
SEGMENT_KEY=''
SITE_NAME='edX'
SOCIAL_UTM_MILESTONE_CAMPAIGN='edxmilestone'
STUDIO_BASE_URL='http://localhost:18010'
SUPPORT_URL='https://support.edx.org'
SUPPORT_URL_CALCULATOR_MATH='https://support.edx.org/hc/en-us/articles/360000038428-Entering-math-expressions-in-assignments-or-the-calculator'
SUPPORT_URL_ID_VERIFICATION='https://support.edx.org/hc/en-us/articles/206503858-How-do-I-verify-my-identity'
SUPPORT_URL_VERIFIED_CERTIFICATE='https://support.edx.org/hc/en-us/articles/206502008-What-is-a-verified-certificate'
TERMS_OF_SERVICE_URL='https://www.edx.org/edx-terms-service'
TWITTER_HASHTAG='myedxjourney'
TWITTER_URL='https://twitter.com/edXOnline'
USER_INFO_COOKIE_NAME='edx-user-info'
PRIVACY_POLICY_URL='http://localhost:18000/privacy'
SHOW_UNGRADED_ASSIGNMENT_PROGRESS=''
ENTERPRISE_LEARNER_PORTAL_URL='http://localhost:Enterprise'
FEATURE_ENABLE_CHAT_V2_ENDPOINT='false'

View File

@@ -1,4 +1,7 @@
coverage/*
dist/
packages/
node_modules/
jest.config.js
jest.config.js
env.config.jsx
example.env.config.jsx

View File

@@ -1,3 +1,24 @@
const { createConfig } = require('@edx/frontend-build');
// eslint-disable-next-line import/no-extraneous-dependencies
const { createConfig } = require('@openedx/frontend-build');
module.exports = createConfig('eslint');
const config = createConfig('eslint', {
rules: {
// TODO: all these rules should be renabled/addressed. temporarily turned off to unblock a release.
'react-hooks/rules-of-hooks': 'off',
'react-hooks/exhaustive-deps': 'off',
'import/no-extraneous-dependencies': 'off',
'no-restricted-exports': 'off',
'react/jsx-no-useless-fragment': 'off',
'react/no-unknown-property': 'off',
'func-names': 'off',
},
settings: {
'import/resolver': {
webpack: {
config: 'webpack.prod.config.js',
},
},
},
});
module.exports = config;

7
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
version: 2
updates:
# Adding new check for github-actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@@ -0,0 +1,19 @@
# Run the workflow that adds new tickets that are either:
# - labelled "DEPR"
# - title starts with "[DEPR]"
# - body starts with "Proposal Date" (this is the first template field)
# to the org-wide DEPR project board
name: Add newly created DEPR issues to the DEPR project board
on:
issues:
types: [opened]
jobs:
routeissue:
uses: openedx/.github/.github/workflows/add-depr-ticket-to-depr-board.yml@master
secrets:
GITHUB_APP_ID: ${{ secrets.GRAPHQL_AUTH_APP_ID }}
GITHUB_APP_PRIVATE_KEY: ${{ secrets.GRAPHQL_AUTH_APP_PEM }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_ISSUE_BOT_TOKEN }}

View File

@@ -0,0 +1,18 @@
# Run the workflow that adds new tickets that are labelled "release testing"
# to the org-wide BTR project board
name: Add release testing issues to the BTR project board
on:
issues:
types: [labeled]
# This workflow is triggered when an issue is labeled with 'release testing'.
# It adds the issue to the BTR project and applies the 'needs triage' label
# if it doesn't already have it.
jobs:
handle-release-testing:
uses: openedx/.github/.github/workflows/add-issue-to-btr-project.yml@master
secrets:
GITHUB_APP_ID: ${{ secrets.GRAPHQL_AUTH_APP_ID }}
GITHUB_APP_PRIVATE_KEY: ${{ secrets.GRAPHQL_AUTH_APP_PEM }}

View File

@@ -0,0 +1,20 @@
# This workflow runs when a comment is made on the ticket
# If the comment starts with "label: " it tries to apply
# the label indicated in rest of comment.
# If the comment starts with "remove label: ", it tries
# to remove the indicated label.
# Note: Labels are allowed to have spaces and this script does
# not parse spaces (as often a space is legitimate), so the command
# "label: really long lots of words label" will apply the
# label "really long lots of words label"
name: Allows for the adding and removing of labels via comment
on:
issue_comment:
types: [created]
jobs:
add_remove_labels:
uses: openedx/.github/.github/workflows/add-remove-label-on-comment.yml@master

10
.github/workflows/commitlint.yml vendored Normal file
View File

@@ -0,0 +1,10 @@
# Run commitlint on the commit messages in a pull request.
name: Lint Commit Messages
on:
- pull_request
jobs:
commitlint:
uses: openedx/.github/.github/workflows/commitlint.yml@master

View File

@@ -0,0 +1,13 @@
#check package-lock file version
name: Lockfile Version check
on:
push:
branches:
- master
pull_request:
jobs:
version-check:
uses: openedx/.github/.github/workflows/lockfileversion-check-v3.yml@master

12
.github/workflows/self-assign-issue.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# This workflow runs when a comment is made on the ticket
# If the comment starts with "assign me" it assigns the author to the
# ticket (case insensitive)
name: Assign comment author to ticket if they say "assign me"
on:
issue_comment:
types: [created]
jobs:
self_assign_by_comment:
uses: openedx/.github/.github/workflows/self-assign-issue.yml@master

View File

@@ -0,0 +1,12 @@
name: Update Browserslist DB
on:
schedule:
- cron: '0 0 * * 1'
workflow_dispatch:
jobs:
update-browserslist:
uses: openedx/.github/.github/workflows/update-browserslist-db.yml@master
secrets:
requirements_bot_github_token: ${{ secrets.requirements_bot_github_token }}

36
.github/workflows/validate.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: validate
on:
push:
branches:
- master
pull_request:
branches:
- '**'
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
- run: make validate.ci
- name: Archive code coverage results
uses: actions/upload-artifact@v6
with:
name: code-coverage-report
path: coverage/*.*
coverage:
runs-on: ubuntu-latest
needs: tests
steps:
- uses: actions/checkout@v5
- name: Download code coverage results
uses: actions/download-artifact@v5
with:
pattern: code-coverage-report
- name: Upload coverage
uses: codecov/codecov-action@v5
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}

16
.gitignore vendored
View File

@@ -1,18 +1,32 @@
.DS_Store
.eslintcache
.idea
*.swp
*.swo
node_modules
npm-debug.log
coverage
env.config.*
dist/
src/i18n/transifex_input.json
temp/babel-plugin-react-intl
logs
### pyenv ###
.python-version
### Emacs ###
### Editors ###
*~
/temp
/.vscode
# Local package dependencies
module.config.js
# Local environment overrides
.env.private
src/i18n/messages/
env.config.jsx

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
24

View File

@@ -1,15 +0,0 @@
language: node_js
node_js: 12
before_install:
- npm install -g npm@6
install:
- npm ci
script:
- make validate-no-uncommitted-package-lock-changes
- npm run i18n_extract
- npm run lint
- npm run test
- npm run build
- npm run is-es5
after_success:
- codecov

View File

@@ -1,8 +0,0 @@
[main]
host = https://www.transifex.com
[edx-platform.frontend-app-learning]
file_filter = src/i18n/messages/<lang>.json
source_file = src/i18n/transifex_input.json
source_lang = en
type = KEYVALUEJSON

View File

@@ -1,21 +1,17 @@
transifex_resource = frontend-app-learning
transifex_langs = "ar,fr,es_419,zh_CN"
intl_imports = ./node_modules/.bin/intl-imports.js
transifex_utils = ./node_modules/.bin/transifex-utils.js
i18n = ./src/i18n
transifex_input = $(i18n)/transifex_input.json
tx_url1 = https://www.transifex.com/api/2/project/edx-platform/resource/$(transifex_resource)/translation/en/strings/
tx_url2 = https://www.transifex.com/api/2/project/edx-platform/resource/$(transifex_resource)/source/
# This directory must match .babelrc .
transifex_temp = ./temp/babel-plugin-react-intl
transifex_temp = ./temp/babel-plugin-formatjs
precommit:
npm run lint
npm audit
requirements:
npm install
npm ci
i18n.extract:
# Pulling display strings from .jsx files into .json files...
@@ -33,22 +29,38 @@ detect_changed_source_translations:
# Checking for changed translations...
git diff --exit-code $(i18n)
# Pushes translations to Transifex. You must run make extract_translations first.
push_translations:
# Pushing strings to Transifex...
tx push -s
# Fetching hashes from Transifex...
./node_modules/reactifex/bash_scripts/get_hashed_strings.sh $(tx_url1)
# Writing out comments to file...
$(transifex_utils) $(transifex_temp) --comments
# Pushing comments to Transifex...
./node_modules/reactifex/bash_scripts/put_comments.sh $(tx_url2)
# Pulls translations from Transifex.
pull_translations:
tx pull -f --mode reviewed --language=$(transifex_langs)
rm -rf src/i18n/messages
mkdir src/i18n/messages
cd src/i18n/messages \
&& atlas pull $(ATLAS_OPTIONS) \
translations/frontend-platform/src/i18n/messages:frontend-platform \
translations/paragon/src/i18n/messages:paragon \
translations/frontend-component-header/src/i18n/messages:frontend-component-header \
translations/frontend-component-footer/src/i18n/messages:frontend-component-footer \
translations/frontend-lib-special-exams/src/i18n/messages:frontend-lib-special-exams \
translations/frontend-app-learning/src/i18n/messages:frontend-app-learning
$(intl_imports) frontend-platform paragon frontend-component-header frontend-component-footer frontend-lib-special-exams frontend-app-learning
# This target is used by Travis.
validate-no-uncommitted-package-lock-changes:
# Checking for package-lock.json changes...
git diff --exit-code package-lock.json
.PHONY: validate
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
.PHONY: validate.ci
validate.ci:
npm ci
make validate

View File

@@ -1,22 +1,255 @@
|Build Status| |Coveralls| |npm_version| |npm_downloads| |license|
frontend-app-learning
#####################
|codecov| |license|
Purpose
*******
This is the Learning MFE (micro-frontend application), which renders all
learner-facing course pages (like the course outline, the progress page,
actual course content, etc).
.. |codecov| image:: https://codecov.io/gh/edx/frontend-app-learning/branch/master/graph/badge.svg?token=3z7XvuzTq3
:target: https://codecov.io/gh/edx/frontend-app-learning
.. |license| image:: https://img.shields.io/badge/license-AGPL-informational
:target: https://github.com/openedx/frontend-app-account/blob/master/LICENSE
Getting Started
***************
Prerequisites
=============
`Tutor`_ is currently recommended as a development environment for the Learning
MFE. Most likely, it already has this MFE configured; however, you'll need to
make some changes in order to run it in development mode. You can refer
to the `relevant tutor-mfe documentation`_ for details, or follow the quick
guide below.
.. _Tutor: https://github.com/overhangio/tutor
.. _relevant tutor-mfe documentation: https://github.com/overhangio/tutor-mfe#mfe-development
Cloning and Setup
=================
1. Clone your new repo:
.. code-block:: bash
git clone https://github.com/openedx/frontend-app-learning.git
2. Use the version of Node specified in ``.nvmrc``.
Using other major versions of node *may* work, but this is unsupported. For
convenience, this repository includes an ``.nvmrc`` file to help in setting the
correct node version via `nvm <https://github.com/nvm-sh/nvm>`_.
3. Stop the Tutor devstack, if it's running: ``tutor dev stop``
4. Next, we need to tell Tutor that we're going to be running this repo in
development mode, and it should be excluded from the ``mfe`` container that
otherwise runs every MFE. Run this:
.. code-block:: bash
tutor mounts add /path/to/frontend-app-learning
5. Start Tutor in development mode. This command will start the LMS and Studio,
and other required MFEs like ``authn`` and ``account``, but will not start
the learning MFE, which we're going to run on the host instead of in a
container managed by Tutor. Run:
.. code-block:: bash
tutor dev start lms cms mfe
Startup
=======
1. Install npm dependencies:
.. code-block:: bash
cd frontend-app-learning && npm ci
2. Start the dev server:
.. code-block:: bash
npm run dev
Then you can access the app at http://local.openedx.io:2000/learning/
Troubleshooting
---------------
If you see an "Invalid Host header" error, then you're probably using a different domain name for your devstack such as
``local.edly.io`` or ``local.overhang.io`` (not the new recommended default, ``local.openedx.io``). In that case, run
these commands to update your devstack's domain names:
.. code-block:: bash
tutor dev stop
tutor config save --set LMS_HOST=local.openedx.io --set CMS_HOST=studio.local.openedx.io
tutor dev launch -I --skip-build
tutor dev stop learning # We will run this MFE on the host
Local module development
=========================
Please tag **@edx/teaching-and-learning** on any PRs or issues. Thanks.
To develop locally on modules that are installed into this app, you'll need to create a ``module.config.js``
file (which is git-ignored) that defines where to find your local modules, for instance:
Introduction
------------
.. code-block:: js
React app for edX learning.
module.exports = {
/*
Modules you want to use from local source code. Adding a module here means that when this app
runs its build, it'll resolve the source from peer directories of this app.
.. |Build Status| image:: https://api.travis-ci.org/edx/frontend-app-learning.svg?branch=master
:target: https://travis-ci.org/edx/frontend-app-learning
.. |Coveralls| image:: https://img.shields.io/coveralls/edx/frontend-app-learning.svg?branch=master
:target: https://coveralls.io/github/edx/frontend-app-learning
.. |npm_version| image:: https://img.shields.io/npm/v/@edx/frontend-app-learning.svg
:target: @edx/frontend-app-learning
.. |npm_downloads| image:: https://img.shields.io/npm/dt/@edx/frontend-app-learning.svg
:target: @edx/frontend-app-learning
.. |license| image:: https://img.shields.io/npm/l/@edx/frontend-app-learning.svg
:target: @edx/frontend-app-learning
moduleName: the name you use to import code from the module.
dir: The relative path to the module's source code.
dist: The sub-directory of the source code where it puts its build artifact. Often "dist", though you
may want to use "src" if the module installs React as a peer/dev dependency.
*/
localModules: [
{ moduleName: '@openedx/paragon/scss', dir: '../paragon', dist: 'scss' },
{ moduleName: '@openedx/paragon', dir: '../paragon', dist: 'dist' },
{ moduleName: '@openedx/frontend-enterprise', dir: '../frontend-enterprise', dist: 'src' },
{ moduleName: '@openedx/frontend-platform', dir: '../frontend-platform', dist: 'dist' },
],
};
See https://github.com/openedx/frontend-build#local-module-configuration-for-webpack for more details.
Deployment
==========
The Learning MFE is similar to all the other Open edX MFEs. Read the Open
edX Developer Guide's section on
`MFE applications <https://openedx.github.io/frontend-platform/>`_.
Plugins
=======
This MFE can be customized using `Frontend Plugin Framework <https://github.com/openedx/frontend-plugin-framework>`_.
The parts of this MFE that can be customized in that manner are documented `here </src/plugin-slots>`_.
Environment Variables
=====================
This MFE is configured via environment variables supplied at build time.
All micro-frontends have a shared set of required environment variables,
as documented in the Open edX Developer Guide under
`Required Environment Variables <https://openedx.github.io/frontend-platform/>`_.
The learning micro-frontend also supports the following additional variables:
CREDIT_HELP_LINK_URL
A link to resources to help explain what course credit is and how to earn it.
ENABLE_JUMPNAV
Enables the new Jump Navigation feature in the course breadcrumbs, defaulted to the string 'true'.
Disable to have simple hyperlinks for breadcrumbs. Setting it to any other value but 'true' ('false','I love flags', 'etc' would disable the Jumpnav).
This feature flag is slated to be removed as jumpnav becomes default. Follow the progress of this ticket here:
https://openedx.atlassian.net/browse/TNL-8678
SOCIAL_UTM_MILESTONE_CAMPAIGN
This value is passed as the ``utm_campaign`` parameter for social-share
links when celebrating learning milestones in the course. Optional.
Example: ``milestone``
SUPPORT_URL_CALCULATOR_MATH
A link that explains how to use the in-course calculator. You can use the
one in the example below if you don't want to have your own branded version.
Example: https://support.edx.org/hc/en-us/articles/360000038428-Entering-math-expressions-in-assignments-or-the-calculator
SUPPORT_URL_ID_VERIFICATION
A link that explains how to verify your ID. Shown in contexts where you need
to verify yourself to earn a certificate. The example link below is probably too
edx.org-specific to use for your own site.
Example: https://support.edx.org/hc/en-us/articles/206503858-How-do-I-verify-my-identity
SUPPORT_URL_VERIFIED_CERTIFICATE
A link that explains what a verified certificate is. You can use the
one in the example below if you don't want to have your own branded version.
Optional.
Example: https://support.edx.org/hc/en-us/articles/206502008-What-is-a-verified-certificate
TWITTER_HASHTAG
This value is used in the Twitter social-share link when celebrating learning
milestones in the course. Will prefill the suggested post with this hashtag.
Optional.
Example: ``brandedhashtag``
TWITTER_URL
A link to your Twitter account. The Twitter social-share link won't appear
unless this is set. Optional.
Example: https://twitter.com/openedx
Getting Help
============
If you're having trouble, we have `discussion forums`_
where you can connect with others in the community.
Our real-time conversations are on Slack. You can request a `Slack
invitation`_, then join our `community Slack workspace`_. Because this is a
frontend repository, the best place to discuss it would be in the `#wg-frontend
channel`_.
For anything non-trivial, the best path is to open an issue in this repository
with as many details about the issue you are facing as you can provide.
https://github.com/openedx/frontend-app-learning/issues
For more information about these options, see the `Getting Help`_ page.
.. _Slack invitation: https://openedx.org/slack
.. _community Slack workspace: https://openedx.slack.com/
.. _#wg-frontend channel: https://openedx.slack.com/archives/C04BM6YC7A6
.. _Getting Help: https://openedx.org/community/connect
.. _discussion forums: https://discuss.openedx.org
Contributing
============
Contributions are very welcome. Please read `How To Contribute`_ for details.
.. _How To Contribute: https://openedx.org/r/how-to-contribute
This project is currently accepting all types of contributions, bug fixes,
security fixes, maintenance work, or new features. However, please make sure
to discuss your new feature idea with the maintainers before
beginning development to maximize the chances of your change being accepted.
You can start a conversation by creating a new issue on this repo summarizing
your idea.
The Open edX Code of Conduct
============================
All community members are expected to follow the `Open edX Code of Conduct`_.
.. _Open edX Code of Conduct: https://openedx.org/code-of-conduct/
License
=======
The code in this repository is licensed under the AGPLv3 unless otherwise
noted.
Please see `LICENSE <LICENSE>`_ for details.
Reporting Security Issues
=========================
Please do not report security issues in public. Please email security@openedx.org.

19
catalog-info.yaml Normal file
View File

@@ -0,0 +1,19 @@
# This file records information about this repo. Its use is described in OEP-55:
# https://open-edx-proposals.readthedocs.io/en/latest/processes/oep-0055-proc-project-maintainers.html
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: 'frontend-app-learning'
description: "This is the Learning MFE, which renders all learner-facing course pages."
links:
- url: "https://github.com/openedx/frontend-app-learning"
title: "Learning MFE"
icon: "Web"
annotations:
openedx.org/arch-interest-groups: ""
openedx.org/release: "master"
spec:
owner: group:committers-frontend-app-learning
type: 'website'
lifecycle: 'production'

View File

@@ -1,5 +1,7 @@
# Courseware Page Decisions
**See [0009-courseware-api-direction.md](0009-courseware-api-direction.md) for updates!**
## Courseware data loading
Today we have strictly hierarchical courses - a course contains sections, which contain sequences, which contain units, which contain components.
@@ -37,6 +39,9 @@ Today, if the URL only specifies the course ID, we need to pick a sequence to sh
Similarly, if the URL doesn't contain a unit ID, we use the `position` field of the sequence to determine which unit we want to display from that sequence. If the position isn't specified in the sequence, we choose the first unit of the sequence. After determining which unit to display, we update the URL to match. After the URL is updated, the application will attempt to load that unit via an iFrame.
_This URL scheme has been expanded upon in
[ADR #8: Liberal courseware path handling](./0008-liberal-courseware-path-handling.md)._
## "Container" components vs. display components
This application makes use of a few "container" components at the top level - CoursewareContainer and CourseHomeContainer.

View File

@@ -4,4 +4,6 @@ Because we have a variety of models in this app (course, section, sequence, unit
https://redux.js.org/faq/organizing-state#how-do-i-organize-nested-or-duplicate-data-in-my-state
(As an additional data point, djoy has stored data in this format in multiple projects over the years and found it to be very effective)
Different modules of the application maintain individual/lists of IDs that reference data stored in the model store. These are akin to indices in a database, in that they allow you to quickly extract data from the model store without iteration or filtering.
A common pattern when loading data from an API endpoint is to use the model-store's redux actions (addModel, updateModel, etc.) to load the "models" themselves into the model store by ID, and then dispatch another action to save references elsewhere in the redux store to the data that was just added. When adding courses, sequences, etc., to model-store, we also save the courseId and sequenceId in the 'courseware' part of redux. This means the courseware React Components can extract the data from the model-store quickly by using the courseId as a key: `state.models.courses[state.courseware.courseId]`. For an array, it iterates once over the ID list in order to extract the models from model-store. This iteration is done when React components' re-render, and can be done less often through memoization as necessary.

View File

@@ -0,0 +1,24 @@
# Naming API functions and redux thunks
Because API functions and redux thunks are two parts of a larger process, we've informally settled on some naming conventions for them to help differentiate the type of code we're looking at.
## API Functions
This micro-frontend follows a pattern of naming API functions with a prefix for their HTTP verb.
Examples:
`getCourseBlocks` - The GET request we make to load course blocks data.
`postSequencePosition` - The POST request for saving sequence position.
## Redux Thunks
Meanwhile, we use a different set of verbs for redux thunks to differentiate them from the API functions. For instance, we use the `fetch` prefix for loading data (primarily via GET requests), and `save` for sending data back to the server (primarily via POST or PATCH requests)
Examples:
`fetchCourse` - The thunk for getting course data across several APIs.
`fetchSequence` - The thunk for the process of retrieving sequence data.
`saveSequencePosition` - Wraps the POST request for sending sequence position back to the server.
The verb prefixes for thunks aren't perfect - but they're a little more 'friendly' and semantically meaningful than the HTTP verbs used for APIs. So far we have `fetch`, `save`, `check`, `reset`, etc.

View File

@@ -0,0 +1,66 @@
# Testing
## Status
Draft
Let's live with this a bit longer before deciding it's a solid approach and marking this Approved.
## Context
We'd like to all be on the same page about how to approach testing, what is
worth testing, and how to do it.
## React Testing Library
We'll use react-testing-library and jest as the main testing tools.
This has some implications about how to test. You can read the React Testing Library's
[Guiding Principles](https://testing-library.com/docs/guiding-principles), but the main
takeaway is that you should be interacting with React as closely as possible to the way
the user will interact with it.
For example, they discourage using class or element name selectors to find components
during a test. Instead, you should find them by user-oriented attributes like labels,
text, or roles. As a last resort, by a `data-testid` tag.
## Mocking data
We'll use [Rosie](https://github.com/rosiejs/rosie) as a tool for building JavaScript objects.
Our main use case for Rosie is to use factories in order to mock the data we'd like to fetch when rendering components.
[axios-mock-adapter](https://www.npmjs.com/package/axios-mock-adapter) allows us to mock the response of an HTTP request.
For example, we may use a factory to build a course metadata object:
`const courseMetadata = Factory.build('courseMetadata');`
Then we'd pass that `courseMetadata` object into an axios mock call:
`axiosMock.onGet('example.com').reply(200, courseMetadata);`
This way, when a component sends a GET request to `example.com` within the test's lifecycle, the request will be intercepted
by the axios-mock-adapter, and the courseMetadata object will be returned.
These factories should live within the data directories they intend to mock
```
courseware
| data
| __factories__
| courseMetadata.factory.js /* used to define the Rosie factory */
| api.js /* getCourseMetadata() lives here */
```
## What to Test
We have not found exhaustive unit testing of frontend code to be worth the trouble.
Rather, let's focus on testing non-obvious behavior.
In essence: `test behavior that wouldn't present itself to a developer playing around`.
Practically speaking, this means error states, interactive components, corner cases,
or anything that wouldn't come up in a demo course. Something a developer wouldn't
notice in the normal course of working in devstack.
## Snapshots
In practice, we've found snapshots of component trees to be too brittle to be worth it,
as refactors occur or external libraries change.
They can still be useful for data (like redux tests) or tiny isolated components.
But please avoid for any "interesting" component. Prefer inspecting the explicit behavior
under test, rather than just snapshotting the entire component tree.

View File

@@ -0,0 +1,90 @@
# Liberal courseware path handling
## Status
Accepted
_This updates some of the content in [ADR #2: Courseware page decisions](./0002-courseware-page-decisions.md)._
## Context
The courseware container currently accepts three path forms:
1. `/course/:courseId`
2. `/course/:courseId/:sequenceId`
3. `/course/:courseId/:sequenceId/:unitId`
Forms #1 and #2 are always redirected to Form #3 via simple set of rules:
* If the sequenceId is not specified, choose the first sequence in the course.
* If the unitId is not specified, choose the active unit in the sequence,
or the first unit if none are active.
Thus, Form #3 is effectively the canonoical path;
all Learning MFE units should be served from it.
We acknowledge that the best user experience is to link directly to the canonoical
path when possible, since it skips the redirection steps.
Still, there are times when it is necessary or prudent to link just to a course or
a sequence.
Through recent work in the LMS, we are realizing that there are _also_ times where it
would be simpler or more performant to link a user to an
_entire section without specifying a squence_ or to a
_unit without including the sequence_.
Specifically, this capability would let as avoid further modulestore or
block transformer queries in order to discern the course structure when trying to
direct a learner to a section or unit.
Futhermore, we hypothesize that being able to build a Learning MFE courseware link
with just a unit ID or a section ID will be a nice simplifying quality for future
development or debugging.
## Decision
The courseware container will accept five total path forms:
1. `/course/:courseId`
2. `/course/:courseId/:sectionId`
3. `/course/:courseId/:sectionId/:unitId`
4. `/course/:courseId/:sequenceId`
5. `/course/:courseId/:unitId`
6. `/course/:courseId/:sequenceId/:unitId`
The redirection rules are as follows:
* Forms #1 redirects to Form #4 by selecting the first sequence in the course.
* Form #2 redirects to Form #4 by selecting to the first sequence in the section.
* Form #3 redirects to Form #5 by dropping the section ID.
* Form #4 redirects to Form #6 by choosing the active unit in the sequence
(or the first unit, if none are active).
* Form #5 redirects to Form #6 by filling in the ID of the sequence that the
specified unit belongs to (in the edge case where the unit belongs to multiple
sequences, the first sequence is selected).
As before, Form #5 is the canonocial courseware path, which is always redirected to
by any of the other courseware path forms.
## Consequences
The above decision is implemented.
## Further work
At some point, we may decide to further extend the URL scheme to be
more human-readable.
We can't make UsageKeys themselves more readable because they're tied to student state,
but we could introduce a new optional `slug` field on Sequences,
which would be captured and propagated to the learning_sequences API.
We could eventually do something similar to Units, since those slugs only have to be sequence-local.
So eventually, URLs could look less like:
```
https://learning.edx.org/course/course-v1:edX+DemoX.1+2T2019/block-v1:edX+DemoX.1+2T2019+type@sequential+block@e0a61b3d5a2046949e76d12cac5df493/block-v1:edX+DemoX.1+2T2019+type@vertical+block@52dbad5a28e140f291a476f92ce11996
```
And more like:
```
https://learning.edx.org/course/course-v1:edX+DemoX.1+2T2019/Being_Social/Teams
```

View File

@@ -0,0 +1,62 @@
# Direction of Courseware APIs
In order to allow for greater flexibility and separation of concerns, we're going to stop using the Course Blocks API for navigational data, and pull that data from the Learning Sequences Outlines API instead. The intention is to give us four distinct layers of courseware that can eventually be composed in different ways:
* Learning Context Metadata
* Learning Context Navigation
* Sequence Navigation
* Unit Rendering
Note that "Learning Context" is a generalization of "Course" that includes other things like Content Libraries, Learning Pathways, and potentially other logical groupings of content.
This is a refinement of [0002-courseware-page-decisions.md](0002-courseware-page-decisions.md). The fundamental layers remain the same, but this document tries to better clarify the boundaries and path forward for these layers. We're not making these layers completely swappable/pluggable now, but we should separate the data access in a way that allows for that in the future.
## Background
We currently make four primary requests to the LMS when rendering courseware instructional content:
1. Course Metadata: `/api/courseware/course/{courseId}` (REST API)
2. Course Blocks API: `/api/courses/v2/blocks/?course_id={courseId}` (REST API)
3. Sequence Metadata: `/api/courseware/sequence/{sequenceUsageKey}` (REST API)
4. Unit: `/xblock/{unitBlockUsageKey}` (rendered in an iframe)
There is a significant amount of overlap between the Course Blocks API and the others at the moment, since Course Blocks takes a static snapshot of the entire tree of course content at once. There are a few problems with the current arrangement:
* It's slow and complex. The Course Blocks API can be difficult to maintain and reason about, and trickier to optimize.
* Assuming that all course structures are the same makes it difficult to support other content types, like LabXchange Learning Pathways or adaptive content.
* The overlap between Course Blocks and the other APIs means that there can be conflicts about the state.
## Motivating Vision
We have seen a desire to extend or enhance the courseware experience in various ways:
Learning Context Navigation
* Allowing for shorter, human-readable URLs in courseware.
* Smaller courses that do not need the current navigational hierarchy.
* LabXchange pathways.
Sequence Navigation
* Adaptive content, where the full list of units is not known up front.
* More limited navigation, where content is pushed linearly, without the ability to jump ahead.
* Different layouts for content browsing.
Unit Rendering
* Use of QTI content (currently serviced by cc2olx conversion).
* Desire to experiment with a next-gen version of XBlock.
* Use of entirely LTI units.
The idea would be to insulate each layer from the layers above and below it. Sequence rendering shouldn't be affected by whether or not it's in a two level hierarchy (Course → Section → Sequence), or a flat one (Course → Sequence). Learning Context Navigation should be able to reference Sequences without caring if a Sequence is an adaptive one or not. Sequences should be able to have a common interface to call Unit iframes, whether those Units are rendering XBlocks or QTI content.
Note that supporting these types of course structures would require downstream changes in other systems as well (e.g. analytics).
## Next Step: Removing use of the Course Blocks API.
The next step in this process is to remove the call to the Course Blocks API, and split its responsibilities across just the existing Learning Sequences Outline and Sequence Metadata APIs. This will involve at least a couple of steps.
### Complete rollout of Learning Sequences Outline calls.
We're currently in a transitional state between these APIs where the Learning Sequences Outline calls are only rolled out on a small handful of courses.
### Shift Sequence and Unit metadata to only come from Sequence Metadata API.
We currently pull this information from both Course Blocks and the Sequence Metadata API. We can consolidate on just the Sequence Metadata API. There is also server side optimization that can be done with the Sequence Metadata API calls as part of this work.

24
example.env.config.jsx Normal file
View File

@@ -0,0 +1,24 @@
import UnitTranslationPlugin from '@edx/unit-translation-selector-plugin';
import { PLUGIN_OPERATIONS, DIRECT_PLUGIN } from '@openedx/frontend-plugin-framework';
// Load environment variables from .env file
const config = {
...process.env,
pluginSlots: {
unit_title_plugin: {
plugins: [
{
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'unit_title_plugin',
type: DIRECT_PLUGIN,
priority: 1,
RenderWidget: UnitTranslationPlugin,
},
},
],
},
},
};
export default config;

4
global-setup.js Normal file
View File

@@ -0,0 +1,4 @@
// Force all tests to run in UTC to prevent tests from being sensitive to host timezone.
module.exports = async () => {
process.env.TZ = 'UTC';
};

View File

@@ -1,11 +1,43 @@
const { createConfig } = require('@edx/frontend-build');
const { createConfig } = require('@openedx/frontend-build');
module.exports = createConfig('jest', {
setupFiles: [
const config = createConfig('jest', {
setupFilesAfterEnv: [
'<rootDir>/src/setupTest.js',
],
coveragePathIgnorePatterns: [
'src/setupTest.js',
'src/i18n',
'src/.*\\.exp\\..*',
],
moduleNameMapper: {
// See https://stackoverflow.com/questions/72382316/jest-encountered-an-unexpected-token-react-markdown
'react-markdown': '<rootDir>/node_modules/react-markdown/react-markdown.min.js',
'@src/(.*)': '<rootDir>/src/$1',
// Explicit mapping to ensure Jest resolves the module correctly
'@edx/frontend-lib-special-exams': '<rootDir>/node_modules/@edx/frontend-lib-special-exams',
},
testTimeout: 30000,
globalSetup: "./global-setup.js",
verbose: true,
testEnvironment: 'jsdom',
});
// delete config.testURL;
config.reporters = [...(config.reporters || []), ["jest-console-group-reporter", {
// change this setting if need to see less details for each test
// reportType: "summary" | "details",
// enable: true | false,
afterEachTest: {
enable: true,
filePaths: false,
reportType: "details",
},
afterAllTests: {
reportType: "summary",
enable: true,
filePaths: true,
},
}]];
module.exports = config;

View File

@@ -1,10 +0,0 @@
# This file describes this Open edX repo, as described in OEP-2:
# https://open-edx-proposals.readthedocs.io/en/latest/oep-0002-bp-repo-metadata.html#specification
oeps: {}
owner: edx/platform-core-tnl
openedx-release:
# The openedx-release key is described in OEP-10:
# https://open-edx-proposals.readthedocs.io/en/latest/oep-0010-proc-openedx-releases.html
# The FAQ might also be helpful: https://openedx.atlassian.net/wiki/spaces/COMM/pages/1331268879/Open+edX+Release+FAQ
ref: master

41270
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,64 +4,95 @@
"description": "Frontend learning application.",
"repository": {
"type": "git",
"url": "git+https://github.com/edx/frontend-app-learning.git"
"url": "git+https://github.com/openedx/frontend-app-learning.git"
},
"browserslist": [
"last 2 versions",
"ie 11"
"extends @edx/browserslist-config"
],
"scripts": {
"build": "fedx-scripts webpack",
"i18n_extract": "BABEL_ENV=i18n fedx-scripts babel src --quiet > /dev/null",
"is-es5": "es-check es5 ./dist/*.js",
"lint": "fedx-scripts eslint --ext .js --ext .jsx .",
"snapshot": "fedx-scripts jest --updateSnapshot",
"bundlewatch": "bundlewatch",
"i18n_extract": "fedx-scripts formatjs extract",
"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 .",
"start": "fedx-scripts webpack-dev-server --progress",
"test": "fedx-scripts jest --coverage --passWithNoTests"
},
"husky": {
"hooks": {
"pre-commit": "npm run lint"
}
"start:with-theme": "paragon install-theme && npm start && npm install",
"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": "NODE_ENV=test fedx-scripts jest --coverage --passWithNoTests",
"test:watch": "fedx-scripts jest --watch --passWithNoTests",
"types": "tsc --noEmit"
},
"author": "edX",
"license": "AGPL-3.0",
"homepage": "https://github.com/edx/frontend-app-learning#readme",
"homepage": "https://github.com/openedx/frontend-app-learning#readme",
"publishConfig": {
"access": "public"
},
"bugs": {
"url": "https://github.com/edx/frontend-app-learning/issues"
"url": "https://github.com/openedx/frontend-app-learning/issues"
},
"dependencies": {
"@edx/frontend-component-footer": "^10.0.6",
"@edx/frontend-component-header": "^2.0.3",
"@edx/frontend-platform": "^1.3.1",
"@edx/paragon": "^7.2.1",
"@fortawesome/fontawesome-svg-core": "^1.2.26",
"@fortawesome/free-brands-svg-icons": "^5.12.0",
"@fortawesome/free-regular-svg-icons": "^5.12.0",
"@fortawesome/free-solid-svg-icons": "^5.12.0",
"@fortawesome/react-fontawesome": "^0.1.8",
"@reduxjs/toolkit": "^1.2.3",
"classnames": "^2.2.6",
"core-js": "^3.6.2",
"prop-types": "^15.7.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.1.3",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"redux": "^4.0.5",
"regenerator-runtime": "^0.13.3"
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
"@edx/browserslist-config": "1.5.0",
"@edx/frontend-component-footer": "^14.6.0",
"@edx/frontend-component-header": "^8.0.0",
"@edx/frontend-lib-learning-assistant": "^2.24.0",
"@edx/frontend-lib-special-exams": "^4.0.0",
"@edx/frontend-platform": "^8.4.0",
"@edx/openedx-atlas": "^0.7.0",
"@fortawesome/free-brands-svg-icons": "5.15.4",
"@fortawesome/free-regular-svg-icons": "5.15.4",
"@fortawesome/free-solid-svg-icons": "5.15.4",
"@fortawesome/react-fontawesome": "^0.1.4",
"@openedx/frontend-build": "^14.6.2",
"@openedx/frontend-plugin-framework": "^1.7.0",
"@openedx/paragon": "^23.4.5",
"@popperjs/core": "2.11.8",
"@reduxjs/toolkit": "1.9.7",
"buffer": "^6.0.3",
"classnames": "2.5.1",
"copy-webpack-plugin": "^12.0.0",
"joi": "^17.11.0",
"js-cookie": "3.0.5",
"lodash": "^4.17.21",
"lodash.camelcase": "4.3.0",
"postcss-loader": "^8.1.1",
"prop-types": "15.8.1",
"query-string": "^7.1.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-helmet": "6.1.0",
"react-redux": "7.2.9",
"react-router": "6.15.0",
"react-router-dom": "6.15.0",
"react-share": "4.4.1",
"redux": "4.2.1",
"reselect": "4.1.8",
"sass": "^1.79.3",
"sass-loader": "^16.0.2",
"source-map-loader": "^5.0.0",
"truncate-html": "1.0.4"
},
"devDependencies": {
"@edx/frontend-build": "^3.0.0",
"codecov": "^3.6.1",
"es-check": "^5.1.0",
"glob": "^7.1.6",
"husky": "^3.1.0",
"jest": "^24.9.0",
"reactifex": "^1.1.1"
"@pact-foundation/pact": "^13.0.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "14.6.1",
"axios-mock-adapter": "2.1.0",
"bundlewatch": "^0.4.0",
"eslint-import-resolver-webpack": "^0.13.9",
"jest": "^29.7.0",
"jest-console-group-reporter": "^1.1.1",
"jest-when": "^3.6.0",
"rosie": "2.1.1"
},
"bundlewatch": {
"files": [
{
"path": "dist/*.js",
"maxSize": "1450kB"
}
],
"normalizeFilenames": "^.+?(\\..+?)\\.\\w+$"
}
}

View File

@@ -1,10 +1,17 @@
<!doctype html>
<html lang="en-us">
<head>
<title>Course | edX</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<title>Course | <%= process.env.SITE_NAME %></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="<%=htmlWebpackPlugin.options.FAVICON_URL%>" type="image/x-icon" />
<% if (htmlWebpackPlugin.options.OPTIMIZELY_PROJECT_ID) { %>
<script src="https://www.edx.org/optimizelyjs/<%= htmlWebpackPlugin.options.OPTIMIZELY_PROJECT_ID %>.js"></script>
<% } %>
<% if (htmlWebpackPlugin.options.META_TAG_ROBOTS_CONTENT_ATTR) { %>
<meta name="robots" content="<%= htmlWebpackPlugin.options.META_TAG_ROBOTS_CONTENT_ATTR %>">
<% } %>
</head>
<body>
<div id="root"></div>

View File

@@ -0,0 +1,11 @@
body a {
color: #00688D;
}
body.inline-link a {
text-decoration: underline;
}
body.small {
font-size: 0.875rem;
}

View File

@@ -5,5 +5,12 @@
"patch": {
"automerge": true
},
"rebaseStalePrs": true
"rebaseStalePrs": true,
"packageRules": [
{
"matchPackagePatterns": ["@edx", "@openedx"],
"matchUpdateTypes": ["minor", "patch"],
"automerge": true
}
]
}

View File

@@ -1,36 +0,0 @@
import React from 'react';
import { Switch, Route, useRouteMatch } from 'react-router';
import { getConfig } from '@edx/frontend-platform';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import PageLoading from './PageLoading';
export default () => {
const { path } = useRouteMatch();
return (
<div className="flex-grow-1">
<PageLoading srMessage={(
<FormattedMessage
id="learn.redirect.interstitial.message"
description="The screen-reader message when a page is about to redirect"
defaultMessage="Redirecting..."
/>
)}
/>
<Switch>
<Route
path={`${path}/course-home/:courseId`}
render={({ match }) => {
global.location.assign(`${getConfig().LMS_BASE_URL}/courses/${match.params.courseId}/course/`);
}}
/>
<Route
path={`${path}/dashboard`}
render={({ location }) => {
global.location.assign(`${getConfig().LMS_BASE_URL}/dashboard${location.search}`);
}}
/>
</Switch>
</div>
);
};

View File

@@ -1,21 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Alert } from '../user-messages';
function AccessExpirationAlert(props) {
const {
rawHtml,
} = props;
return rawHtml && (
<Alert type="info">
<div dangerouslySetInnerHTML={{ __html: rawHtml }} />
</Alert>
);
}
AccessExpirationAlert.propTypes = {
rawHtml: PropTypes.string.isRequired,
};
export default AccessExpirationAlert;

View File

@@ -1,28 +0,0 @@
/* eslint-disable import/prefer-default-export */
import { useContext, useState, useEffect } from 'react';
import { UserMessagesContext } from '../user-messages';
import { useModel } from '../model-store';
export function useAccessExpirationAlert(courseId) {
const course = useModel('courses', courseId);
const { add, remove } = useContext(UserMessagesContext);
const [alertId, setAlertId] = useState(null);
const rawHtml = (course && course.courseExpiredMessage) || null;
useEffect(() => {
if (rawHtml && alertId === null) {
setAlertId(add({
code: 'clientAccessExpirationAlert',
topic: 'course',
rawHtml,
}));
} else if (!rawHtml && alertId !== null) {
remove(alertId);
setAlertId(null);
}
return () => {
if (alertId !== null) {
remove(alertId);
}
};
}, [alertId, courseId, rawHtml]);
}

View File

@@ -1,2 +0,0 @@
export { default as AccessExpirationAlert } from './AccessExpirationAlert';
export { useAccessExpirationAlert } from './hooks';

View File

@@ -0,0 +1,135 @@
import PropTypes from 'prop-types';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import { FormattedMessage, FormattedDate, useIntl } from '@edx/frontend-platform/i18n';
import { Alert, Hyperlink } from '@openedx/paragon';
import { Info } from '@openedx/paragon/icons';
import messages from './messages';
const AccessExpirationAlert = ({ payload }) => {
const intl = useIntl();
const {
accessExpiration,
courseId,
org,
userTimezone,
analyticsPageName,
} = payload;
const timezoneFormatArgs = userTimezone ? { timeZone: userTimezone } : {};
if (!accessExpiration) {
return null;
}
const {
expirationDate,
upgradeDeadline,
upgradeUrl,
} = accessExpiration;
const logClick = () => {
sendTrackEvent('edx.bi.ecommerce.upsell_links_clicked', {
org_key: org,
courserun_key: courseId,
linkCategory: 'FBE_banner',
linkName: `${analyticsPageName}_audit_access_expires`,
linkType: 'link',
pageName: analyticsPageName,
});
};
let deadlineMessage = null;
if (upgradeDeadline && upgradeUrl) {
deadlineMessage = (
<>
<br />
<FormattedMessage
id="learning.accessExpiration.deadline"
defaultMessage="Upgrade by {date} to get unlimited access to the course as long as it exists on the site."
description="Warning shown to learner to upgrade while they are enrolled on the audit version and it's possible to upgrade"
values={{
date: (
<FormattedDate
key="accessExpirationUpgradeDeadline"
day="numeric"
month="short"
year="numeric"
value={upgradeDeadline}
{...timezoneFormatArgs}
/>
),
}}
/>
&nbsp;
<Hyperlink
className="font-weight-bold"
style={{ textDecoration: 'underline' }}
destination={upgradeUrl}
onClick={logClick}
>
{intl.formatMessage(messages.upgradeNow)}
</Hyperlink>
</>
);
}
return (
<Alert variant="info" icon={Info}>
<span className="font-weight-bold">
<FormattedMessage
id="learning.accessExpiration.header"
defaultMessage="Audit Access Expires {date}"
description="Headline for auditing deadline"
values={{
date: (
<FormattedDate
key="accessExpirationHeaderDate"
day="numeric"
month="short"
year="numeric"
value={expirationDate}
{...timezoneFormatArgs}
/>
),
}}
/>
</span>
<br />
<FormattedMessage
id="learning.accessExpiration.body"
defaultMessage="You lose all access to this course, including your progress, on {date}."
description="Message body to tell learner the consequences of course expiration."
values={{
date: (
<FormattedDate
key="accessExpirationBodyDate"
day="numeric"
month="short"
year="numeric"
value={expirationDate}
{...timezoneFormatArgs}
/>
),
}}
/>
{deadlineMessage}
</Alert>
);
};
AccessExpirationAlert.propTypes = {
payload: PropTypes.shape({
accessExpiration: PropTypes.shape({
expirationDate: PropTypes.string.isRequired,
masqueradingExpiredCourse: PropTypes.bool.isRequired,
upgradeDeadline: PropTypes.string,
upgradeUrl: PropTypes.string,
}).isRequired,
courseId: PropTypes.string.isRequired,
org: PropTypes.string.isRequired,
userTimezone: PropTypes.string.isRequired,
analyticsPageName: PropTypes.string.isRequired,
}).isRequired,
};
export default AccessExpirationAlert;

View File

@@ -0,0 +1,39 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, FormattedDate } from '@edx/frontend-platform/i18n';
import { PageBanner } from '@openedx/paragon';
const AccessExpirationMasqueradeBanner = ({ payload }) => {
const {
expirationDate,
userTimezone,
} = payload;
const timezoneFormatArgs = userTimezone ? { timeZone: userTimezone } : {};
return (
<PageBanner variant="warning">
<FormattedMessage
id="instructorToolbar.pageBanner.courseHasExpired"
defaultMessage="This learner no longer has access to this course. Their access expired on {date}."
description="It's a warning that is shown to course author when being masqueraded as learner, while the course has expired for the real learner."
values={{
date: <FormattedDate
key="instructorToolbar.pageBanner.accessExpirationDate"
value={expirationDate}
{...timezoneFormatArgs}
/>,
}}
/>
</PageBanner>
);
};
AccessExpirationMasqueradeBanner.propTypes = {
payload: PropTypes.shape({
expirationDate: PropTypes.string.isRequired,
userTimezone: PropTypes.string.isRequired,
}).isRequired,
};
export default AccessExpirationMasqueradeBanner;

View File

@@ -0,0 +1,51 @@
import React, { useMemo } from 'react';
import { useAlert } from '../../generic/user-messages';
import { useModel } from '../../generic/model-store';
const AccessExpirationAlert = React.lazy(() => import('./AccessExpirationAlert'));
const AccessExpirationMasqueradeBanner = React.lazy(() => import('./AccessExpirationMasqueradeBanner'));
function useAccessExpirationAlert(accessExpiration, courseId, org, userTimezone, topic, analyticsPageName) {
const isVisible = accessExpiration && !accessExpiration.masqueradingExpiredCourse; // If it exists, show it.
const payload = useMemo(() => ({
accessExpiration,
courseId,
org,
userTimezone,
analyticsPageName,
}), [accessExpiration, analyticsPageName, courseId, org, userTimezone]);
useAlert(isVisible, {
code: 'clientAccessExpirationAlert',
payload,
topic,
});
return { clientAccessExpirationAlert: AccessExpirationAlert };
}
export function useAccessExpirationMasqueradeBanner(courseId, tab) {
const {
userTimezone,
} = useModel('courseHomeMeta', courseId);
const {
accessExpiration,
} = useModel(tab, courseId);
const isVisible = accessExpiration && accessExpiration.masqueradingExpiredCourse;
const expirationDate = accessExpiration && accessExpiration.expirationDate;
const payload = useMemo(() => ({
expirationDate,
userTimezone,
}), [expirationDate, userTimezone]);
useAlert(isVisible, {
code: 'clientAccessExpirationMasqueradeBanner',
payload,
topic: 'instructor-toolbar-alerts',
});
return { clientAccessExpirationMasqueradeBanner: AccessExpirationMasqueradeBanner };
}
export default useAccessExpirationAlert;

View File

@@ -0,0 +1 @@
export { default, useAccessExpirationMasqueradeBanner } from './hooks';

View File

@@ -0,0 +1,11 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
upgradeNow: {
id: 'learning.accessExpiration.upgradeNow',
defaultMessage: 'Upgrade now',
description: 'The anchor text for the upgrading link',
},
});
export default messages;

View File

@@ -0,0 +1,48 @@
import React from 'react';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import { Alert, Hyperlink } from '@openedx/paragon';
import { WarningFilled } from '@openedx/paragon/icons';
import { getConfig } from '@edx/frontend-platform';
import genericMessages from './messages';
const ActiveEnterpriseAlert = ({ payload }) => {
const intl = useIntl();
const { text, courseId } = payload;
const changeActiveEnterprise = (
<Hyperlink
style={{ textDecoration: 'underline' }}
destination={
`${getConfig().LMS_BASE_URL}/enterprise/select/active/?success_url=${encodeURIComponent(
`${global.location.origin}/course/${courseId}/home`,
)}`
}
>
{intl.formatMessage(genericMessages.changeActiveEnterpriseLowercase)}
</Hyperlink>
);
return (
<Alert variant="warning" icon={WarningFilled}>
{text}
<FormattedMessage
id="learning.activeEnterprise.alert"
description="Prompts the user to log-in with the correct enterprise to access the course content."
defaultMessage=" {changeActiveEnterprise}."
values={{
changeActiveEnterprise,
}}
/>
</Alert>
);
};
ActiveEnterpriseAlert.propTypes = {
payload: PropTypes.shape({
text: PropTypes.string,
courseId: PropTypes.string,
}).isRequired,
};
export default ActiveEnterpriseAlert;

View File

@@ -0,0 +1,25 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import {
initializeTestStore, render, screen,
} from '../../setupTest';
import ActiveEnterpriseAlert from './ActiveEnterpriseAlert';
describe('ActiveEnterpriseAlert', () => {
const mockData = {
payload: {
text: 'test message',
courseId: 'test-course-id',
},
};
beforeAll(async () => {
await initializeTestStore({ excludeFetchCourse: true, excludeFetchSequence: true });
});
it('Shows alert message and links', () => {
render(<ActiveEnterpriseAlert {...mockData} />);
expect(screen.getByRole('alert')).toBeInTheDocument();
expect(screen.getByText('test message', { exact: false })).toBeInTheDocument();
expect(screen.getByRole('link', { name: 'change enterprise now' })).toHaveAttribute('href', `${getConfig().LMS_BASE_URL}/enterprise/select/active/?success_url=http%3A%2F%2Flocalhost%2Fcourse%2Ftest-course-id%2Fhome`);
});
});

View File

@@ -0,0 +1,28 @@
import React, { useMemo } from 'react';
import { ALERT_TYPES, useAlert } from '../../generic/user-messages';
import { useModel } from '../../generic/model-store';
const ActiveEnterpriseAlert = React.lazy(() => import('./ActiveEnterpriseAlert'));
export default function useActiveEnterpriseAlert(courseId) {
const { courseAccess } = useModel('courseHomeMeta', courseId);
/**
* This alert should render if
* 1. course access code is incorrect_active_enterprise
*/
const isVisible = courseAccess && !courseAccess.hasAccess && courseAccess.errorCode === 'incorrect_active_enterprise';
const payload = useMemo(() => ({
text: courseAccess && courseAccess.userMessage,
courseId,
}), [courseAccess, courseId]);
useAlert(isVisible, {
code: 'clientActiveEnterpriseAlert',
topic: 'outline',
dismissible: false,
type: ALERT_TYPES.ERROR,
payload,
});
return { clientActiveEnterpriseAlert: ActiveEnterpriseAlert };
}

View File

@@ -0,0 +1,3 @@
import useActiveEnterpriseAlert from './hooks';
export default useActiveEnterpriseAlert;

View File

@@ -0,0 +1,11 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
changeActiveEnterpriseLowercase: {
id: 'learning.activeEnterprise.change.alert',
defaultMessage: 'change enterprise now',
description: 'Text in a link, prompting the user to change active enterprise. Used in learning.activeEnterprise.change.alert"',
},
});
export default messages;

View File

@@ -0,0 +1,105 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
FormattedDate,
FormattedMessage,
FormattedRelativeTime,
FormattedTime,
} from '@edx/frontend-platform/i18n';
import { Alert } from '@openedx/paragon';
import { Info } from '@openedx/paragon/icons';
import { useModel } from '../../generic/model-store';
const DAY_SEC = 24 * 60 * 60; // in seconds
const DAY_MS = DAY_SEC * 1000; // in ms
const YEAR_SEC = 365 * DAY_SEC; // in seconds
const CourseStartAlert = ({ payload }) => {
const {
courseId,
} = payload;
const {
start: startDate,
userTimezone,
} = useModel('courseHomeMeta', courseId);
const timezoneFormatArgs = userTimezone ? { timeZone: userTimezone } : {};
const delta = new Date(startDate) - new Date();
const timeRemaining = (
<FormattedRelativeTime
key="timeRemaining"
value={delta / 1000}
numeric="auto"
// 1 year interval to help auto format. It won't format without updateIntervalInSeconds.
updateIntervalInSeconds={YEAR_SEC}
{...timezoneFormatArgs}
/>
);
if (delta < DAY_MS) {
return (
<Alert variant="info" icon={Info}>
<FormattedMessage
id="learning.outline.alert.start.short"
defaultMessage="Course starts {timeRemaining} at {courseStartTime}."
description="Used when the time remaining is less than a day away."
values={{
courseStartTime: (
<FormattedTime
key="courseStartTime"
day="numeric"
month="short"
year="numeric"
timeZoneName="short"
value={startDate}
{...timezoneFormatArgs}
/>
),
timeRemaining,
}}
/>
</Alert>
);
}
return (
<Alert variant="info" icon={Info}>
<strong>
<FormattedMessage
id="learning.outline.alert.start.long"
defaultMessage="Course starts {timeRemaining} on {courseStartDate}."
description="Used when the time remaining is more than a day away."
values={{
courseStartDate: (
<FormattedDate
key="courseStartDate"
day="numeric"
month="short"
year="numeric"
value={startDate}
{...timezoneFormatArgs}
/>
),
timeRemaining,
}}
/>
</strong>
<br />
<FormattedMessage
id="learning.outline.alert.start.calendar"
defaultMessage="Dont forget to add a calendar reminder!"
description="It's just a recommendation for learners to set a reminder for the course starting date and is shown when the course starting date is more than a day. "
/>
</Alert>
);
};
CourseStartAlert.propTypes = {
payload: PropTypes.shape({
courseId: PropTypes.string,
}).isRequired,
};
export default CourseStartAlert;

View File

@@ -0,0 +1,44 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, FormattedDate } from '@edx/frontend-platform/i18n';
import { PageBanner } from '@openedx/paragon';
import { useModel } from '../../generic/model-store';
const CourseStartMasqueradeBanner = ({ payload }) => {
const {
courseId,
} = payload;
const {
start,
userTimezone,
} = useModel('courseHomeMeta', courseId);
const timezoneFormatArgs = userTimezone ? { timeZone: userTimezone } : {};
return (
<PageBanner variant="warning">
<FormattedMessage
id="instructorToolbar.pageBanner.courseHasNotStarted"
defaultMessage="This learner does not yet have access to this course. The course starts on {date}."
description="It's a warning that is shown to course author when being masqueraded as learner, while the course hasn't started for the real learner yet."
values={{
date: <FormattedDate
key="instructorToolbar.pageBanner.courseStartDate"
value={start}
{...timezoneFormatArgs}
/>,
}}
/>
</PageBanner>
);
};
CourseStartMasqueradeBanner.propTypes = {
payload: PropTypes.shape({
courseId: PropTypes.string.isRequired,
}).isRequired,
};
export default CourseStartMasqueradeBanner;

View File

@@ -0,0 +1,62 @@
import React, { useMemo } from 'react';
import { useAlert } from '../../generic/user-messages';
import { useModel } from '../../generic/model-store';
const CourseStartAlert = React.lazy(() => import('./CourseStartAlert'));
const CourseStartMasqueradeBanner = React.lazy(() => import('./CourseStartMasqueradeBanner'));
function IsStartDateInFuture(courseId) {
const {
start,
} = useModel('courseHomeMeta', courseId);
const today = new Date();
const startDate = new Date(start);
return startDate > today;
}
function useCourseStartAlert(courseId) {
const {
isEnrolled,
} = useModel('courseHomeMeta', courseId);
const isVisible = isEnrolled && IsStartDateInFuture(courseId);
const payload = useMemo(() => ({
courseId,
}), [courseId]);
useAlert(isVisible, {
code: 'clientCourseStartAlert',
payload,
topic: 'outline-course-alerts',
});
return {
clientCourseStartAlert: CourseStartAlert,
};
}
export function useCourseStartMasqueradeBanner(courseId, tab) {
const {
isMasquerading,
} = useModel('courseHomeMeta', courseId);
const isVisible = isMasquerading && tab === 'progress' && IsStartDateInFuture(courseId);
const payload = useMemo(() => ({
courseId,
}), [courseId]);
useAlert(isVisible, {
code: 'clientCourseStartMasqueradeBanner',
payload,
topic: 'instructor-toolbar-alerts',
});
return {
clientCourseStartMasqueradeBanner: CourseStartMasqueradeBanner,
};
}
export default useCourseStartAlert;

View File

@@ -0,0 +1 @@
export { default, useCourseStartMasqueradeBanner } from './hooks';

View File

@@ -0,0 +1,70 @@
import React from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import { Alert, Button } from '@openedx/paragon';
import { Info, WarningFilled } from '@openedx/paragon/icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faSpinner } from '@fortawesome/free-solid-svg-icons';
import { useModel } from '../../generic/model-store';
import messages from './messages';
import useEnrollClickHandler from './clickHook';
const EnrollmentAlert = ({ payload }) => {
const intl = useIntl();
const {
canEnroll,
courseId,
extraText,
isStaff,
} = payload;
const {
org,
} = useModel('courseHomeMeta', courseId);
const { enrollClickHandler, loading } = useEnrollClickHandler(
courseId,
org,
intl.formatMessage(messages.success),
);
let text = intl.formatMessage(messages.alert);
let type = 'warning';
let icon = WarningFilled;
if (isStaff) {
text = intl.formatMessage(messages.staffAlert);
type = 'info';
icon = Info;
} else if (extraText) {
text = `${text} ${extraText}`;
}
const button = canEnroll && (
<Button disabled={loading} variant="link" className="p-0 border-0 align-top mx-1" size="sm" style={{ textDecoration: 'underline' }} onClick={enrollClickHandler}>
{intl.formatMessage(messages.enrollNowSentence)}
</Button>
);
return (
<Alert variant={type} icon={icon}>
<div className="d-flex">
{text}
{button}
{loading && <FontAwesomeIcon icon={faSpinner} spin />}
</div>
</Alert>
);
};
EnrollmentAlert.propTypes = {
payload: PropTypes.shape({
canEnroll: PropTypes.bool,
courseId: PropTypes.string,
extraText: PropTypes.string,
isStaff: PropTypes.bool,
}).isRequired,
};
export default EnrollmentAlert;

View File

@@ -0,0 +1,35 @@
import { useContext, useState, useCallback } from 'react';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import { UserMessagesContext, ALERT_TYPES } from '../../generic/user-messages';
import { postCourseEnrollment } from './data/api';
// Separated into its own file to avoid a circular dependency inside this directory
function useEnrollClickHandler(courseId, orgId, successText) {
const [loading, setLoading] = useState(false);
const { addFlash } = useContext(UserMessagesContext);
const enrollClickHandler = useCallback(() => {
setLoading(true);
postCourseEnrollment(courseId).then(() => {
addFlash({
dismissible: true,
flash: true,
text: successText,
type: ALERT_TYPES.SUCCESS,
topic: 'course',
});
setLoading(false);
sendTrackEvent('edx.bi.user.course-home.enrollment', {
org_key: orgId,
courserun_key: courseId,
});
global.location.reload();
});
}, [addFlash, courseId, orgId, successText]);
return { enrollClickHandler, loading };
}
export default useEnrollClickHandler;

View File

@@ -0,0 +1,39 @@
/* eslint-disable import/prefer-default-export */
import React, {
useContext, useMemo,
} from 'react';
import { AppContext } from '@edx/frontend-platform/react';
import { useAlert } from '../../generic/user-messages';
import { useModel } from '../../generic/model-store';
const EnrollmentAlert = React.lazy(() => import('./EnrollmentAlert'));
export function useEnrollmentAlert(courseId) {
const { authenticatedUser } = useContext(AppContext);
const course = useModel('courseHomeMeta', courseId);
const outline = useModel('outline', courseId);
const enrolledUser = course && course.isEnrolled !== undefined && course.isEnrolled;
const privateOutline = outline && outline.courseBlocks && !outline.courseBlocks.courses;
/**
* This alert should render if
* 1. the user is not enrolled,
* 2. the user is authenticated, AND
* 3. the course is private.
*/
const isVisible = !enrolledUser && authenticatedUser !== null && privateOutline;
const payload = useMemo(() => ({
canEnroll: outline && outline.enrollAlert ? outline.enrollAlert.canEnroll : false,
courseId,
extraText: outline && outline.enrollAlert ? outline.enrollAlert.extraText : '',
isStaff: course && course.isStaff,
}), [course, courseId, outline]);
useAlert(isVisible, {
code: 'clientEnrollmentAlert',
payload,
topic: 'outline',
});
return { clientEnrollmentAlert: EnrollmentAlert };
}

View File

@@ -0,0 +1 @@
export { useEnrollmentAlert as default } from './hooks';

View File

@@ -1,22 +1,28 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
'learning.enrollment.alert': {
alert: {
id: 'learning.enrollment.alert',
defaultMessage: 'You must be enrolled in the course to see course content.',
description: 'Message shown to indicate that a user needs to enroll in a course prior to viewing the course content. Shown as part of an alert, along with a link to enroll.',
},
'learning.staff.enrollment.alert': {
staffAlert: {
id: 'learning.staff.enrollment.alert',
defaultMessage: 'You are viewing this course as staff, and are not enrolled.',
description: 'Message shown to indicate that a user is not enrolled, but is able to view a course anyway because they are staff. Shown as part of an alert, along with a link to enroll.',
},
'learning.enrollment.enroll.now': {
id: 'learning.enrollment.enroll.now',
defaultMessage: 'Enroll Now',
enrollNowInline: {
id: 'learning.enrollment.enrollNow.Inline',
defaultMessage: 'Enroll now',
description: 'A link prompting the user to click on it to enroll in the currently viewed course.'
+ 'This text is meant to be used at the beginning of a sentence (example: Enroll now to view course content.)',
},
enrollNowSentence: {
id: 'learning.enrollment.enrollNow.Sentence',
defaultMessage: 'Enroll now.',
description: 'A link prompting the user to click on it to enroll in the currently viewed course.',
},
'learning.enrollment.success': {
success: {
id: 'learning.enrollment.success',
defaultMessage: "You've successfully enrolled in this course!",
description: 'A message telling the user that their course enrollment was successful.',

View File

@@ -0,0 +1,127 @@
import React, { useState } from 'react';
import Cookies from 'js-cookie';
import { getConfig } from '@edx/frontend-platform';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import {
AlertModal,
Button,
Spinner,
Icon,
} from '@openedx/paragon';
import { Check, ArrowForward } from '@openedx/paragon/icons';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { sendActivationEmail } from '../../courseware/data';
import messages from './messages';
const AccountActivationAlert = () => {
const intl = useIntl();
const [showModal, setShowModal] = useState(false);
const [showSpinner, setShowSpinner] = useState(false);
const [showCheck, setShowCheck] = useState(false);
const handleOnClick = () => {
setShowSpinner(true);
setShowCheck(false);
sendActivationEmail().then(() => {
setShowSpinner(false);
setShowCheck(true);
});
};
const showAccountActivationAlert = Cookies.get('show-account-activation-popup');
if (showAccountActivationAlert !== undefined) {
Cookies.remove('show-account-activation-popup', { path: '/', domain: process.env.SESSION_COOKIE_DOMAIN });
// extra check to make sure cookie was removed before updating the state. Updating the state without removal
// of cookie would make it infinite rendering
if (Cookies.get('show-account-activation-popup') === undefined) {
setShowModal(true);
}
}
const button = (
<Button
variant="primary"
className=""
onClick={() => setShowModal(false)}
>
<FormattedMessage
id="account-activation.alert.button"
defaultMessage="Continue to {siteName}"
description="account activation alert continue button"
values={{
siteName: getConfig().SITE_NAME,
}}
/>
<Icon src={ArrowForward} className="ml-1 d-inline-block align-bottom" />
</Button>
);
const children = () => {
let bodyContent;
const message = (
<FormattedMessage
id="account-activation.alert.message"
defaultMessage="We sent an email to {boldEmail} with a link to activate your account. Cant find it? Check your spam folder or
{sendEmailTag}."
description="Message for account activation alert which is shown after the registration"
values={{
boldEmail: <b>{getAuthenticatedUser() && getAuthenticatedUser().email}</b>,
sendEmailTag: (
// eslint-disable-next-line jsx-a11y/anchor-is-valid
<a href="#" role="button" onClick={handleOnClick}>
<FormattedMessage
id="account-activation.resend.link"
defaultMessage="resend the email"
description="Message for resend link in account activation alert which is shown after the registration"
/>
</a>
),
}}
/>
);
bodyContent = (
<div>
{message}
</div>
);
if (!showCheck && showSpinner) {
bodyContent = (
<div>
{message}
<Spinner
animation="border"
variant="secondary"
style={{ height: '1.5rem', width: '1.5rem' }}
/>
</div>
);
}
if (showCheck && !showSpinner) {
bodyContent = (
<div>
{message}
<Icon
src={Check}
style={{ height: '1.7rem', width: '1.25rem' }}
className="text-success-500 d-inline-block position-fixed"
/>
</div>
);
}
return bodyContent;
};
return (
<AlertModal
isOpen={showModal}
title={intl.formatMessage(messages.accountActivationAlertTitle)}
footerNode={button}
onClose={() => ({})}
>
{children()}
</AlertModal>
);
};
export default AccountActivationAlert;

View File

@@ -0,0 +1,47 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import { getLoginRedirectUrl } from '@edx/frontend-platform/auth';
import { Alert, Hyperlink } from '@openedx/paragon';
import { WarningFilled } from '@openedx/paragon/icons';
import genericMessages from '../../generic/messages';
const LogistrationAlert = () => {
const intl = useIntl();
const signIn = (
<Hyperlink
style={{ textDecoration: 'underline' }}
destination={`${getLoginRedirectUrl(global.location.href)}`}
>
{intl.formatMessage(genericMessages.signInLowercase)}
</Hyperlink>
);
// TODO: Pull this registration URL building out into a function, like the login one above.
// This is complicated by the fact that we don't have a REGISTER_URL env variable available.
const register = (
<Hyperlink
style={{ textDecoration: 'underline' }}
destination={`${getConfig().LMS_BASE_URL}/register?next=${encodeURIComponent(global.location.href)}`}
>
{intl.formatMessage(genericMessages.registerLowercase)}
</Hyperlink>
);
return (
<Alert variant="warning" icon={WarningFilled}>
<FormattedMessage
id="learning.logistration.alert"
description="Prompts the user to sign in or register to see course content."
defaultMessage="To see course content, {signIn} or {register}."
values={{
signIn,
register,
}}
/>
</Alert>
);
};
export default LogistrationAlert;

View File

@@ -0,0 +1,28 @@
/* eslint-disable import/prefer-default-export */
import React, { useContext } from 'react';
import { AppContext } from '@edx/frontend-platform/react';
import { ALERT_TYPES, useAlert } from '../../generic/user-messages';
import { useModel } from '../../generic/model-store';
const LogistrationAlert = React.lazy(() => import('./LogistrationAlert'));
export function useLogistrationAlert(courseId) {
const { authenticatedUser } = useContext(AppContext);
const outline = useModel('outline', courseId);
const privateOutline = outline && outline.courseBlocks && !outline.courseBlocks.courses;
/**
* This alert should render if
* 1. the user is not authenticated, AND
* 2. the course is private.
*/
const isVisible = authenticatedUser === null && privateOutline;
useAlert(isVisible, {
code: 'clientLogistrationAlert',
topic: 'outline',
dismissible: false,
type: ALERT_TYPES.ERROR,
});
return { clientLogistrationAlert: LogistrationAlert };
}

View File

@@ -0,0 +1 @@
export { useLogistrationAlert as default } from './hooks';

View File

@@ -0,0 +1,11 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
accountActivationAlertTitle: {
id: 'account-activation.alert.title',
defaultMessage: 'Activate your account so you can log back in',
description: 'Title for account activation alert which is shown after the registration',
},
});
export default messages;

View File

@@ -0,0 +1,57 @@
import { useSelector } from 'react-redux';
import { useModel } from '../../generic/model-store';
import { ALERT_TYPES, useAlert } from '../../generic/user-messages';
import messages from './messages';
function useSequenceBannerTextAlert(sequenceId) {
const sequence = useModel('sequences', sequenceId);
const sequenceStatus = useSelector(state => state.courseware.sequenceStatus);
// Show Alert that comes along with the sequence
useAlert(sequenceStatus === 'loaded' && sequence.bannerText, {
code: null,
dismissible: false,
text: sequence.bannerText,
type: ALERT_TYPES.INFO,
topic: 'sequence',
});
}
function useSequenceEntranceExamAlert(courseId, sequenceId, intl) {
const course = useModel('coursewareMeta', courseId);
const sequence = useModel('sequences', sequenceId);
const sequenceStatus = useSelector(state => state.courseware.sequenceStatus);
const {
entranceExamCurrentScore,
entranceExamEnabled,
entranceExamId,
entranceExamMinimumScorePct,
entranceExamPassed,
} = course.entranceExamData || {};
const entranceExamAlertVisible = sequenceStatus === 'loaded' && entranceExamEnabled && entranceExamId === sequence.sectionId;
let entranceExamText;
if (entranceExamPassed) {
entranceExamText = intl.formatMessage(
messages.entranceExamTextPassed,
{ entranceExamCurrentScore: entranceExamCurrentScore * 100 },
);
} else {
entranceExamText = intl.formatMessage(messages.entranceExamTextNotPassing, {
entranceExamCurrentScore: entranceExamCurrentScore * 100,
entranceExamMinimumScorePct: entranceExamMinimumScorePct * 100,
});
}
useAlert(entranceExamAlertVisible, {
code: null,
dismissible: false,
text: entranceExamText,
type: ALERT_TYPES.INFO,
topic: 'sequence',
});
}
export { useSequenceBannerTextAlert, useSequenceEntranceExamAlert };

View File

@@ -0,0 +1,14 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
entranceExamTextNotPassing: {
id: 'learn.sequence.entranceExamTextNotPassing',
defaultMessage: 'To access course materials, you must score {entranceExamMinimumScorePct}% or higher on this exam. Your current score is {entranceExamCurrentScore}%.',
},
entranceExamTextPassed: {
id: 'learn.sequence.entranceExamTextPassed',
defaultMessage: 'Your score is {entranceExamCurrentScore}%. You have passed the entrance exam.',
},
});
export default messages;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

74
src/constants.ts Normal file
View File

@@ -0,0 +1,74 @@
export const DECODE_ROUTES = {
ACCESS_DENIED: '/course/:courseId/access-denied',
HOME: '/course/:courseId/home',
LIVE: '/course/:courseId/live',
DATES: '/course/:courseId/dates',
DISCUSSION: '/course/:courseId/discussion/:path/*',
PROGRESS: [
'/course/:courseId/progress/:targetUserId/',
'/course/:courseId/progress',
],
COURSE_END: '/course/:courseId/course-end',
COURSEWARE: [
'/course/:courseId/:sequenceId/:unitId',
'/course/:courseId/:sequenceId',
'/course/:courseId',
'/preview/course/:courseId/:sequenceId/:unitId',
'/preview/course/:courseId/:sequenceId',
],
REDIRECT_HOME: 'home/:courseId',
REDIRECT_SURVEY: 'survey/:courseId',
} as const satisfies Readonly<{ [k: string]: string | readonly string[] }>;
export const ROUTES = {
UNSUBSCRIBE: '/goal-unsubscribe/:token',
PREFERENCES_UNSUBSCRIBE: '/preferences-unsubscribe/:userToken/:updatePatch?',
REDIRECT: '/redirect/*',
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',
ENTERPRISE_LEARNER_DASHBOARD_REDIRECT: 'enterprise-learner-dashboard-redirect',
CONSENT_REDIRECT: 'consent-redirect',
HOME_REDIRECT: 'home-redirect',
SURVEY_REDIRECT: 'survey-redirect',
} as const satisfies Readonly<{ [k: string]: string }>;
export const VERIFIED_MODES = [
'professional',
'verified',
'no-id-professional',
'credit',
'masters',
'executive-education',
'paid-executive-education',
'paid-bootcamp',
] as const satisfies readonly string[];
export const AUDIT_MODES = [
'audit',
'honor',
'unpaid-executive-education',
'unpaid-bootcamp',
] as const satisfies readonly string[];
// In sync with CourseMode.UPSELL_TO_VERIFIED_MODES
// https://github.com/openedx/edx-platform/blob/master/common/djangoapps/course_modes/models.py#L231
export const ALLOW_UPSELL_MODES = [
'audit',
'honor',
] 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;

View File

@@ -1,51 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import classNames from 'classnames';
import messages from './messages';
import Tabs from '../tabs/Tabs';
function CourseTabsNavigation({
activeTabSlug, className, tabs, intl,
}) {
return (
<div className={classNames('course-tabs-navigation', className)}>
<div className="container-fluid">
<Tabs
className="nav-underline-tabs"
aria-label={intl.formatMessage(messages['learn.navigation.course.tabs.label'])}
>
{tabs.map(({ url, title, slug }) => (
<a
key={slug}
className={classNames('nav-item flex-shrink-0 nav-link', { active: slug === activeTabSlug })}
href={url}
>
{title}
</a>
))}
</Tabs>
</div>
</div>
);
}
CourseTabsNavigation.propTypes = {
activeTabSlug: PropTypes.string,
className: PropTypes.string,
tabs: PropTypes.arrayOf(PropTypes.shape({
title: PropTypes.string.isRequired,
priority: PropTypes.number.isRequired,
slug: PropTypes.string.isRequired,
url: PropTypes.string.isRequired,
})).isRequired,
intl: intlShape.isRequired,
};
CourseTabsNavigation.defaultProps = {
activeTabSlug: undefined,
className: null,
};
export default injectIntl(CourseTabsNavigation);

View File

@@ -1,80 +0,0 @@
import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { Dropdown } from '@edx/paragon';
import { getConfig } from '@edx/frontend-platform';
import { AppContext } from '@edx/frontend-platform/react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faUserCircle } from '@fortawesome/free-solid-svg-icons';
import logo from './assets/logo.svg';
function LinkedLogo({
href,
src,
alt,
...attributes
}) {
return (
<a href={href} {...attributes}>
<img className="d-block" src={src} alt={alt} />
</a>
);
}
LinkedLogo.propTypes = {
href: PropTypes.string.isRequired,
src: PropTypes.string.isRequired,
alt: PropTypes.string.isRequired,
};
export default function Header({
courseOrg, courseNumber, courseTitle,
}) {
const { authenticatedUser } = useContext(AppContext);
return (
<header className="course-header">
<div className="container-fluid py-2 d-flex align-items-center ">
<LinkedLogo
className="logo"
href={`${getConfig().LMS_BASE_URL}/dashboard`}
src={logo}
alt={getConfig().SITE_NAME}
/>
<div className="flex-grow-1 course-title-lockup" style={{ lineHeight: 1 }}>
<span className="d-block small m-0">{courseOrg} {courseNumber}</span>
<span className="d-block m-0 font-weight-bold course-title">{courseTitle}</span>
</div>
<Dropdown className="user-dropdown">
<Dropdown.Button>
<FontAwesomeIcon icon={faUserCircle} className="d-md-none" size="lg" />
<span className="d-none d-md-inline">
{authenticatedUser.username}
</span>
</Dropdown.Button>
<Dropdown.Menu className="dropdown-menu-right">
<Dropdown.Item href={`${getConfig().LMS_BASE_URL}/dashboard`}>Dashboard</Dropdown.Item>
<Dropdown.Item href={`${getConfig().LMS_BASE_URL}/u/${authenticatedUser.username}`}>Profile</Dropdown.Item>
<Dropdown.Item href={`${getConfig().LMS_BASE_URL}/account/settings`}>Account</Dropdown.Item>
<Dropdown.Item href={getConfig().ORDER_HISTORY_URL}>Order History</Dropdown.Item>
<Dropdown.Item href={getConfig().LOGOUT_URL}>Sign Out</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</div>
</header>
);
}
Header.propTypes = {
courseOrg: PropTypes.string,
courseNumber: PropTypes.string,
courseTitle: PropTypes.string,
};
Header.defaultProps = {
courseOrg: null,
courseNumber: null,
courseTitle: null,
};

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1168px" height="540px" viewBox="0 0 1168 540" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 53.2 (72643) - https://sketchapp.com -->
<title>logo</title>
<desc>Created with Sketch.</desc>
<g id="logo" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<polygon id="Path" fill="#209FDA" fill-rule="nonzero" points="1166.81993 85.5 1166.81993 2.84217094e-14 953.759925 2.84217094e-14 953.759925 85.5 1002.17993 85.5 915.859925 191.98 829.459925 85.5 878.099925 85.5 878.099925 2.84217094e-14 718.919925 2.84217094e-14 718.919925 95.72 856.479925 265.26 718.919925 434.96 718.919925 452.02 784.499925 452.02 784.499925 539.64 878.099925 539.64 878.099925 452.02 823.919925 452.02 915.919925 338.52 915.939925 338.52 1008.03993 452.02 953.759925 452.02 953.759925 539.64 1166.81993 539.64 1166.81993 452.02 1126.85993 452.02 975.319925 265.26 1121.01993 85.5"></polygon>
<polygon id="Path" fill="#026BA4" fill-rule="nonzero" points="664.019925 7.10542736e-15 664.019925 85.5 710.619925 85.5 718.919925 95.72 718.919925 7.10542736e-15"></polygon>
<polygon id="Path" fill="#026BA4" fill-rule="nonzero" points="718.919925 452.02 718.919925 434.96 705.079925 452.02 664.019925 452.02 664.019925 539.64 784.499925 539.64 784.499925 452.02"></polygon>
<path d="M321.999925,411.86 L397.659925,411.86 C388.805702,433.829527 376.258024,454.122269 360.559925,471.86 C344.364089,454.216816 331.320914,433.921419 321.999925,411.86" id="Path" fill="#78212E" fill-rule="nonzero"></path>
<path d="M360.559925,189.28 C338.58337,213.190393 322.501981,241.908137 313.599925,273.14 C317.134915,280.039338 320.007771,287.25831 322.179925,294.7 L397.059925,294.7 C399.306706,287.354671 402.25356,280.242036 405.859925,273.46 C397.464721,242.277678 381.959326,213.464341 360.559925,189.28 Z M322.179925,294.7 C328.784599,317.438017 328.978396,341.558795 322.739925,364.4 L396.399925,364.4 C389.855554,341.597488 390.06397,317.386469 396.999925,294.7 L322.179925,294.7 Z M322.179925,294.7 L308.679925,294.7 C304.690779,317.752715 304.575868,341.309464 308.339925,364.4 L322.739925,364.4 C328.978396,341.558795 328.784599,317.438017 322.179925,294.7 L322.179925,294.7 Z" id="Shape" fill="#78212E" fill-rule="nonzero"></path>
<path d="M710.619925,85.5 L664.019925,85.5 L664.019925,0.02 L576.019925,0.02 L576.019925,85.5 L632.859925,85.5 L632.859925,159.2 C598.417874,134.487772 557.04992,121.286425 514.659925,121.48 C456.044663,121.405246 400.107354,146.01621 360.559925,189.28 C381.937732,213.470272 397.422343,242.283149 405.799925,273.46 C426.944121,233.500977 468.451514,208.51034 513.659925,208.52 C581.059925,208.52 632.879925,263.16 632.879925,330.52 L632.879925,331.2 C632.539925,398.28 580.879925,452.56 513.659925,452.56 C468.477451,452.593197 426.976426,427.652566 405.799925,387.74 L405.799925,387.74 C401.869213,380.340239 398.718926,372.551658 396.399925,364.5 L308.399925,364.5 C309.686934,372.450225 311.443338,380.317312 313.659925,388.06 C315.970162,396.190434 318.775397,404.171995 322.059925,411.96 L397.659925,411.96 C388.805702,433.929527 376.258024,454.222269 360.559925,471.96 C400.107354,515.22379 456.044663,539.834754 514.659925,539.76 C571.465111,540.091874 625.745998,516.316729 664.019925,474.34 L664.019925,452.04 L705.059925,452.04 L718.899925,434.96 L718.899925,95.74 L710.619925,85.5 Z M632.879925,501.9 L632.879925,539.74 L664.019925,539.74 L664.019925,474.18 C654.623775,484.469293 644.18821,493.758755 632.879925,501.9 L632.879925,501.9 Z M313.599925,273.14 C311.569597,280.231983 309.927163,287.429316 308.679925,294.7 L322.179925,294.7 C320.007771,287.25831 317.134915,280.039338 313.599925,273.14 L313.599925,273.14 Z" id="Shape" fill="#8A8C8F" fill-rule="nonzero"></path>
<path d="M410.399925,294.7 C409.199925,287.5 407.659925,280.4 405.799925,273.46 C402.19356,280.242036 399.246706,287.354671 396.999925,294.7 C390.06397,317.386469 389.855554,341.597488 396.399925,364.4 L410.719925,364.4 C414.264276,341.293291 414.156293,317.77319 410.399925,294.7 L410.399925,294.7 Z M209.059925,121.48 C107.422724,121.487508 20.5081632,194.571683 3.05992537,294.7 L91.3999254,294.7 C107.135726,243.467257 154.465065,208.503753 208.059925,208.52 C252.638644,208.335148 293.496156,233.351373 313.599925,273.14 C322.501981,241.908137 338.58337,213.190393 360.559925,189.28 C322.206855,145.880863 266.976617,121.163964 209.059925,121.48 L209.059925,121.48 Z M297.479925,411.86 C275.077969,437.877726 242.392659,452.761934 208.059925,452.58 C153.691226,452.598435 105.87164,416.63791 90.7999254,364.4 L308.339925,364.4 C304.575868,341.309464 304.690779,317.752715 308.679925,294.7 L3.05992537,294.7 C-0.902504563,317.755068 -1.01739385,341.307372 2.71992537,364.4 L2.71992537,364.4 C19.3292424,465.441984 106.661918,539.594765 209.059925,539.6 C266.986094,539.900862 322.217868,515.161403 360.559925,471.74 C344.364089,454.096816 331.320914,433.801419 321.999925,411.74 L297.479925,411.86 Z" id="Shape" fill="#B72768" fill-rule="nonzero"></path>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -1,41 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
export default function CourseDates({
start,
end,
enrollmentStart,
enrollmentEnd,
enrollmentMode,
isEnrolled,
}) {
return (
<section>
<h4>Upcoming Dates</h4>
<div><strong>Course Start:</strong><br />{start}</div>
<div><strong>Course End:</strong><br />{end}</div>
<div><strong>Enrollment Start:</strong><br />{enrollmentStart}</div>
<div><strong>Enrollment End:</strong><br />{enrollmentEnd}</div>
<div><strong>Mode:</strong><br />{enrollmentMode}</div>
<div>{isEnrolled ? 'Active Enrollment' : 'Inactive Enrollment'}</div>
</section>
);
}
CourseDates.propTypes = {
start: PropTypes.string,
end: PropTypes.string,
enrollmentStart: PropTypes.string,
enrollmentEnd: PropTypes.string,
enrollmentMode: PropTypes.string,
isEnrolled: PropTypes.bool,
};
CourseDates.defaultProps = {
start: null,
end: null,
enrollmentStart: null,
enrollmentEnd: null,
enrollmentMode: null,
isEnrolled: false,
};

View File

@@ -1,72 +0,0 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { Button } from '@edx/paragon';
import { AlertList } from '../user-messages';
import CourseDates from './CourseDates';
import Section from './Section';
import { useModel } from '../model-store';
// Note that we import from the component files themselves in the enrollment-alert package.
// This is because Reacy.lazy() requires that we import() from a file with a Component as it's
// default export.
// See React.lazy docs here: https://reactjs.org/docs/code-splitting.html#reactlazy
const { EnrollmentAlert, StaffEnrollmentAlert } = React.lazy(() => import('../enrollment-alert'));
const LogistrationAlert = React.lazy(() => import('../logistration-alert'));
export default function CourseHome() {
const {
courseId,
} = useSelector(state => state.courseware);
const {
title,
start,
end,
enrollmentStart,
enrollmentEnd,
enrollmentMode,
isEnrolled,
sectionIds,
} = useModel('courses', courseId);
return (
<>
<AlertList
topic="outline"
className="mb-3"
customAlerts={{
clientEnrollmentAlert: EnrollmentAlert,
clientStaffEnrollmentAlert: StaffEnrollmentAlert,
clientLogistrationAlert: LogistrationAlert,
}}
/>
<div className="d-flex justify-content-between mb-3">
<h2>{title}</h2>
<Button className="btn-primary" type="button">Resume Course</Button>
</div>
<div className="row">
<div className="col col-8">
{sectionIds.map((sectionId) => (
<Section
key={sectionId}
id={sectionId}
courseId={courseId}
/>
))}
</div>
<div className="col col-4">
<CourseDates
start={start}
end={end}
enrollmentStart={enrollmentStart}
enrollmentEnd={enrollmentEnd}
enrollmentMode={enrollmentMode}
isEnrolled={isEnrolled}
/>
</div>
</div>
</>
);
}

View File

@@ -1,44 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Collapsible } from '@edx/paragon';
import { faChevronRight, faChevronDown } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import SequenceLink from './SequenceLink';
import { useModel } from '../model-store';
export default function Section({ id, courseId }) {
const section = useModel('sections', id);
const { title, sequenceIds } = section;
return (
<Collapsible.Advanced className="collapsible-card mb-2">
<Collapsible.Trigger className="collapsible-trigger d-flex align-items-start">
<Collapsible.Visible whenClosed>
<div style={{ minWidth: '1rem' }}>
<FontAwesomeIcon icon={faChevronRight} />
</div>
</Collapsible.Visible>
<Collapsible.Visible whenOpen>
<div style={{ minWidth: '1rem' }}>
<FontAwesomeIcon icon={faChevronDown} />
</div>
</Collapsible.Visible>
<div className="ml-2 flex-grow-1">{title}</div>
</Collapsible.Trigger>
<Collapsible.Body className="collapsible-body">
{sequenceIds.map((sequenceId) => (
<SequenceLink
key={sequenceId}
id={sequenceId}
courseId={courseId}
/>
))}
</Collapsible.Body>
</Collapsible.Advanced>
);
}
Section.propTypes = {
id: PropTypes.string.isRequired,
courseId: PropTypes.string.isRequired,
};

View File

@@ -1,18 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { useModel } from '../model-store';
export default function SequenceLink({ id, courseId }) {
const sequence = useModel('sequences', id);
return (
<div className="ml-4">
<Link to={`/course/${courseId}/${id}`}>{sequence.title}</Link>
</div>
);
}
SequenceLink.propTypes = {
id: PropTypes.string.isRequired,
courseId: PropTypes.string.isRequired,
};

View File

@@ -0,0 +1,77 @@
import React, { useMemo } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Tabs, Tab } from '@openedx/paragon';
import { useParams } from 'react-router';
import CoursewareSearchResults from './CoursewareSearchResults';
import messages from './messages';
import { useCoursewareSearchParams } from './hooks';
import { useModel } from '../../generic/model-store';
const filterAll = 'all';
const filterTypes = ['text', 'video', 'sequence'];
const filterOther = 'other';
const validFilters = [filterAll, ...filterTypes, filterOther];
export const CoursewareSearchResultsFilter = () => {
const intl = useIntl();
const { courseId } = useParams();
const lastSearch = useModel('contentSearchResults', courseId);
const { filter: filterKeyword, setFilter } = useCoursewareSearchParams();
if (!lastSearch) { return null; }
const { results: data = [] } = lastSearch;
// If there's no data, we show an empty result.
if (!data.length) { return <CoursewareSearchResults />; }
const results = useMemo(() => {
// This reducer distributes the data into different groups to make it easy to
// use on the filters.
// All results are added to the "all" key and then to its proper group key as well.
const grouped = data.reduce((acc, { type, ...rest }) => {
const resultType = filterTypes.includes(type) ? type : filterOther;
acc[filterAll].push({ type: resultType, ...rest });
acc[resultType] = [...(acc[resultType] || []), { type: resultType, ...rest }];
return acc;
}, { [filterAll]: [] });
// This is just to format the output object with the expected tab order.
const output = {};
validFilters.forEach(key => { if (grouped[key]) { output[key] = grouped[key]; } });
return output;
}, [lastSearch]);
const tabKeys = Object.keys(results);
// Filter has no use if it has only 2 tabs (The "all" tab and another one with the same items).
if (tabKeys.length < 3) { return <CoursewareSearchResults results={results[filterAll]} />; }
const filters = useMemo(() => tabKeys.map((key) => ({
key,
label: intl.formatMessage(messages[`filter:${key}`]),
count: results[key].length,
})), [results]);
const activeKey = validFilters.includes(filterKeyword) ? filterKeyword : filterAll;
return (
<Tabs
id="courseware-search-results-tabs"
className="courseware-search-results-tabs"
data-testid="courseware-search-results-tabs"
variant="tabs"
activeKey={activeKey}
onSelect={setFilter}
>
{filters.filter(({ count }) => (count > 0)).map(({ key, label }) => (
<Tab key={key} eventKey={key} title={label} data-testid={`courseware-search-results-tabs-${key}`}>
<CoursewareSearchResults results={results[key]} />
</Tab>
))}
</Tabs>
);
};
export default CoursewareSearchResultsFilter;

View File

@@ -0,0 +1,132 @@
import React from 'react';
import { AppProvider } from '@edx/frontend-platform/react';
import { Route, Routes } from 'react-router-dom';
import { history } from '@edx/frontend-platform';
import {
initializeMockApp,
render,
screen,
waitFor,
} from '../../setupTest';
import { CoursewareSearchResultsFilter } from './CoursewareResultsFilter';
import { useCoursewareSearchParams } from './hooks';
import initializeStore from '../../store';
import { useModel } from '../../generic/model-store';
import searchResultsFactory from './test-data/search-results-factory';
jest.mock('./hooks');
jest.mock('../../generic/model-store', () => ({
useModel: jest.fn(),
}));
global.ResizeObserver = jest.fn().mockImplementation(() => ({
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
}));
const decodedCourseId = 'course-v1:edX+DemoX+Demo_Course';
const decodedSequenceId = 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@edx_introduction';
const decodedUnitId = 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_0270f6de40fc';
const pathname = `/course/${decodedCourseId}/${decodedSequenceId}/${decodedUnitId}`;
const intl = {
formatMessage: (message) => message?.defaultMessage || '',
};
const coursewareSearch = {
query: '',
filter: '',
setQuery: jest.fn(),
setFilter: jest.fn(),
clearSearchParams: jest.fn(),
};
function renderComponent(props = {}) {
const store = initializeStore();
history.push(pathname);
const { container } = render(
<AppProvider store={store}>
<Routes>
<Route path="/course/:courseId/:sequenceId/:unitId" element={<CoursewareSearchResultsFilter intl={intl} {...props} />} />
</Routes>
</AppProvider>,
);
return container;
}
describe('CoursewareSearchResultsFilter', () => {
beforeAll(initializeMockApp);
beforeEach(() => {
useCoursewareSearchParams.mockReturnValue(coursewareSearch);
});
afterEach(() => {
jest.clearAllMocks();
});
describe('when returning full results', () => {
beforeEach(() => {
useModel.mockReturnValue(searchResultsFactory());
renderComponent();
});
it('should render without errors', async () => {
await waitFor(() => {
expect(useCoursewareSearchParams).toBeCalled();
});
expect(screen.queryByTestId('courseware-search-results-tabs')).toBeInTheDocument();
expect(screen.queryByTestId('courseware-search-results-tabs-all')).toBeInTheDocument();
expect(screen.queryByTestId('courseware-search-results-tabs-text')).toBeInTheDocument();
expect(screen.queryByTestId('courseware-search-results-tabs-video')).toBeInTheDocument();
expect(screen.queryByTestId('courseware-search-results-tabs-sequence')).toBeInTheDocument();
expect(screen.queryByTestId('courseware-search-results-tabs-other')).toBeInTheDocument();
});
});
describe('when returning only one result type', () => {
beforeEach(async () => {
// Get results for only videos
const data = searchResultsFactory();
const onlyVideos = data.results.filter(({ type }) => type === 'video');
const filteredResults = {
...data,
results: onlyVideos,
};
useModel.mockReturnValue(filteredResults);
await renderComponent();
});
it('should not render', async () => {
await waitFor(() => {
expect(useCoursewareSearchParams).toBeCalled();
});
expect(screen.queryByTestId('courseware-search-results-tabs')).not.toBeInTheDocument();
});
});
describe('when there are not results', () => {
beforeEach(async () => {
useModel.mockReturnValue(searchResultsFactory('blah', {
results: [],
filters: [],
total: 0,
maxScore: null,
ms: 5,
}));
await renderComponent();
});
it('should not render', async () => {
await waitFor(() => {
expect(useCoursewareSearchParams).toBeCalled();
});
expect(screen.queryByTestId('courseware-search-results-tabs')).not.toBeInTheDocument();
});
});
});

View File

@@ -0,0 +1,176 @@
import React, { useEffect, useRef } from 'react';
import { useParams } from 'react-router';
import { useDispatch } from 'react-redux';
import { sendTrackingLogEvent } from '@edx/frontend-platform/analytics';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
Alert, Button, Icon, Spinner,
} from '@openedx/paragon';
import {
Close,
} from '@openedx/paragon/icons';
import { setShowSearch } from '../data/slice';
import { useCoursewareSearchParams, useElementBoundingBox, useLockScroll } from './hooks';
import messages from './messages';
import CoursewareSearchForm from './CoursewareSearchForm';
import CoursewareSearchResultsFilterContainer from './CoursewareResultsFilter';
import { updateModel, useModel } from '../../generic/model-store';
import { searchCourseContent } from '../data/thunks';
const CoursewareSearch = ({ ...sectionProps }) => {
const { formatMessage } = useIntl();
const { courseId } = useParams();
const { query: searchKeyword, setQuery, clearSearchParams } = useCoursewareSearchParams();
const dispatch = useDispatch();
const { org } = useModel('courseHomeMeta', courseId);
const {
loading,
searchKeyword: lastSearchKeyword,
errors,
total,
} = useModel('contentSearchResults', courseId);
const dialogRef = useRef();
useLockScroll();
const info = useElementBoundingBox('courseTabsNavigation');
const top = info ? `${Math.floor(info.top)}px` : 0;
const clearSearch = () => {
clearSearchParams();
dispatch(updateModel({
modelType: 'contentSearchResults',
model: {
id: courseId,
searchKeyword: '',
results: [],
errors: undefined,
loading:
false,
},
}));
};
const handleSubmit = (value) => {
if (!value) {
clearSearch();
return;
}
sendTrackingLogEvent('edx.course.home.courseware_search.submit', {
org_key: org,
courserun_key: courseId,
event_type: 'searchKeyword',
keyword: value,
});
dispatch(searchCourseContent(courseId, value));
setQuery(value);
};
const handleOnChange = (value) => {
if (value === searchKeyword) { return; }
if (!value) { clearSearch(); }
};
const close = () => {
clearSearch();
dispatch(setShowSearch(false));
};
const handlePopState = () => close();
const handleBackdropClick = function (event) {
if (event.target === dialogRef.current) {
dialogRef.current.close();
}
};
useEffect(() => {
// We need this to keep the dialog reference when unmounting.
const dialog = dialogRef.current;
// Open the dialog as a modal on render to confine focus within it.
dialogRef.current.showModal();
if (searchKeyword) {
handleSubmit(searchKeyword); // In case it's opened with a search link, we run the search.
}
const controller = new AbortController();
const { signal } = controller;
window.addEventListener('popstate', handlePopState, { signal });
dialog.addEventListener('click', handleBackdropClick, { signal });
return () => controller.abort(); // Removes event listeners.
}, []);
const handleSearchClose = () => close();
let status = 'idle';
if (loading) {
status = 'loading';
} else if (errors) {
status = 'error';
} else if (lastSearchKeyword) {
status = 'results';
}
return (
<dialog ref={dialogRef} className="courseware-search" style={{ '--modal-top-position': top }} data-testid="courseware-search-dialog" onClose={handleSearchClose} {...sectionProps}>
<div className="courseware-search__outer-content">
<div className="courseware-search__content" data-testid="courseware-search-content">
<div className="courseware-search__form">
<h1 className="h2">{formatMessage(messages.searchModuleTitle)}</h1>
<CoursewareSearchForm
searchTerm={searchKeyword}
onSubmit={handleSubmit}
onChange={handleOnChange}
placeholder={formatMessage(messages.searchBarPlaceholderText)}
/>
<div className="courseware-search__close">
<Button
variant="tertiary"
className="p-1"
aria-label={formatMessage(messages.searchCloseAction)}
onClick={() => dialogRef.current.close()}
data-testid="courseware-search-close-button"
><Icon src={Close} />
</Button>
</div>
</div>
<div className="courseware-search__results" aria-live="polite" data-testid="courseware-search-results">
{status === 'loading' ? (
<div className="courseware-search__spinner" data-testid="courseware-search-spinner">
<Spinner animation="border" variant="light" screenReaderText={formatMessage(messages.loading)} />
</div>
) : null}
{status === 'error' && (
<Alert className="mt-4" variant="danger" data-testid="courseware-search-error">
{formatMessage(messages.searchResultsError)}
</Alert>
)}
{status === 'results' ? (
<>
{total > 0 ? (
<div
className="courseware-search__results-summary"
aria-relevant="all"
aria-atomic="true"
data-testid="courseware-search-summary"
>{formatMessage(messages.searchResultsLabel, { total, keyword: lastSearchKeyword })}
</div>
) : null}
<CoursewareSearchResultsFilterContainer />
</>
) : null}
</div>
</div>
</div>
</dialog>
);
};
export default CoursewareSearch;

View File

@@ -0,0 +1,287 @@
import React from 'react';
import { history } from '@edx/frontend-platform';
import { AppProvider } from '@edx/frontend-platform/react';
import { Route, Routes } from 'react-router-dom';
import { sendTrackingLogEvent } from '@edx/frontend-platform/analytics';
import {
initializeMockApp,
render,
screen,
waitFor,
fireEvent,
within,
} from '../../setupTest';
import { CoursewareSearch } from './index';
import { useElementBoundingBox, useLockScroll, useCoursewareSearchParams } from './hooks';
import initializeStore from '../../store';
import { searchCourseContent } from '../data/thunks';
import { setShowSearch } from '../data/slice';
import { updateModel, useModel } from '../../generic/model-store';
jest.mock('./hooks');
jest.mock('../../generic/model-store', () => ({
...jest.requireActual('../../generic/model-store'),
updateModel: jest.fn(),
useModel: jest.fn(),
}));
jest.mock('@edx/frontend-platform/analytics', () => ({
sendTrackingLogEvent: jest.fn(),
}));
jest.mock('../data/thunks', () => ({
searchCourseContent: jest.fn(),
}));
jest.mock('../data/slice', () => ({
setShowSearch: jest.fn(),
}));
const mockDispatch = jest.fn();
jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useDispatch: () => mockDispatch,
}));
const decodedCourseId = 'course-v1:edX+DemoX+Demo_Course';
const decodedSequenceId = 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@edx_introduction';
const decodedUnitId = 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_0270f6de40fc';
const pathname = `/course/${decodedCourseId}/${decodedSequenceId}/${decodedUnitId}`;
const tabsTopPosition = 128;
const defaultProps = {
org: 'edX',
loading: false,
searchKeyword: '',
errors: undefined,
total: 0,
};
const defaultSearchParams = {
query: '',
filter: '',
setQuery: jest.fn(),
setFilter: jest.fn(),
clearSearchParams: jest.fn(),
};
const intl = {
formatMessage: (message) => message?.defaultMessage || '',
};
function renderComponent(props = {}) {
const store = initializeStore();
history.push(pathname);
const { container } = render(
<AppProvider store={store}>
<Routes>
<Route path="/course/:courseId/:sequenceId/:unitId" element={<CoursewareSearch intl={intl} {...props} />} />
</Routes>
</AppProvider>,
);
return container;
}
const mockModels = ((props = defaultProps) => {
useModel.mockReturnValue({
...defaultProps,
...props,
});
updateModel.mockReturnValue({
type: 'MOCK_ACTION',
payload: {
modelType: 'contentSearchResults',
model: defaultProps,
},
});
});
const mockSearchParams = ((params) => {
const props = { ...defaultSearchParams, ...params };
useCoursewareSearchParams.mockReturnValue(props);
});
describe('CoursewareSearch', () => {
beforeAll(() => initializeMockApp());
beforeEach(() => {
mockModels();
mockSearchParams();
});
afterEach(() => {
jest.clearAllMocks();
});
describe('when rendering normally', () => {
beforeAll(() => {
useElementBoundingBox.mockImplementation(() => ({ top: tabsTopPosition }));
});
it('should use useElementBoundingBox() and useLockScroll() hooks', () => {
renderComponent();
expect(useElementBoundingBox).toHaveBeenCalledTimes(1);
expect(useLockScroll).toHaveBeenCalledTimes(1);
});
it('should have a "--modal-top-position" CSS variable matching the CourseTabsNavigation top position', () => {
renderComponent();
const section = screen.getByTestId('courseware-search-dialog');
expect(section.style.getPropertyValue('--modal-top-position')).toBe(`${tabsTopPosition}px`);
});
});
describe('when clicking on the "Close" button', () => {
it('should close the dialog', async () => {
renderComponent();
await waitFor(() => {
const close = screen.queryByTestId('courseware-search-close-button');
fireEvent.click(close);
});
expect(HTMLDialogElement.prototype.close).toHaveBeenCalled();
expect(setShowSearch).toHaveBeenCalledWith(false);
});
});
describe('when CourseTabsNavigation is not present', () => {
it('should use "--modal-top-position: 0" if nce element is not present', () => {
useElementBoundingBox.mockImplementation(() => undefined);
renderComponent();
const section = screen.getByTestId('courseware-search-dialog');
expect(section.style.getPropertyValue('--modal-top-position')).toBe('0');
});
});
describe('when passing extra props', () => {
it('should pass on extra props to section element', () => {
renderComponent({ foo: 'bar' });
const section = screen.getByTestId('courseware-search-dialog');
expect(section).toHaveAttribute('foo', 'bar');
});
});
describe('when submitting an empty search', () => {
it('should clear the search by dispatch updateModel', async () => {
renderComponent();
await waitFor(() => {
const submit = screen.queryByTestId('courseware-search-form-submit');
fireEvent.click(submit);
});
expect(updateModel).toHaveBeenCalledWith({
modelType: 'contentSearchResults',
model: {
id: decodedCourseId,
searchKeyword: '',
results: [],
errors: undefined,
loading: false,
},
});
});
});
describe('when submitting a search', () => {
it('should show a loading state', () => {
mockModels({
loading: true,
});
renderComponent();
expect(screen.queryByTestId('courseware-search-spinner')).toBeInTheDocument();
});
it('should call searchCourseContent', async () => {
renderComponent();
const searchKeyword = 'course';
await waitFor(() => {
const input = screen.queryByTestId('courseware-search-form').querySelector('input');
fireEvent.change(input, { target: { value: searchKeyword } });
});
await waitFor(() => {
const submit = screen.queryByTestId('courseware-search-form-submit');
fireEvent.click(submit);
});
expect(sendTrackingLogEvent).toHaveBeenCalledWith('edx.course.home.courseware_search.submit', {
org_key: defaultProps.org,
courserun_key: decodedCourseId,
event_type: 'searchKeyword',
keyword: searchKeyword,
});
expect(searchCourseContent).toHaveBeenCalledWith(decodedCourseId, searchKeyword);
});
it('should show an error state if any', () => {
mockModels({
errors: ['foo'],
});
renderComponent();
expect(screen.queryByTestId('courseware-search-error')).toBeInTheDocument();
});
it('should not show a summary if there are no results', () => {
mockModels({
searchKeyword: 'test',
total: 0,
});
renderComponent();
expect(screen.queryByTestId('courseware-search-summary')).not.toBeInTheDocument();
});
it('should show a summary for the results within a container with aria-live="polite"', () => {
mockModels({
searchKeyword: 'fubar',
total: 1,
});
renderComponent();
const results = screen.queryByTestId('courseware-search-results');
expect(results).toHaveAttribute('aria-live', 'polite');
expect(within(results).queryByTestId('courseware-search-summary').textContent).toBe('Results for "fubar":');
});
});
describe('when clearing the search input', () => {
it('should clear the search by dispatch updateModel', async () => {
mockSearchParams({ query: 'fubar' });
mockModels({
searchKeyword: 'fubar',
total: 2,
});
renderComponent();
await waitFor(() => {
const input = screen.queryByTestId('courseware-search-form').querySelector('input');
fireEvent.change(input, { target: { value: '' } });
});
expect(updateModel).toHaveBeenCalledWith({
modelType: 'contentSearchResults',
model: {
id: decodedCourseId,
searchKeyword: '',
results: [],
errors: undefined,
loading: false,
},
});
});
});
});

View File

@@ -0,0 +1,14 @@
import React from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import messages from './messages';
const CoursewareSearchEmpty = () => {
const intl = useIntl();
return (
<div className="courseware-search-results">
<p className="courseware-search-results__empty" data-testid="no-results">{intl.formatMessage(messages.searchResultsNone)}</p>
</div>
);
};
export default CoursewareSearchEmpty;

View File

@@ -0,0 +1,28 @@
import React from 'react';
import {
initializeMockApp,
render,
screen,
} from '../../setupTest';
import CoursewareSearchEmpty from './CoursewareSearchEmpty';
import messages from './messages';
function renderComponent() {
const { container } = render(<CoursewareSearchEmpty />);
return container;
}
describe('CoursewareSearchEmpty', () => {
beforeAll(async () => {
initializeMockApp();
});
it('render empty results text and corresponding classes', () => {
renderComponent();
const emptyText = screen.getByText(messages.searchResultsNone.defaultMessage);
expect(emptyText).toBeInTheDocument();
expect(emptyText).toHaveClass('courseware-search-results__empty');
expect(emptyText).toHaveAttribute('data-testid', 'no-results');
expect(emptyText.parentElement).toHaveClass('courseware-search-results');
});
});

View File

@@ -0,0 +1,55 @@
import PropTypes from 'prop-types';
import { SearchField } from '@openedx/paragon';
import { useIntl } from '@edx/frontend-platform/i18n';
import messages from './messages';
const CoursewareSearchForm = ({
searchTerm,
onSubmit,
onChange,
placeholder,
}) => {
const { formatMessage } = useIntl();
return (
<SearchField.Advanced
value={searchTerm}
onSubmit={onSubmit}
onChange={onChange}
submitButtonLocation="external"
className="courseware-search-form"
screenReaderText={{
label: formatMessage(messages.searchSubmitLabel),
clearButton: formatMessage(messages.searchClearAction),
submitButton: null, // Remove the sr-only label in the button.
}}
>
<div className="pgn__searchfield_wrapper" data-testid="courseware-search-form">
<SearchField.Label />
<SearchField.Input placeholder={placeholder} autoFocus />
<SearchField.ClearButton />
</div>
<SearchField.SubmitButton
buttonText={formatMessage(messages.searchSubmitLabel)}
submitButtonLocation="external"
data-testid="courseware-search-form-submit"
/>
</SearchField.Advanced>
);
};
CoursewareSearchForm.propTypes = {
searchTerm: PropTypes.string,
onSubmit: PropTypes.func,
onChange: PropTypes.func,
placeholder: PropTypes.string,
};
CoursewareSearchForm.defaultProps = {
searchTerm: undefined,
onSubmit: undefined,
onChange: undefined,
placeholder: undefined,
};
export default CoursewareSearchForm;

View File

@@ -0,0 +1,60 @@
import React from 'react';
import {
act,
initializeMockApp,
render,
screen,
waitFor,
fireEvent,
} from '../../setupTest';
import CoursewareSearchForm from './CoursewareSearchForm';
function renderComponent(placeholder, onSubmit, onChange) {
const { container } = render(<CoursewareSearchForm
placeholder={placeholder}
onSubmit={onSubmit}
onChange={onChange}
/>);
return container;
}
describe('CoursewareSearchToggle', () => {
const placeholderText = 'Search for courseware';
let onSubmitHandlerMock;
let onChangeHandlerMock;
beforeAll(async () => {
onChangeHandlerMock = jest.fn();
onSubmitHandlerMock = jest.fn();
initializeMockApp();
});
it('should render', async () => {
await act(async () => renderComponent(placeholderText, onSubmitHandlerMock, onChangeHandlerMock));
await waitFor(() => {
expect(screen.queryByTestId('courseware-search-form')).toBeInTheDocument();
});
});
it('should call onChange handler when input changes', async () => {
await act(async () => renderComponent(placeholderText, onSubmitHandlerMock, onChangeHandlerMock));
await waitFor(() => {
const element = screen.queryByPlaceholderText(placeholderText);
fireEvent.change(element, { target: { value: 'test' } });
expect(onChangeHandlerMock).toHaveBeenCalledTimes(1);
});
});
it('should call onSubmit handler when submit is clicked', async () => {
await act(async () => renderComponent(placeholderText, onSubmitHandlerMock, onChangeHandlerMock));
await waitFor(async () => {
const element = await screen.findByTestId('courseware-search-form-submit');
fireEvent.click(element);
expect(onSubmitHandlerMock).toHaveBeenCalledTimes(1);
});
});
afterEach(() => {
jest.clearAllMocks();
});
});

View File

@@ -0,0 +1,86 @@
import React from 'react';
import {
Folder, TextFields, VideoCamera, Article,
} from '@openedx/paragon/icons';
import { getConfig } from '@edx/frontend-platform';
import { Icon } from '@openedx/paragon';
import PropTypes from 'prop-types';
import CoursewareSearchEmpty from './CoursewareSearchEmpty';
const iconTypeMapping = {
text: TextFields,
video: VideoCamera,
sequence: Folder,
other: Article,
};
const defaultIcon = Article;
const CoursewareSearchResults = ({ results = [] }) => {
if (!results?.length) {
return <CoursewareSearchEmpty />;
}
const baseUrl = `${getConfig().LMS_BASE_URL}`;
return (
<div className="courseware-search-results" data-testid="search-results">
{results.map(({
id,
title,
type,
location,
url,
contentHits,
}) => {
const key = type.toLowerCase();
const icon = iconTypeMapping[key] || defaultIcon;
const isExternal = !url.startsWith('/');
const linkProps = isExternal ? {
href: url,
target: '_blank',
rel: 'nofollow',
} : { href: `${baseUrl}${url}` };
return (
<a key={id} className="courseware-search-results__item" {...linkProps}>
<div className="courseware-search-results__icon"><Icon src={icon} /></div>
<div className="courseware-search-results__info">
<div className="courseware-search-results__title">
<span>{title}</span>
{contentHits ? (<em>{contentHits}</em>) : null }
</div>
{location?.length ? (
<ul className="courseware-search-results__breadcrumbs">
{
// This ignore is necessary because the breadcrumb texts might have duplicates.
// The breadcrumbs are not expected to change.
// eslint-disable-next-line react/no-array-index-key
location.map((breadcrumb, i) => (<li key={`${i}:${breadcrumb}`}><div>{breadcrumb}</div></li>))
}
</ul>
) : null}
</div>
</a>
);
})}
</div>
);
};
CoursewareSearchResults.propTypes = {
results: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string,
title: PropTypes.string,
type: PropTypes.string,
location: PropTypes.arrayOf(PropTypes.string),
url: PropTypes.string,
contentHits: PropTypes.number,
})),
};
CoursewareSearchResults.defaultProps = {
results: [],
};
export default CoursewareSearchResults;

View File

@@ -0,0 +1,87 @@
import React from 'react';
import {
initializeMockApp,
render,
screen,
} from '../../setupTest';
import CoursewareSearchResults from './CoursewareSearchResults';
import messages from './messages';
import searchResultsFactory from './test-data/search-results-factory';
import * as mock from './test-data/mocked-response.json';
jest.mock('react-redux');
function renderComponent({ results }) {
const { container } = render(<CoursewareSearchResults results={results} />);
return container;
}
describe('CoursewareSearchResults', () => {
beforeAll(async () => {
initializeMockApp();
});
describe('when an empty array is provided', () => {
beforeEach(() => { renderComponent({ results: [] }); });
it('should render a "no results found" message.', () => {
expect(screen.getByTestId('no-results').textContent).toBe(messages.searchResultsNone.defaultMessage);
});
});
describe('when list of results is provided', () => {
beforeEach(() => {
const { results } = searchResultsFactory('course');
renderComponent({ results });
});
it('should render complete list', () => {
const courses = screen.getAllByRole('link');
expect(courses.length).toBe(mock.results.length);
});
it('should render correct link for internal course', () => {
const courses = screen.getAllByRole('link');
const firstCourse = courses[0];
const firstCourseTitle = firstCourse.querySelector('.courseware-search-results__title span');
expect(firstCourseTitle.innerHTML).toEqual(mock.results[0].data.content.display_name);
expect(firstCourse.href).toContain(mock.results[0].data.url);
expect(firstCourse).not.toHaveAttribute('target', '_blank');
expect(firstCourse).not.toHaveAttribute('rel', 'nofollow');
});
it('should render correct link if is External url course', () => {
const courses = screen.getAllByRole('link');
const externalCourse = courses[courses.length - 1];
const externalCourseTitle = externalCourse.querySelector('.courseware-search-results__title span');
expect(externalCourseTitle.innerHTML).toEqual(mock.results[mock.results.length - 1].data.content.display_name);
expect(externalCourse.href).toContain(mock.results[mock.results.length - 1].data.url);
expect(externalCourse).toHaveAttribute('target', '_blank');
expect(externalCourse).toHaveAttribute('rel', 'nofollow');
const icon = externalCourse.querySelector('svg');
expect(icon).toBeInTheDocument();
});
it('should render location breadcrumbs', () => {
const breadcrumbs = screen.getAllByText(mock.results[0].data.location[0]);
expect(breadcrumbs.length).toBeGreaterThan(0);
const firstBreadcrumb = breadcrumbs[0].closest('li');
expect(firstBreadcrumb).toBeInTheDocument();
expect(firstBreadcrumb.querySelector('div').textContent).toBe(mock.results[0].data.location[0]);
expect(firstBreadcrumb.nextSibling.querySelector('div').textContent).toBe(mock.results[0].data.location[1]);
});
});
describe('when results are provided with content hits', () => {
beforeEach(() => {
const { results } = searchResultsFactory('Passing');
renderComponent({ results });
});
it('should render content hits', () => {
const contentHits = screen.getByText('1');
expect(contentHits).toBeInTheDocument();
expect(contentHits.tagName).toBe('EM');
});
});
});

View File

@@ -0,0 +1,43 @@
import React, { useEffect } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Button } from '@openedx/paragon';
import { ManageSearch } from '@openedx/paragon/icons';
import { useDispatch } from 'react-redux';
import messages from './messages';
import { useCoursewareSearchFeatureFlag, useCoursewareSearchParams } from './hooks';
import { setShowSearch } from '../data/slice';
const CoursewareSearchToggle = () => {
const intl = useIntl();
const dispatch = useDispatch();
const enabled = useCoursewareSearchFeatureFlag();
const { query } = useCoursewareSearchParams();
const handleSearchOpenClick = () => {
dispatch(setShowSearch(true));
};
useEffect(() => {
if (enabled && !!query) { handleSearchOpenClick(); }
}, [enabled]);
if (!enabled) { return null; }
return (
<div className="courseware-search-toggle">
<Button
variant="outline-primary"
size="sm"
className="p-1 mt-2 mr-2"
aria-label={intl.formatMessage(messages.searchOpenAction)}
onClick={handleSearchOpenClick}
data-testid="courseware-search-open-button"
iconAfter={ManageSearch}
>
{intl.formatMessage(messages.contentSearchButton)}
</Button>
</div>
);
};
export default CoursewareSearchToggle;

View File

@@ -0,0 +1,91 @@
import React from 'react';
import {
act,
fireEvent,
initializeMockApp,
render,
screen,
waitFor,
} from '../../setupTest';
import { fetchCoursewareSearchSettings } from '../data/thunks';
import { setShowSearch } from '../data/slice';
import { CoursewareSearchToggle } from './index';
const mockDispatch = jest.fn();
const mockCoursewareSearchParams = jest.fn();
jest.mock('../data/thunks');
jest.mock('../data/slice');
jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useDispatch: () => mockDispatch,
}));
jest.mock('./hooks', () => ({
...jest.requireActual('./hooks'),
useCoursewareSearchParams: () => mockCoursewareSearchParams,
}));
const coursewareSearch = {
query: '',
filter: '',
setQuery: jest.fn(),
setFilter: jest.fn(),
clearSearchParams: jest.fn(),
};
const mockSearchParams = ((props = coursewareSearch) => {
mockCoursewareSearchParams.mockReturnValue(props);
});
function renderComponent() {
const { container } = render(<CoursewareSearchToggle />);
return container;
}
describe('CoursewareSearchToggle', () => {
beforeAll(async () => {
initializeMockApp();
});
afterEach(() => {
jest.clearAllMocks();
});
it('Should not render when the waffle flag is disabled', async () => {
fetchCoursewareSearchSettings.mockImplementation(() => Promise.resolve({ enabled: false }));
mockSearchParams();
await act(async () => renderComponent());
await waitFor(() => {
expect(fetchCoursewareSearchSettings).toHaveBeenCalledTimes(1);
expect(screen.queryByTestId('courseware-search-open-button')).not.toBeInTheDocument();
});
});
it('Should render when the waffle flag is enabled', async () => {
fetchCoursewareSearchSettings.mockImplementation(() => Promise.resolve({ enabled: true }));
mockSearchParams();
await act(async () => renderComponent());
await waitFor(() => {
expect(fetchCoursewareSearchSettings).toHaveBeenCalledTimes(1);
expect(screen.queryByTestId('courseware-search-open-button')).toBeInTheDocument();
});
});
it('Should dispatch setShowSearch(true) when clicking the search button', async () => {
fetchCoursewareSearchSettings.mockImplementation(() => Promise.resolve({ enabled: true }));
mockSearchParams();
await act(async () => renderComponent());
const button = await screen.findByTestId('courseware-search-open-button');
fireEvent.click(button);
expect(mockDispatch).toHaveBeenCalledTimes(1);
expect(setShowSearch).toHaveBeenCalledTimes(1);
expect(setShowSearch).toHaveBeenCalledWith(true);
});
});

View File

@@ -0,0 +1,181 @@
.courseware-search {
background: white;
position: fixed;
top: var(--modal-top-position, 0);
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
max-width: none;
margin: 0;
border-top: 1px solid var(--pgn-color-light-300);
z-index: var(--pgn-elevation-modal-zindex); // Bootstrap's z-index layer for Modals.
&__form {
position: relative;
.h2 {
margin-right: 2.5rem;
}
}
&__close {
position: absolute !important; // For some reason it gets overridden
top: 0;
right: 0;
font-size: 1.5rem;
line-height: 1;
}
&__outer-content {
overflow-y: auto;
height: 100%;
}
&__content {
padding-top: 2rem;
padding-left: 1rem;
padding-right: 1rem;
max-width: 42rem;
margin: auto;
h2 {
margin-bottom: 2rem;
}
}
&__results-summary {
font-size: .9rem;
color: var(--pgn-color-gray-500);
padding: 1rem 0 .5rem;
}
&__spinner {
display: grid;
place-items: center;
min-height: 20vh;
}
}
.courseware-search-results {
margin-top: 1.5rem;
&__empty {
color: var(--pgn-color-gray-500);
padding: 6rem 0;
text-align: center;
}
&__item {
display: block;
padding: .75rem 1rem;
font-weight: 500;
display: flex;
gap: 0.625rem;
&:hover {
text-decoration: none;
background: var(--pgn-color-light-300);
}
&:not(:first-child) {
border-top: 1px solid var(--pgn-color-light-300);
}
}
&__icon {
padding: 0.375rem 0 0 0.375rem;
color: var(--pgn-color-gray-300);
}
&__info {
flex: 1;
overflow: hidden;
}
&__title {
display: flex;
align-items: center;
line-height: 2.5;
font-size: 0.875rem;
color: var(--pgn-color-black);
> span {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
em {
padding: 0.125rem 0.375rem;
font-variant-numeric: lining-nums tabular-nums;
min-width: 1.25rem;
line-height: 1rem;
background: var(--pgn-color-light-300);
border-radius: 99rem;
font-style: normal;
margin-left: 0.375rem;
font-size: 0.6875rem;
text-align: center;
}
}
&__breadcrumbs {
display: flex;
gap: 1.25rem;
color: var(--pgn-color-gray-500);
overflow: hidden;
list-style: none;
padding: 0;
margin: 0;
> li {
position: relative;
flex-shrink: 1;
min-width: 0;
&:not(:first-child)::before {
content: '';
position: absolute;
top: 50%;
transform: translate(-50%, -55%);
left: -0.625rem;
}
}
div {
font-size: 0.75rem;
line-height: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
.courseware-search-results-tabs {
border-bottom-color: var(--pgn-color-gray-400) !important;
&.nav-tabs .nav-link.active {
border-bottom-width: 4px !important;
}
}
@media (--pgn-size-breakpoint-min-width-md) {
.courseware-search {
&__close {
right: -2.5rem;
}
&__content {
padding-top: 8rem;
}
}
}
body._search-no-scroll {
overflow-y: hidden;
}

View File

@@ -0,0 +1,87 @@
import { useState, useEffect, useLayoutEffect } from 'react';
import { useParams, useSearchParams } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { debounce } from 'lodash';
import { fetchCoursewareSearchSettings } from '../data/thunks';
const DEBOUNCE_WAIT = 100; // ms
export function useCoursewareSearchFeatureFlag() {
const { courseId } = useParams();
const [enabled, setEnabled] = useState(false);
useEffect(() => {
fetchCoursewareSearchSettings(courseId).then(response => setEnabled(response.enabled));
}, [courseId]);
return enabled;
}
export function useCoursewareSearchState() {
const enabled = useCoursewareSearchFeatureFlag();
const show = useSelector(state => state.courseHome.showSearch);
return { show: enabled && show };
}
export function useElementBoundingBox(elementId) {
const [info, setInfo] = useState(undefined);
const element = document.getElementById(elementId);
if (!element) {
console.warn(`useElementBoundingBox(): Unable to find element with id='${elementId}' in the document.`); // eslint-disable-line no-console
return undefined;
}
useLayoutEffect(() => {
// Handler to call on window resize and scroll
function recalculate() {
const bounds = element.getBoundingClientRect();
setInfo(bounds);
}
const debouncedRecalculate = debounce(recalculate, DEBOUNCE_WAIT, { leading: true });
// Add event listener
global.addEventListener('resize', debouncedRecalculate);
global.addEventListener('scroll', debouncedRecalculate);
// Call handler right away so state gets updated with initial window size
debouncedRecalculate();
// Remove event listener on cleanup
return () => {
global.removeEventListener('resize', debouncedRecalculate);
global.removeEventListener('scroll', debouncedRecalculate);
};
}, []);
return info;
}
export function useLockScroll() {
useLayoutEffect(() => {
window.scrollTo(0, 0);
document.body.classList.add('_search-no-scroll');
return () => {
document.body.classList.remove('_search-no-scroll');
};
}, []);
}
const initSearchParams = { q: '', f: '' };
export function useCoursewareSearchParams() {
const [searchParams, setSearchParams] = useSearchParams(initSearchParams);
const clearSearchParams = () => setSearchParams(initSearchParams);
const query = searchParams.get('q');
const filter = searchParams.get('f')?.toLowerCase();
const setQuery = (q) => setSearchParams((params) => ({ q, f: params.get('f') }));
const setFilter = (f) => setSearchParams((params) => ({ q: params.get('q'), f }));
return {
query, filter, setQuery, setFilter, clearSearchParams,
};
}

View File

@@ -0,0 +1,232 @@
import { renderHook, act, waitFor } from '@testing-library/react';
import { useParams, useSearchParams } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { fetchCoursewareSearchSettings } from '../data/thunks';
import {
useCoursewareSearchFeatureFlag,
useCoursewareSearchParams,
useCoursewareSearchState,
useElementBoundingBox,
useLockScroll,
} from './hooks';
jest.mock('react-redux');
jest.mock('react-router-dom');
jest.mock('../data/thunks');
describe('CoursewareSearch Hooks', () => {
const courses = {
123: { enabled: true },
456: { enabled: false },
};
beforeEach(() => {
fetchCoursewareSearchSettings.mockImplementation((courseId) => Promise.resolve(courses[courseId]));
});
afterEach(() => {
jest.resetAllMocks();
});
describe('useCoursewareSearchFeatureFlag', () => {
const renderTestHook = async (enabled = true) => {
useParams.mockImplementation(() => ({ courseId: enabled ? 123 : 456 }));
let hook;
await act(async () => { (hook = renderHook(() => useCoursewareSearchFeatureFlag())); });
return hook;
};
it('should return true if feature is enabled', async () => {
const hook = await renderTestHook();
await waitFor(() => expect(fetchCoursewareSearchSettings).toBeCalledTimes(1));
expect(hook.result.current).toBe(true);
});
it('should return false if feature is disabled', async () => {
const hook = await renderTestHook(false);
await waitFor(() => expect(fetchCoursewareSearchSettings).toBeCalledTimes(1));
expect(hook.result.current).toBe(false);
});
});
describe('useCoursewareSearchState', () => {
const renderTestHook = async ({ enabled, showSearch }) => {
useParams.mockImplementation(() => ({ courseId: enabled ? 123 : 456 }));
const mockedStoreState = { courseHome: { showSearch } };
useSelector.mockImplementation(selector => selector(mockedStoreState));
let hook;
await act(async () => { (hook = renderHook(() => useCoursewareSearchState())); });
return hook;
};
it('should return show: true if feature is enabled and showSearch is true', async () => {
const hook = await renderTestHook({ enabled: true, showSearch: true });
expect(hook.result.current).toEqual({ show: true });
});
it('should return show: false in any other case', async () => {
let hook;
hook = await renderTestHook({ enabled: true, showSearch: false });
expect(hook.result.current).toEqual({ show: false });
hook = await renderTestHook({ enabled: false, showSearch: true });
expect(hook.result.current).toEqual({ show: false });
hook = await renderTestHook({ enabled: false, showSearch: false });
expect(hook.result.current).toEqual({ show: false });
});
});
describe('useElementBoundingBox', () => {
let getBoundingClientRectSpy;
const renderTestHook = async ({ elementId, mockedInfo }) => {
getBoundingClientRectSpy = jest.spyOn(document, 'getElementById').mockImplementation(() => (
mockedInfo
? { getBoundingClientRect: () => ({ ...mockedInfo }) }
: undefined
));
let hook;
await act(async () => {
hook = renderHook(() => useElementBoundingBox(elementId));
});
return hook;
};
let addEventListenerSpy;
let removeEventListenerSpy;
beforeEach(() => {
addEventListenerSpy = jest.spyOn(global, 'addEventListener');
removeEventListenerSpy = jest.spyOn(global, 'removeEventListener');
});
describe('when element is present', () => {
const mockedInfo = { top: 128 };
it('should bind resize and scroll events on mount', async () => {
await renderTestHook({ elementId: 'test', mockedInfo });
expect(addEventListenerSpy).toHaveBeenCalledWith('resize', expect.anything());
expect(addEventListenerSpy).toHaveBeenCalledWith('scroll', expect.anything());
});
it('should unbindbind resize and scroll events when unmounted', async () => {
const hook = await renderTestHook({ elementId: 'test', mockedInfo });
hook.unmount();
expect(removeEventListenerSpy).toHaveBeenCalledWith('resize', expect.anything());
expect(removeEventListenerSpy).toHaveBeenCalledWith('scroll', expect.anything());
});
it('should return the element bounding box', async () => {
const hook = await renderTestHook({ elementId: 'test', mockedInfo });
await waitFor(() => expect(getBoundingClientRectSpy).toHaveBeenCalled());
expect(hook.result.current).toEqual(mockedInfo);
});
it('should call getBoundingClientRect on window resize', async () => {
const hook = await renderTestHook({ elementId: 'test', mockedInfo });
act(() => {
// Trigger the window resize event.
global.innerWidth = 500;
global.dispatchEvent(new Event('resize'));
});
expect(hook.result.current).toEqual(mockedInfo);
});
});
describe('when element is NOT present', () => {
let consoleWarnSpy;
beforeEach(() => {
consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
});
it('should log a warning and return undefined', async () => {
await renderTestHook({ elementId: 'happiness' });
expect(consoleWarnSpy).toHaveBeenCalledWith("useElementBoundingBox(): Unable to find element with id='happiness' in the document.");
});
});
});
describe('useLockScroll', () => {
const renderTestHook = () => (
renderHook(() => useLockScroll())
);
let windowScrollSpy;
let addBodyClassSpy;
let removeBodyClassSpy;
let hook;
beforeEach(() => {
windowScrollSpy = jest.spyOn(window, 'scrollTo');
addBodyClassSpy = jest.spyOn(document.body.classList, 'add');
removeBodyClassSpy = jest.spyOn(document.body.classList, 'remove');
hook = renderTestHook();
});
it('should perform a scrollTo(0, 0) on mount', () => {
expect(windowScrollSpy).toHaveBeenCalledWith(0, 0);
});
it('should append a _search-no-scroll on mount to the document body', () => {
expect(addBodyClassSpy).toHaveBeenCalledWith('_search-no-scroll');
});
it('should remove the _search-no-scroll on unmount', () => {
hook.unmount();
expect(removeBodyClassSpy).toHaveBeenCalledWith('_search-no-scroll');
});
});
describe('useSearchParams', () => {
const initSearch = { q: '', f: '' };
const q = { value: '' };
const f = { value: '' };
const mockedQuery = { q, f };
const searchParams = { get: (prop) => mockedQuery[prop].value };
const setSearchParams = jest.fn();
beforeEach(() => {
useSearchParams.mockImplementation(() => [searchParams, setSearchParams]);
});
it('should init the search params properly', () => {
const {
query, filter, setQuery, setFilter, clearSearchParams,
} = useCoursewareSearchParams();
expect(useSearchParams).toBeCalledWith(initSearch);
expect(query).toBe('');
expect(filter).toBe('');
setQuery('setQuery');
expect(setSearchParams).toBeCalledWith(expect.any(Function));
setFilter('setFilter');
expect(setSearchParams).toBeCalledWith(expect.any(Function));
clearSearchParams();
expect(setSearchParams).toBeCalledWith(initSearch);
});
it('should return the query and lowercase filter if any', () => {
q.value = '42';
f.value = 'LOWERCASE';
const { query, filter } = useCoursewareSearchParams();
expect(query).toBe('42');
expect(filter).toBe('lowercase');
});
});
});

View File

@@ -0,0 +1,3 @@
/* eslint-disable import/prefer-default-export */
export { default as CoursewareSearchToggle } from './CoursewareSearchToggle';
export { default as CoursewareSearch } from './CoursewareSearch';

View File

@@ -0,0 +1,117 @@
const Joi = require('joi');
const endpointSchema = Joi.object({
took: Joi.number().required(),
total: Joi.number().required(),
maxScore: Joi.number().allow(null),
results: Joi.array().items(Joi.object({
id: Joi.string(),
contentType: Joi.string(),
location: Joi.array().items(Joi.string()),
url: Joi.string(),
content: Joi.object({
displayName: Joi.string(),
htmlContent: Joi.string(),
transcriptEn: Joi.string(),
}),
}).unknown(true)).strict(),
}).unknown(true).strict();
const defaultType = 'text';
// Parses the search results in a convenient way.
export default function mapSearchResponse(response, searchKeywords = '') {
const { error, value: data } = endpointSchema.validate(response);
if (error) {
throw new Error('Error in server response:', error);
}
const keywords = searchKeywords ? searchKeywords.toLowerCase().split(' ') : [];
const {
took: ms,
total,
maxScore,
results: rawResults,
} = data;
const results = rawResults.map(result => {
const {
score,
data: {
id,
content: {
displayName,
htmlContent,
transcriptEn,
},
contentType,
location,
url,
},
} = result;
const type = contentType?.toLowerCase() || defaultType;
const content = htmlContent || transcriptEn || '';
const searchContent = content.toLowerCase();
let contentHits = 0;
if (keywords.length) {
keywords.forEach(word => {
contentHits += searchContent ? searchContent.toLowerCase().split(word).length - 1 : 0;
});
}
const title = displayName || contentType;
return {
id,
title,
type,
location,
url,
contentHits,
score,
};
});
const filters = rawResults.reduce((list, result) => {
const label = result?.data?.contentType;
if (!label) { return list; }
const key = label.toLowerCase();
const index = list.findIndex(i => i.key === key);
if (index === -1) {
return [
...list,
{
key,
label,
count: 1,
},
];
}
const newItem = { ...list[index] };
newItem.count++;
const newList = list.slice(0);
newList[index] = newItem;
return newList;
}, []);
filters.sort((a, b) => (a.key > b.key ? 1 : -1));
return {
results,
filters,
total,
maxScore,
ms,
};
}

View File

@@ -0,0 +1,72 @@
import { camelCaseObject } from '@edx/frontend-platform';
import mapSearchResponse from './map-search-response';
import mockedResponse from './test-data/mocked-response.json';
describe('mapSearchResponse', () => {
describe('when the response is correct', () => {
let response;
beforeEach(() => {
response = mapSearchResponse(camelCaseObject(mockedResponse));
});
it('should match number of results', () => {
expect(response.results.length).toBe(mockedResponse.results.length);
});
it('should match expected filters', () => {
const expectedFilters = [
{ key: 'capa', label: 'CAPA', count: 7 },
{ key: 'sequence', label: 'Sequence', count: 2 },
{ key: 'text', label: 'Text', count: 9 },
{ key: 'unknown', label: 'Unknown', count: 1 },
{ key: 'video', label: 'Video', count: 2 },
];
expect(response.filters).toEqual(expectedFilters);
});
it('should match expected results', () => {
const mockFirstResult = mockedResponse.results[0];
const expectedFirstResult = {
id: mockFirstResult.data.id,
title: mockFirstResult.data.content.display_name,
type: mockFirstResult.data.content_type.toLowerCase(),
location: mockFirstResult.data.location,
url: mockFirstResult.data.url,
contentHits: 0,
score: mockFirstResult.score,
};
expect(response.results[0]).toEqual(expectedFirstResult);
});
it('should match expected ms and max score', () => {
expect(response.maxScore).toBe(mockedResponse.max_score);
expect(response.ms).toBe(mockedResponse.took);
});
});
describe('when the a keyword is provided', () => {
const searchText = 'Course';
it('should not count matches title', () => {
const response = mapSearchResponse(camelCaseObject(mockedResponse), searchText);
expect(response.results[0].contentHits).toBe(0);
});
it('should count matches on content', () => {
const response = mapSearchResponse(camelCaseObject(mockedResponse), searchText);
expect(response.results[1].contentHits).toBe(1);
});
it('should ignore capitalization', () => {
const response = mapSearchResponse(camelCaseObject(mockedResponse), searchText.toUpperCase());
expect(response.results[1].contentHits).toBe(1);
});
});
describe('when the response has a wrong format', () => {
it('should throw an error', () => {
expect(() => mapSearchResponse({ foo: 'bar' })).toThrow();
});
});
});

View File

@@ -0,0 +1,88 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
searchOpenAction: {
id: 'learn.coursewareSearch.openAction',
defaultMessage: 'Search within this course',
description: 'Aria-label for a button that will pop up Courseware Search.',
},
contentSearchButton: {
id: 'learn.coursewareSearch.contentSearchButton',
defaultMessage: 'Content search',
description: 'Text for a button that will pop up Courseware Search.',
},
searchSubmitLabel: {
id: 'learn.coursewareSearch.submitLabel',
defaultMessage: 'Search',
description: 'Button label that will submit Courseware Search.',
},
searchClearAction: {
id: 'learn.coursewareSearch.clearAction',
defaultMessage: 'Clear search',
description: 'Button label that will the current Courseware Search input.',
},
searchCloseAction: {
id: 'learn.coursewareSearch.closeAction',
defaultMessage: 'Close the search form',
description: 'Aria-label for a button that will close Courseware Search.',
},
searchModuleTitle: {
id: 'learn.coursewareSearch.searchModuleTitle',
defaultMessage: 'Search this course',
description: 'Title for the Courseware Search module.',
},
searchBarPlaceholderText: {
id: 'learn.coursewareSearch.searchBarPlaceholderText',
defaultMessage: 'Search',
description: 'Placeholder text for the Courseware Search input control',
},
loading: {
id: 'learn.coursewareSearch.loading',
defaultMessage: 'Searching...',
description: 'Screen reader text to use on the spinner while the search is performing.',
},
searchResultsNone: {
id: 'learn.coursewareSearch.searchResultsNone',
defaultMessage: 'No results found.',
description: 'Text to show when the Courseware Search found no results matching the criteria.',
},
searchResultsLabel: {
id: 'learn.coursewareSearch.searchResultsLabel',
defaultMessage: 'Results for "{keyword}":',
description: 'Text to show above the search results response list.',
},
searchResultsError: {
id: 'learn.coursewareSearch.searchResultsError',
defaultMessage: 'There was an error on the search process. Please try again in a few minutes. If the problem persists, please contact the support team.',
description: 'Error message to show to the users when there\'s an error with the endpoint or the returned payload format.',
},
// These are translations for labeling the filters
'filter:all': {
id: 'learn.coursewareSearch.filter:all',
defaultMessage: 'All content',
description: 'Label for the search results filter that shows all content (no filter).',
},
'filter:text': {
id: 'learn.coursewareSearch.filter:text',
defaultMessage: 'Text',
description: 'Label for the search results filter that shows results with text content.',
},
'filter:video': {
id: 'learn.coursewareSearch.filter:video',
defaultMessage: 'Video',
description: 'Label for the search results filter that shows results with video content.',
},
'filter:sequence': {
id: 'learn.coursewareSearch.filter:sequence',
defaultMessage: 'Section',
description: 'Label for the search results filter that shows results with section content.',
},
'filter:other': {
id: 'learn.coursewareSearch.filter:other',
defaultMessage: 'Other',
description: 'Label for the search results filter that shows results with other content.',
},
});
export default messages;

View File

@@ -0,0 +1,570 @@
{
"took": 5,
"total": 29,
"max_score": 3.4545178,
"results": [
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@sequential+block@edx_introduction",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Demo Course Overview"
},
"content_type": "Sequence",
"id": "block-v1:edX+DemoX+Demo_Course+type@sequential+block@edx_introduction",
"start_date": "1970-01-01T05:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Introduction",
"Demo Course Overview"
],
"excerpt": "Demo <b>Course</b> Overview",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@sequential+block@edx_introduction"
},
"score": 3.4545178
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@html+block@5e009378f0b64585baa0a14b155974b9",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Passing a Course",
"html_content": "Passing a COurse After the last assignment in a class has been due, you will see the entry in your student profile change to show progress toward generating your certificate. After the certificate generation process has completed, you will be able to download it from your profile page. "
},
"content_type": "Text",
"id": "block-v1:edX+DemoX+Demo_Course+type@html+block@5e009378f0b64585baa0a14b155974b9",
"start_date": "2013-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"About Exams and Certificates",
"edX Exams",
"Passing a Course"
],
"excerpt": "Passing a <b>Course</b><span class=\"search-results-ellipsis\"></span>Passing a <b>COurse</b> After the last assignment in a class has been due,",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@html+block@5e009378f0b64585baa0a14b155974b9"
},
"score": 3.4545178
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@vertical+block@c7e98fd39a6944edb6b286c32e1150ff",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Passing a Course"
},
"content_type": "Sequence",
"id": "block-v1:edX+DemoX+Demo_Course+type@vertical+block@c7e98fd39a6944edb6b286c32e1150ff",
"start_date": "2013-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"About Exams and Certificates",
"edX Exams",
"Passing a Course"
],
"excerpt": "Passing a <b>Course</b>",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@vertical+block@c7e98fd39a6944edb6b286c32e1150ff"
},
"score": 3.4545178
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@0d759dee4f9d459c8956136dbde55f02",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Text Input",
"capa_content": " Here's a very simple example of a text input question. Depending on the course you may have to observe special text requirements for dates, case sensitivity, etc. Which country contains Paris as its capital? "
},
"content_type": "CAPA",
"problem_types": [
"stringresponse"
],
"id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@0d759dee4f9d459c8956136dbde55f02",
"start_date": "2013-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 1: Getting Started",
"Homework - Question Styles",
"Text input"
],
"excerpt": "the <b>course</b> you may have to observe special text requirements for",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@problem+block@0d759dee4f9d459c8956136dbde55f02"
},
"score": 1.5874016
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@c554538a57664fac80783b99d9d6da7c",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Pointing on a Picture",
"capa_content": " Some course questions may show you an image and ask that you click on it to answer a question. Try this example. (If you are correct you will see our famous green check mark.) Which animal is a kitten? "
},
"content_type": "CAPA",
"problem_types": [
"imageresponse"
],
"id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@c554538a57664fac80783b99d9d6da7c",
"start_date": "2013-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 1: Getting Started",
"Homework - Question Styles",
"Pointing on a Picture"
],
"excerpt": " Some <b>course</b> questions may show you an image and ask that you click on",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@problem+block@c554538a57664fac80783b99d9d6da7c"
},
"score": 1.5499392
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@45d46192272c4f6db6b63586520bbdf4",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Getting Answers",
"capa_content": " In some courses a \"show answer\" button might appear below a question. When you click on this button, you can see the correct answer (with an explanation) that would receive full credit. How much does it cost to take an edX course? Enter the number of dollars. "
},
"content_type": "CAPA",
"problem_types": [
"numericalresponse"
],
"id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@45d46192272c4f6db6b63586520bbdf4",
"start_date": "2013-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"About Exams and Certificates",
"edX Exams",
"Getting Answers"
],
"excerpt": " In some <b>course</b>s a \"show answer\" button might appear below a question.",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@problem+block@45d46192272c4f6db6b63586520bbdf4"
},
"score": 1.5003732
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@video+block@0b9e39477cf34507a7a48f74be381fdd",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Welcome!",
"transcript_en": " ERIC: Hi, and welcome to the edX demonstration course. I'm Eric, and I'm here to help you get a better understanding of how fun and easy it is to take an edX course. So, let's get started. Let me show you how all the parts work together. If at any time you want to skip this video and get a firsthand experience of the demonstration course, all you have to do is click week one to the left. Don't worry, I won't be offended. Let's first look along the top of the page. This area's called the navigation bar. Click on Courseware to interact with your course. Course Info contains course announcements and updates from the course staff. If your course has digital textbooks, this is where you'll find them. Discussion is where you can communicate with the fellow students on topics and projects, and even occasionally with the course staff. When available, the course Wiki acts as a knowledge base for your course. It's a helpful resource. Clicking on Progress will reveal how well you're doing in your studies and exams. When you take the demo course, we'll provide you with a simple progress report matching your results. Let's look at the left column now. The left side of the Courseware screen contains a course navigation bar starting from the top down. Many courses start with an overview of edX and an introduction to the course. Below the overview are segments of the course, which are released as the course progresses. Typically, an edX course is delivered in week by week segments, and have lessons and homeworks you need to complete. Many courses are 10 to 12 weeks long. We made this demonstration course three weeks for simplicity. Let's now look at the learning sequence. Each item in the left column reveals a corresponding learning sequence. Work your way from left to right. Learning sequences can contain lectures, exercises, and interactive lessons that you can complete on your own schedule. Next, let's discover what makes edX fun and unique, its interactivity. edX prides itself on its interactive lessons, which can include demonstrations, visualizations, and virtual environments. You can try out some in the demo course. Interactive lessons are often graded and contribute to your final grade. While the edX platform also supports more traditional question formats like multiple choice, our classes also test your understanding by allowing you to use labs and simulators, and even asking you to write an essay. Example of these graded interactions are in the demo course. You can see how the questions the course uses for gauging your learning process can even be auto graded, or detailed feedback given in real time. So while an edX course might be rigorous, the tools and visualizations are really fun and truly interactive. Finally, there are many ways successful students like to you interact to get the most out of a course. Beyond the discussion forums, you can meet and engage with fellow classmates through a local meet up-- which we highly recommend-- a Google Hangout, or even invite students to join you via Twitter, Facebook, or other social networks. It's a proven fact that if you engage with others while taking a course, you're more likely to succeed. Now that you've seen how easy it is to take an edX course, experience this demonstration course. Firsthand all you have to do is click on week one to the left and you can get started. "
},
"content_type": "Video",
"id": "block-v1:edX+DemoX+Demo_Course+type@video+block@0b9e39477cf34507a7a48f74be381fdd",
"start_date": "1970-01-01T05:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Introduction",
"Demo Course Overview",
"Introduction: Video and Sequences"
],
"excerpt": " ERIC: Hi, and welcome to the edX demonstration <b>course</b>. I'm Eric, and",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@video+block@0b9e39477cf34507a7a48f74be381fdd"
},
"score": 1.4792063
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@a0effb954cca4759994f1ac9e9434bf4",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Multiple Choice Questions",
"capa_content": " Many edX courses have homework or exercises you need to complete. Notice the clock image to the left? That means this homework or exercise needs to be completed for you to pass the course. (This can be a bit confusing; the exercise may or may not have a due date prior to the end of the course.) We\u2019ve provided eight (8) examples of how a professor might ask you questions. While the multiple choice question types below are somewhat standard, explore the other question types in the sequence above, like the formula builder- try them all out. As you go through the question types, notice how edX gives you immediate feedback on your responses - it really helps in the learning process. What color is the open ocean on a sunny day? 'yellow','blue','green' Which piece of furniture is built for sitting? a table a desk a chair a bookshelf Which of the following are musical instruments? a piano a tree a guitar a window "
},
"content_type": "CAPA",
"problem_types": [
"multiplechoiceresponse",
"choiceresponse",
"optionresponse"
],
"id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@a0effb954cca4759994f1ac9e9434bf4",
"start_date": "2013-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 1: Getting Started",
"Homework - Question Styles",
"Multiple Choice Questions"
],
"excerpt": " Many edX <b>course</b>s have homework or exercises you need to complete.",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@problem+block@a0effb954cca4759994f1ac9e9434bf4"
},
"score": 1.4341705
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@75f9562c77bc4858b61f907bb810d974",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Numerical Input",
"capa_content": " Some course questions ask that you insert numbers into web-text fields, and your answers can be judged exactly - or approximately - according to the question. Note that the edX system uses a period to indicate decimals, so fifteen and three quarters is written \"15.75\", not \"15,75\". Enter the numerical value of Pi: Enter the approximate value of 502*9: Enter the number of fingernails on a healthy human hand. For the purposes of this question, please consider the thumb as a finger: "
},
"content_type": "CAPA",
"problem_types": [
"numericalresponse"
],
"id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@75f9562c77bc4858b61f907bb810d974",
"start_date": "2013-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 1: Getting Started",
"Homework - Question Styles",
"Numerical Input"
],
"excerpt": " Some <b>course</b> questions ask that you insert numbers into web-text",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@problem+block@75f9562c77bc4858b61f907bb810d974"
},
"score": 1.2987298
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@video+block@636541acbae448d98ab484b028c9a7f6",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Connecting a Circuit and a Circuit Diagram",
"transcript_en": "SPEAKER 1: What we see here-- a mess. OK? What we have is a voltmeter and an amp meter. The amp meter measures current, the voltmeter measures voltage of course. And we're measuring the voltage across the light bulb-- the lamp. And we're measuring the current into the lamp. PETER: So we've got a voltmeter measuring across the-- volts meter-- across there. And then we've got an amp reader measuring into. SPEAKER 1: Right. Exactly. Now, we're going to connect that to a battery. The three cell battery that you've seen before. And we're going to see, of course, that the light bulb lit up. And the current we measure is 122 milliamperes going into the light bulb. 122 milliamperes. And the voltage across is from the plus to minus, 4.31 volts. OK? Now, we can do another experiment. Notice how the light bulb is lit up and how much it's lit, approximately. Now, I'm going to reverse the battery so that we connect the battery in the opposite polarity. OK. Go ahead, Peter. PETER: You connect it, I will draw. SPEAKER 1: OK, I'm just doing it. PETER: So I'll swap these. SPEAKER 1: Yes, sir. OK. And what we observe is basically the amp meter is measuring 122 milliamperes in the negative direction. So that means it's measuring the current into the light bulb-- because I've not changed the orientation with respect to the light bulb-- of minus 122 milliamperes. And the voltage across the light bulb, from here to here, is minus 4.29 volts. PETER: Sorry, that's a minus? SPEAKER 1: Yes. PETER: So if we look at the power in the first case, 122 milliamps times 4.31 volts, we get 526 milliwatts. SPEAKER 1: Yep. PETER: If we measure the power in this case over here, minus 122 milliamps times minus 4.29 volts, we get approximately the same thing. So I'm going to round it off to, let's say best guess, 524, maybe 23 or something. No less. SPEAKER 1: OK. PETER: So this is equal to that within measurement error. SPEAKER 1: And of course, you see the power is the power going into the light bulb and coming out as light and heat. OK? We have arranged our measurements by having these associated reference directions, so that this is plus and that's minus, and that the current always goes into the terminal that we label with plus. That always means that the power we measure by multiplying these two numbers is the power going into this device. PETER: So this light bulb is dissipating 524 milliwatts. If we were to do the same calculation for the battery, so current would be going to the positive terminal, we would-- SPEAKER 1: Well, you have to measure it then from there to there. PETER: Yeah. Plus, minus. That's what we're doing. So this would be 4.29 volts. The current would still be minus 122 milliamps. The current's moving in a loop, so here is the same as here, but the signs are swapped. That same calculation would give us minus 524 milliwatts. And that's because the battery is outputting power, whereas the light bulb is dissipating power. SPEAKER 1: Think about it as, if we're measuring the power entering the battery, it's minus 524 milliwatts. OK? That's the way to think about it. This always gives you the power entering that element."
},
"content_type": "Video",
"id": "block-v1:edX+DemoX+Demo_Course+type@video+block@636541acbae448d98ab484b028c9a7f6",
"start_date": "2013-02-05T05:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 1: Getting Started",
"Lesson 1 - Getting Started",
"Video Presentation Styles"
],
"excerpt": "measures voltage of <b>course</b>. And we're measuring the voltage across the",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@video+block@636541acbae448d98ab484b028c9a7f6"
},
"score": 1.1870136
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@python_grader",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "",
"capa_content": " We are searching for the smallest monthly payment such that we can pay off the entire balance of a loan within a year. The following values might be useful when writing your solution Monthly interest rate = (Annual interest rate) / 12 Monthly payment lower bound = Balance / 12 Monthly payment upper bound = (Balance x (1 + Monthly interest rate)12) / 12 The following variables contain values as described below: balance - the outstanding balance on the credit card annualInterestRate - annual interest rate as a decimal Write a program that uses these bounds and bisection search (for more info check out the Wikipedia page on bisection search) to find the smallest monthly payment to the cent such that we can pay off the debt within a year. Note that if you do not use bisection search, your code will not run - your code only has 30 seconds to run on our servers. If you get a message that states \"Your submission could not be graded. Please recheck your submission and try again. If the problem persists, please notify the course staff.\", check to be sure your code doesn't take too long to run. The code you paste into the following box should not specify the values for the variables balance or annualInterestRate - our test code will define those values before testing your submission. monthlyInterestRate = annualInterestRate/12 lowerBound = balance/12 upperBound = (balance * (1+annualInterestRate/12)**12)/12 originalBalance = balance # Keep testing new payment values # until the balance is +/- $0.02 while abs(balance) &gt; .02: # Reset the value of balance to its original value balance = originalBalance # Calculate a new monthly payment value from the bounds payment = (upperBound - lowerBound)/2 + lowerBound # Test if this payment value is sufficient to pay off the # entire balance in 12 months for month in range(12): balance -= payment balance *= 1+monthlyInterestRate # Reset bounds based on the final value of balance if balance &gt; 0: # If the balance is too big, need higher payment # so we increase the lower bound lowerBound = payment else: # If the balance is too small, we need a lower # payment, so we decrease the upper bound upperBound = payment # When the while loop terminates, we know we have # our answer! print(\"Lowest Payment:\", round(payment, 2)) {\"grader\": \"ps02/bisect/grade_bisect.py\"} Note: Depending on where, and how frequently, you round during this function, your answers may be off a few cents in either direction. Try rounding as few times as possible in order to increase the accuracy of your result. Hints Test Cases to test your code with. Be sure to test these on your own machine - and that you get the same output! - before running your code on this webpage! Note: The automated tests are lenient - if your answers are off by a few cents in either direction, your code is OK. Test Cases: Test Case 1: balance = 320000 annualInterestRate = 0.2 Result Your Code Should Generate: ------------------- Lowest Payment: 29157.09 Test Case 2: balance = 999999 annualInterestRate = 0.18 Result Your Code Should Generate: ------------------- Lowest Payment: 90325.07 The autograder says, \"Your submission could not be graded.\" Help! If the autograder gives you the following message: Your submission could not be graded. Please recheck your submission and try again. If the problem persists, please notify the course staff. Don't panic! There are a few things that might be wrong with your code that you should check out. The number one reason this message appears is because your code timed out. You only get 30 seconds of computation time on our servers. If your code times out, you probably have an infinite loop. What to do? The number 1 thing to do is that you need to run this code in your own local environment. Your code should print one line at the end of the loop. If your code never prints anything out - you have an infinite loop! To debug your infinite loop - check your loop conditional. When will it stop? Try inserting print statements inside your loop that prints out information (like variables) - are you incrementing or decrementing your loop counter correctly? Search the forum for people with similar issues. If your search turns up nothing, make a new post and paste in your loop conditional for others to help you out with. Please don't email the course staff unless your code legitimately works and prints out the correct answers in your local environment. In that case, please email your code file, a screenshot of the code printing out the correct answers in your local environment, and a screenshot of the exact same code not working on the tutor. The course staff is otherwise unable to help debug your problem set via email - we can only address platform issues. "
},
"content_type": "CAPA",
"problem_types": [
"coderesponse"
],
"id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@python_grader",
"start_date": "2013-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 2: Get Interactive",
"Homework - Labs and Demos",
"Code Grader"
],
"excerpt": "notify the <b>course</b> staff.\", check to be sure your code doesn't take too",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@problem+block@python_grader"
},
"score": 1.0107487
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@9cee77a606ea4c1aa5440e0ea5d0f618",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Interactive Questions",
"capa_content": " Most courses have interactive questions that test your knowledge like the one below. They can be part of a learning sequence or an exam. Notice the visual feedback. Go ahead, try it out! Questions which are part of assignments or exams may have due dates - the last possible time you can submit an assignment for grading. Once this time has passed, you will not be able to get credit for any incomplete problems in the assignment. If an assignment has a due date, you can see the due date in the sidebar. (This demo course does not have any assignments with due dates.) If no due date is displayed, the assignment can be turned in at any time. All assignment due dates are displayed in the time zone that you select in your account settings. If you do not specify a time zone, assignment due dates display in your browser's time zone. What kinds of late policies does edX allow? late penalties instructor forgiveness late time budget none of the above "
},
"content_type": "CAPA",
"problem_types": [
"choiceresponse"
],
"id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@9cee77a606ea4c1aa5440e0ea5d0f618",
"start_date": "2013-02-05T05:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 1: Getting Started",
"Lesson 1 - Getting Started",
"Interactive Questions"
],
"excerpt": " Most <b>course</b>s have interactive questions that test your knowledge like",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@problem+block@9cee77a606ea4c1aa5440e0ea5d0f618"
},
"score": 0.96387196
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@html+block@030e35c4756a4ddc8d40b95fbbfff4d4",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Blank HTML Page",
"html_content": "Welcome to the Open edX Demo Course Introduction. This is where you can explore how to take an edX course (like this one). Most courses have an \"intro\" video that shows you how it all works. You can watch the introduction video (below) or scroll though the course studies and assignments using the toolbar (above). Just for fun, we'll keep track of your work in this demo course, and show you your progress in the toolbar just like in a real course. Watch the overview video (below), then click on \"Example Week One\" in the left hand navigation to get started. "
},
"content_type": "Text",
"id": "block-v1:edX+DemoX+Demo_Course+type@html+block@030e35c4756a4ddc8d40b95fbbfff4d4",
"start_date": "1970-01-01T05:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Introduction",
"Demo Course Overview",
"Introduction: Video and Sequences"
],
"excerpt": "Welcome to the Open edX Demo <b>Course</b> Introduction. This is where you",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@html+block@030e35c4756a4ddc8d40b95fbbfff4d4"
},
"score": 0.8844358
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@html+block@html_49b4494da2f7",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Discussion Forums",
"html_content": "Discussion FORUMS The discussion forum for each course is found at the top of the course page. You might come across a subset of the discussion forum inside the course (see below), where you can talk with fellow students about the course in context. Go ahead and be social! Make your first post in this demo course. Keep an eye out for posts with a green check mark. The green check means the post has been recognized by a staff member or forum moderator as a great post. You can also actively upvote a post. Others can search on user \u201cupvoted\u201d posts. They tend to be very helpful. "
},
"content_type": "Text",
"id": "block-v1:edX+DemoX+Demo_Course+type@html+block@html_49b4494da2f7",
"start_date": "1978-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 3: Be Social",
"Lesson 3 - Be Social",
"Discussion Forums"
],
"excerpt": "Discussion FORUMS The discussion forum for each <b>course</b> is found at the",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@html+block@html_49b4494da2f7"
},
"score": 0.8803684
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@html+block@f4a39219742149f781a1dda6f43a623c",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Overall Grade",
"html_content": " OVERALL GRADE PERFORMANCE The progress tab (selectable near the top of each page in your course) shows your performance. Click on it now, and you will see how you're doing in this demo course. The bar chart shows the overall percentage that you have earned on each assignment in the course, and how each of those assignments combine into your overall grade. Further down the page is a detailed breakdown of your score on every graded question in the class. You might notice that some of your assignments on the bar chart show an 'x'. The 'x's indicate the assignments that the edX system will NOT be counting toward your final grade, according to the course grading. The 'x's go to the assignments that you scored the lowest on. Each course has its own percentage cutoff for a Certificate of Mastery. You can see where those cutoffs are by looking at the vertical description. In this demo, a \"pass\" is considered 60%. When you \"pass\" a live edX course, you will receive a certificate after the class has closed. Sorry - the demo course does not grant certificates! "
},
"content_type": "Text",
"id": "block-v1:edX+DemoX+Demo_Course+type@html+block@f4a39219742149f781a1dda6f43a623c",
"start_date": "2013-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"About Exams and Certificates",
"edX Exams",
"Overall Grade Performance"
],
"excerpt": "of each page in your <b>course</b>) shows your performance. Click on it now,",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@html+block@f4a39219742149f781a1dda6f43a623c"
},
"score": 0.87981963
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@html+block@87fa6792d79f4862be098e5169e93339",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Blank HTML Page",
"html_content": "Find Your Study Buddy Working with other students offline can help you get the most out of an online course and even increase the likelihood you will successfully complete the course. So, your homework is to find a study buddy. The course specific discussion forums are a great place to find neighbors or even new friends to invite to a Meetup you are looking to organize or even a virtual Google Hangout. "
},
"content_type": "Text",
"id": "block-v1:edX+DemoX+Demo_Course+type@html+block@87fa6792d79f4862be098e5169e93339",
"start_date": "1978-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 3: Be Social",
"Lesson 3 - Be Social",
"Homework - Find Your Study Buddy"
],
"excerpt": "get the most out of an online <b>course</b> and even increase the likelihood",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@html+block@87fa6792d79f4862be098e5169e93339"
},
"score": 0.84284115
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@html+block@6018785795994726950614ce7d0f38c5",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Find Your Study Buddy",
"html_content": "Find Your Study Buddy Working with other students offline can help you get the most out of an online course and even increase the likelihood you will successfully complete the course. So, your homework is to find a study buddy. The course specific discussion forums are a great place to find neighbors or even new friends to invite to a Meetup you are looking to organize or even a virtual Google Hangout. "
},
"content_type": "Text",
"id": "block-v1:edX+DemoX+Demo_Course+type@html+block@6018785795994726950614ce7d0f38c5",
"start_date": "2013-02-05T05:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 3: Be Social",
"Homework - Find Your Study Buddy",
"Homework - Find Your Study Buddy"
],
"excerpt": "get the most out of an online <b>course</b> and even increase the likelihood",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@html+block@6018785795994726950614ce7d0f38c5"
},
"score": 0.84284115
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@html+block@f9f3a25e7bab46e583fd1fbbd7a2f6a0",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "Be Social",
"html_content": "Be SOCIAL A big part of learning online includes \u201cbeing social.\u201d We encourage all students to communicate within the course discussion forums \u2013 a great place to connect with other students and to get support from the course staff. Some students and professors also engage through other social mediums like Meetup or Facebook. Recent research has found that if you take a class with a friend, or engage socially with other learners while taking a course, there is a higher likelihood that you will complete a course. If you haven\u2019t already, consider finding a study buddy! Check out more information about the discussion forum by navigating to the next item in this learning sequence. In the discussion forums, remember to be polite and respectful. Simply put, treat others the way you want to be treated. "
},
"content_type": "Text",
"id": "block-v1:edX+DemoX+Demo_Course+type@html+block@f9f3a25e7bab46e583fd1fbbd7a2f6a0",
"start_date": "1978-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 3: Be Social",
"Lesson 3 - Be Social",
"Be Social"
],
"excerpt": "encourage all students to communicate within the <b>course</b> discussion",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@html+block@f9f3a25e7bab46e583fd1fbbd7a2f6a0"
},
"score": 0.84210813
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@html+block@8293139743f34377817d537b69911530",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "EdX Exams",
"html_content": " EDX EXAMS Not all edX courses have exams; many do, but not all. When choosing a course, it's a good idea to check the exam and study requirements, as well as any prerequisites. Of course - you can \"audit\" any edX course, which means you can study alongside other students using the same content, tools and materials, but you're not focused on grades and might skip the exams and assignments. Follow this learning sequence via the links above to understand more about how we grade your work and track your progress. "
},
"content_type": "Text",
"id": "block-v1:edX+DemoX+Demo_Course+type@html+block@8293139743f34377817d537b69911530",
"start_date": "2013-02-05T00:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"About Exams and Certificates",
"edX Exams",
"EdX Exams"
],
"excerpt": " EDX EXAMS Not all edX <b>course</b>s have exams; many do, but not all. When",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@html+block@8293139743f34377817d537b69911530"
},
"score": 0.8306555
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "block-v1:edX+DemoX+Demo_Course+type@html+block@9d5104b502f24ee89c3d2f4ce9d347cf",
"data": {
"course": "course-v1:edX+DemoX+Demo_Course",
"org": "edX",
"content": {
"display_name": "When Are Your Exams? ",
"html_content": "WHEN ARE YOUR Exams? Every course treats the timing on its exams differently, and you should be really careful to pay attention to any announcements about exam timing that your course makes. "
},
"content_type": "Text",
"id": "block-v1:edX+DemoX+Demo_Course+type@html+block@9d5104b502f24ee89c3d2f4ce9d347cf",
"start_date": "2013-02-05T05:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": [
"Example Week 1: Getting Started",
"Lesson 1 - Getting Started",
"When Are Your Exams? "
],
"excerpt": "WHEN ARE YOUR Exams? Every <b>course</b> treats the timing on its exams",
"url": "/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@html+block@9d5104b502f24ee89c3d2f4ce9d347cf"
},
"score": 0.82610154
},
{
"_index": "courseware_content",
"_type": "_doc",
"_id": "some-external-reference",
"data": {
"course": "External Course",
"org": "edX",
"content": {
"display_name": "External Course Link Test",
"html_content": "This should open a new tab when following the link."
},
"content_type": "Unknown",
"id": "random-element-id",
"start_date": "2013-02-05T05:00:00+00:00",
"content_groups": null,
"course_name": "Demonstration Course",
"location": null,
"excerpt": "Just testing external links",
"url": "https://www.edx.org"
},
"score": 0.82610154
}
],
"access_denied_count": 0
}

View File

@@ -0,0 +1,17 @@
import { camelCaseObject } from '@edx/frontend-platform';
import mockedData from './mocked-response.json';
import mapSearchResponse from '../map-search-response';
function searchResultsFactory(searchKeywords = '', moreInfo = {}) {
const data = camelCaseObject(mockedData);
const info = mapSearchResponse(data, searchKeywords);
const result = {
...info,
...moreInfo,
};
return result;
}
export default searchResultsFactory;

View File

@@ -0,0 +1,123 @@
import { Factory } from 'rosie'; // eslint-disable-line import/no-extraneous-dependencies
import courseMetadataBase from '../../../shared/data/__factories__/courseMetadataBase.factory';
Factory.define('courseHomeMetadata')
.extend(courseMetadataBase)
.option('host', 'http://localhost:18000')
.attrs({
title: 'Demonstration Course',
is_new_discussion_sidebar_view_enabled: false,
is_self_paced: false,
is_enrolled: false,
is_staff: false,
can_view_certificate: true,
celebrations: null,
course_access: {
additional_context_user_message: null,
developer_message: null,
error_code: null,
has_access: true,
user_fragment: null,
user_message: null,
},
number: 'DemoX',
original_user_is_staff: false,
org: 'edX',
start: '2013-02-05T05:00:00Z',
user_timezone: 'UTC',
username: 'MockUser',
verified_mode: {
access_expiration_date: null,
currency: 'USD',
upgrade_url: 'http://localhost:18130/basket/add/?sku=8CF08E5',
sku: '8CF08E5',
price: 149,
currency_symbol: '$',
},
})
.attr('tabs', ['id', 'host'], (id, host) => [
Factory.build(
'tab',
{
title: 'Course',
priority: 0,
slug: 'courseware',
type: 'courseware',
},
{
courseId: id,
host,
path: 'course/',
},
),
Factory.build(
'tab',
{
title: 'Discussion',
priority: 1,
slug: 'discussion',
type: 'discussion',
},
{
courseId: id,
host,
path: 'discussion/forum/',
},
),
Factory.build(
'tab',
{
title: 'Wiki',
priority: 2,
slug: 'wiki',
type: 'wiki',
},
{
courseId: id,
host,
path: 'course_wiki',
},
),
Factory.build(
'tab',
{
title: 'Progress',
priority: 3,
slug: 'progress',
type: 'progress',
},
{
courseId: id,
host,
path: 'progress',
},
),
Factory.build(
'tab',
{
title: 'Instructor',
priority: 4,
slug: 'instructor',
type: 'instructor',
},
{
courseId: id,
host,
path: 'instructor',
},
),
Factory.build(
'tab',
{
title: 'Dates',
priority: 5,
slug: 'dates',
type: 'dates',
},
{
courseId: id,
host,
path: 'dates',
},
),
]);

View File

@@ -0,0 +1,222 @@
import { Factory } from 'rosie'; // eslint-disable-line import/no-extraneous-dependencies
// Sample data helpful when developing & testing, to see a variety of configurations.
// This set of data is not realistic (mix of having access and not), but it
// is intended to demonstrate many UI results.
Factory.define('datesTabData')
.attrs({
dates_banner_info: {
content_type_gating_enabled: false,
missed_gated_content: false,
missed_deadlines: false,
verified_upgrade_link: 'http://localhost:18130/basket/add/?sku=8CF08E5',
},
course_date_blocks: [
{
date: '2020-05-01T17:59:41Z',
date_type: 'course-start-date',
description: '',
learner_has_access: true,
link: '',
title: 'Course Starts',
extra_info: null,
},
{
assignment_type: 'Homework',
complete: true,
date: '2020-05-04T02:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
title: 'Multi Badges Completed',
extra_info: null,
},
{
assignment_type: 'Homework',
date: '2020-05-05T02:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
title: 'Multi Badges Past Due',
extra_info: null,
},
{
assignment_type: 'Homework',
date: '2020-05-27T02:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
link: 'https://example.com/',
title: 'Both Past Due 1',
extra_info: null,
},
{
assignment_type: 'Homework',
date: '2020-05-27T02:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
link: 'https://example.com/',
title: 'Both Past Due 2',
extra_info: null,
},
{
assignment_type: 'Homework',
complete: true,
date: '2020-05-28T08:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
link: 'https://example.com/',
title: 'One Completed/Due 1',
extra_info: null,
},
{
assignment_type: 'Homework',
date: '2020-05-28T08:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
link: 'https://example.com/',
title: 'One Completed/Due 2',
extra_info: null,
},
{
assignment_type: 'Homework',
complete: true,
date: '2020-05-29T08:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
link: 'https://example.com/',
title: 'Both Completed 1',
extra_info: null,
},
{
assignment_type: 'Homework',
complete: true,
date: '2020-05-29T08:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
link: 'https://example.com/',
title: 'Both Completed 2',
extra_info: null,
},
{
date: '2020-06-16T17:59:40.942669Z',
date_type: 'verified-upgrade-deadline',
description: "Don't miss the opportunity to highlight your new knowledge and skills by earning a verified certificate.",
learner_has_access: true,
link: 'https://example.com/',
title: 'Upgrade to Verified Certificate',
extra_info: null,
},
{
assignment_type: 'Homework',
date: '2030-08-17T05:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: false,
link: 'https://example.com/',
title: 'One Verified 1',
extra_info: null,
},
{
assignment_type: 'Homework',
date: '2030-08-17T05:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
link: 'https://example.com/',
title: 'One Verified 2',
extra_info: null,
},
{
assignment_type: 'Homework',
date: '2030-08-17T05:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
link: 'https://example.com/',
title: 'ORA Verified 2',
extra_info: "ORA Dates are set by the instructor, and can't be changed",
},
{
assignment_type: 'Homework',
date: '2030-08-18T05:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: false,
link: 'https://example.com/',
title: 'Both Verified 1',
extra_info: null,
},
{
assignment_type: 'Homework',
date: '2030-08-18T05:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: false,
link: 'https://example.com/',
title: 'Both Verified 2',
extra_info: null,
},
{
assignment_type: 'Homework',
date: '2030-08-19T05:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
title: 'One Unreleased 1',
},
{
assignment_type: 'Homework',
date: '2030-08-19T05:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
link: 'https://example.com/',
title: 'One Unreleased 2',
extra_info: null,
},
{
assignment_type: 'Homework',
date: '2030-08-20T05:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
title: 'Both Unreleased 1',
extra_info: null,
},
{
assignment_type: 'Homework',
date: '2030-08-20T05:59:40.942669Z',
date_type: 'assignment-due-date',
description: '',
learner_has_access: true,
title: 'Both Unreleased 2',
extra_info: null,
},
{
date: '2030-08-23T00:00:00Z',
date_type: 'course-end-date',
description: '',
learner_has_access: true,
link: '',
title: 'Course Ends',
extra_info: null,
},
{
date: '2030-09-01T00:00:00Z',
date_type: 'verification-deadline-date',
description: 'You must successfully complete verification before this date to qualify for a Verified Certificate.',
learner_has_access: false,
link: 'https://example.com/',
title: 'Verification Deadline',
extra_info: null,
},
],
has_ended: false,
learner_is_full_access: true,
});

View File

@@ -0,0 +1,5 @@
import './courseHomeMetadata.factory';
import './datesTabData.factory';
import './outlineTabData.factory';
import './progressTabData.factory';
import './upgradeNotificationData.factory';

Some files were not shown because too many files have changed in this diff Show More