Compare commits

...

1537 Commits

Author SHA1 Message Date
Neo
c751c8b19a Andal Learning branding: Apply orange color #ff4f00 to buttons/navbar/tabs, hide footer
Some checks failed
validate / tests (push) Has been cancelled
validate / coverage (push) Has been cancelled
Lockfile Version check / version-check (push) Has been cancelled
Update Browserslist DB / update-browserslist (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 14:52:43 +07:00
renovate[bot]
449af65d01 chore(deps): update dependency oxlint-tsgolint to ^0.16.0 (#2930)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-09 09:40:45 -07:00
edX requirements bot
fce65c0215 chore: update browserslist DB (#2929)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2026-03-09 00:26:52 +00:00
Muhammad Waleed
abcef4a502 fix: refresh search token after library (#2924)
creation for course creator access

  When a course creator creates a new library, the cached JWT token for
  Meilisearch needs to be refreshed to include the new library's access_id.
  Without this, newly added components won't appear in search results until
  the page is refreshed.

  This works in conjunction with the backend fix that creates SearchAccess
  records immediately on library creation.

  The fix invalidates the content_search query, triggering React Query to
  refetch the token with updated access permissions.
2026-03-05 14:17:27 +05:00
dependabot[bot]
5c1cdcf01c chore(deps): bump actions/upload-artifact from 6 to 7 (#2920)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  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>
2026-03-02 13:43:43 -08:00
dependabot[bot]
4dccc12883 chore(deps): bump actions/download-artifact from 7 to 8 (#2921) 2026-03-02 13:43:20 -08:00
renovate[bot]
f0e735b3a1 chore(deps): update codemirror (#2895)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-02 13:41:55 -08:00
Chris Chávez
091d9a1c3e refactor: Migrate courseExport from redux store to React Query (#2908) 2026-03-02 17:12:02 +00:00
edX requirements bot
7157d17a4e chore: update browserslist DB (#2918)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2026-03-02 00:43:27 +00:00
Muhammad Anas
65096fde0e feat: add card in Pages and Resources to allow hiding the dates tab (#2834) 2026-02-27 15:37:41 -08:00
Braden MacDonald
af204c78a5 test: run only oxlint, not eslint (#2909) 2026-02-27 09:12:24 -08:00
Rômulo Penido
2e6209314f feat: add fullscreen button to XBlock editor (#2892) 2026-02-27 10:05:14 -05:00
Navin Karkera
060f7d4618 refactor(course-outline): replace thunks with react query, add typed APIs, and improve type usages (#2900)
* Replaces configure xblock and section highlights redux functions with react-query.
* Replaces section highlights thunks with react query
* Replaces duplicate block thunks
* Removes add subsection, unit redux functions
* Replaces scrollTo redux state to react-query based state.
* Replaces paste unit block redux functions
* Removes a lot of redux related functions as a result.
* Reduces API calls without compromising data integrity.
2026-02-27 09:23:46 -05:00
Chris Chávez
815b80a944 refactor: Migrate advancedSettings from the redux store to React Query (#2893) 2026-02-26 23:17:57 +00:00
Bryann Valderrama
e8cd7c2dcc feat: add team groups section in group configurations (#1728) 2026-02-26 14:02:31 -08:00
Chris Chávez
c4a09a2b43 refactor: Migrate courseImport from redux store to React query (#2902) 2026-02-26 14:34:13 -05:00
Areeb Sajjad
3599630cd7 fix: allow configure modal overflow to prevent datepicker clipping (#2901) 2026-02-25 17:19:18 -08:00
Chris Chávez
56726448fc Refactor: Move courseTeam from redux store to react query (#2888)
* refactor: Move `courseTeam` from redux store to react query

* fix: Broken types

* fix: Show user readable error

* fix: Broken coverage

* fix: Broken coverage

* refactor: Add default message error
2026-02-24 10:11:36 -05:00
renovate[bot]
b57386b9b6 chore(deps): update dependency oxlint-tsgolint to ^0.14.0 (#2896)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-23 22:46:26 +00:00
renovate[bot]
e9bf4566de chore(deps): update dependency @types/lodash to v4.17.24 (#2897)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-23 21:09:45 +00:00
edX requirements bot
1324b33789 chore: update browserslist DB (#2899)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2026-02-23 21:09:26 +00:00
Taylor Payne
b256036527 fix: correct typos in user-facing messages (#2894) 2026-02-21 11:43:13 -08:00
Navin Karkera
ee6006e0e3 refactor(course-outline): improve query cache handling and remove redux thunks (#2884)
- Centralizes and reuses query cache handling logic:
Introduces a `ParentIds` type (src/generic/types.ts) and standardizes its use across data/API hooks for updating or invalidating parent/child query caches.
- Ensures cache coherence using `cancelQueries` before updating query data:
Before calling `setQueryData` for any block, any inflight queries are cancelled to prevent race conditions and stale UI.
- Simplifies post-sync/invalidation flows:
Removes Redux thunk usages in favor of direct query invalidations using React Query APIs within course outline cards, sidebars, publish modal, and `unlinkmodal`.
- Refactors data types for clarity:
Splits XBlock into `XBlockBase` and derived interfaces so the presence of `childInfo` is explicit.
- Cleans up redundant code and props:
Removes unnecessary `memoization`, `useDispatch` imports, and duplicate logic in React components.
2026-02-20 13:10:28 -05:00
MuPp3t33r
8f8c6d8dd2 refactor: update relative path to absolute path alias (#2891) 2026-02-20 09:10:25 -08:00
Chris Chávez
7c1eb59f18 feat: Make selectable component cards & Component Info Sidebar [FC-0114] (#2880)
- Changes in the Unit sidebar context to enable selected components
- Implements the component info sidebar.
- Implements the container/component selection when opening the align sidebar
2026-02-19 17:02:26 -05:00
Rodrigo Mendez
5ccf39d130 feat: Add validation for Advanced Settings permissions using openedx-authz (#2869)
* feat: Add validation for Advanced Settings permissions using openedx-authz

* squash!: Increase test coverage

* squash!: Fix lint issues

* squash!: Validate advanced settings permission on HelpSidebar

* squash!: Increase test coverage

* squash!: Attend PR comments
2026-02-19 14:39:04 -06:00
Chris Chávez
42f26e7404 refactor: Move redux to react query in course checklist (#2870) 2026-02-19 13:10:18 -05:00
renovate[bot]
01ddf0d2ad chore(deps): update dependency @edx/frontend-platform to v8.5.5 (#2882)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-18 23:20:06 +00:00
renovate[bot]
7a8b4ced01 chore(deps): update dependency fast-xml-parser to v5.3.6 [security] (#2886)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-18 23:18:47 +00:00
Muhammad Faraz Maqsood
e116e10845 fix: localize rerun button text (#2887)
* fix: localize rerun button text

* chore: use <FormattedMessage /> instead of formatMessage()

---------

Co-authored-by: Muhammad Faraz  Maqsood <faraz.maqsood@A006-01130.local>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2026-02-18 22:58:12 +00:00
MuPp3t33r
0b357a1be1 fix: Replace duplicate hardcoded max file size with constant (#2875) 2026-02-18 14:26:08 -08:00
edX requirements bot
e281681168 chore: update browserslist DB (#2881)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2026-02-16 00:32:33 +00:00
Chris Chávez
c39923fc81 fix: Nits on UX/UI in the new sidebars in course outline and unit page [FC-0114] (#2871)
- Fixes the open nits/issues listed in https://github.com/openedx/frontend-app-authoring/issues/2868
- Fixes the small nit in the back button in the import workflow: https://github.com/openedx/frontend-app-authoring/issues/2524#issuecomment-3849649651
- Fixes the small nit in the unsupported text in the import workflow: https://github.com/openedx/frontend-app-authoring/issues/2525#issuecomment-3862737018. This fix depends on https://github.com/openedx/openedx-platform/pull/38005
2026-02-13 15:09:28 -05:00
Chris Chávez
4d401a9c22 feat: Unit align sidebar [FC-0114] (#2856)
Implements the align sidebar in the unit page for the unit and components
2026-02-13 15:07:53 -05:00
renovate[bot]
72421969d9 chore(deps): update dependency @tanstack/react-query to v5.90.21 (#2858)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-13 14:28:28 -05:00
renovate[bot]
0aad03420b chore(deps): update codemirror (#2857)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-13 19:28:19 +00:00
renovate[bot]
45811ce6de chore(deps): update dependency fast-xml-parser to v5.3.5 (#2867)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-13 11:14:30 -08:00
renovate[bot]
d1c3fb96de chore(deps): update dependency @types/react to v18.3.28 (#2866)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-09 10:38:36 -08:00
Chris Chávez
2d5421e09f feat: Unit Add sidebar [FC-0114] (#2837)
Implements the new Unit add Sidebar
2026-02-09 13:17:04 -05:00
Chris Chávez
a16087a1d0 fix: Nits on the style of library icon [FC-0114] (#2863) 2026-02-09 11:59:24 -05:00
Navin Karkera
bb6b2ab33c feat: container info sidebar and add sidebar updates (#2830)
* Adds section, subsection and unit sidebar info tab in course outline as described in https://github.com/openedx/frontend-app-authoring/issues/2638
* Updates the sidebar design and behaviour as per https://github.com/openedx/frontend-app-authoring/issues/2826
* Updates course outline to use react query and removes redux store usage as much as possible. Updated parts that require absolutely cannot work without redux without heavy refactoring (will require quiet some time) to work in tandem with react-query.
2026-02-09 11:03:27 -05:00
renovate[bot]
eae178a9ec chore(deps): update dependency lodash to v4.17.23 [security] (#2861)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-09 00:44:37 +00:00
edX requirements bot
2ab1219f36 chore: update browserslist DB (#2865)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2026-02-09 00:28:05 +00:00
Rômulo Penido
7173b71cc4 fix: update sidebar design (#2852) 2026-02-05 15:44:46 -05:00
Brian Smith
f900ace15c chore(deps): regenerate package-lock.json (#2862)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-02-02 13:58:30 -08:00
Braden MacDonald
d44425c68f test: lint using oxlint as well as eslint (#2847)
PR enables the use of oxlint (type-aware) alongside eslint, on a trial basis. Oxlint supports most of the same rules, plus more, is eslint compatible, and is much, much faster.
2026-02-02 11:47:31 -05:00
Braden MacDonald
6effb4d39e chore: fix various lint/type issues found by oxlint (#2850) 2026-01-31 01:01:11 +00:00
Rômulo Penido
b0066e547c feat: create context for sidebarPages (#2827)
Creates the `OutlineSidebarPagesContext` so we can add new pages using plugins, as in https://github.com/openedx/frontend-plugin-aspects/pull/115
2026-01-30 17:52:52 -05:00
Rômulo Penido
6558c2b1ed fix: access restricted label refresh (#2846) 2026-01-30 17:09:42 -05:00
Braden MacDonald
747c2bc1b0 chore: clean up ValidationResult for NumericalInput problems (#2849) 2026-01-29 09:48:40 -08:00
Braden MacDonald
27e709912d fix: don't use eval() to parse OLX (#2848) 2026-01-29 10:39:48 -05:00
Braden MacDonald
9d9d7a7167 fix: resolve incorrect or missing 'await' usages (#2592)
* chore: fix incorrect or missing 'await' usages
* test: fix broken test
* chore: ignore lines causing patch coverage to fail
2026-01-28 16:48:13 -08:00
renovate[bot]
7e53e1143f chore(deps): update codemirror (#2840)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-28 16:32:53 -08:00
renovate[bot]
66656753b4 fix(deps): update dependency @edx/browserslist-config to v1.5.1 (#2844)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-28 10:41:07 -08:00
Irtaza Akram
05de984fa4 fix: show deafult grading method 2026-01-28 08:57:04 -05:00
Irtaza Akram
f6da58a950 fix: test 2026-01-28 08:57:04 -05:00
Irtaza Akram
5e5c92f487 fix: type error 2026-01-28 08:57:04 -05:00
Irtaza Akram
10705bc921 fix: test failures 2026-01-28 08:57:04 -05:00
Irtaza Akram
2e836a55cf fix: add grading method view 2026-01-28 08:57:04 -05:00
Braden MacDonald
292a457834 chore: rename more files from .js to .ts (#2842)
* chore: rename more files from .js to .ts

* fix: fix some little issues caught by TS

* fix: fix type of 'certificateId'
2026-01-27 13:16:47 -08:00
renovate[bot]
5d97a98294 chore(deps): update dependency @edx/frontend-platform to v8.5.4 (#2838)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-26 17:46:53 -08:00
renovate[bot]
53923d0db4 chore(deps): update dependency @testing-library/react to v16.3.2 (#2841)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-26 15:44:27 -08:00
Chris Chávez
5157cbcfb2 feat: New Unit info sidebar [FC-0114] (#2822)
- Implements the basics for the Unit Sidebar:
    - Splits the sidebar in legacy sidebar and in the new sidebar
- Implements the Unit Info Sidebar:
    - Implements a new design for the visibility and publish status card.
    - Implements the new Visibility field.
    - Implements the settings tab for the sidebar. Implements all the new form to edit the 
      settings in the sidebar.
2026-01-26 16:18:32 -05:00
Chris Chávez
ef93e95dd7 feat: New header in course unit page [FC-0114] (#2751)
- `ENABLE_UNIT_PAGE_NEW_DESIGN` flag created
- New Status Bard implemented in the header of the course unit page.
- New buttons added in the header of the course unit page.
- Which user roles will this change impact? "Course Author".
2026-01-26 12:52:50 -05:00
Braden MacDonald
1626d6808d chore: rename all 'messages.js' to 'messages.ts' (#2836) 2026-01-26 12:22:09 -05:00
edX requirements bot
b1c3151ca1 chore: update browserslist DB (#2839)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2026-01-26 00:24:23 +00:00
renovate[bot]
bea1619537 chore(deps): update dependency @openedx/paragon to v23.19.1 (#2765)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-23 23:00:25 +00:00
Navin Karkera
89e327b633 feat: course outline header update [FC-0114] (#2823)
Modifies new course outline header and actions
2026-01-23 09:08:19 -05:00
Braden MacDonald
0db79f3527 fix: clean up invalid breadcrumb usages in library updates (#2811) 2026-01-22 09:45:34 -08:00
Chris Chávez
82e24193a8 refactor: Use preview migration API & feat: Block import when the import would exceed the block limit [FC-0112] (#2700)
- Use the new preview migration API implemented in https://github.com/openedx/edx-platform/pull/37818
- Clean the code for the preview.
- Implements the commented in https://github.com/openedx/frontend-app-authoring/issues/2525#issuecomment-3554310315
2026-01-20 14:44:35 -05:00
renovate[bot]
f57d33a74e chore(deps): update react-router monorepo to v6.30.3 (#2819)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-19 16:35:50 -08:00
Chris Chávez
0b2b8e142c feat: New align sidebar for Course Outline [FC-0114] (#2812)
- Adds the align sidebar for Course and Section/Subsection/Unit cards (https://github.com/openedx/frontend-app-authoring/issues/2625)
- Add a new library lock icon to tags imported from upstream (https://github.com/openedx/frontend-app-authoring/issues/2234)
2026-01-19 11:59:43 -05:00
edX requirements bot
d5352b8632 chore: update browserslist DB (#2828)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2026-01-19 00:24:56 +00:00
Chris Chávez
3076dc7598 fix: Bug when adding spaces to containers names in course outline (#2825)
- Fixes the bug introduced in https://github.com/openedx/frontend-app-authoring/pull/2732
- Removes the unnecessary `preventDefault`
2026-01-15 09:12:35 -05:00
Navin Karkera
a23a4da0a2 feat: add content in location in course outline [FC-0114] (#2820)
- Add container in-location in course outline using new add sidebar.
- Creates the placeholder card while creating a container
2026-01-15 07:29:26 -05:00
Chris Chávez
4cda17e046 feat: Make sections/subsections/units selectable in course outline [FC-0114] (#2732) 2026-01-12 21:12:46 -05:00
renovate[bot]
969f7a2858 chore(deps): update dependency @types/lodash to v4.17.23 (#2818)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-12 09:47:14 -08:00
edX requirements bot
12f1c2b1f5 chore: update browserslist DB (#2817)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2026-01-12 00:26:34 +00:00
Muhammad Anas
6464f37e2a feat: plugin slot for marketing banner on Schedule & Details page (#2748)
* feat: add Page Banner Slot for Schedule and Details Page

* fix: js to ts

* fix: remove js

* fix: lint issues

* fix: issues

* fix: lint issues

* fix: issues

* fix: issue

* fix: issue
2026-01-09 15:21:12 -08:00
renovate[bot]
5641daf68d chore(deps): update dependency react-responsive to v10 (#2784)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-09 11:16:35 -08:00
Navin Karkera
3c22e4bbe1 feat: Add sidebar and library dropdown filter [FC-0114] (#2778)
* Add flow in course outline sidebar. Allows author to add new section/subsection/unit or any container from existing libraries via sidebar.
* Adds library dropdown filter and collections dropdown filter in add sidebar. Allows authors to filter containers by selected libraries and collections.
2026-01-09 12:14:48 -05:00
renovate[bot]
a7cbfead75 chore(deps): update codemirror to v6.5.3 (#2771)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-09 00:52:38 +00:00
renovate[bot]
7b0223cefc chore(deps): update dependency @tanstack/react-query to v5.90.16 (#2781)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-08 16:39:20 -08:00
renovate[bot]
478749028b chore(deps): update dependency @testing-library/react to v16.3.1 (#2770)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-07 09:49:31 -08:00
Rômulo Penido
220924233e feat: course outline sidebar (#2731)
implements the new sidebar design for the Course Outline
2026-01-06 08:13:25 -05:00
edX requirements bot
122414cb73 chore: update browserslist DB (#2780)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2026-01-05 00:25:41 +00:00
Rômulo Penido
fd0395ba03 fix: make sidebar (and content) fill the whole page (#2777) 2025-12-31 18:15:47 -05:00
Navin Karkera
38dfb68286 refactor: course import analysis and details page in libraries (#2774)
* Updates analysis details body text
* Updates partial banner text
* Rounds percentage of supported blocks
* Removes unsupported children blocks from total counts and percentages.
* Updates spacing in analysis page.
2025-12-31 10:36:44 -05:00
Navin Karkera
0f20267cc4 feat: course import filter in library and fix list order (#2773)
* Adds filter to show/hide previously imported courses in course import page in libraries.
* Fix issue with ordering of courses listing.
2025-12-29 09:37:44 -05:00
Rômulo Penido
7f10575b52 fix: import summary text (#2772)
Updates the text on the import summary shown on partial imports.
2025-12-24 12:28:31 -05:00
Chris Chávez
ef6bd073c0 refactor: Migrate accessibilityPage variable in Redux store to React Query (#2760) 2025-12-23 09:18:13 -05:00
Navin Karkera
f4d20eba45 feat: bulk update legacy library references (#2764)
Shows an alert in course outline and review tab of course libraries page when the course contains legacy library content blocks that depend on libraries that are already migrated to library v2, i.e. the blocks are ready to be converted into item banks that can make use of these new v2 libraries.
Authors can click on a single button to convert all references in a single go. The button launches a background task which is then polled by the frontend and the status is presented to the Author.
2025-12-22 12:54:54 -05:00
edX requirements bot
68a4b04475 chore: update browserslist DB (#2769)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-12-22 00:24:49 +00:00
Diana Villalvazo
c2592a7e6e Add external links override support (#2730)
* feat: add external links override support

* fix: add note, fix 404 url and fix unrelated typo

* test: fix
2025-12-19 13:06:03 -06:00
Jesus Balderrama
9072bb66b7 feat: better validation for NumericalInput problem editor (#2615)
* feat(form): add validation to NumericalInput to accept only numeric values

* style(format): fix spaces and update message to camelCase

* fix(content): update text for clarity

Co-authored-by: Kyle McCormick <kyle@kylemccormick.me>

* feat(validation): validation added to numeric input with new endpoint to see if is a valid math expression

* fix(content): change in input validation to use react query instead of redux

* fix(content): change in types to avoid ci errors

* fix(content): remove unnecessary code after changing to react query

* fix(content): change numeric input validation path to new url and loader added

* feat: returning data in camelcase, improve UI in validation

* feat: tests added to problem editor

---------

Co-authored-by: Kyle McCormick <kyle@kylemccormick.me>
2025-12-19 10:38:19 -08:00
Areeb Sajjad
8b9f156149 fix: keyboard accessibility for time picker (#2613) 2025-12-17 16:56:54 -08:00
María Fernanda Magallanes
9c70fd9216 fix: only show library actions available for the user (#2712)
* fix: only show the options available for the user

* test: fix and add tests

* fix: improve following the best practices

* fix: apply the changes for collections and containers
2025-12-17 16:49:54 -08:00
Max Sokolski
4df44ab6cf fix: coerce multiple choice text elements to String (#2752) 2025-12-17 16:22:31 -08:00
renovate[bot]
0405156f91 chore(deps): update dependency @reduxjs/toolkit to v2.11.2 (#2755)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-17 23:55:12 +00:00
renovate[bot]
1e2e711eaf chore(deps): update dependency fast-xml-parser to v5.3.3 (#2754)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-17 15:42:14 -08:00
Navin Karkera
3eeca244d7 feat: add temporary message alert in sections settings tab in libraries (#2734)
- add temporary message alert in sections settings tab in libraries 
- increase sidebar width to remove `More` option and display all tabs
together
2025-12-17 14:21:13 -05:00
Navin Karkera
ae67be83a0 feat: new course outline header [FC-0114] (#2735)
Adds new header and subheader to course outline. Converts existing js code to ts.
2025-12-17 13:13:19 -05:00
Navin Karkera
6f37118960 refactor: update placeholder block and import details page (#2761)
* Updates placeholder block color and icon.
* Moves `View Imported Content` & `Retry import` buttons in import details page inside alert at the top.
* Updates page title to include Import status in import details page.
2025-12-17 11:43:12 -05:00
Chris Chávez
41a326f7b4 feat: New library sync icon [FC-0114] (#2739)
Updates the library sync icon with new states: error, broken, ready to sync and with overrides
2025-12-16 14:54:28 -05:00
dependabot[bot]
b7dd6706c2 chore(deps): bump actions/upload-artifact from 5 to 6 (#2756)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 17:59:54 +00:00
dependabot[bot]
64ab7ea4fe chore(deps): bump actions/download-artifact from 6 to 7 (#2757)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '7'
  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-12-15 09:42:37 -08:00
edX requirements bot
89d2393d6e chore: update browserslist DB (#2753)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-12-15 00:24:21 +00:00
Santhosh Kumar
42acb53201 feat!: remove "Create Zendesk Tickets for suspicious attempts" setting from Proctored Exam Settings (#2517)
BREAKING CHANGE: This PR removes the deprecated “Create Zendesk Tickets for suspicious attempts”
setting from the Proctored Exam Settings modal in the frontend-app-authoring
MFE. This option was previously used with PSI and Zendesk to generate support
tickets for suspicious exam attempts. Since both systems are retired, the
setting no longer serves a purpose and has been fully removed.

Part of: https://github.com/openedx/edx-platform/issues/36329
2025-12-11 17:05:05 -05:00
David Ormsbee
225c82d037 fix: support "in progress" status for lib upload
When uploading a library archive file during the creation of a new
library, the code prior to this commit did not properly handle the "In
Progress" state, which is when the celery task doing the archive
processing is actively running. Note that this is distinct from the
"Pending" state, which is when the task is waiting in the queue to be
run (which in practice should almost never happen unless there is an
operational issue).

Since celery tasks run in-process during local development, the task
was always finished by the time that the browser made a call to check
on the status. The problem only happened on slower sandboxes, where
processing truly runs asynchronously and might take a few seconds.
Because this case wasn't handled, the frontend would never poll for
updates either, so the upload was basically lost as far as the user
was concerned.
2025-12-11 12:58:06 -05:00
Muhammad Arslan
a596bf5d38 fix: bugs with some static asset paths in TinyMCE editors (#2702)
* fix: only convert assets static file path

* fix: direct static file is fixed

* fix: setting newContent now load the content in html as well
2025-12-11 09:19:40 -08:00
Kyle McCormick
67a5694ca3 fix: Generalize a couple remaining Proctortrack references (#2746)
Just a few leftovers from: https://github.com/openedx/frontend-app-authoring/pull/2645

Full context: https://github.com/openedx/edx-platform/issues/36329
2025-12-11 00:07:29 -05:00
dependabot[bot]
833a838348 chore(deps): bump node-forge from 1.3.1 to 1.3.2 (#2708)
Bumps [node-forge](https://github.com/digitalbazaar/forge) from 1.3.1 to 1.3.2.
- [Changelog](https://github.com/digitalbazaar/forge/blob/main/CHANGELOG.md)
- [Commits](https://github.com/digitalbazaar/forge/compare/v1.3.1...v1.3.2)

---
updated-dependencies:
- dependency-name: node-forge
  dependency-version: 1.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-10 15:21:18 -08:00
renovate[bot]
3cf1ce2b5d chore(deps): update dependency @reduxjs/toolkit to v2 (#2369)
* fix(deps): update dependency @reduxjs/toolkit to v2

* chore: minor updates to work with RTK version 2

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-12-10 22:46:58 +00:00
dependabot[bot]
7eea38e623 chore(deps): bump express from 4.21.2 to 4.22.1 (#2726)
Bumps [express](https://github.com/expressjs/express) from 4.21.2 to 4.22.1.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/v4.22.1/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.21.2...v4.22.1)

---
updated-dependencies:
- dependency-name: express
  dependency-version: 4.22.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-10 14:38:49 -08:00
renovate[bot]
128de3ffc4 chore(deps): update react-router monorepo to v6.30.2 (#2742)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-10 14:03:43 -08:00
Anton Melser
6724e1a296 docs: Generify currently supported node version (#2744)
- remove some non-meaningful trailing whitespace
2025-12-10 19:37:30 +00:00
Areeb Sajjad
8fc00709b4 chore: upgrade react-datepicker (#2709) 2025-12-10 11:29:19 -08:00
renovate[bot]
f367a7641d fix(deps): update dependency @tanstack/react-query to v5.90.12 (#2741)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-08 14:41:03 -05:00
edX requirements bot
49d809b809 chore: update browserslist DB (#2740)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-12-08 00:24:10 +00:00
Chris Chávez
dad736f9d1 refactor: Migration of course details to React query (#2724)
- Migrates the `courseDetails` part from the Redux Store to React Query.
- Creates a new `CourseAuthoringContext` 
- Update the pages in `<CourseAuthoringRoutes>` to use the newly created context.
- Migrates some files to Typescript
- Migrates some tests to use `src/testUtils.tsx`
2025-12-06 00:14:32 +00:00
Chris Chávez
50f4f70671 feat: Import Course Details Page [FC-0112] (#2664)
Implements all the states for the Import Course Details
2025-12-05 12:03:55 -05:00
Rodrigo Mendez
0796e897ae feat: Implement querying openedx-authz for publish permissions (#2685) 2025-12-04 14:40:32 -05:00
Chris Chávez
b76b003e01 refactor: Migrate Help Urls from Redux store to React Query (#2714) 2025-12-02 22:00:06 +00:00
renovate[bot]
e95758cc55 chore(deps): update dependency @types/lodash to v4.17.21 (#2716)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-01 18:07:35 -05:00
renovate[bot]
c7ab2b2837 chore(deps): update dependency @types/react to v18.3.27 (#2717)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-01 18:07:02 -05:00
edX requirements bot
dfe87f983b chore: update browserslist DB (#2715)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-12-01 00:25:55 +00:00
Muhammad Anas
f9e09f0601 fix: replace hardcoded edX with platformName in basicBannerTitle message (#2711) 2025-11-28 13:26:00 -05:00
Navin Karkera
0c1554b337 feat: placeholder blocks for failed import blocks (#2703)
Adds placeholder blocks in home page and respective collections tab in library for failed blocks during import from course.
2025-11-27 12:42:21 -05:00
Daniel Wong
294fe42942 feat: add support for origin server and user info (#2663)
* feat: add support for origin server and user info

* test: add coverage for restore archive summary

* test: increase coverage for restore archive summary

* fix: address comments
2025-11-27 10:04:15 -05:00
Chris Chávez
95ec41d2e7 feat: dock buttons to the bottom in import course stepper (#2694) 2025-11-26 18:18:41 -05:00
renovate[bot]
e620d70793 chore(deps): update dependency @openedx/paragon to v23.18.1 (#2701)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-26 18:15:14 -05:00
Rahat Ali
fa562a691b refactor: Replace ProctorTrack references with Generic Checks (#2645)
This pull request removes frontend-level handling of the ProctorTrack
proctoring provider from the frontend-app-authoring application.

As part of the broader ProctorTrack deprecation effort
(openedx/edx-platform#36329), the backend now provides generic proctoring
configuration rules instead of vendor-specific conditions. The frontend has
been updated to rely on these generic rules while still performing client-side
validation.

By removing the ProctorTrack-specific logic and using the backend’s generic
configuration model, this change keeps frontend-app-authoring aligned with
current backend behavior and avoids relying on deprecated vendor-specific
handling.

Co-authored-by: Taimoor  Ahmed <taimoor.ahmed@A006-01711.local>
2025-11-26 12:26:30 -05:00
Kyle McCormick
70c19a3ffb fix: "Back up" is two words when used as a verb (#2696)
There is a new menu item "Backup to local archive". Backup is the correct
spelling when using it as a noun or adjective, but the menu item uses as a
verb, so it should be two words, back up, i.e. "Back up to local archive"
2025-11-26 17:15:51 +00:00
Navin Karkera
ef36156d55 fix: consider children blocks of unsupported blocks while analyzing course import (#2684)
The analysis step before importing a course considers the parent block while counting unsupported blocks but does not include children in the unsupported count.

We fetch usage_keys of all unsupported blocks and fetch the children blocks that contain these usage_keys in their breadcrumb field i.e., they are part of the unsupported blocks.
2025-11-25 16:24:01 -05:00
dependabot[bot]
735159311d chore(deps): bump actions/checkout from 5 to 6 (#2692)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [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/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  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-11-24 16:02:45 -05:00
edX requirements bot
4fd52b9a4d chore: update browserslist DB (#2691)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-11-24 00:23:39 +00:00
Braden MacDonald
4a81ddbe74 refactor: convert <UnitButton> and <UnitIcon> to TSX (#2649) 2025-11-20 14:29:00 -05:00
Navin Karkera
2215fc53cc fix: don't revert to advanced editor if block contains copied_from fields (#2661) 2025-11-19 15:43:52 -05:00
renovate[bot]
23ab74da14 chore(deps): update dependency formik to v2.4.9 (#2655)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-18 18:19:25 -05:00
dependabot[bot]
1d385c6b4d chore(deps): bump js-yaml (#2659)
Bumps [js-yaml](https://github.com/nodeca/js-yaml).

Updates `js-yaml` from 3.14.1 to 3.14.2
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/3.14.1...3.14.2)

Updates `js-yaml` from 4.1.0 to 4.1.1
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/3.14.1...3.14.2)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 3.14.2
  dependency-type: indirect
- dependency-name: js-yaml
  dependency-version: 4.1.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-18 13:45:45 -05:00
renovate[bot]
acbd1de548 chore(deps): update dependency react-datepicker to v8 (#2572)
* fix(deps): update dependency react-datepicker to v8

* chore(deps): update code to work with react-datepicker v8

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-11-18 13:10:38 -05:00
Rômulo Penido
650bb62fa7 fix: migrate library alert text (#2651)
This PR updates the alert texts on the Migrate Libraries Stepper
2025-11-18 12:09:03 -05:00
Navin Karkera
e2f1aedf9a feat: import analysis step (#2657)
Shows course analysis information in review import details step in course import stepper page. Also handles alerts based on the import status, like, reimport or unsupported number of blocks.
2025-11-18 11:41:27 -05:00
Kyle McCormick
5fadccabe2 fix: Rename builtin discussion providers, "edX" -> "Open edX" (#2660) 2025-11-18 14:55:33 +00:00
renovate[bot]
daed664404 chore(deps): update dependency fast-xml-parser to v5.3.2 (#2594)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-17 18:07:45 +00:00
Asad Ali
495a682926 fix: do not reload multiple tabs on block save (#2600) 2025-11-17 12:54:07 -05:00
renovate[bot]
6f41cd76da chore(deps): update codemirror (#2535)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-17 17:07:01 +00:00
renovate[bot]
64489e1b4d chore(deps): update dependency @openedx/paragon to v23.18.0 (#2643)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-17 17:06:10 +00:00
renovate[bot]
91c813b214 fix(deps): update dependency @tanstack/react-query to v5.90.10 (#2654)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-17 17:05:46 +00:00
Chris Chávez
2e7a29465f refactor: Update title in ImportStepperModal (#2658)
Updates the title of one card from "Import Details" to "Analysis Details"
2025-11-17 16:51:44 +00:00
edX requirements bot
0f58329cb4 chore: update browserslist DB (#2653)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-11-17 00:22:55 +00:00
Chris Chávez
54cfbeb756 feat: import course in library stepper [FC-0112] (#2567)
- Implemented the course import stepper described in https://github.com/openedx/frontend-app-authoring/issues/2524
- Adds the new `ENABLE_COURSE_IMPORT_IN_LIBRARY` flag
2025-11-14 13:07:00 -05:00
Muhammad Anas
7cf01de84c fix: grading settings save button stuck in pending state (#2614) 2025-11-14 08:54:57 -05:00
Navin Karkera
a1abd43a11 refactor: rename team access navbar and sidebar (#2644) 2025-11-13 20:27:06 -05:00
Muhammad Anas
8f06263e27 fix: unit button active state (#2617) 2025-11-13 12:08:18 -05:00
Braden MacDonald
e10ab270dd chore: don't name unused errors in catch expressions (#2591) 2025-11-12 18:11:22 -05:00
Braden MacDonald
a5d65abea2 chore: fix no-base-to-string (#2597) 2025-11-12 13:34:00 -05:00
Braden MacDonald
5ec00236cb chore: fix unnecessary 'undefined' types (#2589) 2025-11-12 13:26:01 -05:00
Devasia Joseph
2530b01b82 fix: restrict single select questions to one correct answer (#2618) 2025-11-12 17:43:42 +05:00
renovate[bot]
13c51ce5a8 chore(deps): update dependency @tanstack/react-query to v5.90.7 (#2611)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-10 10:49:02 -05:00
edX requirements bot
b2cfafc00e chore: update browserslist DB (#2610)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-11-10 00:22:49 +00:00
Rômulo Penido
6d619b9c40 feat: add course import page [FC-0112] (#2580)
Adds the Library Import Home, which lists course migrations to the library
2025-11-07 16:32:11 -05:00
Muhammad Arslan
6afe6095a5 fix: self-closing script tag fixed for TinyMceEditor (#2510)
(not really valid HTML but preserves backwards compatibility)
2025-11-06 09:38:04 -08:00
Muhammad Arslan
1b357cb2b6 fix: broken Course Overview editor on Schedule & Details page (#2599) 2025-11-05 15:15:31 -08:00
Chris Chávez
2de987b254 style: Update some texts in legacy libraries migration flow (#2601) 2025-11-05 18:13:32 -05:00
renovate[bot]
4299bf16b4 chore(deps): update dependency @openedx/paragon to v23.16.0 (#2583)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-05 15:07:54 -08:00
Navin Karkera
5cda284cdb fix: pass readOnly flag to Header in library authoring page (#2598) 2025-11-04 17:56:37 -05:00
Navin Karkera
436ac3155d feat: nav dropdowns in library authoring view (#2556)
Updates navbar in library authoring page to include `Team Access` and `Import` menu options. Clicking on `Team Access` button opens Team management modal.

As per this new PR: https://github.com/openedx/frontend-app-authoring/pull/2570, if admin console url is set, it should be used instead of team access modal. So updated this PR accordingly.
2025-11-03 17:06:50 -05:00
renovate[bot]
86a7e06a3c chore(deps): update dependency @tanstack/react-query to v5.90.6 (#2595)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-03 09:31:38 -08:00
Navin Karkera
bd82c1d33d fix: publish status of container on adding new children (#2587)
Updates publish status of container when adding new child components to a unit or other containers.
2025-11-03 10:01:30 -05:00
Navin Karkera
75ae9d549c feat: handle duplicate children in container pages [FC-0112] (#2584)
If we have duplicate container or component in parent page in library, clicking on one of them selects both and removing any one from the parent blocks removes all instances.
This PR handles duplicates by including index/order_number of each child component in the url and using it to exclude a single instance and update parent structure.
2025-11-03 09:59:37 -05:00
edX requirements bot
cec074e6d4 chore: update browserslist DB (#2593)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-11-03 00:23:01 +00:00
Braden MacDonald
36c9eba66d refactor: remove remaining injectIntl(), ban it using eslint (#2585)
This finished the removal of `injectIntl` from this codebase, and configures a new eslint rule to ban it completely.
2025-10-30 20:10:52 -05:00
Navin Karkera
2dc087f87a feat: differentiate between renamed and data edit in sync preview diff [FC-0112] (#2577)
Use `downstream_customized` field from upstream link to determine whether the text component was locally renamed or content updated or both and display correct notes in preview diff.
Also update libraries v2 alert wording as per https://github.com/openedx/frontend-app-authoring/issues/2169#issuecomment-3434735901
2025-10-29 17:24:04 -05:00
Javier Ontiveros
9b77a40284 feat: add restore from file UI for libraries v2 (#2558) 2025-10-29 21:37:35 +00:00
renovate[bot]
871d98828c chore(deps): update dependency @openedx/paragon to v23.15.1 (#2569)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-29 09:31:41 -07:00
renovate[bot]
f116740184 chore(deps): update github artifact actions (#2571)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-27 10:49:02 -07:00
renovate[bot]
cd967a9878 chore(deps): update dependency @edx/frontend-platform to v8.5.2 (#2568)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-27 10:47:21 -07:00
Farhaan Bukhsh
d8805bf2b4 chore: Updates frontend-component-header to include new slots (#2576)
Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
2025-10-27 16:07:51 +00:00
Diana Olarte
0972b7e62d feat: [FC-0099] redirect to admin console MFE (#2570)
* feat: redirect to admin console MFE

This PR redirects to admin console MFE if the URL is configured, to leverage the new experience of team management this is part of the AuthZ project https://github.com/openedx/openedx-authz/tree/main/docs/decisions

* refactor: split the logic into 2 variables for readability
2025-10-27 15:59:25 +00:00
Kshitij Sobti
15a728d0e7 feat: Add slots for video and file upload components and alerts (#1523)
This change add plugin slots for the file and video upload components, and the alerts components on those pages.
2025-10-24 14:39:50 -07:00
Braden MacDonald
157e2464aa test: fix test code improperly using/missing 'await' (#2560) 2025-10-24 21:31:51 +00:00
Braden MacDonald
c54c21e2b4 test: fix warnings when StrictDict values are checked with propTypes (#2565) 2025-10-24 14:16:07 -07:00
Muhammad Anas
dc05ccfd16 feat: add never_but_include_grade visibility option (#2489)
This PR introduces a new visibility option for assignment scores:

“Never show individual assessment results, but show overall assessment results after the due date.”

With this option, learners cannot see question-level correctness or scores at any time. However, once the due date has passed, they can view their overall score in the total grades section on the Progress page.
2025-10-24 15:08:32 -03:00
Chris Chávez
106f22b3c2 chore: Enable legacy libraries migration by default (#2561) 2025-10-22 18:20:55 -05:00
Chris Chávez
76d8b2e03a feat: Add error messages for partial migration [FC-0107] (#2555)
Adds the error messages for partial migrations
2025-10-22 17:07:24 -05:00
Kyle McCormick
5ce61fa5e5 feat: Add ability to create Legacy Libraries (#2551)
This adds a CreateLegacyLibrary component. It functions the same as
CreateLibrary, but it calls the V1 (legacy) creation REST API rather the V2
(new/beta) REST API.

This reinstates, in the MFE, something that was possible using the legacy
frontend until it was prematurely removed by
https://github.com/openedx/edx-platform/pull/37454. 

We plan to re-remove this ability between Ulmo and Verawood as part of:
https://github.com/openedx/edx-platform/issues/32457.
So, we have intentionally avoided factoring out common logic between
CreateLibrary and CreateLegacyLibrary, ensuring that the latter
remains easy to remove and clean up.
2025-10-22 21:33:59 +00:00
Chris Chávez
46fa17ea83 fix: UI fixes in legacy library migrator
- Keep state of all migration steps on nevigation
- Reword alert in confirm dialog
- Add scroll to help sidebar in migration
- Keep the same migration filter
2025-10-22 21:24:52 +00:00
Chris Chávez
9f1604110b feat: Deleted/Added level diff in sync modal [FC-0097] (#2549)
- Adds the Deleted and the Added level diff in sync container modal.
- Fix the icons in the sync container modal
2025-10-22 20:53:12 +00:00
Muhammad Anas
82a3c2815b feat: enable markdown to OLX conversion (#2518) 2025-10-21 16:58:20 -07:00
renovate[bot]
191be55b2e chore(deps): update dependency @tanstack/react-query to v5.90.5 (#2545)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-20 17:55:40 -07:00
renovate[bot]
8f7e48421f chore(deps): update actions/setup-node action to v6 (#2546)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-20 17:32:11 -07:00
dependabot[bot]
b6de9a8883 chore(deps): bump actions/setup-node from 5 to 6 (#2547)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 5 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  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-10-20 17:29:38 -07:00
Javier Ontiveros
7bfc73073b [feature] add backup view for libraries v2 (#2532)
* feat: add backup view for libraries v2

* chore: updated paths and cleanup

* chore: cleanup text

* chore: added test

* chore: fix contracts after rebase

* chore: more tests to improve coverage

* chore: more test for coverage

* chore: more test for coverage

* chore: fixed lint issues

* chore: update naming for a more semantic one

* chore: changed fireEvent to userEvent

* chore: improved queryKeys

* chore: lint cleanup

* chore: changed tests and time to 1min

* chore: even more tests

* chore: split hook for library menu items

* chore: fixed typo on refactor

* chore: improved test to use available mocks

* chore: change from jest.mocks to spyon

* chore: update test based on commets

* chore: update test to get URL from a better place

* chore: added extra getters for new endpoints

* chore: update test to prevent issues with useContentLibrary

* chore: added comments for clarity

* chore: lint fix

* chore: updated url handle to use full URL

* chore: linting fixes
2025-10-20 16:51:05 -06:00
renovate[bot]
98009b3e6a chore(deps): update dependency @edx/frontend-component-footer to v14.9.3 2025-10-20 16:34:05 -03:00
Navin Karkera
e80930e06f fix: add components button in item bank children page (#2491)
`Add components` button in item bank children page was not working.
2025-10-20 12:09:58 -05:00
edX requirements bot
66dad5ff32 chore: update browserslist DB (#2544)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-10-20 00:22:22 +00:00
bydawen
e4ea69266f fix: pointer-events issue on toast container (#2139) 2025-10-17 14:26:03 -07:00
Rômulo Penido
8b6a350808 feat: add copy container menu (#2538)
Adds copy support for Library Containers and updates the useClipboard hook to provide info on copied containers.
2025-10-17 14:11:18 -05:00
renovate[bot]
a56faf8ca7 fix(deps): update dependency @tinymce/tinymce-react to v6 (#2536)
* fix(deps): update dependency @tinymce/tinymce-react to v6

* refactor: validating typing of tinymce-react usage (no runtime changes)

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-10-16 22:07:27 +00:00
renovate[bot]
77215eeb5e chore(deps): update dependency @openedx/paragon to v23.14.9 (#2533)
* chore(deps): update dependency @openedx/paragon to v23.14.9

* test: update tests because of paragon role=presentation modal changes

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-10-16 16:53:39 +00:00
Chris Chávez
311bef67ed feat: Shows an alert in container sync if the only change is a local override to a text component [FC-0097] (#2516)
- Implements the alert described in https://github.com/openedx/frontend-app-authoring/issues/2438#issuecomment-3358670967
2025-10-15 19:17:56 -05:00
Chris Chávez
195249ef26 feat: Legacy libraries migration help sidebar [FC-0097] (#2503)
- Implements the Legacy Libraries Migration Help Sidebar
- Shows the sidebar in the studio home
- Shows the sidebar in the Legacy Libraries Migration Page
2025-10-15 20:35:08 +00:00
Ihor Romaniuk
4a26a86c90 fix: answer range format validation in numerical input problems (#2426) 2025-10-15 11:33:31 -07:00
vladislavkeblysh
411d4f053c fix: fixed delete for additional video url fields in video editor (#2470) 2025-10-15 09:47:03 -07:00
Chris Chávez
9c0b545b2f feat: Connect bulk migration backend with frontend (#2493)
- Connects the `Confirm` button with the bulk migrate backend
- Updates the library page to get the migration task status and refresh the component on success.
2025-10-14 00:04:36 +00:00
Ahtesham Quraish
cd36407457 fix: [Library browse] Unintended scroll upon unit selection #2452 (#2472) 2025-10-13 09:22:22 -05:00
Chris Chávez
46d2465064 fix: Multiple UI/UX improvements (#2529)
This includes multiple improvements described in https://github.com/openedx/frontend-app-authoring/issues/2528
2025-10-13 09:21:00 -05:00
edX requirements bot
6c829b9421 chore: update browserslist DB (#2534)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-10-13 00:22:24 +00:00
Kyle McCormick
1d6fdc39fd feat: frontend-component-header to 8.0.0, to rm Maintenance link (#2521)
BREAKING CHANGE: Removes Maintenance link in header, part of
https://github.com/openedx/edx-platform/issues/36263

Full diff:
https://github.com/openedx/frontend-component-header/compare/v6.2.0...v8.0.0
2025-10-10 12:38:02 -04:00
Ahtesham Quraish
04e9a253ba fix: library card icons are not vertically aligned #2473 (#2474) 2025-10-10 09:01:13 -07:00
Ahtesham Quraish
8470d7cd4d fix: Rename field should use full available width #2337 (#2436) 2025-10-10 09:00:40 -07:00
renovate[bot]
b774084a10 chore(deps): update dependency @openedx/paragon to v23.14.5 (#2530)
* chore(deps): update dependency @openedx/paragon to v23.14.5

* fix: correct type of ContainerPropsType

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-10-09 17:14:33 +00:00
MuPp3t33r
aadccc748c fix: course assets state persistence bug (#2401) 2025-10-08 11:36:26 -07:00
Navin Karkera
c4a439df47 fix: show before and after title in diff preview (#2509)
Fix display of Before and After display name in section/subsection sync preview modal.
2025-10-07 14:52:22 -05:00
renovate[bot]
8fe5fb6a20 chore(deps): update dependency universal-cookie to v8 (#2512)
* fix(deps): update dependency universal-cookie to v8

* refactor: validate typing of universal-cookie usages

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-10-06 23:08:46 +00:00
renovate[bot]
0315c05e11 chore(deps): update dependency fast-xml-parser to v5 (#2515)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-06 22:41:17 +00:00
renovate[bot]
a5d51ce4f4 chore(deps): update dependency @types/react to v18.3.26 (#2513)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-06 15:25:18 -07:00
renovate[bot]
3a6378e569 chore(deps): update dependency @testing-library/jest-dom to v6.9.1 (#2508)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-06 14:40:55 -07:00
renovate[bot]
e37f2e0071 chore(deps): update dependency @types/react to v18.3.25 (#2507)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-06 14:40:18 -07:00
edX requirements bot
835de77385 chore: update browserslist DB (#2506)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-10-06 00:21:27 +00:00
renovate[bot]
7f23e9b585 chore(deps): update dependency @openedx/paragon to v23.14.4 (#2504)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-04 00:30:06 +00:00
renovate[bot]
32ed2f183b chore(deps): update codemirror (#2487)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-04 00:29:54 +00:00
renovate[bot]
292068af6e chore(deps): update dependency @tanstack/react-query to v5.90.2 (#2488)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-03 17:17:05 -07:00
Chris Chávez
a975f3b716 feat: New modal to sync changes for standalone text components [FC-0097] (#2449)
Adds a new sync modal when a Text component has local changes.
2025-09-30 09:45:13 -05:00
Chris Chávez
1c7ad2f725 feat: Migrate Legacy Libraries Flow [FC-0097] (#2425)
- Creates all steps of the flow described in https://github.com/openedx/frontend-app-authoring/issues/2201
2025-09-29 18:02:15 -05:00
renovate[bot]
7ba3db0187 chore(deps): update dependency @openedx/paragon to v23.14.3 (#2485)
* chore(deps): update dependency @openedx/paragon to v23.14.3

* fix: ref was invalid and causing console error

"Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?"

(Paragon does not support refs for IconButtonWithTooltip, although it could be added at any time.)

* fix: react query console error in tags drawer

"No queryFn was passed as an option, and no default queryFn was found. The queryFn parameter is only optional when using a default queryFn."

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-09-29 21:07:49 +00:00
edX requirements bot
fdf98a1400 chore: update browserslist DB (#2486)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-09-29 00:21:05 +00:00
Chris Chávez
56d3eede64 feat: Adding loading and done states to the publish library button [FC-0097] (#2237)
Adds loading and done states to the publish library button.
2025-09-26 15:15:23 +00:00
oleksandr.buhaienko
c5de944d72 test: Remove support for Node 20 2025-09-26 10:29:24 -03:00
Rômulo Penido
523dd1f389 feat: add library v2 alert (#2413)
Adds an Alert to the Legacy Library Page to notify the user of the process of deprecating Legacy Libraries and a Button to open the Migrate Library interface.
2025-09-25 16:01:57 -05:00
Navin Karkera
cffc4d77c9 feat: migration filter and search bar in legacy libraries tab [FC-0097] (#2421)
Adds search bar and migration filter in legacy libraries tab
2025-09-25 17:00:26 +00:00
Navin Karkera
25160347b3 feat: container library-course sync diff prevew [FC-0097] (#2464)
Container sync preview implemented
2025-09-25 11:13:58 -05:00
Navin Karkera
d63680083d feat: show migration status in libraries list [FC-0097] (#2417)
Adds migration status to library cards in legacy libraries tab in studio home.
Also converts javascript files to typescript and replaces redux with react query for related api calls.
2025-09-25 10:49:13 -05:00
bydawen
39e5f89b45 build: Upgrade to Node 24 (#2459) 2025-09-22 09:49:04 -07:00
edX requirements bot
7e81b52583 chore: update browserslist DB (#2469)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-09-22 00:22:14 +00:00
Rômulo Penido
1efa94d410 fix: update delete and remove modals design [FC-0097] (#2453)
Changes the Remove/Delete Component/Container dialogs according to the design. It also standardized the messages from Components and Containers.
2025-09-18 16:27:35 -05:00
bydawen
d98a34ac3f test: Add Node 24 to CI matrix (#2443) 2025-09-18 10:09:51 -07:00
Akanshu Aich
8b530481de fix: remove unused ENABLE_HOME_PAGE_COURSE_API_V2 config reference (#2461) 2025-09-18 09:49:03 -07:00
Muhammad Faraz Maqsood
9f6a882e61 fix: course optimizer issues (#2450)
- don't show `Scan results` heading until there are some results to show.
- change spinner from paragon with spinner icon which looks better than spinner itself.
- disable `update all` button when single update prev Link is in progress.

Co-authored-by: Muhammad Faraz  Maqsood <faraz.maqsood@A006-01130.local>
2025-09-18 10:44:18 +05:00
renovate[bot]
b95b3a60ad chore(deps): update dependency @tanstack/react-query to v5 (#2404)
* fix(deps): update dependency @tanstack/react-query to v5

* chore: update for compatibility with React Query v5

* chore: update for compatibility with React Query v5

* test: update tests

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-09-17 16:10:08 -07:00
Navin Karkera
61c87fe6a6 feat: allow editing imported unit blocks (#2405)
Allows authors to edit imported unit display name in outline.
2025-09-17 12:27:04 -05:00
renovate[bot]
c21b664a8b chore(deps): update codemirror to v6.4.10 (#2432)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-16 10:50:08 -07:00
Chris Chávez
71376fa22b feat: ENABLE_LEGACY_LIBRARY_MIGRATOR flag added (#2440)
- Adds the `ENABLE_LEGACY_LIBRARY_MIGRATOR` flag. **Reason:** The migrator frontend is finishing before the backend; this flag is mainly to hide it until it is fully connected and working with the backend.
- Puts the migration warning under the new flag.
2025-09-12 11:20:31 -05:00
Chris Chávez
23b4f4731e fix: Use the correct branch of openedx/.github repo for add-cc-to-board (#2441) 2025-09-11 12:33:10 -07:00
Chris Chávez
ab645ad86b feat: add-to-cc-board Github action created. (#2302)
- This is a label trigger to add an Issue or PR to the front-end [Core Contributor project board](https://github.com/orgs/openedx/projects/80).
- This action uses the `Core Contributor assignee` label as a trigger.
- This action reuses https://github.com/openedx/.github/pull/169
- When you add the label to an issue or PR, it is automatically added to the board https://github.com/orgs/openedx/projects/80
2025-09-10 17:10:38 -05:00
Navin Karkera
720b591add feat: display only one card action overflow menu (#2427)
Instead of stopping whole click event propagation from actions to card element, specifically stop click event if the source target is actions menu.
2025-09-08 16:47:17 -05:00
renovate[bot]
87239ab723 chore(deps): update dependency @types/react to v18.3.24 (#2431)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-08 09:41:52 -07:00
Asad Ali
0117c1eae3 fix: allow thumbnail upload on Videos page if no thumbnail (#2388)
* fix: allow thumbnail upload if no thumbnail

* fix: improve thumbnail upload impl

* test: fix tests

* test: fix tests

* fix: do not show thumbnail upload if not allowed

* test: fix coverage

* test: add thumbnail test

* fix: display thumbnail overlay when video status is success
2025-09-08 09:40:32 -07:00
Ahtesham Quraish
0f7c8de882 fix: files page web url missing #2409 (#2420)
Co-authored-by: Ahtesham Quraish <ahtesham.quraish@A006-01455.local>
2025-09-08 09:33:19 -07:00
dependabot[bot]
387c45a5b2 chore(deps): bump actions/setup-node from 4 to 5 (#2433)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 5.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-node
  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-09-08 09:00:29 -07:00
edX requirements bot
6377fbd896 chore: update browserslist DB (#2430)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-09-08 00:22:14 +00:00
Chris Chávez
67fab054ab feat: Secondary publish workflow for components [FC-0097] (#2399)
- Adds the new publish button and the new confirm publish box for components.
- Deletes the old confirm publish modal for components
- Adds the publish button next to the open button for containers 
- Update changes to grand-parent and grand-child items.
2025-09-05 17:12:40 +00:00
renovate[bot]
a7860b8392 chore(deps): update dependency @edx/frontend-component-header to v6.6.1 (#2407)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-04 02:20:41 +00:00
renovate[bot]
3082eca91c chore(deps): update dependency @edx/frontend-component-footer to v14.9.1 (#2415)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-03 19:07:46 -07:00
Rômulo Penido
2fb04d670f feat: add legacy library alert (#2412)
Adds an Alert to the Legacy Library Page to notify the user of the process of deprecating Legacy Libraries and a Button to open the Migrate Library interface.
2025-09-02 14:23:49 -05:00
Samuel Allan
f79b65c273 fix: update frontend-build to fix install issues (#2387)
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-02 09:48:30 -07:00
Pandi Ganesh
472d77823f feat: Enhance Course Optimizer Page with Previous Run Links and Improved UI (#2356)
* feat: enhance course optimizer page design in studio

* feat: enhance course optimizer with prev run links update

* fix: increase container size and resolve style issues

* fix: enhance code structure and i18n support
2025-09-02 17:01:28 +05:00
edX requirements bot
09f4304daa chore: update browserslist DB (#2414)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-09-01 00:23:43 +00:00
Rômulo Penido
950bfee7c1 feat: add unlink upstream menu [FC-0097] (#2393)
Adds the Unlink feature to the Course Outline for Sections, Subsections and Units.
2025-08-28 11:44:15 -05:00
Pradeep
0f2dd4a88f fix: ensure hyperlink renders correctly based on videoSource presence (#2400)
* fix: ensure hyperlink renders correctly based on videoSource presence

* refactor: remove unnecessary blank lines in VideoPreviewWidget tests
2025-08-28 14:44:17 +05:00
Chris Chávez
6646c8ed0f style: Fixing nits about sync units [FC-0097] (#2319)
* Stay visible the sync icon in the course outline
* Update the message in the sync unit/subsection/section modal
* Add a tooltip to the edit and sync button.
2025-08-27 19:29:24 -05:00
Vivek Ambaliya
9a9806ccad feat: add new help section in course team page 2025-08-27 14:08:16 +05:00
Muhammad Faraz Maqsood
86e9c6b1fa fix: tinyMCE images previews in image selection modal 2025-08-26 11:28:27 +05:00
renovate[bot]
2a787953ef chore(deps): update dependency @testing-library/jest-dom to v6.8.0 (#2403)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-25 12:29:24 -07:00
Braden MacDonald
c90195e0fd refactor: move 'isMarkdownEditorEnabledForContext' into EditorContext (#2398)
This just moves one single state variable, `isMarkdownEditorEnabledForCourse` out of the Redux state and into the `EditorContext`.
2025-08-25 12:31:39 -05:00
edX requirements bot
dfd3b93f0a chore: update browserslist DB (#2402)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-08-25 00:22:18 +00:00
renovate[bot]
ae449b914b chore(deps): update dependency @openedx/paragon to v23.14.2 (#2375)
* fix(deps): update dependency @openedx/paragon to v23.14.2

* chore: fix invalid 'size' passed to <Spinner>

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-08-22 16:45:18 +00:00
Kshitij Sobti
5c006af6ec fix: restore styling for header title and button on outline page (#2385)
In a previous PR #2374 some of the styling applied in addition to truncation
was lost. This restores that.
2025-08-22 09:14:48 -07:00
Braden MacDonald
641fc589a4 Add TypeScript types to the redux state (#2394)
Adds some TypeScript types to the global redux state that's in `src/store.ts`. I've only added types for a few parts of the state but already it's caught quite a few bugs in the code, which I've tried to fix in this PR.
2025-08-22 11:00:19 -05:00
Chris Chávez
0c88fd6da9 feat: show sync button on section/subsections [FC-0097] (#2324)
- Adds the sync button on section/subsection cards
2025-08-21 21:38:16 +00:00
Braden MacDonald
8e680dc8d4 refactor: minor typing improvements (#2395)
This makes some minor typing improvements in our test code. Specifically instead of just `{...} as XBlock` which is an unsafe cast, we can use `{...} satisfies Partial<XBlock> as XBlock` which is a safer cast that lets you omit fields but requires that the fields you do include have the correct type.
2025-08-21 12:24:18 -05:00
Jillian
2f6e510b09 Display Container Publish status and confirm before publish (#2186)
Updates the Container sidebar to display:

* A confirmation step before publishing the container.
* Text + a full hierarchy to better demonstrate what will be published when the container is published.
2025-08-20 13:22:30 -05:00
Ahtesham Quraish
87af7e8973 refactor: Replace of injectIntl with useIntl() part 8 #2288 (#2357)
Co-authored-by: Ahtesham Quraish <ahtesham.quraish@192.168.1.4>
2025-08-20 11:07:24 -07:00
Ahtesham Quraish
33c445ebc2 refactor: Replace of injectIntl with useIntl() part 6 - files-and-videos/generic/EditFileErrors (#2358)
Co-authored-by: Ahtesham Quraish <ahtesham.quraish@192.168.1.4>
2025-08-20 10:58:02 -07:00
dependabot[bot]
7825bcde75 chore(deps): bump brace-expansion (#2381)
Bumps  and [brace-expansion](https://github.com/juliangruber/brace-expansion). These dependencies needed to be updated together.

Updates `brace-expansion` from 2.0.1 to 2.0.2
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v2.0.1...v2.0.2)

Updates `brace-expansion` from 1.1.11 to 1.1.12
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v2.0.1...v2.0.2)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 2.0.2
  dependency-type: indirect
- dependency-name: brace-expansion
  dependency-version: 1.1.12
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-18 18:19:11 -07:00
Rômulo Penido
2c9f90ba5a fix: change container sync status icon [FC-0097] (#2360)
Changes the sync icon for Sections, Subsections, and Units in case the Upstream source is deleted.
2025-08-18 17:21:47 -05:00
renovate[bot]
ada52c3169 chore(deps): update dependency @testing-library/jest-dom to v6.7.0 (#2382)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-18 09:35:24 -07:00
renovate[bot]
38b0b6543b chore(deps): update actions/checkout action to v5 (#2383)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-18 09:34:54 -07:00
Muhammad Faraz Maqsood
e6b72453b3 chore: add missing problem text for localization 2025-08-18 17:12:13 +05:00
edX requirements bot
0820a1e7df chore: update browserslist DB (#2350)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-08-18 00:23:20 +00:00
Sara Burns
be82e96e6f feat: add xblockScroll event handler to iframeMessageTypes (#2363)
* fix: new message type to scroll outer window to xblock location

* fix: reset after testing

* fix: formatting

* test: add test coverage

* fix: fix test mocks

* fix: formatting

* fix: add smooth to scroll
2025-08-15 09:11:21 -04:00
renovate[bot]
b2203f0ece chore(deps): update dependency @codemirror/lang-markdown to v6.3.4 (#2367)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-15 02:31:13 +00:00
Kshitij Sobti
53e925e07a fix: Replace Truncate.Deprecated with CSS-based truncation (#2374)
The Truncate element as it exists has a bug where it can end up in an infinite loop when truncating to a very small size on mobiles. This makes the course outline view unresponsive on mobile and can lead to a crash.

This replaces the Truncate element with some CSS.
2025-08-14 19:12:07 -07:00
Chris Chávez
25830a2130 feat: Show sections/subsections/units available for sync in library sync page [FC-0097] (#2271)
- Adds Units, Subsection, and section cards in the libraries sync page.
- Rename of `mockGetEntityLinks` to `mockGetComponentEntityLinks`
- Use the top-level parent logic
- Which user roles will this change impact? "Course Author".
2025-08-14 12:59:29 -05:00
renovate[bot]
6ce7b86e83 chore(deps): update dependency @testing-library/jest-dom to v6.6.4 (#2366)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-11 14:16:14 -07:00
Victor Navarro
5bdef7cffa fix: disable special exams config if feature flag is disabled (#2325)
* fix: disable special exams config if feature flag is disabled

* test: add testcases

* fix: convert AdvancedTab to typescript
2025-08-11 13:24:38 -07:00
renovate[bot]
f0c5a513de chore(deps): update actions/download-artifact action to v5 (#2364)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-08 13:03:05 -07:00
Navin Karkera
da46fe0a48 fix: remove interactivity from section/subsection preview in sidebar (#2362)
Removes interactivity from section/subsection preview in sidebar. Also fixes an issue with unit sidebar, where users could press enter after clicking on any component and it would select it.
2025-08-08 10:45:15 -05:00
Ahtesham Quraish
7c4ef47da5 refactor: replace one injectIntl with useIntl, fix JSX return (#2354)
Co-authored-by: Ahtesham Quraish <ahtesham.quraish@192.168.1.4>
2025-08-07 13:47:43 -07:00
renovate[bot]
8003453b73 chore(deps): update dependency @edx/frontend-platform to v8.5.0 (#2355)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-07 12:52:14 -07:00
Navin Karkera
92c3a98a3d fix: show/hide add unit button based on childAddable flag of parent in unit page (#2351)
Course unit page shows Add Unit option without checking whether the parent subsection allows adding children. This fixes it.
2025-08-06 14:41:05 -05:00
dependabot[bot]
0e1550a45b chore(deps): bump js-toml from 1.0.1 to 1.0.2 (#2353)
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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-05 16:05:06 -07:00
renovate[bot]
15c79ceb21 chore(deps): update dependency @openedx/paragon to v23.14.1 (#2348)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-05 13:37:42 -07:00
renovate[bot]
43de4d1e32 chore(deps): update dependency @edx/frontend-component-header to v6.6.0 (#2349)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-05 13:36:10 -07:00
Braden MacDonald
591444d72d test: Clean up editor tests (#2343)
* test: improve the editorRender helper

* fix: redux state bug introduced in #2326

* test: add note for future reference about accessing the editor redux store
2025-08-05 10:41:44 -07:00
Pradeep Patro
2f9566c4f5 refactor: Problem type handling to support localization
- Updated hooks and components to utilize localized problem titles and descriptions.
- Introduced `getProblemTypes` and `getAdvanceProblems` functions for internationalization support.
- Enhanced tests to verify localized titles and descriptions for problem types.
- Added new messages for various problem types and their descriptions.
- Refactored `TypeCard`, `TypeRow`, and `SelectTypeModal` components to use localized strings.
- Improved test coverage for problem type selection and rendering.
2025-08-05 15:37:18 +05:00
Navin Karkera
915bd559e0 feat: disable drag handles for children of library imported containers in course outline [FC-0097] (#2311)
* Hides/disables drag handles for children components of containers imported from library.
* Disables move, delete and duplicate options for children components.
* Move up and down option skips containers that cannot accept children (imported from library).
* Authors cannot drag and drop xblocks under containers imported from library.
* Improves drag-n-drop by creating a representational drag overlay.
2025-08-04 11:46:39 -05:00
Ishan Masdekar
00ce3d7856 feat: navigates subsection breadcrumb to first unit page (#2329)
- navigates the breadcrumb to the first unit under the subsection
instead of the outline page.

Closes #1924
2025-07-31 14:26:18 -07:00
Kyle McCormick
90ddc5e71c chore: Delete CODEOWNERS (#2347)
See: https://github.com/openedx/axim-engineering/issues/1511
2025-07-31 16:18:31 -04:00
renovate[bot]
9ceebbe137 chore(deps): update dependency @edx/frontend-component-header to v6.5.2 (#2334)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-29 13:19:42 -07:00
Ahtesham Quraish
8326257938 refactor: Replace connect with useSelector() and useDispatch() 1/5 2025-07-29 13:03:04 +05:00
Ahtesham Quraish
30cfd269e2 refactor: Replace of injectIntl with useIntl() part 5 #2285 2025-07-29 10:08:31 +05:00
renovate[bot]
082a1c6510 chore(deps): update dependency @edx/frontend-component-header to v6.5.1 (#2309)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 15:09:34 -07:00
renovate[bot]
a146307a4f chore(deps): update dependency @codemirror/view to v6.38.1 (#2303)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 14:10:55 -07:00
Jacobo Dominguez
556bb1e56d docs: update readme for AdditionalTranslationsComponentSlot (#2321) 2025-07-25 13:57:08 -07:00
Jorg Are
bd2e2d8655 feat: Add pt-BR to videoTranscriptLanguages (#2242) 2025-07-25 12:47:11 -04:00
dependabot[bot]
11de4022f0 chore(deps): bump on-headers and compression (#2328)
Bumps [on-headers](https://github.com/jshttp/on-headers) and [compression](https://github.com/expressjs/compression). These dependencies needed to be updated together.

Updates `on-headers` from 1.0.2 to 1.1.0
- [Release notes](https://github.com/jshttp/on-headers/releases)
- [Changelog](https://github.com/jshttp/on-headers/blob/master/HISTORY.md)
- [Commits](https://github.com/jshttp/on-headers/compare/v1.0.2...v1.1.0)

Updates `compression` from 1.8.0 to 1.8.1
- [Release notes](https://github.com/expressjs/compression/releases)
- [Changelog](https://github.com/expressjs/compression/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/compression/compare/1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: on-headers
  dependency-version: 1.1.0
  dependency-type: indirect
- dependency-name: compression
  dependency-version: 1.8.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 17:06:52 -07:00
dependabot[bot]
9caa4351ba chore(deps): bump form-data from 4.0.2 to 4.0.4 (#2308)
---
updated-dependencies:
- dependency-name: form-data
  dependency-version: 4.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 16:54:00 -07:00
Muhammad Qasim Gulzar
74e671d08b fix: Course outline — issue when editing Section/Subsection/Unit name, and executing an action on the page (#2275)
When editing the title of a section, subsection or unit name, if someone created a new subsection, it would be duplicated and created twice. This change filters out the duplicate entry and eliminates the issue.
2025-07-24 12:40:48 +05:30
Navin Karkera
5b7efc65bc feat: add library reuse indicators to all components in course outline [FC-0097] (#2295)
Add library reuse indicator to units, subsections and sections in course outline.
2025-07-23 13:13:28 -05:00
Ahtesham Quraish
f9cd15eee6 fix: press Cancel it's not properly refreshing the unit and not showing the blank component was added. 2025-07-23 14:13:06 +05:00
Jacobo Dominguez
bad66caadd docs: update readme for additional course plugin slot (#2315) 2025-07-22 13:42:48 -07:00
Jacobo Dominguez
2ae594f23c refactor: replacing injectIntl with useIntl part 4 (#2301) 2025-07-22 09:49:33 -07:00
renovate[bot]
8e3ea89339 chore(deps): update dependency axios-mock-adapter to v2 (#2304)
* chore(deps): update dependency axios-mock-adapter to v2

* test: update tests for compatibility with axios-mock-adapter v2

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-07-21 23:27:28 +00:00
Navin Karkera
537b3292ee feat: library section subsection reuse in course (#2279)
Adds option for course author to import and use sections and subsections from library v2.
2025-07-21 15:38:47 -05:00
Ahtesham Quraish
46d5917303 refactor: Replace of injectIntl with useIntl() part 7 (#2297) 2025-07-18 14:52:57 -07:00
Jacobo Dominguez
4f3904ea4c refactor: replacing injectIntl with useIntl part 3 (#2300) 2025-07-18 14:47:18 -07:00
Ahtesham Quraish
215f7280da refactor: Replace of injectIntl with useIntl() part 6 (#2298) 2025-07-18 14:37:03 -07:00
Jacobo Dominguez
60417a76cb refactor: replacing injectIntl with useIntl part 2 (#2299) 2025-07-18 14:21:39 -07:00
Jacobo Dominguez
cbec6505f5 refactor: replacing injectIntl with useIntl part 1 (#2296) 2025-07-18 14:21:26 -07:00
Diana Villalvazo
654daa58ee fix: Change "choose library" phrasing depending on contentType (#2276)
* fix: change library dialog phrasing depending on contentType

* fix: separate i18n messages

* fix: i18n improvements
2025-07-17 16:20:24 -07:00
Braden MacDonald
bd18e874b5 Fix broken StudioHome tests (#2291)
There were a ton of problems with these tests, but the main one was the use of `waitFor` without `await`, causing all of the code inside each `waitFor` block to essentially be ignored.

Other problems fixed:
* Rendering a router inside a router was causing most of the render() calls to fail (our custom `render()` already provides a router so there's no need to provide one in the test case)
* Use of `testid` instead of queries based on what users see
* Tests could match on content in the body when trying to make assertions about the header
* Mock imported via `index.js` was causing `jest-haste-map` to print warnings about duplicate mock names (this is still happening for other mocks)
* Passing `courses: null` instead of `courses: []` was causing a broken render on two of the tests.

I also made other cleanups to follow best practices.
2025-07-17 15:45:22 -05:00
jacobo-dominguez-wgu
2db6d89fca test: upgrading user-event to v14 (#2277) 2025-07-17 09:26:16 -07:00
Ahtesham Quraish
a51ff99042 fix: Files and Uploads search text is lost when using Sort and Filter more than once 2025-07-17 10:36:34 +05:00
renovate[bot]
966767ffd4 chore(deps): update dependency react-select to v5.10.2 (#2273)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 14:32:29 -07:00
renovate[bot]
fc9ded432a chore(deps): update dependency @edx/frontend-component-header to v6.4.2 (#2272)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 14:30:29 -07:00
Muhammad Faraz Maqsood
a3e03dc12f Revert "Remove unused <EditorContainer> and URL route" (#2274) 2025-07-14 12:10:13 -04:00
Devasia Joseph
77fe2d1086 feat: Update Course Optimizer label from BETA to NEW 2025-07-11 19:03:30 +05:00
jacobo-dominguez-wgu
efd967a42b test: replacing shallow snapshots with RTL part 2 (#2267) 2025-07-10 16:49:16 -07:00
jacobo-dominguez-wgu
eaba380417 test: replacing shallow snapshots with RTL (#2266) 2025-07-10 16:47:20 -07:00
Diana Villalvazo
f3332a214f fix: remove old editorContainer (#2268) 2025-07-10 16:44:41 -07:00
jacobo-dominguez-wgu
bc11aaf5ce test: removing @edx/react-unit-test-utils library (#2263) 2025-07-08 13:27:36 -07:00
jacobo-dominguez-wgu
4ae9d3c8df test: replacing snapshot tests with RTL tests part 16 (#2252) 2025-07-08 10:08:32 -07:00
jacobo-dominguez-wgu
3673c5f561 test: replacing snapshot tests with RTL tests part 14 (#2236) 2025-07-08 09:37:07 -07:00
jacobo-dominguez-wgu
2fe24f39ac test: replacing snapshot tests with RTL tests part 13 (#2233) 2025-07-08 09:33:53 -07:00
jacobo-dominguez-wgu
c4f565bf76 test: replacing snapshot tests with RTL tests part 15 (#2248) 2025-07-07 16:44:01 -07:00
Braden MacDonald
e8e5a3c4ce docs: update PR template (#2215)
* docs: update PR template

* docs: incorporate suggestions from PR review
2025-07-07 23:04:58 +00:00
renovate[bot]
749c0022ec chore(deps): update dependency @edx/frontend-component-header to v6.4.1 (#2245)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 22:47:12 +00:00
Daniel Valenzuela
642be162d7 fix: open component with keyboard within unit page (#2256)
When selecting a component inside a unit with the keyboard, opening it in the sidebar by pressing enter was not working.
2025-07-07 17:34:21 -05:00
jacobo-dominguez-wgu
a969de4d90 test: replacing snapshot tests with RTL tests part 12 (#2222) 2025-07-07 15:25:27 -07:00
renovate[bot]
8d86433748 chore(deps): update dependency codemirror to v6.0.2 (#2240)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 22:12:46 +00:00
renovate[bot]
90f375939a chore(deps): update codemirror sub-packages (#1908)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 15:12:22 -07:00
renovate[bot]
a1214f7fa9 chore(deps): update react-router monorepo to v6.30.1 (#2156)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 14:57:24 -07:00
renovate[bot]
88821077cb chore(deps): update dependency @openedx/paragon to v23.14.0 (#2191)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 21:56:17 +00:00
renovate[bot]
3ebd2372d2 chore(deps): update dependency @tanstack/react-query to v4.40.1 (#2260)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 21:55:52 +00:00
renovate[bot]
6014da9a22 chore(deps): update dependency @types/lodash to v4.17.20 (#2259)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 14:42:36 -07:00
edX requirements bot
f355a17943 chore: update browserslist DB (#2258)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-07-07 00:22:40 +00:00
Daniel Valenzuela
ae82486d72 fix: cannot open item sidebar after closing with 'X' button (#2241)
When closing an item (component, unit, section, container, etc) sidebar, and trying to reopen it inmediately by clicking the card, it was not opening because navigateTo was being used, but the URL already was the same you were being navigated to. So we also have to update the sidebar item info in the sidebar context in order for it to reopen properly.
2025-07-04 04:38:37 -05:00
Muhammad Faraz Maqsood
dd2853900b feat: apply 2 column format for P&R page widgets 2025-07-04 10:40:15 +05:00
Rômulo Penido
2533724203 fix: increase sidebar width to prevent menu overflow (#2247) 2025-07-03 03:27:01 -05:00
Chris Chávez
ffd430d321 fix: Update add content existing content icons in section/subsection pages (#2224) 2025-07-03 02:36:19 -05:00
Muhammad Faraz Maqsood
ad62519af7 fix: publish btn doesn't show after component edit
When we edit & save the component, publish button doesn't show up until we refresh the page manualy or open this unit by opening previous unit and coming back to this unit again.
In this commit, we are dispatching a storage event whenever we edit the component, it'll refresh the page & show the publish button as expected.
2025-07-01 15:19:39 +05:00
Daniel Valenzuela
76b5dd5925 fix: delete and remove modals styling (#2243) 2025-06-30 15:49:25 -05:00
Navin Karkera
701e41b664 fix: invalidate library queries on restore container (#2231)
Restoring containers should invalidate queries in the library to show the deleted component without needing to refresh.
2025-06-30 15:30:48 -05:00
Rômulo Penido
ac9faacc4d feat: add ParentBreadcrumbs component [FC-0090] (#2223)
Adds the `ParentBreadcrumbs` component to show a list of parent containers on the Unit and Subsection breadcrumbs.
2025-06-30 12:30:48 -05:00
renovate[bot]
37313b30bd chore(deps): update dependency @types/lodash to v4.17.19 (#2239)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 01:25:47 -07:00
edX requirements bot
6f79e4475d chore: update browserslist DB (#2238)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-06-30 00:22:35 +00:00
Daniel Valenzuela
e2da13d129 feat: remove unit/subsection from subsection/section (#2149)
Let the user remove a unit/subsection from a subsection/section.
2025-06-27 08:08:40 -05:00
Daniel Valenzuela
aeefcc639f fix: open section/unit with keyboard inside section/subsection page (#2209)
When selecting a unit/subsection inside a subsection/section with the keyboard, opening it in the sidebar by pressing enter was not working.
2025-06-25 12:06:33 -05:00
Navin Karkera
4905f3bbc7 feat: container delete confirmation modal (#2145)
Update container delete confirmation modal based on #1982 and #1981
2025-06-24 12:37:14 -05:00
Brayan Cerón
60cebf703d fix: clear selection on files & uploads page after deleting (#2056)
* refactor: remove selected rows when deleting or adding elements

* refactor: ensure unique asset IDs when adding new ones

* refactor: remove unnecessary loading checks in mockStore function

* test: add unit tests for TableActions component
2025-06-24 08:19:36 -07:00
jacobo-dominguez-wgu
71fa247c61 test: replacing snapshot tests with RTL tests part 11 (#2214) 2025-06-24 03:04:03 -07:00
renovate[bot]
31fc0453b4 chore(deps): update dependency @types/react to v18.3.23 (#2212)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-24 10:03:43 +00:00
renovate[bot]
75137bc651 chore(deps): update dependency @types/lodash to v4.17.18 (#2211)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-24 10:03:31 +00:00
jacobo-dominguez-wgu
085cd7d05c test: replacing snapshot tests with RTL tests part 10 (#2207) 2025-06-24 02:50:54 -07:00
Muhammad Faraz Maqsood
810dd420fd fix: course optimizer styling 2025-06-24 12:51:41 +05:00
Jillian
747f7b6133 Add subsection/unit to section/subsection full-page view within library [FC-0090] (#2152)
* Removes the "content type" tab bar from the "Add Existing Component/Unit/Subsection" modal, and in all cases where only one type of content is shown for selection.
* Updates the section/subsection sidebar to show "Existing Library Content" + "New Subsection" / "New Unit" buttons.
* Updates the "Add New Unit/Subsection" buttons to directly launch the new container modal, instead of going via the container sidebar.
* Ensures that whenever a subsection/unit is created from within a section/subsection, that it is linked to the parent section/subsection after created.
2025-06-24 02:05:35 -05:00
Chris Chávez
ebf4b7c162 feat: Open Manage tags on click tag count in section/subsection page [FC-0090] (#2136)
Add functionality to open the manage tags when clicking the tag count in the section/subsection page.
2025-06-23 12:11:09 -05:00
jacobo-dominguez-wgu
962b30bed9 test: replacing snapshot tests with RTL tests part 9 (#2206) 2025-06-20 12:05:34 -07:00
Chris Chávez
75ea7500e1 fix: Rename optimistic update in children containers (#2141)
Fix: When you update the title of a unit/subsection in the subsection/section page, the text returns to the previous value for a while
2025-06-19 16:11:13 -05:00
jacobo-dominguez-wgu
08c3d123d8 test: replacing snapshot tests with RTL tests part 7 (#2181) 2025-06-19 09:11:51 -07:00
Devasia Joseph
920f4a54e1 fix: TNL-10093 Removed inaccurate course rerun message 2025-06-19 14:49:50 +05:00
renovate[bot]
d9e1a4dea6 chore(deps): update dependency @openedx/frontend-build to v14.6.1 (#1561)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-18 15:31:30 -07:00
renovate[bot]
8b9a80eb04 chore(deps): update dependency @tanstack/react-query to v4.40.0 (#2155)
* fix(deps): update dependency @tanstack/react-query to v4.40.0

* fix: npm was trying to install react-native which conflicted with React 18

The problem is that react-query 4.40.0 specifies an optional, unpinned peerDependency on react-native, and then it depends on @types/react 19, causing a conflict with our React 18. Putting an explicit dependency on the React types solves this. As would upgrading to React Query v5.

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-06-18 22:12:04 +00:00
jacobo-dominguez-wgu
a5c17452e7 test: replacing snapshot tests with RTL tests part 8 (#2184) 2025-06-18 15:09:21 -07:00
renovate[bot]
4b4ab92383 chore(deps): update dependency redux to v4.2.1 (#1936)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-18 21:51:17 +00:00
Chris Chávez
97710c262e fix: Truncated text in InplaceTextEditor [FC-0090] (#2146)
* Fix the truncated text in InplaceTextEditor.
* Fix the truncated text in the breadcrumbs in the subsection page
2025-06-18 21:38:17 +00:00
Muhammad Faraz Maqsood
b510b6f69f fix: update advanced module list not working (#2189)
Backend was still expecting `{'advanced_modules', {'value': ['poll', 'problem-builder', 'h5pxblock']}}` but without this change, it was receiving `{'advancedModules', ['poll', 'problem-builder', 'h5pxblock']}`

Follow up to https://github.com/openedx/frontend-app-authoring/pull/1581

Co-authored-by: Muhammad Faraz  Maqsood <faraz.maqsood@A006-01130.local>
2025-06-18 13:33:03 -07:00
Kyle McCormick
488173ebdb fix: Subsections should come before Sections 2025-06-18 12:19:50 -07:00
Brian Smith
5a84d8c52f feat!: add design tokens support (#2187)
BREAKING CHANGE: Pre-design-tokens theming is no longer supported.

Co-authored-by: Diana Olarte <diana.olarte@edunext.co>
2025-06-18 15:17:18 -04:00
Daniel Valenzuela
ac7f90065d feat: create subsections, units from within containers (#2104)
Functionality to create subsections, and units from within sections, and subsections respectively.
2025-06-18 12:58:03 -05:00
jacobo-dominguez-wgu
19f81cc05d test: replacing snapshot tests with RTL tests part 6 (#2173)
* test: replacing snapshot tests with rtl tests part 6

* fix: removing testing purposed text

* test: fixing test mocking issues
2025-06-17 12:29:34 -07:00
Jillian
fa9d66c5e5 fix: show "This <containerType> is empty" (#2157)
Shows "This is empty" text when container child list is empty for units, subsections, and sections.
2025-06-16 17:09:55 -05:00
renovate[bot]
dc16b226f0 chore(deps): update dependency @openedx/paragon to v22.20.2 (#2150)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 17:12:41 +00:00
jacobo-dominguez-wgu
cba4e684ab test: replacing snapshot tests with RTL tests part 5 (#2143)
* test: replacing snapshot tests with rtl tests part 5

* test: removig extra tests

* test: snaps update

* test: adding import shorthand and turning tests into ts

* docs: clarify which line the comment is about

---------

Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-06-16 16:56:59 +00:00
renovate[bot]
96df339be5 chore(deps): update dependency @types/lodash to v4.17.17 (#2154)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 09:54:23 -07:00
Muhammad Faraz Maqsood
eaee5257bd fix: disable tolerance for multiple answers
As tolerance was being only applied to first correct answer. So, disable tolerance and do not apply it in case of multiple correct answers for Numerical input problem type according to the given documentation: https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/manage_numerical_input_problem.html#add-a-tolerance:~:text=hints%20to%20problems.-,Add%20Multiple%20Correct%20Responses%20via%20the%20Advanced%20Editor,text%20string%20as%20correct%20answers.
2025-06-16 11:10:57 +05:00
edX requirements bot
154b411ad8 chore: update browserslist DB (#2153)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-06-16 00:22:22 +00:00
José Ignacio Palma
284e9c7d68 fix: advanced-settings api should not camel-case return value (#1581) 2025-06-13 23:54:32 +00:00
bydawen
fcf1e5cb33 fix: Text truncate issue in the search modal (#2137) 2025-06-13 16:28:29 -07:00
jacobo-dominguez-wgu
2e9b5b7e78 test: replacing snapshot tests with RTL tests part 3 (#2134)
* test: replacing snapshot tests with rtl tests part 3

* test: addint alt text to icon buttons and test refactor
2025-06-13 09:05:48 -07:00
renovate[bot]
8a423ebf10 chore: update dependency yup to v0.32.11 (#1937) 2025-06-12 15:50:38 -07:00
renovate[bot]
b6db457c6f chore: update dependency @edx/browserslist-config to v1.5.0 (#1562) 2025-06-12 22:47:12 +00:00
renovate[bot]
80dabca88e chore: update dependency @edx/frontend-platform to v8.4.0 (#2086)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-12 15:32:22 -07:00
renovate[bot]
376414a653 chore: update dependency @openedx/paragon to v22.20.1 (#2023)
* fix(deps): update dependency @openedx/paragon to v22.20.1

* fix: minor type warnings from new Paragon version

* test: update snapshot test

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-06-12 15:29:01 -07:00
jacobo-dominguez-wgu
ca85ca8e4b test: replacing snapshot tests with RTL tests part 4 (#2135)
* test: replacing snapshot tests with rtl tests part 4

* test: removing not needed icon mocks, and changing name to render function for editors
2025-06-12 14:12:28 -07:00
Braden MacDonald
4a1f454855 fix: searching "all courses" from studio home wasn't working (#2083) 2025-06-12 09:25:31 -07:00
Chris Chávez
4adf2ff087 fix: Refresh section list on subsection page (#2103)
Invalidates the query in the subsection page used to get the list of sections that contains the subsection
2025-06-12 00:57:25 +00:00
Chris Chávez
569a981a85 fix: show unit published name in sidebar on content picker (#2100)
Fix the bug for show unit published name in sidebar on content picker.
2025-06-12 00:48:56 +00:00
jacobo-dominguez-wgu
3097976b7b test: replacing snapshot tests with RTL tests part 2 (#2132) 2025-06-11 10:15:59 -07:00
Diana Villalvazo
acef2e70cc fix: remove icon and empty breadcrumb from libraries (#2129) 2025-06-11 09:36:45 -07:00
Jillian
c1d874f94f fix: show Preview tab in sidebar when container child selected [FC-0090] (#2128)
Shows the sidebar Preview tab when a container child is selected, while hiding the Preview tab when sidebar shows the container itself, since it's "preview" is already in the main page body.

Adds tests to ensure this behavior is maintained.
2025-06-10 20:05:11 -05:00
jacobo-dominguez-wgu
dc16c42746 test: replacing snapshot tests with RTL tests part 1 (#2108)
* test: replacing snapshot tests with rtl tests part 1

* test: using screen to query and refactor some tests
2025-06-10 15:09:19 -07:00
Ihor Romaniuk
ea33c15b36 fix: remove an extra editing xblock modal on unit page (#2111) 2025-06-10 10:11:01 -07:00
Muhammad Anas
d440394067 fix: remove duplicate markdown_edited save request (#2112)
Removes the unnecessary duplicate save  request of markdown_edited
value to the backend.

Part of: https://github.com/openedx/frontend-app-authoring/issues/2099
Will be backported to Teak.
2025-06-10 11:59:23 -04:00
Arunmozhi
73ac6d725a feat: add v2 CourseAuthoringUnitSidebarSlot (#2000) 2025-06-10 11:46:27 -04:00
Chris Chávez
0e2cab2838 fix: Issue on the in-place editor when renaming library containers (#2101)
* fix: Rename icon size & make the button disappear while editing

* style: Use the correct type in useUpdateContainer
2025-06-09 13:48:51 -07:00
Jillian
b3605fa1b8 refactor: make the unit sidebar code work for any type of container [FC-0090] (#2066)
Refactors the library sidebar and unit info code to make it work for subsections and subsections too
2025-06-09 17:28:58 +00:00
Chris Chávez
be13c18e5d feat: Section/Subsection Card Preview [FC-0090] (#2057)
Section/Subsection card previews
2025-06-09 11:10:18 -05:00
edX requirements bot
019eede7c2 chore: update browserslist DB (#2105)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-06-09 00:22:11 +00:00
Braden MacDonald
5991fd3997 refactor: Load waffle flags using React Query (#2068)
* refactor: use React Query to load waffle flags

* test: add test case

* fix: more clear handling of data loading and fallbacks

* refactor: simplify handling of useReactMarkdownEditor

* test: use new mockWaffleFlags() helper

* test: simplify test mocks in hooks.test.js

* refactor: avoid duplicating flag names, clarify how defaults work
2025-06-05 11:02:57 -07:00
Ihor Romaniuk
9a2dac6d4b fix: load sequences in unit page (#1867)
This handles loading errors when opening the course unit page via direct link as an unauthorized user.
2025-06-05 09:39:43 -03:00
jacobo-dominguez-wgu
061855c31e feat: update to latest footer component, remove broken links (#2072) 2025-06-04 16:17:13 -07:00
diana-villalvazo-wgu
5df4cd941d fix: refactor best practices checklist logic (#2038)
The Best Practices Checklist behavior was wrong for some cases:

* Video: if duration is null it shouldn't be marked as completed
* Video: if there are no videos it shouldn't be marked as completed
* Unit depth: if course doesn't have units it shouldn't be marked as completed
* Diverse learning sequence: description mentions that 80% should contain multiple content types, so if it is exactly 80% it should be marked as completed
2025-06-04 16:46:01 -03:00
Adolfo R. Brandes
7274316eb8 chore: Remove extraneous config file 2025-06-04 16:31:32 -03:00
diana-villalvazo-wgu
151b3e30bf fix: files & uploads menu was truncated due to overflow-x (#2071) 2025-06-04 10:45:22 -07:00
Navin Karkera
dd6780ff41 feat: library section and subsection page (#2032)
* Adds section and subsection library pages. 
* Refactors routing to support them and fix routing from collections page to other pages.
* Refactors library context to reliably set component, unit, and other container ids even when the url changes when user goes back in history rapidly.
2025-06-04 17:32:29 +00:00
Muhammad Anas
99e11d3534 fix: markdown editor issues in modal (#2074)
This PR resolves rendering issues with the Markdown editor inside the modal.
The problem began after a PR [1] introduced the use of modals for the editor.
The EditorPage [2] component expects a `isMarkdownEditorEnabledForCourse` prop,
which was missing in that implementation.

[1] https://github.com/openedx/frontend-app-authoring/pull/1838 
[2] https://github.com/openedx/frontend-app-authoring/pull/1838/files#diff-147218ef88726880178ea895988a5d3feaf2c0c4459086a8de7a4080cbe37de7R226
2025-06-04 12:13:55 -04:00
Victor Navarro
ee7992bde5 fix: Expand all now expands subsections (#1998)
* fix: Expand all now expands subsections

* fix: test cases
2025-06-04 13:02:41 -03:00
Braden MacDonald
1dee2bba58 test: refactor many test suites to use testUtils/initializeMocks (#2067)
Simplifies a bunch of test code by converting it to use our handy testUtils module.

None of the app code is change, just test code. And none of the test cases are modified in any meaningful way - this just simplifies the setup/cleanup significantly.
2025-06-03 15:52:56 -05:00
dependabot[bot]
d806b6150d chore(deps): bump tar-fs (#2069)
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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-03 10:12:59 -07:00
Muhammad Faraz Maqsood
c7f3e26798 feat: keep content inside the card 2025-06-03 15:11:04 +05:00
Muhammad Faraz Maqsood
27a2b1235e feat: align icons and re-design sections layout
- TNL-11990: Icons Alignment
- TNL-11982: Re-design Sections layout
2025-06-03 15:11:04 +05:00
Muhammad Faraz Maqsood
3c69733170 feat: add sections filter & UI changes
- TNL-11973: Previously Filters functionality was only working for subsections and units inside sections. Now sections are also filtered.
- TNL-11974: New request, Show "no results found" if no results match the filters
- TNL-11975: UI Change, Align filter menu popup to left side of filter button
- TNL-11976: UI Change, Remove underline below "Course optimizer" title
- TNL-11978: UI Change, Change title to "Scan my course"
- TNL-11989: UI Change, Use empty space to display link, don't truncate text before the space runs out
- TNL-11977: New request, Remove this stuff(scanning steps) when scan is complete, it'll disappear after 2.5 seconds
- TNL-11979: UI Change, Move "This tool will scan your course..." text inside of Scan card
- TNL-11980: UI Change, Move "Last scanned on..." date text below Scan button
- TNL-11981: UI Change, Remove icon from "Start scanning" button
- TNL-11983: UI Change, "Start scanning" button should be smaller, made it medium sized
- TNL-11984: UI Change, Remove dividing line under subsection name in expanded card
- TNL-11985: UI Change, Fix alignment of dividing lines, links, and icons in expanded cards to match Figma.
- TNL-11986: UI Change, Match color of the broken icon with other Icons
- TNL-11987: UI Change, Fix alignment of Filter chips to match Figma
- Also added Beta Badge for course optimizer.
- Added tests for codecov coverage
2025-06-03 15:11:04 +05:00
Rômulo Penido
cfb4944d43 feat: refactor library routes and add section/subsection tabs (#2039)
Adds the "Section" and "Subsections" tabs to the library authoring and refactors our library router hook to fix some ambiguities and solve some bugs.
2025-06-02 14:05:31 -05:00
Tony Busa
17e514f937 Add html lang prop to CodeEditor Component inside the SourceCodeModal (#2043) 2025-06-02 09:18:38 -04:00
Muhammad Faraz Maqsood
0c7cef66ab feat: fix toolbar of text editor at top while scrolling 2025-06-02 09:40:33 +05:00
edX requirements bot
c677e7fef3 chore: update browserslist DB (#2058)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-06-02 00:21:33 +00:00
diana-villalvazo-wgu
50cb8608c4 feat: add library name to review updates block card (#2037) 2025-05-30 22:04:02 +00:00
Brayan Cerón
5bb8a5d47c refactor: remove references of ENABLE_HOME_PAGE_COURSE_API_V2 (#1611)
* refactor: remove references of ENABLE_HOME_PAGE_COURSE_API_V2
* fix: infinite requests when clearing filters
* fix: some requests were being duplicated when changing filters
* test: adapt tests to the latest changes
* test: improve test coverage
* refactor: drop tab for archived courses
* test: filter reset functionality in CoursesTab component
* refactor: revert deletion of isShowProcessing
* test: update visibility check for pagination text in TabsSection tests
* refactor: update dropdown and button accessibility in CardItem and CoursesTab components
2025-05-30 14:31:47 -07:00
Braden MacDonald
f02347dd71 perf: only import JSZip when needed (bundle splitting) (#1933) 2025-05-30 09:45:20 -07:00
Maria Grimaldi
0eaa7f6f88 fix: add file extension to .yml 2025-05-30 08:31:53 -04:00
Maria Grimaldi
e6c1c95260 refactor: use workflow from .github repo 2025-05-30 08:13:39 -04:00
Maria Grimaldi
a18444e691 chore: add workflow to pull release testing issues into the BTR board 2025-05-30 08:13:39 -04:00
Maria Grimaldi
5561c030e8 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:13:39 -04:00
Rômulo Penido
fffa9e2566 fix: selection card wiggle (#2045)
Removes the library cards' resize because of the border change on selection.
2025-05-29 18:54:02 +00:00
Rômulo Penido
f18274533e fix: set unit preview readonly on sidebar (#2008)
Make the unit preview on the sidebar read-only and add `Truncate` to the `InplaceTextEditor`
2025-05-29 13:33:23 -05:00
Jillian
3fc0f27d67 fix: upstreamInfo is not always provided (#2041) 2025-05-29 10:58:20 -05:00
sundasnoreen12
36e57a0cfb fix: passed course id and fixed test cases 2025-05-29 08:53:47 +05:00
Navin Karkera
afd6afdbb9 feat: create section and subsection in library (#2013)
Adds create section and subsection buttons in sidebar.
2025-05-28 16:10:17 -05:00
Braden MacDonald
01243afdd9 chore: bump UUID to v11 (#1932) 2025-05-27 13:08:24 -05:00
diana-villalvazo-wgu
b0e194e512 fix: Display "details" tab as default in collections (#2027) 2025-05-26 15:59:30 -07:00
Daniel Valenzuela
260582b6f0 fix(search-manager): send search keywords to facet search too (#2020)
Filter counts depends on the response for the meilisearch faceted search. Since the search keywords affect the search results, in order to make the block type filter counts reflect the search results, we need to include the search keywords into the faceted search too.
2025-05-26 13:54:54 -05:00
sundasnoreen12
ce337aedef test: added test case 2025-05-26 13:31:04 +05:00
sundasnoreen12
44d47f8783 fix: removed commented line 2025-05-26 13:31:04 +05:00
sundasnoreen12
65c8b8ba4b test: fixed test case issue 2025-05-26 13:31:04 +05:00
sundasnoreen12
80dba704da fix: fixed spacing issues 2025-05-26 13:31:04 +05:00
Ahtisham Shahid
9906901262 fix: updated failing tests 2025-05-26 13:31:04 +05:00
Ahtisham Shahid
5167b167eb feat: added process to sync discussions topic on page load
feat: added process to sync discussions topic on page load

fix: updated failing unit tests

feat: added course creation date in index api

feat: added course creation date in index api

fix: updated unit tests
2025-05-26 13:31:04 +05:00
Muhammad Faraz Maqsood
951b707c7d fix: increase max value for the grace period
- increase max value for the grace period as same as it was before in the legacy experience
2025-05-26 11:03:46 +05:00
dependabot[bot]
8e1e2fdb46 build(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>
2025-05-26 10:51:26 +05:00
edX requirements bot
ca8ce5b253 chore: update browserslist DB (#1997)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-05-26 00:21:21 +00:00
Jillian
c5f7d0cf3b fix: set maxHeight on TextEditor TinyMce widget [FC-0090] (#2024)
Sets a max_height=500px for the TinyMCE editor when editing a Text/Html component.
This prevents the autoresize plugin from expanding the editor textarea beyond the bounds of the editor modal.

⚠️ Because the max height can only be a numeric pixel value, we can't use clever settings like vh or %, and so we're forced to limit the height of the editor to a fixed size for all screen sizes in order to address this issue.
2025-05-23 13:51:39 -05:00
Jillian
ac5574d2c4 fix: refresh xblock inline after accepting/rejecting library sync (#2022)
Instead of reloading the entire Unit after syncing changes from the
library, just reload the xblock that was changed.
2025-05-22 10:49:23 -05:00
Muhammad Faraz Maqsood
df3577241f fix: studio time zone conversion issue 2025-05-22 10:32:41 +05:00
Chris Chávez
65605bf937 fix: Remove never published filter from component picker (#1947)
Removes the never-published filter option from the component picker and unit picker.
2025-05-22 00:37:42 +00:00
Rômulo Penido
9e978057bc fix: rename library publish button to "Publish All" (#2016)
renames the Library publish button from "Publish All Changes" to "Publish All"
2025-05-21 18:12:17 -05:00
diana-villalvazo-wgu
279a900a10 fix: rename "updates" and "libraries" menu items for clarity (#2004) 2025-05-21 11:46:29 -07:00
jacobo-dominguez-wgu
f2d5bc4680 fix: removing edX text reference on video fallback message (#1996) 2025-05-21 11:41:58 -07:00
Chris Chávez
ee5e51d371 fix: Inconsistent publish status filter menu placement (#1966) 2025-05-21 10:22:34 -07:00
Chris Chávez
0e40aa295d feat: New confirmation modal when deleting library components (#1906)
* feat: New units message on delete confirm modal when deleting components
* test: Tests for new delete confirmation messages
* refactor: useComponentsFromSearchIndex added
* refactor: Move fetch units to ComponentDeleter
* style: Delete unnecessary code
2025-05-21 10:04:19 -07:00
Rômulo Penido
e212e1a1ef fix: rename library publish button (#1993)
This PR renames the Library publish button from "Publish" to "Publish All Changes"
2025-05-20 18:22:51 -05:00
Daniel Valenzuela
1568067980 fix: do open editor of new xblock when duplicating (#1887)
Fixes bug where after duplicating an xblock, the editor modal of the old xblock is being open instead of the new copied xblock.
2025-05-20 17:51:42 -05:00
Navin Karkera
503642be8c feat: open collection or unit page on double click only (#2002)
Opens collection or unit page only on double click.
2025-05-20 15:34:03 -05:00
Navin Karkera
6f3b7ab962 fix: search text flickering (#1999)
Fix flickering issue in search field.
2025-05-19 12:30:16 -05:00
Navin Karkera
08ac1c0c4d feat: select component and show sidebar on edit (#1949)
Select component that is being edited in library and show its sidebar. Also fixes issue with children component listing in library unit page
2025-05-19 12:24:14 -05:00
Rômulo Penido
6a3b0064ff fix: change InplaceTextEditor style and add optimistic update (#1953)
* Optimistic update for renaming Components, Collections and Containers
* Change the InplaceTextEditor to show the new text until the onSave promise resolves
* Change the InplaceTextEditor style to: Always show the rename button
2025-05-19 11:46:54 -05:00
renovate[bot]
1d45fa2e38 fix(deps): update dependency @edx/frontend-platform to v8.3.7 (#1469)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 09:40:50 -04:00
Muhammad Faraz Maqsood
62bffc06d7 feat: add never show assessment msg in subsection
- add never show assessment result message in subsection card
2025-05-19 09:06:50 +05:00
jacobo-dominguez-wgu
88aa4c1524 fix: various additional i18n issues
* fix: adding messages for i18n issues related to aria labels

* fix: replacing ternary operator

* refactor: injecting intl object to prevent extra modifications on license details component

* test: fixing failing snapshot test

* chore: best descriptions to aria label and removing aria label not needed

* test: snapshot update and fixing ut

* chore: best descriptions to aria labels
2025-05-13 20:14:14 +00:00
Braden MacDonald
4ebc1590e7 docs: update maintainer to me in catalog-info.yaml
https://discuss.openedx.org/t/frontend-app-authoring-maintanership-transfer/15786
2025-05-13 13:14:05 -07:00
Navin Karkera
97e5fbaa5e chore: add comment to prevent course search reload on type 2025-05-13 11:34:27 -07:00
Ivo Branco
03a757de21 fix: include plugins in i18n extraction script (#1802)
Add the additional source `plugins` folder on the `fedx-scripts` extract translations.
This can be configured because the frontend-build v14.5.0 now supports additional source folders using the `--include` extra argument.
2025-05-13 12:56:11 -04:00
Braden MacDonald
d8eda2494b chore: remove unused dependencies "npm" and "start" (#1931) 2025-05-12 15:24:29 -05:00
jacobo-dominguez-wgu
db07092880 fix: various i18n issues
* fix: adding messages for i18n issues related to placeholders

* fix: adding messages for i18n issues related to import tag wizard stepper titles

* fix: changing name to duplicated id on i18n message

* fix: replacing hardcoded string with constants to solve i18n issue

* fix: typo on title prop

* fix: adding components prop name correctly

* test: adding ut for select video modal

* chore: adding description to placeholder, changing extension to constant file and adding uts for code coverage

* chore: removing outdated comment lines
2025-05-12 09:49:03 -07:00
Navin Karkera
26c6a71624 fix: search modal refresh on typing (#1938)
The whole page was being refreshed while searching content from course
outline page due to fetching of waffle flag on changes in location
search field.
2025-05-12 11:42:59 -05:00
Rômulo Penido
d5dc8b5ebe fix: review/sync bugs [FC-0083] (#1905)
Fixes issues related to component libraries' review/sync flow

* Inconsistent sync pane title versions
* Library content shown in preview warning only appears in review changes modal when that modal is opened from the review tab
* Some new changes only appear within library review tab on scroll at top of list
* Vertically misaligned sync icon in review changes message on course outline
* Show available updates whenever content is updated, regardless of number of updates available
2025-05-12 09:57:38 -05:00
Chris Chávez
7b2cc125a5 fix: Issue with read-only units in libraries & published version of units in library units picker [FC-0083] (#1926)
Fixes the issues from https://github.com/openedx/frontend-app-authoring/issues/1633#issuecomment-2828953801

* In successfully added units, the "add new component" widget appears sometimes
* In the "add existing unit" modal, the preview shows draft versions of units
2025-05-12 09:45:46 -05:00
edX requirements bot
9a2dc8061a chore: update browserslist DB (#1935)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-05-12 00:21:47 +00:00
Rômulo Penido
cc47616256 fix: improve focus/selected style on library authoring (#1918)
Improves the focus and selected styles from the LibraryPage and UnitPage.
2025-05-09 11:05:03 -05:00
Muhammad Faraz Maqsood
e8463f7a6a feat: add more unit tests for code coverage
- add more unit tests for code coverage to cover more use cases
- ignore Modal close in code coverage as our modal does not have close button
2025-05-09 11:28:21 +05:00
Muhammad Faraz Maqsood
c77c4f3c91 feat: add unit tests for filter functionality 2025-05-09 11:28:21 +05:00
Muhammad Faraz Maqsood
36277d8ef5 feat: course optimizer page better design
- Add filter functionality to course optimizer broken links to check different results
- modify design, make use of logo with better tooltip
- change message texts in different area of the page
2025-05-09 11:28:21 +05:00
Braden MacDonald
cdb8016657 fix: invalidate search results when publishing all changes in library (#1925) 2025-05-08 17:28:07 -05:00
Navin Karkera
8c3fab3792 fix: UX issues in unit page (#1913)
Fixes the following issues:

* Selection behavior
* Component selection is by header click only
* Newly created blocks within a unit should be selected on creation/save, appear selected, and have their sidebar open
* Some long text components seem to display at the default height rather than a longer height
* Within the full-page unit view, the "add to collection" overflow menu item on components does not seem to work/only opens the sidebar.
* Draft status indicator text is not vertically centered with icon
* When reordering, dragging a short component past a long component often causes a strange stutter effect.
* When dragging to reorder a component, moving quickly or scrolling often causes the drag handle to be lost / causes the block to jump somewhere else
* Reordering may not consistently support a keyboard-accessible option to change order, like in course authoring
* Tag button on component header opens the old tag side pane
2025-05-07 17:30:25 -05:00
Ihor Romaniuk
04e8f3a488 fix: manage access modal on duplicated xblock (#1866) 2025-05-07 15:40:09 -03:00
Rômulo Penido
d7173036a5 fix: unit pages ux bugs [FC-0083] (#1884)
This PR fixes some UX bugs related to the unit pages:

* Sort for "recently modified" on unit tab does not update after adding new components to units
* Change component delete warning message
2025-05-06 20:34:07 -05:00
edX requirements bot
208b0c9195 chore: update browserslist DB (#1907)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-05-05 00:21:37 +00:00
Jillian
24e469542d perf: use Library search results to populate container card preview (#1820)
* fix: use Library search results to populate container card preview

* feat: show published children when showing only published Unit content

* fix: nits
2025-05-01 19:13:43 -07:00
Rômulo Penido
0fdc460c5b fix: several library unit page UX bugs (#1868)
* fix: rename "Organize" tab to "Manage"

* fix: duplicate key warnings

* fix: uniform messages while adding to collection

* fix: do not allow units be added to a unit
2025-05-01 15:31:43 -07:00
renovate[bot]
a7b10495e6 fix(deps): update dependency react-textarea-autosize to v8.5.9 (#1769)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-01 15:34:49 -04:00
renovate[bot]
fdfc30dbd5 fix(deps): update dependency react-select to v5.10.1 (#1787)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-01 15:20:12 -04:00
dependabot[bot]
75e0531c5b chore(deps): bump @babel/helpers from 7.25.0 to 7.27.0 (#1763)
Bumps [@babel/helpers](https://github.com/babel/babel/tree/HEAD/packages/babel-helpers) from 7.25.0 to 7.27.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.27.0/packages/babel-helpers)

---
updated-dependencies:
- dependency-name: "@babel/helpers"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 15:02:15 -04:00
dependabot[bot]
b697a44f36 chore(deps): bump http-proxy-middleware from 2.0.7 to 2.0.9 (#1840)
Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.7 to 2.0.9.
- [Release notes](https://github.com/chimurai/http-proxy-middleware/releases)
- [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.9/CHANGELOG.md)
- [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.7...v2.0.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 14:52:19 -04:00
dependabot[bot]
db0f562d93 chore(deps): bump formidable from 3.5.2 to 3.5.4 (#1877)
Bumps [formidable](https://github.com/node-formidable/formidable) from 3.5.2 to 3.5.4.
- [Release notes](https://github.com/node-formidable/formidable/releases)
- [Changelog](https://github.com/node-formidable/formidable/blob/master/CHANGELOG.md)
- [Commits](https://github.com/node-formidable/formidable/commits)

---
updated-dependencies:
- dependency-name: formidable
  dependency-version: 3.5.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 14:42:16 -04:00
renovate[bot]
11835d28aa fix(deps): update dependency @edx/openedx-atlas to ^0.7.0 (#1855)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-01 13:55:41 -04:00
renovate[bot]
b023173ed4 fix(deps): update dependency @codemirror/view to v6.36.6 (#1315)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-01 13:40:13 -04:00
Navin Karkera
bc18fffedf refactor: remove custom order function from course libraries list (#1865) 2025-04-30 13:41:17 -07:00
Jansen Kantor
484154b9bd fix: pages and resources plugins not rendered (#1885) 2025-04-30 15:56:49 -04:00
Muhammad Faraz Maqsood
65aca04708 fix: Error when viewing text component in RAW HTML (#1869) 2025-04-28 16:51:54 -04:00
Ivo Branco
d92b27ee93 fix(i18n): translate files and videos table view (#1591)
Fix translation issue on Files and Videos table view mode on the columns.
2025-04-28 12:38:27 -05:00
Brayan Cerón
0f5c752eb0 fix: update MIME type for tar.gz file acceptance in dropzone (#1862)
This solves an issue that allowed the users to import files .gz.
We make the drop zone allow only .tar.gz files.

Resolves https://github.com/openedx/frontend-app-authoring/issues/1386
2025-04-28 12:45:36 -04:00
Raymond Zhou
3d2df5f4be chore: update readme on legacy flags (#1861) 2025-04-28 11:34:17 -04:00
Daniel Valenzuela
dbb1a996e1 feat: display editors as modals (#1838) 2025-04-25 19:48:28 +00:00
Jillian
b30a1c8c5e fix: NaN library components are out of sync [FC-0083] (#1864) 2025-04-25 10:08:33 -05:00
Chris Chávez
855b44f745 feat: Add 'This unit can only be edited from the library' banner (#1860) 2025-04-24 20:50:29 -07:00
Jillian
2d55ba4ccc fix: allow units sourced from libraries to update their settings (#1863) 2025-04-24 17:58:37 -07:00
Chris Chávez
d62c4cf4f8 feat: Sync units in course outline [FC-0083] (#1850)
* Adds the sync button in unit cards in the course outline.
* Opens the compare previews.
* Functionality to sync units.
* Functionality to decline sync units.
2025-04-24 20:18:04 +00:00
Rômulo Penido
9824502278 feat: disallow edits to units in courses that are sourced from a library (#1833) 2025-04-24 19:20:46 +00:00
Chris Chávez
d6b51ecf0c feat: Add unit from library into course (#1829)
* feat: Initial worflow to add unit to course
* test: Add initial tests
* feat: Show only published units
* test: Update Subsection card test and ComponentPicker tests
* feat: Connect add unit from library API
* test: Test for Add unit from library in CourseOutline
* fix: create a new Vertical from a Library Unit
* docs: add a little note about avoiding 'vertical' where possible
* refactor: Use visibleTabs instead of showOnlyHomeTab

---------

Co-authored-by: Jillian Vogel <jill@opencraft.com>
Co-authored-by: Braden MacDonald <braden@opencraft.com>
2025-04-24 12:07:54 -07:00
Muhammad Faraz Maqsood
1fe1f93314 fix: incorrect video durations (#1856)
- fix: incorrect video durations in video info tab and  videos list view

Co-authored-by: Muhammad Faraz  Maqsood <faraz.maqsood@A006-01130.local>
2025-04-24 13:17:40 -04:00
Brian Smith
fbc1273955 feat: import StudioFooterSlot from component package instead of slot package (#1832) 2025-04-24 12:58:27 -04:00
Brian Smith
7edb3528ba feat: standardize slot ids (#1854) 2025-04-24 07:27:04 -04:00
renovate[bot]
e7c22b1cbf fix(deps): update dependency @edx/frontend-component-header to v6.4.0 (#1790)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 16:24:47 -04:00
Muhammad Anas
380f3be164 feat: added markdown editor for editing problems in markdown format (#1805) 2025-04-23 13:24:27 -07:00
Chris Chávez
74d7d66c59 feat: New Transcript widget state on video editors on creation workflow [FC-0076] (#1825)
* New Transcript widget state on video editors on creation workflow
* Which edX user roles will this change impact? "Course Author",
2025-04-23 09:52:10 -05:00
Arunmozhi
e2189f2fdd feat: Enhance Sidebar Slot properties (#1845)
The commit add some extra properties to the CourseAuthoringSidebarSlot
and CourseAuthoringUnitSidebarSlot components to enable
the widgets in the sidebar to have more context to work with.
2025-04-23 09:46:00 -04:00
Muhammad Faraz Maqsood
293b7941dd fix: video & file page toggles
- react redux state changes back to default whenever page refreshes.
 - On course authoring mfe, whenever we redirect from one page to another, it automatically refreshes the page which react app shouldn't do.
 - So, instead of managing video and file pages previously selected view in react redux, save & manage these values in localStorage. So that page refreshes doesn't bother end users.
2025-04-23 12:22:17 +05:00
Rômulo Penido
eaa075464c feat: rename component on library unit page (#1823) 2025-04-22 22:16:38 -07:00
Muhammad Faraz Maqsood
03d732846e fix: TypeError r is not function for custom pages
- fix TypeError r is not a function for custom pages by replacing injectIntl with useIntl() hook.
- fix import for textbooks app
2025-04-23 10:13:45 +05:00
Muhammad Faraz Maqsood
c1302f1089 fix: TypeError r is not a function
- injectIntl is deprecated, Used useIntl() hook instead.
- ErrorLog
```
React Router caught the following error during render TypeError: r is not a function {
  "componentStack": "
    at A (https://course-authoring.edx.org/817.bfc0047cf532fb354633.js:2:5259944)
    at Suspense
    at d (https://course-authoring.edx.org/817.bfc0047cf532fb354633.js:2:65420)
    at t (https://course-authoring.edx.org/817.bfc0047cf532fb354633.js:2:7316739)
    at g (https://course-authoring.edx.org/817.bfc0047cf532fb354633.js:2:8043115)
    at w (https://course-authoring.edx.org/817.bfc0047cf532fb354633.js:2:4746781)
    at div
    at https://course-authoring.edx.org/817.bfc0047cf532fb354633.js:2:6453516
    at div
    at https://course-authoring.edx.org/817.bfc0047cf532fb354633.js:2:7617877
    at div
    at h (https://course-authoring.edx.org/817.bfc0047cf532fb354633.js:2:4740935)
    at rR (https://course-authoring.edx.org/app.756074826164c8adbdbb.js:2:1102691)
    at r (https://course-authoring.edx.org/817.bfc0047cf532fb354633.js:2:1493518)
    at injectIntl(r)
    at main
    at l (https://course-authoring.edx.org/app.756074826164c8adbdbb.js:2:2224276)
    at cR (https://course-authoring.edx.org/app.756074826164c8adbdbb.js:2:1103620)
    at r (https://course-authoring.edx.org/817.bfc0047cf532fb354633.js:2:1493518)
    at injectIntl(r)"
}
```
2025-04-23 10:13:45 +05:00
Chris Chávez
ea26981393 feat: Enable ORA2 in libraries by default (#1847) 2025-04-22 14:34:34 -07:00
Braden MacDonald
55e505eb36 chore: simplify imports in library-authoring/data/apiHooks.ts (#1842)
This just simplifies how API methods are imported into one apiHooks.ts file, reducing the overall lines of code and chance for conflicts. Since we're importing all the API methods anyways, there is nothing to gain from explicitly importing each one separately.
2025-04-22 11:50:06 -05:00
Muhammad Faraz Maqsood
9002f7acfe chore: upgrade footer version 2025-04-22 12:28:18 +05:00
edX requirements bot
febf5cf5d0 chore: update browserslist DB (#1839)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-04-21 00:20:48 +00:00
Raymond Zhou
ac127e2b15 Revert "fix: use navigate instead of Link from react-dom"
This reverts commit 06bdff1796.
2025-04-19 10:26:42 +05:00
Muhammad Faraz Maqsood
06bdff1796 fix: use navigate instead of Link from react-dom
getting TypeError: r is not a function. Replace Link with navigate.
2025-04-18 21:26:22 +05:00
Braden MacDonald
ea0a031d7b feat: button to publish a container [FC-0083] (#1827)
- Publish button with functionality of publish units and components inside the unit
2025-04-18 09:34:46 -05:00
Muhammad Faraz Maqsood
ea8a8e5285 fix: toggle behaviour for video & file view
- fix toggle behaviour for video and file view.
- Before:
  - The default view was card. And The videos and files both pages were sharing same variable & default view.
  - Whenever user selects list view on videos/files page and redirects to another page, the toggle/view shifts again to default(card) view whenever it returns to videos/files page.

- After:
  - The default view is list now. And The videos and files both pages can have different state & default view.
  - Whenever user selects card view on videos/files page and redirects to another page, the toggle/view remain same whatever user had selected before when it returns to videos/files page.

Note: Refreshing a page will use default(list) view.
2025-04-18 11:13:32 +05:00
Chris Chávez
9adfa58d65 feat: Remove component from unit [FC-0083] (#1824)
* Users can remove a component from a unit
* The component is NOT deleted, and remains present in the library
* A toast shows that the component was removed, and allows the user to undo
* Overflow menu item appears in sidebar for selected components in unit
* Overflow menu item appears directly on components in full page unit view
2025-04-17 17:51:42 -05:00
Navin Karkera
4ddb8c3168 feat: edit components in unit page [FC-0083] (#1821)
Allows authors to edit components from unit page. It makes sure that the component preview is updated on save, allows user to double click and open editor in modal etc.
2025-04-17 09:59:16 -05:00
Navin Karkera
3b2adc2fc1 feat: reorder components in unit page [FC-00083] (#1816)
Reorders components in unit page via drag and drop. This PR also refactors and moves draggable list and sortable item components to appropriate location.

Course authors will be affected by this change.
2025-04-16 14:34:28 -05:00
Régis Behmo
4bd2c3b29a feat: lighter build by rewriting lodash imports (#1772)
Incorrect lodash imports are causing MFEs to import the entire lodash
library. This change shaves off a few kB of the compressed build.
2025-04-15 17:07:16 -07:00
Braden MacDonald
f531d5471d fix: merge errors in previous commit (#1819) 2025-04-15 23:46:16 +00:00
Braden MacDonald
f24b89c847 feat: allow pasting units from a course into a library (#1812) 2025-04-15 15:26:19 -07:00
Rômulo Penido
d9dcdfe1e3 feat: add existing components to unit [FC-0083] (#1811)
allows adding existing components to units
2025-04-15 16:49:53 -05:00
Rômulo Penido
990073cb38 feat: renames unit in LibraryUnitPage and adds InplaceTextEditor component (#1810) 2025-04-15 15:42:36 -05:00
Jillian
afecd8ba83 fix: sort Advanced Blocks by default display name (#1817) 2025-04-15 15:07:21 -05:00
Rômulo Penido
aa8a5bfba4 feat: add collections support for containers [FC-0083] (#1797)
Adds support to add Units to Collections.
2025-04-15 13:13:12 -05:00
Navin Karkera
87695ae636 fix: auto adjust min height of xblock previews [FC-0083] (#1813)
Sets minimum height of library block previews based on its render
location and block type.
2025-04-15 10:37:59 -05:00
Braden MacDonald
681854209a fix: Copy to clipboard would seemingly fail even if it worked 2025-04-14 17:21:10 -07:00
Chris Chávez
a522c48045 feat: Add component to Unit [FC-0083] (#1784)
Creation workflow in unit page.
2025-04-14 22:36:46 +00:00
edX requirements bot
f46e4ce4e8 chore: update browserslist DB (#1814)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-04-14 00:21:14 +00:00
Navin Karkera
a43027b328 feat: library unit page skeleton [FC-0083] (#1779)
* View a unit page, which has its own URL
* Components appear within a unit as full previews. Their top bar shows type icon and title on the left, and draft status (if any), tag count, overflow menu, and drag handle on the right.
* Components have an overflow menu within a unit
* Components can be selected within a unit
* When components are selected, the standard component sidebar appears. The preview tab is hidden, since component previews are visible in the main content area.
* Components within a unit full-page view have hover and selected states
* Unit sidebar preview.
* Frontend implementation Drag-n-drop components to reorder them in unit.
2025-04-11 13:50:40 -05:00
Muhammad Anas
01365d080e feat: replace StudioFooter with StudioFooterSlot (#1729) 2025-04-11 13:29:41 -04:00
Chris Chávez
e00a4c4d03 refactor: Build new action buttons for cancel confirmation modal (#1732)
Build new action buttons for cancel confirmation modal in basic block and advanced block editors.
2025-04-11 11:55:32 -05:00
Kshitij Sobti
341a03c50b feat: Add plugin slots for sidebars (#1752) 2025-04-11 07:19:13 -04:00
Chris Chávez
5df7adffec feat: Delete unit [FC-0083] (#1773)
* Adds the delete menu item in unit cards.
* Delete a unit with a confirmation modal.
* Restore a component
2025-04-10 23:59:10 +00:00
Rômulo Penido
04faf54ad8 feat: add container (e.g. unit) tag support (#1782) 2025-04-09 12:10:31 -07:00
Bryann Valderrama
d688cf57b7 fix: add user partition id when update groups 2025-04-09 11:55:11 -07:00
sundasnoreen12
fe36e65d2d fix: removed all varaibles of feedback url 2025-04-09 12:45:56 +05:00
sundasnoreen12
8e99ebf072 test: removed variables from test file 2025-04-09 12:45:56 +05:00
sundasnoreen12
024537c80e feat: hide feedback widget 2025-04-09 12:45:56 +05:00
Muhammad Faraz Maqsood
0ddcbbb7a5 fix: ignore altText to avoid replace &quot; with "
- ignore altText to avoid replacing &quot; with "(double quotes) in alt text value
- modify unit tests to cover this new code
2025-04-09 11:58:22 +05:00
Jillian
7ceeb32820 feat: Unit card previews [FC-0083] (#1774)
Adds block tiles to the Unit card to indicate type and quantity of children in the container.
2025-04-08 17:47:04 -05:00
Sarina Canelake
451b821c3b docs: Update references to docs.edx.org (#1783)
With the transition to docs.openedx.org, update links to docs.edx.org to the community-supported site.
2025-04-07 13:55:19 -04:00
Rômulo Penido
68d62cd62f feat: library unit sidebar [FC-0083] (#1762)
Implements the placeholder for the Unit Sidebar.
2025-04-07 11:51:10 -05:00
Rômulo Penido
2a31434a55 fix: prevent multiple submits while creating units [FC-0083] (#1776)
Fixes a bug where the form is submitted multiple times when the user presses Enter on the Unit create form.

The issue was that when the user hit Enter, the form was submitted without calling the button's onClick, allowing multiple calls. Also, because the onClick was not called, we had to add the isLoading property to the LoadingButton to display the status correctly.
2025-04-07 09:24:51 -05:00
Muhammad Faraz Maqsood
fdd8928f36 feat: add manual check count to collapsed view 2025-04-07 10:40:11 +05:00
Muhammad Faraz Maqsood
552ff395df chore: rename course optimizer name in dropdown 2025-04-07 10:40:01 +05:00
edX requirements bot
c324446722 chore: update browserslist DB (#1785)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-04-07 00:20:14 +00:00
Arunmozhi
15fcb55075 feat: adds slots for in-context metrics in studio outline and unit views (#1725) 2025-04-04 07:29:36 -04:00
Régis Behmo
d1a6af51a4 chore: remove husky 🪓🐶
We remove husky, which is triggering pre-push git hooks, including
running "npm lint". This is causing failures when building Docker
images, because "npm clean-install --omit=dev" automatically triggers "npm
prepare", which attemps to run "husky". But husky is not listed in the
build dependencies, only in devDependencies. As a consequence, package
installation is failing with the following error:

        14.13 > @edx/frontend-app-ora-grading@0.0.1 prepare
        14.13 > husky install
        14.13
        14.15 sh: 1: husky: not found

Similar to: https://github.com/openedx/frontend-app-learning/pull/1622
2025-04-02 14:00:02 -07:00
sarina
55344bc55d docs: Update edx.rtd links to docs.openedx.org 2025-04-02 15:59:31 -04:00
sarina
a23f6a6fa7 docs: Update README: s/devstack/tutor/ 2025-04-02 15:59:31 -04:00
sarina
5cedaacc3e docs: Add note to use .nvmrc node version 2025-04-02 15:59:31 -04:00
Brian Smith
0ce0b7526e feat: upgrade to react 18 (#1766) 2025-04-02 12:04:48 -04:00
Ihor Romaniuk
3685dbd6a1 feat: [FC-0070] rendering split test content in unit page (#1492)
Introduces functionality to display Split Test Content within the new Unit page interface.
2025-04-01 11:37:14 -03:00
Rômulo Penido
272e30f1b1 feat: library units tab (#1754)
Implements the "Units" tab on the Library Authoring.
2025-03-31 13:34:25 -05:00
Rômulo Penido
98ae74e78c feat: unit cards in library [FC-0083] (#1742)
Unit cards in library and rename BaseComponentCard -> BaseCard
2025-03-31 10:54:07 -05:00
Rômulo Penido
df7405ec39 feat: create unit workflow (#1741)
Implements the basic workflow to create a Unit in a Library.
2025-03-28 15:44:58 -05:00
Muhammad Farhan
d497bf2ccc fix: update useRef before dispatching file upload action 2025-03-28 19:38:06 +05:00
Muhammad Faraz Maqsood
94f34074ce fix: link navigation for BrokenLink and GoToBlock
In this commit, Fix link navigation in BrokenLinkHref and GoToBlock components
- Updated BrokenLinkHref to prevent default anchor behavior and open broken links directly in a new tab.
- Updated GoToBlock to prevent default anchor behavior and open block URLs directly in a new tab.
- added test coverage for this fix code in `CourseOptimizerPage.test.js`, this wasn't covered before: https://github.com/openedx/frontend-app-authoring/pull/1760/checks?check_run_id=39390124321
2025-03-28 12:19:29 +05:00
Brian Smith
92a8b42e36 feat(deps): update @openedx dependencies to versions that support React 18 (#1759) 2025-03-27 12:19:00 -04:00
Muhammad Farhan
08368582e3 fix: video ID not populating issue 2025-03-26 23:07:27 +05:00
Navin Karkera
a52f6d9b94 fix: prevent editor from loading twice before initialization (#1761)
Data from previous editor instance was being processed by current editor
instance and sometimes failed due to mismatch. For example, editing text
editor or any other basic editor after opening an advanced problem like
drag-n-drop crashed. Now the editor is only rendered after the
initialization process is complete.
2025-03-25 20:14:57 -05:00
Navin Karkera
bac63583ac refactor: don't dismiss out of sync alert on review (#1750)
Clicking review button on out of sync alert should not dismiss the alert
and it should be displayed again in outline or all tab.
2025-03-24 11:39:10 -05:00
Hina Khadim
545bb4a8a6 feat: add manual check links section separately for 403 links (#1751) 2025-03-24 19:55:56 +05:00
Kyle McCormick
9e65424ca6 refactor: Remove unused defaultToAdvanced and getBetaParsedOLXData (#1753)
edx-platform would pass a default_to_advanced flag in through the REST
API, depending on the value of a waffle flag. The flag did not actually
cause anything to default to advanced. What it actually did was switch
from getParsedOLXData to getParsedBetaOLXData. However, getBetaOLXParser
was never implemented--it just logs a console warning and return
getOLXParser.

We remove this unused flag and unused function.
The underlying default_to_advanced API flag and the backing waffle flag
will be removed from edx-platform in a separate PR.
2025-03-20 15:49:36 -04:00
Navin Karkera
27c4eec746 refactor: open review tab in course libraries if out of sync (#1743) 2025-03-19 12:49:22 -05:00
Muhammad Farhan
cc20dfd8ca fix: fetch only studio home data without courses 2025-03-19 12:57:03 +05:00
Rômulo Penido
a26e3f9e92 fix: show error information when taxonomy import fails (#1730)
Adds the error information when we have a failure while importing a Taxonomy
2025-03-17 10:00:33 -05:00
Navin Karkera
e66da2cb49 fix: image rendering in single and multi select problems (#1731)
Fix images in single and multi select problems in libraries. Found following issues and fixed them:

* Images were not being rendered in any of the fields in these problems.
* Base url was not being set which is used by tinymce to load images with relative path.
* Answer fields were set to inline mode which does not initialize images or base paths
* If same image twice is used twice in a problem, the logic of replacing `static/image.jpg` with `/static/image.jpg` would replace the first occurrence twice resulting in `//static/image.jpg`, breaking both the links.
* On initialization of answer fields, the absolute static asset urls were being replaced by relative urls causing the editor being set as dirty without user changes.
2025-03-13 11:11:44 -05:00
Navin Karkera
77a55d9ad3 feat: course libraries review tab [FC-0076] (#1699)
Adds review tab to course libraries page. Also refactors all libraries page as per new designs.
2025-03-12 12:58:27 -05:00
Chris Chávez
3aa409d065 feat: Add Publish confirmation modal [FC-0076] (#1677) 2025-03-11 17:37:40 -05:00
Muhammad Farhan
732fd28eb9 refactor: Improve conditions readability 2025-03-12 00:08:06 +05:00
Muhammad Farhan
091e120224 fix: Use defaultValue when item is null or empty 2025-03-12 00:08:06 +05:00
Brayan Ceron
1174b09ac4 fix: render proper visibility message on self-paced course type 2025-03-11 16:50:59 +05:00
Chris Chávez
b2472cfc0a refactor: Separate Publish order sort from publish filter [FC-0076] (#1701) 2025-03-10 10:55:15 -05:00
Rômulo Penido
17ebb90cd1 fix: paste button on unit page wasn't working (#1724) 2025-03-07 11:09:00 -08:00
Hina Khadim
49fbe766b0 fix: Prevent Alt Text from Being Truncated Due to Double Quotation Marks (#1721) 2025-03-07 23:17:37 +05:00
Rômulo Penido
dbba4dd296 fix: excessive calls to the clipboard API endpoint (#1700) 2025-03-07 08:16:39 -08:00
Chris Chávez
0eda5aec23 feat: Create advanced blocks in libraries [FC-0076] (#1653)
List view to show and create the advanced blocks
2025-03-05 12:46:17 -05:00
Dima Alipov
26c919a070 fix: default setting not updating with updated default settings 2025-03-04 17:01:39 +05:00
Demid
e9d85e85d3 fix: broken re-run notification dismiss (#1590) 2025-03-04 16:59:31 +05:00
Dmytro
e100193744 fix: prevent passing empty string in the date field to backend (#1457)
Co-authored-by: Dima Alipov <dimaalipov@192.168.1.101>
2025-03-04 16:59:00 +05:00
Peter Kulko
411607ec59 feat: [FC-0070] Manage Tags interoperation (#1454)
Added interaction between MFE and Legacy tagging functionality for xblocks on the Course unit page.
2025-03-03 11:07:04 -03:00
Rômulo Penido
06d591df13 fix: change ComponentPreview modal size to xl (#1650) 2025-02-26 17:27:51 -05:00
Jillian
e5360dc1f1 fix: allow users who can create orgs to see the full list of orgs when creating a course [FC-0076] (#1689)
The fixes for https://github.com/openedx/frontend-app-authoring/issues/1577 caused issues with edx.org's Global Staff users not being able to create courses. edx.org/2U Global Staff are seeing an empty Organization drop-down list.

This issue arose due to misuse of two similarly-named flags returned by the contentstore's home API

* `can_create_organizations`: granted to Global Staff or everyone if `FEATURES[ENABLE_CREATOR_GROUP] == True`, 
* `allow_to_create_new_org`: which is actually about auto-creating organizations, so both `can_create_organizations` + `settings.ORGANIZATIONS_AUTOCREATE` must be True

In this change, we use `canCreateOrganizations` to decide whether the user can see the full list of organizations when creating courses. We preserve the use of `allowToCreateNewOrg`  when deciding whether to allow users to "typeahead" to create a new organization not in the drop-down list.
2025-02-25 21:07:43 -05:00
Navin Karkera
11a7e78b73 fix: parsing text input problems (#1679)
* Parse incorrect answer fields in text input problems
* Fix feedback order
2025-02-25 15:41:49 -05:00
Rômulo Penido
56b7a7b17a feat: add component usage data in the ComponentDetails component [FC-0076] (#1656)
Adds the list of Courses and Units/Containers using a component to the "Details" tab on the sidebar.
2025-02-25 13:55:36 -05:00
Diana Olarte
6b2ba6e063 feat: cancellable block creation/edit workflow in libraries v2 (#1574)
Before, clicking "new problem" (etc) would create a new block, then launch the editor. Now it launches the editor and then creates the new block only on save. This makes the "Cancel" button work as expected. Only affects libraries so far, not courses.
2025-02-25 10:28:42 -08:00
Hina Khadim
63caf098a5 [TNL-11885] fix: resolve course-optimizer failure case bug (#1674)
* fix: resolve course-optimizer failure case bug

---------

Co-authored-by: Hina Khadim <hina.khadim@PF1H334R.2tor.net>
2025-02-25 14:52:16 +05:00
Kyle McCormick
8fe52d22e7 fix: Upgrade header, temporarily re-introducing Maintenance link (#1676)
We are temporarily re-introducing the Maintenance link, as the
Maintenance Announcements tool is still in use, as discussed on:
openedx/edx-platform#35852

There are no other significant changes in this version bump:
https://github.com/openedx/frontend-component-header/compare/v5.8.0...v5.8.3
2025-02-24 09:41:06 -05:00
Muhammad Faraz Maqsood
a0a0b9dc84 fix: Resolve Course Optimizer Scanning Bug
- Corrected LINK_CHECK_STATUSES.IN_PROGRESS value that is sent by backend.
2025-02-24 13:31:28 +05:00
Chris Chávez
ba896a3b15 feat: Enable transcripts for video library [FC-0076] (#1596)
* Get updateTranscriptHandlerUrl() and call it when is ready.
* Enable LanguageNamesWidget in a library.
* Enable add transcripts for libraries.
* Enable delete transcripts for libraries.
* Enable replace transcripts for libraries.
* Enable download transcripts for libraries.
* Enable download transcripts from YouTube
2025-02-21 13:33:50 -05:00
KEVYN SUAREZ
3e235d3360 fix: Adjust course import dropzone height to make course import status visible (#1664)
Closes: https://github.com/openedx/frontend-app-authoring/issues/1387
2025-02-21 16:48:57 +00:00
Chris Chávez
0db1727537 feat: Add cancel confirmation modal to Advanced editors in libraries [FC-0076] (#1672)
* Extracts the cancel confirmation modal as a new component.
* Adds the cancel confirmation modal to the Advanced editors in libraries.
2025-02-21 11:24:23 -05:00
Peter Kulko
7e4ecff4e8 feat: handle edit modals from advanced xblocks (#1445)
Adds new message types, updates message handlers, and implements a new modal iframe for legacy XBlock editing.
2025-02-20 17:05:48 -03:00
Saad Yousaf
2befd82e51 refactor: Update information message on Course Optimizer page 2025-02-20 16:57:17 +05:00
Navin Karkera
8275bbe8ce feat: course libraries page [FC-0076] (#1641)
Adds Libraries page that lists all library components being used in the current course to Content > Libraries
2025-02-18 10:36:31 -05:00
Chris Chávez
59243b0cb3 fix: Height in Advanced Editor [FC-0076] (#1649)
Updates the height of the Advanced Editor.
2025-02-13 11:22:02 -05:00
Braden MacDonald
0b08d82f03 fix: bugs with ExpandableTextArea toolbars & modals in problem editor (#1646)
* fix: clicking library name in Studio header would show 404

* fix: when ExpandableTextArea is in a modal, the selection toolbar could not be clicked

* fix: in ExpandableTextArea, shrink the "insert toolbar" that blocks the input

* chore: ignore coverage of modal fixer

* fix: make sure emoji/formula modals are working in the text editor too
2025-02-12 13:40:18 -08:00
Peter Kulko
e9130d3852 chore: iframe rendering optimization (#1544)
Iframe reload optimizations for various xblock related actions. Added some improvements related to scrolling to the current xblock. Fixed behavior of the xblock action dropdown list.
2025-02-11 16:31:07 -03:00
Chris Chávez
b0fc3d923b feat: Add drag and drop to LIBRARY_SUPPORTED_BLOCKS (#1651)
Add drag and drop v2 to LIBRARY_SUPPORTED_BLOCKS to enable the block by default
2025-02-07 12:47:33 -05:00
Daniel Valenzuela
05dddce920 feat: allow filtering library by publish status (#1570)
* Adds a filter widget for Publish status.
* Adds "Unpublished changes" badge.
2025-02-05 13:09:27 -05:00
Muhammad Farhan
31f39cb015 fix: regex mismatch in text block (#1597) 2025-01-30 09:13:26 -05:00
Braden MacDonald
b7241a124c docs: clarify/update a TODO comment about Meilisearch functionality (#1638)
Just a small update to a comment in the code, now that Meilisearch has new functionality that implements a feature we need.
2025-01-29 12:20:48 -05:00
Jillian
be600a91f0 feat: hide some settings fields when editing a library problem (#1601)
Hides some XBlock settings fields when editing library blocks. These hidden settings fields are relevant to course blocks, but not library blocks.

This change impacts Library Authors, and Course Authors who use Library Blocks and/or Problem Banks.
2025-01-27 10:47:09 -05:00
salman2013
de7affd97f chore: update catalog-info file and remove openedx.yaml file 2025-01-24 09:35:54 -05:00
Kristin Aoki
2102c7a612 fix: hidden remove button (#1600)
This PR fixes the visibility of the "Remove" button for grade segments. Previously, the button would appear on hover above the segment. But the styling of the button blocked it from being visible. Now, the button appears on hover under the grade range. This change impacts Course Authors.
2025-01-24 17:25:15 +05:00
Jillian
654c06b596 fix: a11y and performance issues with library authoring navigation [FC-0076] (#1593)
Fixes some a11y and performance issues for Library Authors

**Accessibility**

* When navigating between the various Library Authoring pages, the search keyword box should not be auto-focused, so focus will follow the user's click/tab events and keep that continuity.
The course content search modal behavior is unchanged -- loading this modal auto-focuses the search input box as one would expect.

**Performance**

* Navigating between the various Library Authoring pages was causing a full re-mount of the `<LibraryLayout/>` component
* React query's `staleTime` option is used to control how long data is considered fresh in both queries and routes. By default, the `staleTime` for queries is set to 0 milliseconds, meaning that the data will always be considered stale and will be refetched whenever the query is mounted.
2025-01-22 11:39:47 -05:00
Rômulo Penido
13b2ed5363 feat: add last published date to HistoryWidget [FC-0076] (#1585)
Adds the "Last Published" date to the `HistoryWidget`
2025-01-20 12:30:10 -05:00
Chris Chávez
fd6a6dd443 feat: Add AdvancedEditors with an iframe [FC-0076] (#1568)
Creates the AdvancedEditor to support editors like Drag and Drop, openresponse, poll, survey, and other advanced editors.

- AdvancedEditor created to call studio_view of the block
- Update LibraryBlock to support any view (and use studio_view in AdvancedEditor)
Intercept xblock-event message to close the Advanced editor on cancel or save
2025-01-16 13:22:27 -05:00
Ihor Romaniuk
619ab9a267 feat: [FC-0070] rendering library content in unit page (#1475)
The enables opening a Library Content page within the new Studio unit page. This page displays the xBlocks from the specified library and provides basic configuration options for the library.
2025-01-16 14:06:48 -03:00
Peter Kulko
98fbcff842 feat: [FC-0070] listen to xblock interaction events (#1431)
This is part of the effort to support the new embedded Studio Unit Page.  It includes changes to the CourseUnit component and the functionality of interaction between xblocks in the iframe and the react page.

The following events have been processed:

* delete event
* Manage Access event (opening and closing a modal window)
* edit event for new xblock React editors
* clipboard events
* duplicate event
2025-01-15 13:28:43 -05:00
Jillian
45f6ef42a7 fix: allow user provided value if can auto-create orgs [FC-0076] (#1582)
Allows Content Authors to auto-create an organization when creating a library, if auto-creating orgs is allowed by the platform.
2025-01-15 12:44:30 -05:00
Jesper Hodge
8385c4e8ed Feat course optimizer page (#1533)
Course Optimizer is a feature approved by the Openedx community that adds a "Course Optimizer" page to studio where users can run a scan of a course for broken links - links that point to pages that have a 404.

Depends on backend: openedx/edx-platform#35887 - test together.

This also requires adding a nav menu item to edx-platform legacy studio. That should be implemented before enabling the waffle flag on prod.

Links:
- [Internal JIRA ticket](https://2u-internal.atlassian.net/browse/TNL-11809)
- [Course Optimizer Discovery](https://2u-internal.atlassian.net/wiki/spaces/TNL/pages/1426587703/TNL-11744+Course+Optimizer+Discovery)
- [Openedx community proposal](https://github.com/openedx/platform-roadmap/issues/388)
2025-01-13 11:44:25 -05:00
Farhaan Bukhsh
e6bce560bc feat: Adding human readable 403 error access restricted (#1569)
Updated to have human-readable forbidden error (403)
2025-01-10 13:22:49 -05:00
Jillian
811be226d1 feat: shareable URLs for library components and searches [FC-0076] (#1575)
Adds new routes and URL parameters to use when viewing and performing searches on library components. These changes allow these pages to be bookmarked or shared by copy/pasting the browser's current URL.

No changes were made to the UI.

Use cases covered:

* As an author working with content libraries, I want to easily share any component in a library with other people on my team, by copying the URL from my browser and sending it to them.
* As an author working with content libraries, I want to easily share any search results with other people on my team, by copying the URL from my browser and sending it to them.
* As an author working with content libraries, I want to bookmark a search in my browser and return to it at any time, with the same filters and keywords applied.
* As an author of a content library with public read access, I want to easily share any component in a library with any authors on the same Open edX instance, by copying the URL from my browser and sending it to them.
* As an author of a content library, I want to easily share a library's "Manage Team" page with other people on my team by copying the URL from my browser and sending it to them.
* As an author working with content libraries, I want to easily share any selected sidebar tab with other people on my team, by copying the URL from my browser and sending it to them.
2025-01-10 10:36:46 -05:00
edX requirements bot
f586b095fa chore: update browserslist DB (#1494)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2025-01-06 10:38:02 -08:00
Rômulo Penido
dc0ba6aac4 fix: disable filter by block on collections tab [FC-0076] (#1576)
Adds the disabled prop for `FilterByBlockType` component and uses it on the Library Collection tab.
2024-12-21 07:01:22 -05:00
Rômulo Penido
230960b711 refactor: improve library sub header (#1573)
Changes the Library (and Collection) subheader
2024-12-18 12:56:21 -05:00
Chris Chávez
64906a1b9d refactor: Update error message while adding library team member [FC-0062] (#1572)
Update the error message while adding a library team member to show the error message generated by the server
2024-12-18 12:50:09 -05:00
Navin Karkera
b110b6bdc9 feat: undo component delete [FC-0076] (#1556)
Allows library authors to undo component deletion by displaying a toast message with an undo button for some duration after deletion.
2024-12-13 13:18:29 -05:00
Rômulo Penido
69bbeda816 refactor: split up library context (#1539)
Split the library context into smaller contexts:

* LibraryContext
* ComponentPickerContext
* SidebarContext
2024-12-12 13:14:45 -05:00
Brayan Cerón
c7e2bf9934 fix: find proper courses when searching (#1497)
When active/archived filters were on or there was selected any order filter, the search skipped these values and it was just returned the courses list without the respective filters. Additionally, when a search keyword was applied and a filter was selected, the keyword stayed stuck and the search list returned were not the appropriate
2024-12-09 14:44:02 -08:00
Daniel Valenzuela
73490a5741 fix: avoid changing url when removing filters (#1530)
* Makes the Active Tab Key independent from the URL, except for the initial load, where the active tab is set from the url.
*Avoids unnecessarily changing SearchParams: Due to a limitation of the useSearchParams react hook, which uses a memoized value for the URL that becomes stale after selecting a tab, it unexpectedly changes the URL value. Unfortunately there's no way to completely avoid this, so if there's a usageKey url param, the hook setter function will be called and the URL will revert to the stale memoized url.
2024-12-06 16:24:04 -05:00
Chris Chávez
d2d753203f fix: Update error messages when adding user to library [FC-0062] (#1543)
Updates the message error when the user doesn't exist when adding a new team member to a library.
2024-12-06 15:46:52 -05:00
Rômulo Penido
0e9025a670 fix: legacy library links were not working (#1548) 2024-12-06 18:50:53 +00:00
Rômulo Penido
2f1263ab5a fix: show/hide "new library" button based on separate v1/v2 permissions (#1545) 2024-12-06 10:40:45 -08:00
Chris Chávez
a0f6f4357e fix: Show published OLX in Library Content Picker [FC-0062] (#1534) 2024-12-05 14:13:04 -05:00
Braden MacDonald
e75ce15a67 refactor: Add TypeScript types for the Editors' Redux state (#1537)
It starts to add type information to the messy Redux state used by the editors, mostly focusing on the state shared by all editors and the problem editor.
2024-12-03 17:51:52 -05:00
Rômulo Penido
0771923183 feat: preserve library sidebar tab while switching items (#1535)
In the library home page, makes the selected tab on the sidebar persist while selecting Components or Collections Info Sidebar.
2024-12-03 17:13:22 -05:00
Braden MacDonald
6e53e37bfe refactor: Convert more Taxonomy code to TypeScript (2) (#1536)
* Converts some files from .js or .mjs to .ts
* Refactors some tests to use the new initializeMocks helper
* Cleans up and improves some type definitions
2024-12-02 09:24:17 -05:00
Braden MacDonald
abe68ac599 refactor: Convert more Taxonomy code to TypeScript (#1532)
* Converts some files from .js or .mjs to .ts
* Moves the API code from src/taxonomy/tag-list/data into src/taxonomy/data
* Cleans up and improves some type definitions
* No user-visible changes / functionality changes.
2024-11-27 15:31:55 -05:00
Rômulo Penido
f86c609ff1 fix: editor flicker after creating xblock (#1531) 2024-11-26 14:41:04 -08:00
Kyle McCormick
ec3f78f0ea feat!: remove Maintenance header link (#1526)
...by bumping frontend-component-header 5.7.0 -> 5.8.0

Our reasoning is that the two functions of the Studio Maintenance
dashboard (Announcements and Maintenance Banner) have been broken
for a while.

It's actually version 5.7.2 that removes the link [1] but since 5.8.0
has no breaking changes, it seemed prudent to jump straight to latest.

[1] https://github.com/openedx/frontend-component-header/releases/v5.7.2

Related PR: https://github.com/openedx/edx-platform/pull/35852
2024-11-26 09:49:34 -05:00
Navin Karkera
55fe87a3db feat: show problem bank component picker on window msg [FC-0062] (#1522)
Fix for: If you have a unit with many components and a problem bank on the NEW MFE unit page (with an iframe), clicking "Add Components" will open a modal that's way too tall.
2024-11-22 20:29:18 +00:00
Navin Karkera
7aa5accdbb feat: preview library block changes in course unit [FC-0062] (#1506)
Creates a new preview library block modal. Intercepts the message when the block is iframed to open the new modal.
2024-11-22 15:18:43 -05:00
Diana Olarte
31f59d6bca fix: Schedule and Details page was not loading (#1527)
The page relied on obscure behavior of setting "isLibrary" to disable image uploads even in a course context. This commit refactors to use an explicit enableImageUpload prop in TinyMceWidget.
2024-11-22 12:10:11 -08:00
Peter Kulko
bc8d59b0eb chore: [FC-0070] Some tests refactoring (#1518) 2024-11-21 15:24:31 -03:00
Ihor Romaniuk
b5419acd74 feat: [FC-0070] implement move xblock modal (#1422) 2024-11-21 15:22:41 -03:00
Braden MacDonald
66577b0d59 chore: bump frontend-build, remove exceptions for prefer-default-export (#1519) 2024-11-20 09:00:02 -08:00
Chris Chávez
624f5addcf fix: Show published count component in library content picker (#1481)
When using the library component picker, show the correct number on component count (published components) in collection cards.
2024-11-19 16:10:00 -05:00
Chris Chávez
0365e3809b fix: TinyMce aux modal issues in text editors [FC-0062] (#1500)
The following bugs were found with the TinyMCE aux modal (used in emoticons, formulas and embed iframe):

* The TinyMCE aux modal and the Editor modal close when clicking on any content in the aux modal.
* When the user opens the Edit Source Code modal, this adds data-focus-on-hidden to the TinyMce aux modal, making it unusable (not clickable).
* Since they are two separate modals, the focus remains on the editor modal, making it impossible to use scrolling or inputs from the modal aux.

Solution: Move the aux modal inside the editor modal.

One discarded solution: Block the modal editor from closing when interacting with the modal aux. The modal editor still retained focus.
2024-11-19 15:10:04 -05:00
Diana Olarte
b260708080 test: fix contentContainer test (#1516) 2024-11-19 12:24:32 -05:00
Diana Olarte
f740f57454 feat: upload images to v2 library components from the TinyMCE in library editor (#1458) 2024-11-18 10:38:08 -08:00
Peter Kulko
ba48a273a1 fix: fixed Configure modal for unit page (#1452) 2024-11-18 11:39:44 -03:00
Peter Kulko
0706a09acb fix: error handling (#1079)
Added alert message if 403 error occurs.
2024-11-18 11:27:36 -03:00
Régis Behmo
771c5d3e19 docs: minor README improvements (#1504) 2024-11-15 10:32:22 -08:00
Kyle McCormick
6ffdb01c24 refactor: remove pointless maintenance link message (#1503)
This link is defined in frontend-component-header, so the message
shouldn't be here. Anyway, we are deleting the link from
frontend-component-header too

Related:
* https://github.com/openedx/frontend-component-header/pull/553
* https://github.com/openedx/edx-platform/pull/35852
2024-11-15 10:55:23 -05:00
Pooja Kulkarni
32e5fa68d8 fix: Adjust styling when title is truncated (#1382) 2024-11-14 17:30:19 -05:00
Navin Karkera
cee88885d9 feat: enable problem bank button functionality on unit page (#1480) 2024-11-14 12:00:23 -08:00
Navin Karkera
033acc45f1 fix: remove unnecessary toast notification on adding component (#1490)
Fix for: #1489
2024-11-14 12:03:09 -05:00
Navin Karkera
efd2b3d27d feat: show info banner in component picker (#1498)
Displays a infor banner if only published content is visible in component picker.
2024-11-13 13:54:20 -05:00
Peter Kulko
9b4cf8718f fix: fixing broken tests 2024-11-11 11:20:15 -03:00
Rômulo Penido
67faf9a63a fix: infinite scroll bug on library page (#1483) 2024-11-08 10:59:48 -08:00
Peter Kulko
e59f2846e3 feat: render iframe with xblocks (#1375)
This refactors the CourseUnit component by removing the DraggableList and CourseXBlock components and replacing them with a simpler XBlockContainerIframe. Additionally, it introduces new constants for iframe handling.
2024-11-08 10:53:32 -03:00
Peter Kulko
f9ef00e29f feat: [FC-0070] Remove backend redirects (use SPA functionality) (#1372)
Introduces the ability to utilize SPA functionality when the relevant waffle flags are enabled for current MFE pages. When any new MFE page is loaded, a request is made to retrieve the waffle flags. This includes both global waffle flags related to MFE Authoring pages, as well as waffle flags specific to the current course.
2024-11-08 08:19:23 -03:00
Daniel Valenzuela
979c69b48e feat: simplify Library Home Page (v2) (#1443) 2024-11-07 09:48:19 -08:00
Rômulo Penido
d99e3f0f62 fix: add spacing to searchbar and simplify render conditions (#1461)
Adds padding between the search bar and the library list.

Also, the render method was refactored to be a bit simpler.
2024-11-06 22:01:38 -05:00
Jillian
f1bdc6200f fix: show a more detailed error on Bad Request (#1468)
Show a detailed error when 400 Bad Request received while adding a component to a library, either a new or pasted component. The most likely error from the backend here is "library can only have {max} components", and since this error is translated already, we can just report it through.
2024-11-06 21:53:24 -05:00
Navin Karkera
e118eb5971 chore: hide transcripts in video preview for library (#1459)
Fixes: #1453
2024-11-05 15:15:28 -05:00
Jillian
d7bbd40de1 fix: Hide / error on Libraries v2 pages if !librariesV2Enabled (#1449)
Show an error message if the user tries to view a v2 Library while Libraries V2 are disabled in the platform.
2024-11-05 15:14:09 -05:00
edX requirements bot
fc94667a57 chore: update browserslist DB (#1381)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-11-04 12:27:02 -08:00
Navin Karkera
df8a65dc4e feat: handle unsaved changes in text & problem editors (#1444)
The text & problem xblock editors will display a confirmation box before
cancelling only if user has changed something else it will directly go
back.
2024-11-04 12:41:00 -05:00
Rômulo Penido
949e4ac94c fix: enable publish button on library after component edit [FC-0062] (#1446)
Fixes the following bug: After publishing a library then editing a component, the "Publish" button in Library Info doesn't become enabled until you refresh. Updates the apiHooks to invalidates library query.
2024-11-01 13:58:39 -05:00
Navin Karkera
549dbaa0fa fix: add component to collection on paste [FC-0062] (#1450)
Link component to collection if pasted in a collection page.
Fixes: https://github.com/openedx/frontend-app-authoring/issues/1435
2024-10-31 17:44:34 -05:00
Bilal Qamar
28569aa3da test: Remove support for Node 18 (#1247)
* test: Remove support for Node 18

* chore: update code coverage artifact naming
2024-10-31 15:32:54 -04:00
Rômulo Penido
ecfe27b043 fix: empty state for library selection on component picker [FC-0062] (#1440)
This PR fixes the empty state text for adding library content if the user can't access any library.
2024-10-28 18:49:18 -05:00
Chris Chávez
cff1177ae9 fix: Library Preview Expand button covers dropdown (#1438) 2024-10-25 13:55:24 -07:00
Kshitij Sobti
4d4adce715 feat: Use configured DEFAULT_GRADE_DESIGNATIONS (#1227)
Support was recently added to edx-platform to add customisised default grade
designations, this change adds support for them to this MFE as well to bring it
to partiy with the edx-platform UI

It also refactors the grading-settings page to use React Query and updates the
logic used when partitioning grades by default to make it work better when there
are more than 5 partitions.

Co-authored-by: Farhaan Bukhsh <farhaan@opencraft.com>
2024-10-25 15:34:04 +05:30
Jillian
774728a9c0 fix: use absolute URL for Export Tags menu item (#1432)
use absolute URL for Export Tags menu item so that the menu item works no matter where in the course it's used. Fix this issue: https://github.com/openedx/frontend-app-authoring/issues/1380
2024-10-24 21:03:51 -05:00
Braden MacDonald
3d8d248599 feat: arbitrary asset upload/deletion for Library Components [FC-0062] (#1430)
Allow users to upload and delete assets associated with Content Library
components via the sidebar panel, under the "Advanced Details" section
of the "Details" tab. This is intended as a debug tool and power-user
feature, similar to the OLX editor provided there. It's also serving as
our interim image-upload solution, because it was easier to implement
than the full modal that integrates with TinyMCE.

---------

Co-authored-by: XnpioChV <xnpiochv@gmail.com>
2024-10-24 09:46:27 -04:00
Cristhian Garcia
e1ce3eb484 fix: display image preview in libraries editor (#1403)
Prior to this commit, the TinyMCE editor image preview only worked in
courses, and did not work for content libraries.
2024-10-24 09:39:37 -04:00
Rômulo Penido
a8aa495542 feat: add existing content to a collection [FC-0062] (#1416)
Allows library components to be added to a collection using the add-content
sidebar. For the Libraries Relaunch Beta.

For: https://github.com/openedx/frontend-app-authoring/issues/1173
2024-10-23 11:49:46 -04:00
Navin Karkera
c0c74dec83 feat: show confirmation dialog before discarding library changes [FC-0062] (#1428)
* feat: show confirmation dialog before discarding library changes
2024-10-23 10:47:23 -05:00
Navin Karkera
f67c3ffc4c feat: direct link to single block in library [FC-0062] (#1392)
* feat: direct link to single block in library

Adds support for displaying single xblock in a library when passed a
query param: usageKey. This is required for directing users to a
specific block from course.

* feat: show alert while editing library block from course
2024-10-23 10:25:54 -05:00
Rômulo Penido
11470f256d feat: library component picker now supports multi-select (#1417) 2024-10-22 16:41:49 -07:00
Brian Smith
fe37d119f2 feat(deps): update header to 5.6.0 (#1424) 2024-10-22 19:18:50 -04:00
Braden MacDonald
8c8d9119d4 fix: don't revert to advanced editor if problem contains fields like url_name (#1421) 2024-10-22 18:53:22 +00:00
Chris Chávez
21cbf80f23 feat: Show published components on content picker (#1420)
* feat: Show published components on content picker

---------

Co-authored-by: Braden MacDonald <braden@opencraft.com>
2024-10-22 13:47:07 -05:00
Daniel Valenzuela
966e1c3d91 feat: publish single library component (#1407) 2024-10-22 17:31:17 +00:00
Braden MacDonald
57e7baf59e fix: this repo has been renamed to frontend-app-authoring (#1419) 2024-10-22 10:19:24 -07:00
Navin Karkera
675e02fcbd feat: "add to collection" menu item functionality (#1413) 2024-10-22 09:49:51 -07:00
Braden MacDonald
841aede8cd perf: don't load advanced info details (library components) before they're needed (#1409) 2024-10-21 14:07:28 -07:00
Braden MacDonald
6ae68bd122 feat: Menu option to delete a component + small fixes (#1408)
* feat: menu option to delete a component
* feat: close component sidebar if it's open when that component id deleted
* feat: hide unsupported block types from the "Add Content" menu
* fix: expand and internationalize the "component usage" text
2024-10-21 14:04:45 -07:00
Navin Karkera
d49fc85163 refactor: remove parentLocator and next button from lib component picker (#1412) 2024-10-21 10:05:04 -07:00
Navin Karkera
56e025a4f0 refactor: lib component picker modal to only post message with block info (#1401) 2024-10-19 11:55:25 -07:00
Max Sokolski
a94df2fdf0 fix: set original value for TypeaheadDropdown component 2024-10-18 16:35:53 -03:00
Jillian
cfe19894d1 feat: Let Studio Home REST API determine if libraries v1 and/or v2 are enabled (#1329) 2024-10-18 12:03:26 -07:00
Braden MacDonald
40a6ee9ca5 feat: View for comparing published version of library block to previous (#1393) 2024-10-18 11:27:10 -07:00
Chris Chávez
4facf1cf5d feat: add tags to collections [FC-0062] (#1379)
* feat: Add ContentTagsDrawer to collection

* test: Add test to show ContentTagsDrawer on CollectionInfo
2024-10-16 21:50:17 -05:00
Rômulo Penido
b81f611a0e feat: add library component picker (#1356) 2024-10-16 10:18:12 -07:00
Maria Grimaldi
8a4d1f4810 refactor!: turn on homepage course API V2 consumption by default (#1307)
* refactor!: turn on homepage course API V2 consumption by default

Turn on getting courses from the HomePageCourses API
which allows pagination, filtering and ordering. See https://github.com/openedx/edx-platform/pull/34173
for more details on the API implementation.

* fix: home page initial a-z course sort

---------

Co-authored-by: Diana Olarte <diana.olarte@edunext.co>
2024-10-16 12:29:20 -04:00
David Ormsbee
1bdea093b0 fix: disable static asset mangling for v2 Content Libraries
The static asset substitution used to make images show up properly when
in the TinyMCE editor doesn't work for Content Libraries. Unfortunately,
this will cause the static asset references in XBlock content to get
mangled and saved incorrectly. So until we can handle it correctly,
we're just going to disable it entirely if the LearningContext is a v2
Content Library.

This means that static assets won't display properly in the editor
itself, but it should at least get written/preserved correctly, so that
those assets will show up properly in XBlock previews.
2024-10-16 11:54:19 -04:00
David Ormsbee
a1181f3d49 refactor: switch Content Library XBlock preview to Studio
edx-platform commit 7316111 (PR #35598) moved the XBlock embed view so
that it can be rendered on either LMS or Studio. This commit moves the
frontend to actually call the Studio endpoint. This will make Content
Library static asset display easier, because that view will only be made
available through Studio and not the LMS.
2024-10-16 11:54:19 -04:00
Stanislav
ba8e3d448e fix: Calendar icon over datepicker modal (#1365) 2024-10-16 10:20:27 -04:00
Jillian
1ee3229104 feat: UI to manage users/permissions for the content libraries (#1362) 2024-10-15 17:24:00 +00:00
Navin Karkera
84487602cc feat: manage collections in component sidebar [FC-0062] (#1373)
* feat: add to collection in sidebar

* feat: manage collections

* test: add tests for manage collections

* feat: remove from collection menu option
2024-10-15 10:20:23 -05:00
Navin Karkera
7fb460019e feat: add an allowlist of for supported blocks in library [FC-0062] (#1378)
* feat: show error msg from server on paste

* feat: add an allowlist of for supported blocks in library

Libraries v2 currently don't support editing blocks other than problem,
text and videos. This commit adds a configuration variable called
`LIBRARY_SUPPORTED_BLOCKS` to setup allowed list of block types users
can paste into libraries. By default it is set to support
'problem,text,video,html`.

* feat: enable add button for blocks based on setting


---------

Co-authored-by: Rômulo Penido <romulo@opencraft.com>
2024-10-15 09:52:35 -05:00
Braden MacDonald
66b14a5b16 docs: update the README with an easy way to run the MFE on your host (#1364) 2024-10-10 14:02:42 -07:00
ABBOUD Moncef
3696836de6 feat: save discussion alert dismissal (#1245) 2024-10-09 16:23:12 -04:00
Navin Karkera
434fea3a95 feat: delete collection [FC-0062] (#1333)
* feat: delete collection

* feat: update button status on delete

* test: add tests for collection delete
2024-10-08 16:59:06 +00:00
Braden MacDonald
75f937e11a feat: Libraries v2: Advanced Component Info & OLX Editor (#1346) 2024-10-08 09:41:21 -07:00
Rômulo Penido
85b5730114 fix: change collection details component slots (#1363) 2024-10-07 21:34:48 -05:00
Braden MacDonald
8c125df9aa feat: Open Editors in a Modal (library components only) [FC-0062] (#1357)
* feat: allow opening editors in modals

* refactor: add an EditorContext

* test: update tests accordingly

* test: make testUtils call clearAllMocks() automatically :)
2024-10-07 21:04:49 -05:00
edX requirements bot
83322e2052 chore: update browserslist DB (#1367)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-10-07 10:15:40 -07:00
dependabot[bot]
b6eeec8e60 build(deps): bump actions/checkout from 3 to 4 (#1371) 2024-10-07 10:12:16 -07:00
Jillian
b957f3b4e3 Use block type label instead of Library block_types REST API [FC-0062] (#1361)
* style: avoid using reserved word "type" as variable name

use componentType or blockType instead.

* refactor: let BlockTypeLabel handle displaying the component label

including the child count, if one is provided.

This change removes hooks for the block_types REST API

* test: add tests for BlockTypeLabel

---------

Co-authored-by: Chris Chávez <xnpiochv@gmail.com>
2024-10-04 13:04:23 -05:00
Jillian
9c1fd5a68c fix: Show spinner while loading library components (#1331) 2024-10-03 21:02:32 -07:00
Braden MacDonald
652af9f6a5 refactor: Improve LibraryContext, convert tests to testUtils (#1345) 2024-10-03 19:35:43 -07:00
Jillian
dc6ede4d80 fix: use "other" component type in decide Card header background (#1359)
if no other background color is found
2024-10-03 15:26:12 -07:00
Jesper Hodge
8c6bbb895f fix: update express (#1351)
Just a package update
2024-10-03 15:21:37 -04:00
Braden MacDonald
4d0f92e265 fix: upload codecov report as a separate workflow step (#1355) 2024-10-02 10:49:38 -07:00
Rômulo Penido
0349188c42 feat: allow full width content in library authoring [FC-0062] (#1258)
* feat: allow full width content in library authoring

* chore: update header and footer versions

---------

Co-authored-by: Jillian <jill@opencraft.com>
2024-10-02 06:16:25 -05:00
Rômulo Penido
b1772383f4 fix: component preview modal overflow (#1348) 2024-10-01 16:56:58 -07:00
Kristin Aoki
b71f2148c9 feat: update ora settings to only be flexible peer grading (#1332) 2024-10-01 13:11:52 -04:00
edX requirements bot
e9c10c7f9e chore: update browserslist DB (#1347)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-09-29 17:35:01 -07:00
Rômulo Penido
4d67e8bda9 feat: improve collection sidebar (#1320)
* feat: improve collection sidebar

* feat: add comments to splice blockTypesArray code

Co-authored-by: Jillian <jill@opencraft.com>
---------

Co-authored-by: Jillian <jill@opencraft.com>
Co-authored-by: Chris Chávez <xnpiochv@gmail.com>
2024-09-27 21:24:12 -05:00
Dmytro
c80483c053 fix: Create button remains deactivated until pick a new org (#1279)
Co-authored-by: Dima Alipov <dimaalipov@192.168.1.101>
2024-09-27 11:37:32 -04:00
Chris Chávez
2cd77ce455 feat: Add tags to manage sidebar of library components (#1299) 2024-09-26 23:33:36 -07:00
Braden MacDonald
95c17537c1 fix: don't revert to advanced problem editor when max_attempts is set (#1326) 2024-09-26 09:50:28 -07:00
Braden MacDonald
3662fadad4 feat!: Remove support for the (deprecated) library authoring MFE (#1327) 2024-09-26 08:38:16 -07:00
Braden MacDonald
ccce44a1c8 fix: library metadata times are actually displayed in local time (#1309) 2024-09-25 17:26:36 -07:00
Rômulo Penido
ff67c9a952 feat: add component Details sidebar [FC-0062] (#1303)
* feat: add ComponentDetails component

---------

Co-authored-by: Jillian <jill@opencraft.com>
2024-09-25 14:33:45 -05:00
renovate[bot]
c13ab00344 chore(deps): update dependency @openedx/frontend-build to v14.1.4 (#1308)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-25 10:17:08 -07:00
Rômulo Penido
b6ec5e1e3a fix: remove preview overlay from library component sidebar (#1323) 2024-09-25 09:32:49 -07:00
Braden MacDonald
5f41db83c2 feat: Enable the Video editor in content libraries [FC-0062] (#1319)
* feat: enable video editor in libraries

* fix: a11y issue in video editor - URL and ID fields were combined

* test: tests for video editor
2024-09-24 21:11:06 -05:00
Braden MacDonald
95521d3b8d Cleanups for the video editor [FC-0062] (#1318)
* refactor: cleanups to video editor code

* test: ignore coverage of blank default data
2024-09-24 20:55:15 -05:00
Braden MacDonald
64d718d198 fix: Use soft nav when clicking a library from studio home (#1306) 2024-09-24 09:32:56 -07:00
edX requirements bot
353ef508df chore: update browserslist DB (#1312)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-09-23 13:22:37 -07:00
renovate[bot]
8b50449c1f fix(deps): update dependency npm to v10.8.3 (#1313)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 09:38:30 -07:00
Navin Karkera
b7ae82bde2 feat: Collections page (in libraries) (#1281) 2024-09-20 10:15:25 -07:00
renovate[bot]
0d472ae66f chore(deps): update dependency eslint-import-resolver-webpack to v0.13.9 (#1284)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-19 13:52:05 -07:00
Zachary Hancock
4e609e02e5 feat: improve error message for proctored exam settings (#1300) 2024-09-19 16:03:34 -04:00
Braden MacDonald
8d49f2ed4e feat: display library title in browser tab (#1305) 2024-09-19 12:34:48 -07:00
Stanislav
f3274e70a6 fix: Fix content overflow in the Pages & Resources modal windows (#1301) 2024-09-19 15:16:53 -04:00
Navin Karkera
9d3a05f1bd feat: show children count in collection card (#1298) 2024-09-19 09:50:38 -07:00
Chris Chávez
053a9b1074 fix: inconsistency with the select all functionality in problem capa type filter (#1294) 2024-09-18 11:35:56 -07:00
Rômulo Penido
fc4b700624 fix: responsiveness on library authoring sidebar (#1293)
* fix: responsiveness on library authoring sidebar

* fix: adjust margin to prevent height change

* fix: prevent button stretch
2024-09-18 11:19:56 -07:00
Braden MacDonald
314dfa60e2 feat: Enable capa problem editor for components in libraries (#1290)
* feat: enable the problem editor for library components

* fix: don't try to load "advanced settings" when editing problem in library

* fix: don't fetch images when editing problem in library

* docs: add a note about plans for the editor modal

* fix: choosing a problem type then cancelling resulted in an error

* chore: remove unused mockApi, clean up problematic 'module' self import

* test: update workflow test to test problem editor

* feat: show capa content summary on cards in library search results

* docs: fix comment typos found in code review

* refactor: add 'key-utils' to consolidate opaque key logic
2024-09-18 17:45:41 +00:00
Braden MacDonald
b01090902a fix: propTypes warnings in Problem Editor, refactor some code to TS (#1280)
* fix: a11y - missing 'alt' text for Problem Editor IconButton
* fix: warning in <ProblemTypeSelect> component - missing key prop in list
* fix: warning: `problemType` required in `ProblemEditor`, but is `null`
* fix: warning: The prop `onClose` marked as required in `SelectTypeModal`
* fix: warning: prop `name` is marked as required in `ForwardRef(_c)`
* fix: warning: props `alt`, `id`, and `key` are required
* test: improve test coverage of SelectTypeModal, refactor some code
* test: improve test coverage
2024-09-18 17:01:56 +00:00
Stanislav
82a3b7c986 fix: Fix content overflow in the Overwrite Files modal window (#1291) 2024-09-17 10:28:18 -04:00
renovate[bot]
fb3533ad49 fix(deps): update dependency frontend-components-tinymce-advanced-plugins to v1.0.4 (#1285)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 19:34:58 +00:00
Rômulo Penido
dd7e4d4297 feat: add component sidebar manage tab [FC-0062] (#1275) 2024-09-16 14:13:41 -05:00
Kristin Aoki
902853d649 fix: isInitialized selector depends on unitUrl for course blocks (#1288) 2024-09-16 14:34:56 -04:00
Kyle McCormick
6eed6438cb docs: update README based on rename (#1289) 2024-09-16 13:05:12 -04:00
edX requirements bot
644f1706a2 chore: update browserslist DB (#1283)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-09-16 09:49:11 -07:00
Brayan Cerón
80e3592669 refactor: remove thumbnail for non-edX videos & allow removing fallback URLs (#1241)
* refactor: remove thumbnail from non-edx videos

* fix: when deleting a fallback URL the app crashed

* refactor: simplify conditional rendering
2024-09-16 11:53:05 -04:00
Rômulo Penido
121ced42ec feat: preview components (xblocks) on library authoring pages (#1242) 2024-09-14 10:03:49 -07:00
Chris Chávez
a37a1b1ef8 feat: Create collection Modal [FC-0062] (#1259)
* feat: Enable Collection button on Create Component in Library

* feat: CreateCollectionModal added

* test: For CreateCollectionModal

* refactor: Migrate FormikControl to TypeScript

* test: Add tests for EmptyStates
2024-09-13 21:07:02 -05:00
Braden MacDonald
fd48fef299 feat: edit Text components within content libraries [FC-0062] (#1240) 2024-09-12 19:39:42 -07:00
Navin Karkera
9b61037311 feat: collections tab [FC-0062] (#1257)
* feat: add collections query to search results

* feat: collections tab with basic cards

* feat: add collection card also fix inifinite scroll for collections

* feat: collection empty states

* test: add test for collections card
2024-09-12 18:55:34 -05:00
renovate[bot]
4035931cbb fix(deps): update dependency @openedx/paragon to v22.8.1 (#1268)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-12 19:26:42 +00:00
renovate[bot]
e2e3104474 fix(deps): update dependency @edx/frontend-component-footer to v14.0.10 (#1244)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-12 19:25:27 +00:00
edX requirements bot
88a038c0ea chore: enable github action auto update in dependabot.yml (#1256) 2024-09-12 15:12:17 -04:00
Demid
45c68d6ca4 Hide "Advanced Settings" settings item [BB-9081] (#1252)
* refactor: convert header utils to hooks

* feat: hide advanced settings button if a user doesn't have access
2024-09-12 14:55:01 -04:00
Dmytro
56728310f4 fix: create course button inactive after using org drop-down (#1276)
Co-authored-by: Dima Alipov <dimaalipov@192.168.1.101>
2024-09-12 12:46:04 -04:00
renovate[bot]
9bbbf610b7 fix(deps): update dependency @edx/openedx-atlas to v0.6.2 (#1228) 2024-09-11 11:30:51 -07:00
Braden MacDonald
6255768c97 test: refactor and fix flakiness of LibraryAuthoringTest (#1263) 2024-09-10 13:34:22 -07:00
Dmytro
513309c160 fix: no validation for combined length of org, number, run (#1262)
Co-authored-by: Dima Alipov <dimaalipov@192.168.1.101>
2024-09-10 10:24:11 -04:00
edX requirements bot
bbe15afbe9 chore: update browserslist DB (#1175)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-09-09 14:41:08 -07:00
Braden MacDonald
f9c11f8129 feat: Add type stubs for frontend-platform/i18n (#1251) 2024-09-09 09:30:14 -07:00
Braden MacDonald
376f31ebae chore: clean up dependencies (#1255) 2024-09-09 09:27:15 -07:00
renovate[bot]
849471bfed chore(deps): update dependency @openedx/frontend-build to v14.1.2 (#1213) 2024-09-06 13:27:43 -07:00
Kaustav Banerjee
6b10fa7401 feat: remove new library button if user does not have create access for v1 libraries (#1216) 2024-09-06 10:49:38 -07:00
Kyr
3a61e84c50 feat: fixed height for prerequisite course dropdown list (#1154)
Co-authored-by: Kyrylo Hudym-Levkovych <kyr.hudym@kyrs-MacBook-Pro.local>
2024-09-06 10:28:55 -04:00
Kristin Aoki
dcf05cde07 fix: tinymce render outside of editors (#1254) 2024-09-05 13:18:26 -07:00
Chris Chávez
34f0bf5253 fix: UX nits on Library Info Sidebar (#1253) 2024-09-04 10:25:36 -07:00
Rômulo Penido
c4d00017e0 fix: FilterItem key warning (#1246) 2024-09-04 08:51:13 -05:00
Braden MacDonald
735d978894 refactor: Merge frontend-lib-content-components into this repository 2024-08-29 10:19:17 -07:00
Braden MacDonald
9d0898cdfe chore: update with master 2024-08-29 10:03:55 -07:00
Bilal Qamar
1e7e3e7036 build: Upgrade to Node 20 (#1209)
* feat: updated node to v20

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

* refactor: updated lockfile version workflow
2024-08-29 12:08:30 -04:00
Rômulo Penido
48e0ec1f70 feat: add library component sidebar [FC-0062] (#1217) 2024-08-29 07:22:13 -05:00
Braden MacDonald
af2b4dd3cb fix: remove another accidental import of test code from the build 2024-08-28 10:51:36 -07:00
Chris Chávez
64ffaddf3c feat: Capa problem types submenu [FC-0059] (#1207) 2024-08-28 08:16:02 -05:00
Braden MacDonald
7d7394521b chore: update with latest master 2024-08-27 13:45:23 -07:00
Ihor Romaniuk
f36b2183d6 fix: reset active answers for single answer problem type (#426) 2024-08-27 13:44:11 -07:00
Braden MacDonald
83fda560c1 fix: remove accidental import of test code from the build 2024-08-27 13:41:55 -07:00
Chris Chávez
d99a09efba fix: Library v2 info sidebar UI fixes (#1226) 2024-08-26 13:33:54 -07:00
Jillian
259a50c468 UI fixes for Sort Library Component [FC-0059] (#1222)
fix: use "Recently Modified" as the default sort option

When search keyword(s) are entered, use "Most Relevant" as default.

Also

* Hides "Most Relevant" option if no keyword is entered.
* Re-orders the sort menu options
* Ensures the default sort option is not stored in the query string
* Shows the selected sort option on the drop-down toggle button
* Shows "Sort By" as a header inside the drop-down menu
2024-08-23 19:11:53 -05:00
Bilal Qamar
3e0f7b5758 test: Add Node 20 to CI matrix (#1224) 2024-08-22 14:37:36 -04:00
Rômulo Penido
21c9e30207 refactor: change toast component (#1211) 2024-08-22 08:50:43 -05:00
Muhammad Anas
8ae9dfbd88 feat: customize the certificate link in header (#1223)
* feat: customize the certificate link in header

* fix: lint issues

* fix: tests
2024-08-21 10:36:14 -04:00
Navin Karkera
3089d0b993 fix: discard button [FC-0062] (#1214)
* fix: discard changes

* refactor: disable discard btn for new libs

Enable it if components are added.

* refactor: invalidate library related content queries

* chore: add comment about content search query invalidation
2024-08-20 21:12:06 -05:00
renovate[bot]
47cec6e4c9 fix(deps): update dependency @edx/frontend-lib-content-components to v2.6.8 (#1218)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-20 15:21:54 -04:00
Rômulo Penido
f370b565c2 fix: dropdown checkbox click area (#1215) 2024-08-17 16:43:27 -07:00
Braden MacDonald
155a710aa8 chore: work around type error with <SelectableBox> 2024-08-17 16:41:12 -07:00
Braden MacDonald
591a02e8a7 chore: update with master 2024-08-17 16:27:00 -07:00
Braden MacDonald
f90bbb2de7 chore: update to frontend-lib-content-components 2.6.8 2024-08-17 16:23:19 -07:00
Braden MacDonald
28e1956708 chore: update imports, fix lint issues 2024-08-17 16:12:58 -07:00
Ihor Romaniuk
b55e5c9f8f fix: answer range validation in Numerical input (#482) 2024-08-16 12:19:11 -04:00
Kyr
a9e8bd5558 fix: license widget checkbox and link (#486)
* fix: share alike after save, license link for creative common

* test: update snapshot

---------

Co-authored-by: Kyrylo Hudym-Levkovych <kyr.hudym@kyrs-MacBook-Pro.local>
2024-08-16 10:19:13 -04:00
Yusuf Musleh
95ac0983a3 feat: Add "Paste from Clipboard" to lib v2 sidebar (#1187) 2024-08-15 10:03:39 -07:00
renovate[bot]
7c59b4a210 fix(deps): update dependency @openedx/paragon to v22.7.0 (#1180)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-13 16:39:37 -04:00
renovate[bot]
de3befec08 fix(deps): update dependency @edx/frontend-component-header to v5.3.4 (#1179)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-13 18:08:37 +00:00
renovate[bot]
6ff3847c6c fix(deps): update dependency @edx/openedx-atlas to v0.6.1 (#1123)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-13 13:53:33 -04:00
renovate[bot]
ea90e7e93c fix(deps): update dependency @edx/frontend-lib-content-components to v2.6.6 (#1210)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-13 17:50:42 +00:00
renovate[bot]
48ffa0f970 fix(deps): update dependency @edx/frontend-component-footer to v14.0.8 (#1161)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-13 17:49:42 +00:00
Chris Chávez
4f5346ed31 feat: Library info sidebar - allows lib rename+publish (#1138) 2024-08-13 10:37:34 -07:00
Ihor Romaniuk
940482dd9a fix: add validation to problem number fields (#425) 2024-08-12 11:04:28 -04:00
renovate[bot]
8285f8ec5a fix(deps): update dependency @edx/frontend-lib-content-components to v2.6.5 (#1206)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-12 09:43:34 -04:00
Braden MacDonald
afa2317131 feat: 'frontend-lib-content-components' into this repo 2024-08-09 11:48:49 -07:00
Braden MacDonald
d3d5fe0e1b Removed unneeded files from lib-content-components 2024-08-09 11:47:35 -07:00
Kristin Aoki
b088a8fe3d fix: asset name parsing in static converter (#501) 2024-08-09 13:02:34 -04:00
Rômulo Penido
bb88101255 feat: add "copy to clipboard" feature to library authoring UI (#1197) 2024-08-08 09:32:04 -07:00
Chris Chávez
a7645afd22 fix: UI fixes for read-only libraries etc. (#1198)
* fix: Hide open Create content buttons without permissions

* feat: Read only badge on library Home

* refactor: library authoring to get canEditLibrary from useContentLibrary

* style: Typo on the code
2024-08-07 18:26:32 -07:00
Kristin Aoki
7379e734a0 feat: replace progress bar with loading spinner (#1192) 2024-08-07 12:07:22 -04:00
Kristin Aoki
3d82d37943 Revert "fix(deps): update dependency @edx/frontend-lib-content-components to …" (#1205)
This reverts commit 6f13164998.
2024-08-06 12:50:21 -04:00
Brandon Bodine
553acd8fcc chore: remove unused ai-translations env vars (#1204) 2024-08-06 07:17:08 -06:00
renovate[bot]
6f13164998 fix(deps): update dependency @edx/frontend-lib-content-components to v2.6.4 (#1184)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-05 09:31:12 -04:00
Jorg Are
9efb583cdc feat: replace ai-translations component with a plugin slot (#1186)
* feat: replace ai-translations component with a plugin slot

* feat: move ai-translations enabled check to plugin
2024-08-05 13:46:50 +01:00
Kristin Aoki
b68257e176 fix: remove imports breaking build (#500) 2024-08-02 15:04:49 -04:00
Rômulo Penido
680b5ff160 refactor: convert a couple files to TS and improve typings/tests (#1181)
* refactor: convert files to ts and improve typings/tests

* fix: set return type to unkown for future fix
2024-08-02 09:26:10 -07:00
Kristin Aoki
beb4813c53 fix: setAssetToStaticUrl regex matcher (#497) 2024-08-01 15:56:32 -04:00
Ihor Romaniuk
ce8703799b fix: add rtl support to editor (#424) 2024-08-01 13:21:01 -04:00
Adolfo R. Brandes
5825dd36d3 Merge pull request #487 from open-craft/braden/fix-extra-scss
fix: don't accidentally bundle paragon CSS x2
2024-08-01 09:55:35 -03:00
Jillian
cba85ab96d test: fix flaky library-authoring test (#1193) 2024-07-30 13:33:24 -07:00
Kristin Aoki
cc3bbfd9af fix: package.json out of sync with package-lock.json and upgrade (#1194) 2024-07-30 20:24:37 +00:00
Jillian
4f88948844 feat: adds sort widget to search manager and library component page (#1147) 2024-07-30 09:41:10 -07:00
Yusuf Musleh
699cbeadb3 feat: Add cancel create library button (#1182) 2024-07-26 09:39:24 -07:00
Rômulo Penido
6382898213 chore: add ts* files to lint --fix script 2024-07-26 09:06:54 -07:00
Kristin Aoki
3dfc579745 feat: add conditional for new parser beta testing (#496) 2024-07-26 10:59:40 -04:00
renovate[bot]
649863d094 fix(deps): update dependency @edx/frontend-lib-content-components to v2.5.2 (#1178)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 11:21:40 -04:00
renovate[bot]
1be693b826 fix(deps): update dependency npm to v10.8.2 2024-07-24 15:02:19 -07:00
renovate[bot]
0933bae314 chore(deps): update actions/checkout action to v4 2024-07-24 14:43:33 -07:00
Rômulo Penido
f159b2b31c chore: update frontend-build (#1155) 2024-07-24 21:42:03 +00:00
Rômulo Penido
25ab1fffa1 feat: adds filter by tags and contentType to library home (#1141)
Refactor to add search-manager feature.

Co-authored-by: Yusuf Musleh <yusuf@opencraft.com>
2024-07-24 12:13:24 -07:00
Milad Emami
ebab15f046 fix: correct typo in Alert component prop (#494)
Corrected the typo in the prop name of the Alert component from 'varaint' to 'variant'. This change ensures the proper functioning of the alert in informational variant.
2024-07-24 13:27:16 -04:00
Chris Chávez
77135cde1d feat: Library v2 components tab (#1109) 2024-07-22 18:04:57 -07:00
edX requirements bot
3a14141a4e chore: update browserslist DB (#1156)
Co-authored-by: abdullahwaheed <42172960+abdullahwaheed@users.noreply.github.com>
2024-07-17 10:23:54 +02:00
Chris Chávez
3d24741062 feat: "Add content" sidebar on each library home page (#1065) 2024-07-17 10:15:40 +02:00
Rômulo Penido
e087001905 feat: create library (v2) form (#1116) 2024-07-12 05:54:37 -07:00
Braden MacDonald
cc41a2fda1 fix: source map warning seen during build (#1150) 2024-07-11 15:15:02 -04:00
renovate[bot]
5dee203401 fix(deps): update dependency @edx/frontend-lib-content-components to v2.5.1 (#1153)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-11 09:55:51 -04:00
Kristin Aoki
9bce0a34e3 fix: remove deprecated feedback link (#493) 2024-07-10 15:58:19 -04:00
renovate[bot]
085069abb0 fix(deps): update dependency @edx/frontend-lib-content-components to v2.5.0 (#1143)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-10 19:04:39 +00:00
Kyr
a22a260e27 feat: remove offset when stuio header exists (#491)
Co-authored-by: Kyrylo Hudym-Levkovych <kyr.hudym@kyrs-MacBook-Pro.local>
2024-07-10 14:35:25 -04:00
Kristin Aoki
b6ff6230e7 fix: text editor opening blank with no images (#492)
* fix: pasting and images only insert at beginning

* fix: add image click not showing gallery

* chore: increase code coverage

* fix: empty string when no srcs need updates

* fix: assest to static in raw editor
2024-07-10 13:53:40 -04:00
Braden MacDonald
ab9d57345b chore: remove unused fontawesome dependencies (#1149) 2024-07-10 14:05:02 +00:00
Rômulo Penido
71fcf9f168 fix: only show course blocks in the search modal (#1148) 2024-07-10 05:29:55 -07:00
Rômulo Penido
f60ddb579e feat: library home page ("bare bones") (#1076) 2024-07-10 05:20:00 -07:00
Braden MacDonald
117b4f10e7 chore: remove core-js and regenerator-runtime (#1032) 2024-07-10 05:07:29 -07:00
edX requirements bot
09822c2937 chore: update browserslist DB (#443) 2024-07-10 01:24:44 -07:00
Hunia Fatima
01d4b85205 perf: lockfile version check workflow file updated (#1107)
Co-authored-by: Hunia Fatima <hunia.fatima@A006-01315.local>
2024-07-10 11:05:43 +05:00
Yusuf Musleh
83489b0983 feat: Add filters/sorting for the libraries v2 tab on studio home (#1117) 2024-07-08 14:35:43 +00:00
Braden MacDonald
8cf26e1a75 Version bump for Paragon to 22.6.1, with stricter typing (#1146)
* fix(deps): update dependency @openedx/paragon to v22.6.1

* fix: lint errors from stricter types in new paragon version

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-08 10:10:08 -04:00
renovate[bot]
9528bfde62 chore(deps): update dependency meilisearch to ^0.41.0 (#1136) 2024-07-08 06:49:44 -07:00
Raymond Zhou
292663a5e3 Revert "fix(deps): update dependency @edx/frontend-lib-content-components to …" (#1142)
This reverts commit cdc9af2ed4.
2024-07-02 12:19:19 -04:00
renovate[bot]
9f0be768aa fix(deps): update dependency @edx/frontend-component-footer to v14.0.5 (#1121)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-01 17:11:05 +00:00
Kristin Aoki
efd73f9c0b fix: progress bar display for uploads (#1135) 2024-07-01 12:52:08 -04:00
renovate[bot]
cdc9af2ed4 fix(deps): update dependency @edx/frontend-lib-content-components to v2.4.3 (#1140)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-01 16:51:39 +00:00
Kristin Aoki
fc3cd9a9ce fix: image and paste insert (#490)
* fix: pasting and images only insert at beginning

* fix: add image click not showing gallery

* chore: increase code coverage
2024-07-01 12:29:05 -04:00
Kristin Aoki
eb3e6faba4 fix: update mapToStateProps to match changes in TinyMceWidget (#1133)
* fix: update mapToStateProps to match changes in TinyMceWidget

* feat: bump frontend-lib-content-components
2024-06-27 14:44:12 -04:00
Kristin Aoki
267823414e fix: simple editor without solution not loading (#489)
* fix: update initialize to only call required functions

* feat: update asset urls without asset object

* feat: add pagination to select image modal

* fix: lint errors

* chore: update tests

* fix: asset pattern regex match

* feat: update pagination to be button to prevent page skipping

* fix: e.target.error for feedback fields

* fix: failing snapshots

* fix: new simple problem load error
2024-06-27 12:54:59 -04:00
Braden MacDonald
a4859d2686 chore: convert all 'search-modal' code to TypeScript (#1129)
* chore: convert all 'search-modal' code to TypeScript

* fix: lint should check .ts[x] files too

* fix: remove unused dependency meilisearch-instantsearch
2024-06-27 12:54:01 -04:00
Kristin Aoki
22ea32cf01 feat: video upload progress modal (#1131)
* feat: add upload progress modal

* fix: increase code coverage

* fix: fix code to be more readable

* fix: delete empty file

* fix: failing test and lint

* fix: progress bar not updating

* feat: add missing abort controller on POST to edxVal
2024-06-26 18:00:07 -04:00
renovate[bot]
8b759bc867 fix(deps): update dependency @edx/frontend-lib-content-components to v2.4.1 (#1132)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-26 13:54:56 -04:00
bszabo
0e913739d4 Merge pull request #488 from openedx/revert-484-KristinAoki/improve-asset-loading
Revert "feat: improve asset loading"
2024-06-26 10:08:55 -04:00
bszabo
ba8141ea6a Revert "feat: improve asset loading (#484)"
This reverts commit f3ae225d64.
2024-06-26 10:02:59 -04:00
Kristin Aoki
9317b87564 Revert "feat: add upload progress modal (#1113)" (#1128)
This reverts commit 8ef804bd58.
2024-06-24 12:19:58 -04:00
Kristin Aoki
8ef804bd58 feat: add upload progress modal (#1113)
* feat: add upload progress modal

* fix: increase code coverage

* fix: fix code to be more readable

* fix: delete empty file
2024-06-24 10:53:49 -04:00
renovate[bot]
641419656f fix(deps): update dependency @edx/frontend-lib-content-components to v2.4.0 (#1118)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-24 09:02:05 -04:00
Jillian
6b6d3aaa7a Upgrade frontend-build to v14 (#1052)
* fix: warnings about Duplicate message id
* fix: paragon's Hyperlink no longer accepts a 'content' attribute
* test: ensure all act() calls are async
* test: Removed "async" from "describe"
* fix: DiscussionsSettings tests
* Don't nest userAction.click in act() -- nested act() statements have
  indeterminent behaviour.
* Use getBy* instead of findBy* with userAction to avoid nested act() statements
* Always await userEvent.click
* Use fireEvent.click when the onClick handlers need to be called
* Use queryBy* instead of getBy* when using .toBeInTheDocument or 
* fix: typo in data-testid
* test: Use useLocation to test route changes
* Don't nest userAction.click in act() -- nested act() statements have
* chore: fix lint:fix and lint errors
* remove "indent" setting from .eslintrc.js
* add @typescript-eslint/ prefix to eslint-disable-line statements where flagged by linter
* changed stylelint setting import-notation to "string"
* test: fix failing tests after upgrade
* fix: css error "target selector was not found"
* chore: upgrades dependency frontend-lib-content-components@2.3.0
* chore: bumps @edx/frontend-component-ai-translations to ^2.1.0

---------

Co-authored-by: Yusuf Musleh <yusuf@opencraft.com>
2024-06-22 00:14:46 +05:30
Braden MacDonald
28c7b32bd5 fix: don't accidentally bundle paragon CSS x2 2024-06-20 15:23:08 -07:00
Marcos Rigoli
3936737b48 feat: Include org filter when requesting LTI providers (#1114)
* feat: Include org filter when requesting LTI providers

* chore: Created silent version for CI testing to avoid log flooding
2024-06-20 11:17:08 -03:00
Yusuf Musleh
088a01d716 feat: Add lib v2/legacy tabs in studio home (#1050)
This PR adds a new configuration flag that shows/hides tabs in studio home along with some new functionality around to V1 and V2 Libraries.

When the new LIBRARY_MODE flag is set to "mixed" (default in dev) it will show "Libraries" and "Legacy Libraries" tabs that correspond to v1 and v2 tabs respectively.

When the new LIBRARY_MODE flag is set to "v1 only" (default in production) or "v2 only", only one tab "Libraries" is shown and only the respective libraries are fetched when the tab is clicked.

In addition to the above changes, the URL/route now updates when clicking on the tabs, and navigating to it directly would open up that tab as well as a new placeholder page that you will be redirected to when clicking on a v2 library if the library authoring MFE is not enabled.
2024-06-20 17:30:57 +05:30
vladislavkeblysh
c84e3229f6 feat: Validation for Start time and Stop time fields (#419)
* feat: fixed fields onblur

* feat: fixed fields onblur

* feat: added new tests
2024-06-18 16:51:32 -04:00
Dmytro
d2ddc9099f fix: Not used Number of attempts field (#473)
Co-authored-by: Dima Alipov <dimaalipov@MacBook-Pro-Dima.local>
2024-06-18 16:44:51 -04:00
Ihor Romaniuk
6ac0a6e562 fix: form group controls alignment (#423) 2024-06-18 16:40:49 -04:00
Navin Karkera
e2ed3bc7a7 refactor: show generic message on studio server error (#1112) 2024-06-18 16:07:46 -04:00
Adolfo R. Brandes
6a58779ffe Merge pull request #485 from arbrandes/update-codecov
build: Update codecov and use token
2024-06-17 11:57:12 -03:00
Kristin Aoki
f3ae225d64 feat: improve asset loading (#484)
* fix: update initialize to only call required functions

* feat: update asset urls without asset object

* feat: add pagination to select image modal

* fix: lint errors

* chore: update tests

* fix: asset pattern regex match

* feat: update pagination to be button to prevent page skipping

* fix: e.target.error for feedback fields

* fix: failing snapshots
2024-06-17 09:52:49 -04:00
Adolfo R. Brandes
74776b3663 build: Update codecov and use token
Update codecov to the latest version and start using the org-wide token for uploads.

See https://github.com/openedx/wg-frontend/issues/179
2024-06-14 11:44:01 -03:00
Jesper Hodge
db1250ee95 Revert "feat: flcc to 2.2.0 (#1106)" (#1111)
This reverts commit e22cce9fa6.
Reverts #1106

The reason is that the pipeline to deploy to stage broke. This commit is probably the reason.

The revert is temporary until the pipeline problem is solved.
2024-06-14 14:17:41 +00:00
Jillian
f20e5311a9 Fix some test warnings (#1062)
* fix: paragon's Hyperlink no longer accepts a 'content' attribute
* test: ensure all act() calls are async
* test: Removed "async" from "describe"
Returning a Promise from "describe" is not supported.
* fix: DiscussionsSettings tests
Previous commit revealed several issues with these tests
* Don't nest userAction.click in act() -- nested act() statements have indeterminent behaviour.
* Use getBy* instead of findBy* with userAction to avoid nested act() statements
* Use fireEvent.click when the onClick handlers need to be called
* Use queryBy* instead of getBy* when using .toBeInTheDocument or waitForElementToBeRemoved
  queryBy* return null when the element is not found.
* fix: typo in data-testid
Warning: React does not recognize the `data-testId` prop on a DOM
element. If you intentionally want it to appear in the DOM as a custom
attribute, spell it as lowercase `data-testid` instead.
* test: Use useLocation to test route changes
---------

Co-authored-by: Yusuf Musleh <yusuf@opencraft.com>
2024-06-13 10:37:26 +05:30
Raymond Zhou
e22cce9fa6 feat: flcc to 2.2.0 (#1106) 2024-06-12 12:42:00 -04:00
Bilal Qamar
252ad6a6b9 feat: updated frontend-build & frontend-platform major versions (#475) 2024-06-12 05:29:17 -04:00
Jillian
6760b75774 fix: warnings about Duplicate message id (#1061)
Fixes warnings about "duplicate message IDs", which seem to have been made by copy-paste errors.
2024-06-11 18:01:25 +05:30
Raymond Zhou
7f5e82a844 fix: handle null displayname (#1074) 2024-06-07 13:40:59 -04:00
Kristin Aoki
7aa2baaa8a fix: bump frontend-lib-content-components package (#1071) 2024-06-05 14:19:53 -04:00
Kristin Aoki
e543ccc2e1 fix: parser not saving unlimited attempts (#483)
* fix: default settings not loading for new problems

* fix: unlimited attempts not saving
2024-06-04 16:41:58 -04:00
Yusuf Musleh
8cde43eb5b fix: Search result redirect to unit lib component (#1027)
This change fixes redirection to the library component in the unit when selecting the search result. It also fixes an issue with navigating to the library MFE when selecting a library component.
2024-06-03 17:55:37 +05:30
Chris Chávez
460de7014e [FC-0042] Fix: Bug: Unusable "Languages" taxonomy appears in tagging drawer (#1031)
Hide language taxonomy when is empty
New message on search result when taxonomy is empty
Empty taxonomies message added in drawer
2024-06-03 17:36:54 +05:30
Kristin Aoki
9b4eb10342 fix: allow grace period minutes only (#1064)
* fix: allow grace period minutes only

* fix: zero minutes error
2024-05-31 15:30:00 -04:00
Kristin Aoki
a340320e8f fix: upgrade frontend -lib-content-componets package (#1060) 2024-05-31 09:56:03 -04:00
Kristin Aoki
a959c0543c fix: removal of content after problem type tags (#479)
* fix: removal of content after problem type tags

* fix: readability and error handling
2024-05-30 12:33:43 -04:00
Kristin Aoki
a585a13e97 fix: wrong lock status update message (#1053) 2024-05-28 11:52:39 -04:00
Kristin Aoki
435af2c36f fix: update date using utc timezone instead of local (#1043)
* fix: update date using utc timezone instead of local

* fix: lint error
2024-05-24 13:07:10 -04:00
Rodrigo Martin
732b7ed86c feat(AU-2035): Add disclaimer to AppSettingsModalBase (#1024) 2024-05-24 12:13:42 -03:00
Yusuf Musleh
d0b3328f26 feat: Import new taxonomy dialog flow (#1017)
This PR updates the existing import tags wizard to also handle  importing new taxonomies.
2024-05-24 19:19:26 +05:30
Chris Chávez
c3df0b0692 feat: Show toast when exporting course tags (#995)
Show in  in-progress toast when exporting course tags
2024-05-24 15:54:59 +05:30
Kristin Aoki
7247cc2d71 feat: bump frontend-lib-content-components 2.1.9 (#1028) 2024-05-22 15:40:04 -04:00
Kristin Aoki
3f987f9958 feat: improve error messaging and empty updates (#1025)
* feat: improve error messaging and empty updates

* chore: improve code coverage

* fix: update error messages

* fix: message title for saving handouts
2024-05-22 14:28:53 -04:00
Kristin Aoki
6c743f858d fix: video selection gallery scroll (#477)
* fix: video selection gallery scroll

* fix: lint errors
2024-05-22 12:02:25 -04:00
Peter Kulko
3647bcbbf9 fix: fixed rerun link (#1023)
* fix: fixed rerun link

* refactor: code refactoring

* refactor: updated tests

* refactor: after review
2024-05-21 12:58:53 -04:00
bszabo
54003af07c fix: issue-1018 remove reference to edX user\nIn configure wiki opera… (#1021)
* fix: issue-1018 remove reference to edX user\nIn configure wiki operation

* fix: issue-1018 keep to original they wording
2024-05-21 11:24:21 -04:00
renovate[bot]
f34157e11c fix(deps): update dependency @edx/frontend-lib-content-components to v2.1.8 (#997)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-16 14:26:42 +00:00
renovate[bot]
8a491cc365 fix(deps): update dependency @openedx/paragon to v22.4.0 (#963)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-16 14:15:18 +00:00
Leangseu Kim
7d9dd7535b chore: lock @edx/react-unit-test-utils 2024-05-16 10:02:50 -04:00
Ihor Romaniuk
7c539f346b fix: info icon shrinking on advanced settings page (#984) 2024-05-15 13:02:05 -03:00
ABBOUD Moncef
3315205d15 fix: video status badge translation (#438) 2024-05-13 15:26:07 -04:00
Navin Karkera
d882f2f856 feat: discussion setting and release & due date setting (#976)
* fix: hide release and due dates config in self paced courses

* feat: discussion enable setting for unit in outline

* refactor: message text

Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>

* fix: modal dialog overflow

---------

Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>
2024-05-13 11:21:18 -04:00
Leangseu Kim
65132eead2 fix: allow page grid to take plugin slot id instead (#994)
* fix: allow page grid to take plugin slot id instead

* chore: add config check

* chore: linting

* chore: variable more readable
2024-05-13 10:39:11 -04:00
Peter Kulko
a88066a2c5 fix: fixed course rerun route (#993) 2024-05-09 13:51:22 -03:00
Chris Chávez
e0fb41d8f5 [FC-0049] feat: Other Tags section added on tags drawer (#987)
Adds the new "Other tags" Section to tags drawer that contains the taxonomies/tags that the user doesn't have permission to see/edit. It allow to delete those tags.
2024-05-09 21:34:22 +05:30
Peter Kulko
55adcfe90d feat: Added errors handling 4xx, 5xx (#992)
* feat: [AXIMST-538] Add errors handling 4xx, 5xx

* fix: resolve discussions

* fix: second round of review discussions

refactor: fixing tests for Textbooks page

Co-authored-by: ruzniaievdm <ruzniaievdm@gmail.com>
2024-05-09 11:10:28 -03:00
ruzniaievdm
c884ff2882 fix: Group configurations - Add a counter for usage groups (#991) 2024-05-09 08:59:44 -03:00
Navin Karkera
5c1df3e16e feat: better api error handling (#972)
Improve API error handling.
2024-05-09 11:18:00 +05:30
Yusuf Musleh
8aea28c6e0 feat: search filters refinement (#980)
Sort blocktypes on hierarchy then alphabet.
2024-05-09 11:10:21 +05:30
Braden MacDonald
14245bc6ad feat: Enable taxonomy/tagging feature in MFE by default (#989)
* feat: enable tagging/taxonomy feature by default

* test: improve coverage

* chore: fix lint issue
2024-05-08 18:12:56 -03:00
Chris Chávez
dd9202fafe feat: prevent losing work when users click outside tag drawer after making edits [FC-0036] 2024-05-08 15:56:32 -04:00
Jillian
23fb68f2c3 feat: show "No tags added yet. [Add tags]" on the tag drawer (#988)
when we've expanded a taxonomy in read mode with no content tags added.
2024-05-08 16:47:39 -03:00
Chris Chávez
92b7ae1b77 feat: Add In progress message on import taxonomy (#953)
Message added as a toast
2024-05-08 16:44:21 -03:00
Navin Karkera
087c82c60c refactor: handle relative proctoring link (#974) 2024-05-07 12:01:41 +05:30
Chris Chávez
de408b5a3a [FC-0036] refactor: Further refinements to tag drawer (#970)
* refactor: Further refinements to tag drawer
* Padding to top and left tagging drawer
* Changes in headings in the tagging drawer
2024-05-06 14:46:46 +05:30
Bryann Valderrama
2f5d4f71ec feat: add ENABLE_GRADING_METHOD_IN_PROBLEMS feature flag (#932) 2024-05-03 10:54:52 -04:00
Chris Chávez
64be7e3b37 feat: Send messages after update tags (#975)
Updates the code of Tag Drawer to send two messages to parent (if the drawer is a iframe) when the tags are updated:

- One message with updated content tags.
- One message with the content tags count.
2024-05-03 20:04:42 +05:30
Navin Karkera
a63c808300 refactor: change expand-collapse arrows in outline (#973)
Set arrow down for expanded section/subsection and right arrow for
collapsed items same as legacy
2024-05-03 18:36:51 +05:30
Yusuf Musleh
6d9a8a1eac feat: search modal refinements (#959)
* feat: More spacing between search bar and selectmenu
* feat: Autofocus search field when modal opens
* feat: Fix issues with scroll to search result
This includes the following:
  - The target search element is aligned to the top of the page when scrolling to it
  - Makes sure the section/subsection is expanded in order to scroll to result
* fix: Match focus border radius with button's
* fix: Only expand (sub)section with search result
2024-05-03 15:02:22 +05:30
vladislavkeblysh
65f45f72f0 feat: [FC-0044] Textbooks Page (#890)
Implement Textbooks page.

---------

Co-authored-by: Glib Glugovskiy <glib.glugovskiy@raccoongang.com>
2024-04-30 18:38:43 -03:00
Peter Kulko
a9a73efbb6 feat: [FC-0044] Course unit - Drag and drop for xblocks (#908)
Implements drag and drop for xblocks in the unit page.
2024-04-30 11:21:51 -03:00
Rômulo Penido
e24fb7889e feat: redirect to unit page if the hit or its parent is a unit (#957)
This change adds the feature to redirect from a search result to a Unit, in case the hit parent is a Unit, or the hit is a unit itself.
2024-04-29 19:50:12 +05:30
XnpioChV
9327948b61 feat: [FC-0036] Refined tag drawer
It contains different changes to achieve the reading and editing mode of the drawer tag:

* Manage tags drawer footer with buttons added.
* Creation of ContentTagsDrawerContext.
* Creation of global state and global removed state to allow edit mode.
* Update API client to match with openedx-learning 0.9.1: Save tags of multiple taxonomies; to save all tags added/removed on edit mode
* Extract TagsTree and use it on the Tags Drawer.
* Update TagsTree to allow edit mode.
* Add a Toast on Tags Drawer; show the toast afert save.
* Scrolling + sticky footer on tags drawer
2024-04-25 15:29:13 -04:00
Yusuf Musleh
4146fa6c6e feat: Remove taxonomy export id prompt (#955) 2024-04-26 00:42:32 +05:30
Felipe Montoya
be71668b8d fix: removing ENABLE_NEW_EDITOR_PAGES flag (#951) 2024-04-25 08:35:45 -03:00
Peter Kulko
5686dee43b feat: [FC-0044] Course unit - Copy/paste functionality (#884)
Implement copy/paste.

Co-authored-by: monteri <36768631+monteri@users.noreply.github.com>
Co-authored-by: ihor-romaniuk <ihor.romaniuk@raccoongang.com>
2024-04-24 15:27:29 -03:00
Raymond Zhou
bef6796da4 fix: errors for positive time zones (#961) 2024-04-24 09:07:15 -07:00
Leangseu Kim
e55f031c39 chore: add slot to allow additional course app plugin (#941)
* chore: add @openedx/frontend-plugin-framework

chore: move plugin page setting button to a props

chore: split out app setting modal for reusability

chore: add implementation of WTC plugin

chore: update app setting form

chore: implement the plugin form with mock

chore: follow the UI design

chore: remove translation plugin and move it into frontend-plugin instead

* chore: add eslint ignore for env.config.jsx

* chore: update package-lock.json
2024-04-24 11:55:46 -04:00
connorhaugh
98138181f7 feat: add browser dialog to prevent navigation (#962)
Switching from undefined to "" tells the browser to put in a modal which requires users to confirm thier navigation away. this will prevent continued annoyances from upload failures: https://2u-internal.atlassian.net/browse/TNL-11587
2024-04-24 11:04:12 -04:00
Braden MacDonald
c32462e21e feat: Allow filtering by multiple tags [FC-0040] (#945)
As of #918 , the content search only allows filtering the results by one tag at a time, which is a limitation of Instantsearch.

So with this change, usage of Instantsearch + instant-meilisearch has been replaced with direct usage of Meilisearch. Not only does this simplify the code and make our MFE bundle size smaller, but it allows us much more control over how the tags filtering works, so that we can implement searching by multiple tags.

Trying to modify Instantsearch to do that was too difficult, given the complexity of its codebase.

Related ticket: openedx/modular-learning#201
2024-04-24 09:15:17 +05:30
Kristin Aoki
34104495c5 fix: adding files count in toast (#960)
* fix: adding files count in toast

* fix: toast to use plural function
2024-04-23 16:05:13 -04:00
ruzniaievdm
907ce50071 feat: [FC-0044] group configurations MFE page (#929)
* feat: group configurations - index page

* feat: [AXIMST-63] Index group configurations page

* fix: resolve discussions

* fix: resolve second round discussions

* feat: group configurations - content group actions

* feat: [AXIMST-75, AXIMST-69, AXIMST-81] Content group actions

* fix: resolve conversations

* feat: group configurations - sidebar

* feat: [AXIMST-87] group-configuration page sidebar

* refactor: [AXIMST-87] add changes after review

* refactor: [AXIMST-87] add changes after review

* refactor: [AXIMST-87] add changes ater review

---------

Co-authored-by: Kyrylo Hudym-Levkovych <kyr.hudym@kyrs-MacBook-Pro.local>

* fix: group configurations - the page reloads after the user saves changes

* feat: group configurations - experiment groups

* feat: [AXIMST-93, 99, 105] Group configuration - Experiment Groups

* fix: [AXIMST-518, 537] Group configuration - resolve bugs

* fix: review discussions

* fix: revert classname case

* fix: group configurations - resolve discussions

fix: [AXIMST-714] icon is aligned with text (#210)

* fix: add hook tests

* fix: add thunk tests

* fix: add slice tests

* chore: group configurations - messages

* fix: group configurations - remove delete in edit mode

---------

Co-authored-by: Kyr <40792129+khudym@users.noreply.github.com>
Co-authored-by: Kyrylo Hudym-Levkovych <kyr.hudym@kyrs-MacBook-Pro.local>
Co-authored-by: monteri <lansevermore>
2024-04-23 11:53:49 -04:00
Rômulo Penido
7f668a6ca4 refactor: remove old taxonomy page route (#954) 2024-04-23 14:52:17 +05:30
Ihor Romaniuk
6ec44b5f41 feat: [FC-0044] Unit page - Manage access modal (unit & xblocks) (#901)
* feat: [FC-0044] Unit page - Manage access modal (unit & xblocks)

* fix: add message description
2024-04-22 11:13:16 -04:00
sundasnoreen12
1834655399 fix: fixed scroll issue of provider and settings (#958) 2024-04-22 15:04:52 +05:00
Raymond Zhou
bfcac5c0dd feat: bump flcc (#956) 2024-04-18 15:24:54 -04:00
Raymond Zhou
e0b70f2b17 fix: HTML screen should expand with content (#474) 2024-04-18 14:48:10 -04:00
Chris Chávez
422a5db6f9 [FC-0036] feat: Sort taxonomies (#949)
Taxonomies are now sorted by tag count for those with applied tags, and by name for the rest.
2024-04-18 09:15:33 +05:30
Chris Chávez
08140226c3 [FC-0036] Refined tag drawer UI style (#947)
* feat: Remove 'x' close btn from tags drawer

* feat: Change style for taxonomy tags count

* feat: Update heading styles in tags drawer

* feat: Move dropdown arrows to left of taxonomy

---------

Co-authored-by: Yusuf Musleh <yusuf@opencraft.com>
2024-04-17 19:16:25 +05:30
Rômulo Penido
612d1d8c63 feat: improve search modal results [FC-0040] (#946)
This change makes improvements to the `SearchResult` component which shows the search results in a number of ways:

- It improves the information messages that show up before you start search, and if the results are empty. 
- It adds more context to the search results, by displaying the location of the content
- It adds a link to directly navigate to the relevant content item. 
- It adds an animated highlight to a unit right after you navigate to it. 

---------

Co-authored-by: Jillian <jill@opencraft.com>
Co-authored-by: Braden MacDonald <mail@bradenm.com>
2024-04-17 13:43:56 +05:30
Feanil Patel
b119671ee2 build: Update codecov and start using repo tokens.
Update codecove to the latest version and start using the per repo
tokens which will soon be required to get more reliable coverage builds.

This change also has a corresponding addition of a codecov repo upload
token to the repository secrets for this repo.
2024-04-16 11:55:55 -04:00
Jesper Hodge
0f440c6b3a Fix video upload failures (#952) 2024-04-15 16:49:07 -04:00
Braden MacDonald
2fda48fa5f Bump Paragon to v22.2.1, fix some bugs that turned up (#933)
* chore: bump paragon version

* chore: update snapshot test - alt moved from sr-only to aria-label
2024-04-12 14:05:56 -04:00
Kristin Aoki
63e220ee3e fix: change dropdowns to menus to fix off-screen render (#948) 2024-04-12 13:52:51 -04:00
Jhon Vente
2641aecc8a feat: home studio search filters (#846)
* feat: pagination studio home for courses

* chore: addressing some comments

* refactor: addressing pr comments

* test: adding test for studio home slice

* feat: search input and filters for course home

* fix: using open edx paragon

* feat: usedebounce hook for searching courses

* fix: filters params for searching coruses

* feat: adding coursekey when course name is empty

* chore: remove edit in studio button

* fix: message changed when courses were  not found

* refactor: support courses tab filters and pagination

* test: more cases for course filters component

* refactor: coverage for onsubmit search field

* test: unit test for courses tab component

* feat: loading for search input and layout of course tab

* fix: linter problems

* test: adding more tests for courses tab

* refactor: don't ignore empty string as a case for searching

* refactor: manage empty search bar as special case for searching

* fix: remove expected dispatch mock for clear button

---------

Co-authored-by: Maria Grimaldi <maria.grimaldi@edunext.co>
2024-04-11 16:25:19 -04:00
Braden MacDonald
fc3e38f63b feat: Content Search Modal: Filters [FC-0040] (#918)
Implementation of openedx/modular-learning#201

Implements a modal for searching course content with filters for searching in current or all courses, filtering by content type, content tags and text.
2024-04-11 10:01:06 +05:30
Raymond Zhou
aaf4989610 fix: react datepicker workaround for local time (#944) 2024-04-10 15:57:46 -04:00
Kristin Aoki
fd6b9ae3a6 fix: referencing activeStatus for undefined (#943) 2024-04-10 14:50:40 -04:00
Kristin Aoki
fdcda9833f feat: include usage locations in delete modal (#938) 2024-04-10 15:34:06 +00:00
Jesper Hodge
74eaaa1f9e chore: change github workflow file to not fail pipeline for codecov (#942) 2024-04-10 11:25:08 -04:00
Rômulo Penido
2adff6e51d feat: add content search modal [FC-0040] (#928)
* feat: Prototype search UI using Instantsearch + Meilisearch
---------

Co-authored-by: Braden MacDonald <braden@opencraft.com>
2024-04-08 21:39:15 +05:30
Dmytro
5634e9e507 fix: incorrect redirect link to Pages&Resources from Custom Pages (#916)
Co-authored-by: Dima Alipov <dimaalipov@MacBook-Pro-Dima.local>
2024-04-08 10:03:01 -04:00
Braden MacDonald
ced2c0e891 Fix the TaxonomyMenu test, which wasn't getting run at all (#930)
* test: fix the TaxonomyMenu test, which wasn't getting run at all
Co-authored-by: Rômulo Penido <romulo@opencraft.com>
2024-04-08 13:04:40 +05:30
Rômulo Penido
99a144a869 fix: message case (#924) 2024-04-06 09:00:27 +05:30
Yusuf Musleh
50d2577353 feat: Put Taxonomies tab behind flag (#937) 2024-04-05 12:01:52 -04:00
renovate[bot]
7f3164bbd7 fix(deps): update dependency @edx/frontend-lib-content-components to v2.1.6 (#935)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-04 20:24:38 +00:00
dependabot[bot]
3c64eb75aa chore(deps): bump axios from 0.27.2 to 0.28.1 (#936)
Bumps [axios](https://github.com/axios/axios) from 0.27.2 to 0.28.1.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v0.28.1/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.27.2...v0.28.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-04 20:12:36 +00:00
dependabot[bot]
3c74cd23b2 chore(deps-dev): bump axios from 0.27.2 to 0.28.0 (#848)
Bumps [axios](https://github.com/axios/axios) from 0.27.2 to 0.28.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v0.28.0/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.27.2...v0.28.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-04 16:00:55 -04:00
Kyr
e306b62dd1 feat: [FC-0044] Certificates page (#872)
* feat: [FC-0044]  Certificates page

* feat: add descriptions for details, signatories, sidebar i18n messages

---------

Co-authored-by: Kyrylo Hudym-Levkovych <kyr.hudym@kyrs-MacBook-Pro.local>
2024-04-04 13:28:04 -04:00
Jesper Hodge
dedcb14386 fix: trigger pipeline release for dependency fixes (#472) 2024-04-04 13:26:46 -04:00
dependabot[bot]
cf46e6c6c9 build(deps-dev): bump follow-redirects from 1.15.5 to 1.15.6 (#471)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.5 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.5...v1.15.6)

---
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>
2024-04-04 13:04:17 -04:00
dependabot[bot]
77cdf2614e build(deps): bump express and @openedx/frontend-build (#470)
Bumps [express](https://github.com/expressjs/express) to 4.19.2 and updates ancestor dependency [@openedx/frontend-build](https://github.com/openedx/frontend-build). These dependencies need to be updated together.


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

Updates `@openedx/frontend-build` from 13.0.27 to 13.1.0
- [Release notes](https://github.com/openedx/frontend-build/releases)
- [Commits](https://github.com/openedx/frontend-build/compare/v13.0.27...v13.1.0)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
- dependency-name: "@openedx/frontend-build"
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-04 13:03:56 -04:00
dependabot[bot]
fd3c871585 build(deps): bump follow-redirects from 1.15.5 to 1.15.6 in /www (#469)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.5 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.5...v1.15.6)

---
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>
2024-04-04 13:02:58 -04:00
dependabot[bot]
2bf04b8be6 build(deps-dev): bump webpack-dev-middleware from 5.3.3 to 5.3.4 (#468)
Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.3 to 5.3.4.
- [Release notes](https://github.com/webpack/webpack-dev-middleware/releases)
- [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/v5.3.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-middleware/compare/v5.3.3...v5.3.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-04 12:56:01 -04:00
dependabot[bot]
b61cb5c7cd chore(deps): bump express and @openedx/frontend-build (#931)
Bumps [express](https://github.com/expressjs/express) to 4.19.2 and updates ancestor dependency [@openedx/frontend-build](https://github.com/openedx/frontend-build). These dependencies need to be updated together.


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

Updates `@openedx/frontend-build` from 13.0.27 to 13.1.0
- [Release notes](https://github.com/openedx/frontend-build/releases)
- [Commits](https://github.com/openedx/frontend-build/compare/v13.0.27...v13.1.0)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
- dependency-name: "@openedx/frontend-build"
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-04 12:55:10 -04:00
dependabot[bot]
4ba62d7ee4 build(deps): bump webpack-dev-middleware from 5.3.3 to 5.3.4 in /www (#467)
Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.3 to 5.3.4.
- [Release notes](https://github.com/webpack/webpack-dev-middleware/releases)
- [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/v5.3.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-middleware/compare/v5.3.3...v5.3.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-04 12:52:44 -04:00
dependabot[bot]
0b1505975b chore(deps): bump follow-redirects from 1.15.5 to 1.15.6 (#902)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.5 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.5...v1.15.6)

---
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>
2024-04-04 12:50:41 -04:00
dependabot[bot]
a9d33f612c chore(deps): bump webpack-dev-middleware from 5.3.3 to 5.3.4 (#917)
Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.3 to 5.3.4.
- [Release notes](https://github.com/webpack/webpack-dev-middleware/releases)
- [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/v5.3.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-middleware/compare/v5.3.3...v5.3.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-04 12:42:54 -04:00
Jesper Hodge
57d2fea5fd fix: set feature flag to default to false for pagination (#934) 2024-04-04 13:53:17 +00:00
Ihor Romaniuk
ffa0f14693 feat: [FC-0044] Unit page - display component support label (#913)
* feat: [FC-0044] Unit page - display component support label

* fix: add message description for tooltip of module support
2024-04-04 09:28:39 -04:00
Yusuf Musleh
806591f1cc feat: Add taxonomies tab in home page (#923) 2024-04-04 17:34:13 +05:30
Jhon Vente
fde3872e2e feat: pagination studio home for courses (#825)
This PR adds pagination for the studio home view and makes minor changes to each course card.

NOTE: This needs to be activated by the environment variable ENABLE_HOME_PAGE_COURSE_API_V2 otherwise, it will continue using the old course list

enable this feature flag
new_studio_mfe.use_new_home_page

* feat: pagination studio home for courses

* chore: addressing some comments

* refactor: addressing pr comments

* test: adding test for studio home slice

* chore: deleting unnecessary blank line

* feat: adding feature for pagination

* refactor: change customParams to requestParams

* fix: linter problems

* fix: course home number of 0 courses

* chore: update feature name for pagination

* fix: pagination enabled request and test for tab section added again

* chore: removing cms link in course card items

* chore: addresing some comments

* fix: array dependency for pagination
2024-04-03 11:38:05 -04:00
Ihor Romaniuk
5247ec5022 feat: [FC-0044] Unit page - make xblock edit functional (#912) 2024-04-02 16:15:09 -04:00
Kristin Aoki
dd13ed49aa feat: upgrade frontend-lib-content-components (#927) 2024-04-02 09:35:29 -04:00
Rômulo Penido
0a50bbc9ef fix: content tags drawer width (#910) 2024-04-02 12:40:14 +05:30
Raymond Zhou
d44edb84a0 feat: send content-length in video (#925) 2024-03-28 15:05:08 -04:00
Kristin Aoki
905bea0d59 fix: default setting not updating with updated default settings (#466) 2024-03-28 15:00:16 -04:00
Rômulo Penido
f57d40ea34 feat: tag sections, subsections, and the whole course (FC-0053) (#879)
* feat: tag sections, subsections, and the whole course
* docs: add comments to useContentTagsCount
2024-03-28 17:44:29 +05:30
Kristin Aoki
80bf86992d fix: transcript and thumbnail uploads (#914)
* fix: transcript and thumbnail uploads

* chore: add missing tests
2024-03-25 10:02:09 -04:00
Yusuf Musleh
1dde30a0a2 [FC-0036] feat: Make tags widget keyboard accessible (#900)
Adds the ability to navigate the new "Add Tags" widget using the keyboard, making it fully accessible through the keyboard.
2024-03-21 17:26:22 +05:30
Braden MacDonald
9a6e12bd3b Clean up Taxonomy API files/hooks/queries [FC-0036] (#850)
* chore: rename apiHooks.jsx to apihooks.js

* refactor: consolidate taxonomy API code

* fix: was not invalidating tags after import

* fix: UI was freezing while computing plan for large import files
2024-03-20 09:31:10 +05:30
Kristin Aoki
4fa169556e fix: remove useEffect that fires before search params (#465)
* fix: remove useEffect that fires before search params

* fix: remove disable lint lines
2024-03-18 15:31:00 -04:00
Jeremy Ristau
85ca350591 Merge pull request #463 from openedx/gh-team-update
chore: Github team update
2024-03-12 09:34:04 -04:00
Jeremy Ristau
d8503fbfe2 chore: update CODEOWNERS 2024-03-11 22:33:21 -04:00
Jeremy Ristau
9a8deced9b chore: update CODEOWNERS 2024-03-11 22:32:32 -04:00
Jeremy Ristau
1797707a9a chore: update openedx.yaml 2024-03-11 22:32:01 -04:00
Jesper Hodge
7f73b895d1 fix: gallery (#462) 2024-03-11 15:43:35 -04:00
Jesper Hodge
679e15ed00 fix: gallery 2024-03-11 19:39:18 +00:00
Jesper Hodge
fb2a79985e Fix: selectable box in gallery (#461)
This fixes a bug where images and videos are not clickable when using the Gallery component.
Please see https://github.com/openedx/frontend-lib-content-components/pull/460 for a full description of the bug.
2024-03-11 15:26:54 -04:00
Jesper Hodge
b3b2881efb Revert "fix: gallery"
This reverts commit 736a786e12.
2024-03-11 18:42:17 +00:00
Jesper Hodge
736a786e12 fix: gallery 2024-03-11 18:41:17 +00:00
Jesper Hodge
be00028c4a Fix Problem Type Select (#460)
* fix: override selectablebox with copy of version from edx paragon 21.5.6

* chore: remove console logs

* fix: lint

* chore: update snapshots
2024-03-11 12:59:05 -04:00
Jesper Hodge
5069cf8638 fix: problem type not selectable (#459)
JIRA: https://2u-internal.atlassian.net/browse/TNL-11465

This is a problem we're experiencing on stage due to a bug in paragon. This is intended as a temporary fix until we can dig into why this is happening in paragon. But basically the Context for the SelectableBox is missing a provider in paragon. The short-term fix is to copy over paragon's selectablebox component and fix it. This is done so that our quick fix doesn't break anything else in paragon for now or cause any unexpected issues.
2024-03-07 15:21:02 -05:00
Jeremy Ristau
4e78c07dac Merge pull request #458 from openedx/catalog-info-updates
chore: update tnl team name
2024-03-05 09:19:33 -05:00
Jeremy Ristau
e5a469f7ea chore: update tnl team name 2024-03-04 21:46:23 -05:00
Jhon Vente
90d5ac4ffc feat: TinyMCE plugin insert iframe (#427) 2024-02-16 14:02:34 -05:00
Brian Smith
f33a3b5521 fix(deps)!: support paragon and frontend-build in openedx scope (#457)
BREAKING CHANGE: frontend-platform peer dependency updated to ^7.0.1
BREAKING CHANGE: @edx/paragon peer dependency updated to @openedx/paragon
2024-02-09 14:41:16 -05:00
Feanil Patel
62bff35fcd Merge pull request #381 from Mashal-m/mashal-m/update_lockfile
refactor: updated lock file version check to use new workflow
2024-02-08 14:30:16 -05:00
Syed Ali Abbas Zaidi
dcdaace08d feat: migrate enzyme to edx react-unit-test-utils 2024-01-24 16:51:53 -05:00
Kristin Aoki
1bc4e51c22 fix: url for video uploads (#453)
* fix: url for video uploads

* fix: possible undefined error in postUrlRedirect
2024-01-16 11:00:43 -05:00
Kristin Aoki
4653322fca fix: video upload api fetch body (#454) 2024-01-10 17:13:29 -05:00
Kristin Aoki
13f039ae4c feat: add blockId to return url (#442) 2024-01-05 09:30:35 -05:00
Jesper Hodge
8833f7bfca fix: library editor not working locally (#448)
Internal issue: https://2u-internal.atlassian.net/browse/TNL-11299

In library-authoring, content blocks could not be edited locally due to some problem with the Accept header. This caused some 404s. Visually you would get an infinite loading spinner.

This depends on openedx/frontend-app-library-authoring#399.
2024-01-04 14:36:07 -05:00
Jesper Hodge
70581c54ab refactor: abstract XML parser output operations (#445)
This is a refactoring for a part of the ReactStateXMLParser. I wanted to use functions that are more generic and not just handle a list of edge cases. So I encapsulated the operation that was done in this part of the code to a function `findNodesAndRemoveTheirParentNodes` which is more generic and could be used for different operations.
2024-01-02 15:04:03 -05:00
kenclary
69452344d8 Merge pull request #447 from openedx/kenclary/plugins
fix: update public plugins repo version
2023-12-21 11:13:10 -05:00
Ken Clary
8fdb395680 fix: update public plugins repo version 2023-12-21 11:09:29 -05:00
Jesper Hodge
e77d3d1014 fix: do comment change to trigger release (#446) 2023-12-20 17:23:46 -05:00
Jesper Hodge
50c580cca2 fix editor deleting description (#444)
internal issue: https://2u-internal.atlassian.net/browse/TNL-11311

This fixes a bug where the editor was deleting the OLX tag when editing in the simple editor and then saving.
Also the description was being converted to em for the simple editor, but then not converted back. However, the xblock renders label and then em in reverse order for some reason.
To fix it, the em gets converted back to description now, but not for every em tag (added a class "olx_description" for the tags that should be converted).
2023-12-20 16:44:27 -05:00
kenclary
47a3fd6836 Merge pull request #443 from openedx/kenclary/plugins
fix: re-enable private plugins, with newer version of public plugin repo
2023-12-19 13:09:13 -05:00
Ken Clary
82f6d7d3ca fix: re-enable private plugins, with newer version of public plugin repo 2023-12-19 12:28:57 -05:00
dependabot[bot]
613220441f build(deps): bump sharp from 0.32.1 to 0.32.6 in /www (#441)
Bumps [sharp](https://github.com/lovell/sharp) from 0.32.1 to 0.32.6.
- [Release notes](https://github.com/lovell/sharp/releases)
- [Changelog](https://github.com/lovell/sharp/blob/main/docs/changelog.md)
- [Commits](https://github.com/lovell/sharp/compare/v0.32.1...v0.32.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-18 09:56:26 -05:00
dependabot[bot]
57937995e2 build(deps): bump @babel/traverse from 7.21.5 to 7.23.6 in /www (#440)
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.21.5 to 7.23.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.6/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-18 09:37:57 -05:00
dependabot[bot]
60ccf0fb53 build(deps): bump @babel/traverse from 7.22.5 to 7.23.6 (#439)
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.22.5 to 7.23.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.6/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-18 09:28:08 -05:00
Jesper Hodge
287cc23ee7 fix: disable a11ychecker and powerpaste plugins (#437) 2023-12-14 15:09:04 -05:00
Jesper Hodge
56ffc495dd chore: disable tinymce plugins (#436) 2023-12-14 14:55:36 -05:00
Jesper Hodge
fbd3d8506f fix: editor container can scroll again (#435)
This is a fix to a problem where some css prevented the editors from scrolling.
2023-12-14 11:53:26 -05:00
kenclary
4483214de1 Merge pull request #434 from openedx/revert-432-kenclary/plugins
Revert "fix: disable paid plugins, to test prod issue in stage"
2023-12-13 10:46:40 -05:00
kenclary
aa17203e07 Revert "fix: disable paid plugins, to test prod issue in stage" 2023-12-13 10:39:37 -05:00
Jesper Hodge
57042c90bf Revert "fix: get library blocks editing to work locally (#431)" (#433)
This reverts commit fd3ed5d146.
2023-12-12 15:57:03 -05:00
kenclary
6dab3a1cea Merge pull request #432 from openedx/kenclary/plugins
fix: disable paid plugins, to test prod issue in stage
2023-12-12 15:30:44 -05:00
Ken Clary
7c7b36b402 fix: disable paid plugins, to test prod issue in stage 2023-12-12 15:22:15 -05:00
Jesper Hodge
fd3ed5d146 fix: get library blocks editing to work locally (#431)
* fix: get library blocks editing to work locally

* fix: tests
2023-12-12 14:34:27 -05:00
kenclary
1137c88a02 Merge pull request #428 from openedx/kenclary/plugins
fix: misssing part of paid plugin configuration
2023-12-11 12:07:25 -05:00
Ken Clary
b0ca07d801 fix: misssing part of paid plugin configuration 2023-12-11 11:46:57 -05:00
Artur Gaspar
1c9771b332 feat: video gallery thumbnail fallback (#412) 2023-12-04 09:58:40 -05:00
Artur Gaspar
1ddaf9a662 fix: video editor and uploader layout fixes (#410)
* fix: video upload page layout fixes

* fix: video editor thumbnail fallback icon colour and size

* fix: video uploader close button go back instead of closing app

Change the video uploader close button to always go back in navigation history,
and change the gallery to replace its location with the video uploader's when
automatically loading it due to an empty video list, so that when the uploader
goes back in the history, it goes to what was before the gallery.

* fix: video editor spinners vertical alignment

The Editor component uses the pgn__modal-fullscreen class to be fullscreen,
but it is not structured like a Paragon FullscreenModal and the fullscreen
positioning style is not applied correctly, particularly in the case where
the content is smaller than the body - a vertically centred component will
be centred to the content size, not to the screen.

Here we directly apply the style that would have applied to the relevant
elements of a Paragon FullscreenModal.

* fix: use trailingElement for video uploader input button

Also styles the button so it looks the same on hover/active.
2023-12-04 09:58:17 -05:00
Artur Gaspar
2aeb094315 fix: video gallery design fixes (#407) 2023-12-04 09:35:30 -05:00
Dmytro
ed051c3543 fix: default display of Show Answer and Show reset option (#403)
Hardcoding values for showAnswer and showResetButton
in initialState leads to incorrect selection of additional
states specified in Advanced settings.
2023-12-01 09:26:12 -05:00
Dmytro
60439d5be6 fix: displaying the correct default randomization value (#413) 2023-11-30 16:33:25 -05:00
ABBOUD Moncef
8928d35f17 fix: make filter dropdown closable by clicking outside + revert to single-value video filter (#414) 2023-11-30 14:43:12 -05:00
Ihor Romaniuk
bad763596c fix: video thumbnail availability (#421) 2023-11-30 14:34:19 -05:00
kenclary
c0bc54a664 Merge pull request #420 from openedx/kenclary/plugins
feat: use plugins repo, and enable accessibility checker and powerpaste
2023-11-22 10:50:56 -05:00
Ken Clary
5342f164a2 feat: use plugins repo, and enable accessibility checker and powerpaste 2023-11-21 14:27:10 -05:00
Jeremy Ristau
fc8070025b Merge pull request #415 from Mashal-m/mashal-m/update-README
refactor: updated README file to reflect template changes
2023-10-31 08:39:15 -04:00
Kristin Aoki
3aa9088309 fix: upgrade paragon (#416) 2023-10-30 11:39:09 -04:00
Syed Ali Abbas Zaidi
42614b8d8e chore: bump frontend-platform (#409) 2023-10-27 09:30:51 -04:00
mashal-m
b3811b8f4d refactor: updated README file to reflect template changes 2023-10-27 12:07:46 +05:00
Jesper Hodge
cfa4577b75 chore: add test change for flcc automerge (#408) 2023-10-11 13:58:42 -04:00
kenclary
2377eadcc0 Merge pull request #400 from abdullahwaheed/abdullahwaheed/react-intl-to-formatjs
feat: babel-plugin-react-intl to babel-plugin-formatjs migration
2023-10-11 11:38:30 -04:00
kenclary
b55b86cf56 Merge pull request #404 from open-craft/navin/fix-max-attempts-setting
fix: make max attempts setting fallback to default
2023-10-11 10:04:16 -04:00
Abdullah Waheed
71fd5fb1e0 fix: upgraded frontend-build to fix security issue 2023-10-11 18:44:01 +05:00
Abdullah Waheed
9ddcba2763 Merge branch 'main' of github.com:openedx/frontend-lib-content-components into abdullahwaheed/react-intl-to-formatjs 2023-10-11 18:43:34 +05:00
Jeremy Ristau
a76c93c789 Merge pull request #361 from ghassanmas/fix-360
fix: resolve  #360 make style consistent across outlines
2023-10-10 14:28:38 -04:00
Navin Karkera
6889cd1e82 test: add test for initial attempts display value 2023-10-10 20:19:00 +05:30
Navin Karkera
35a2f3bb7f fix: use only null in state for empty value 2023-10-10 19:52:39 +05:30
Navin Karkera
e676616386 fix: snapshots 2023-10-10 12:53:11 +05:30
Navin Karkera
2209e5b963 fix: lint issues 2023-10-10 12:19:14 +05:30
Navin Karkera
82b770bdef refactor: improve hooks condition handling 2023-10-10 12:13:46 +05:30
Navin Karkera
398839d76c refactor: improve setting parser condition handling 2023-10-09 21:29:53 +05:30
Navin Karkera
5df26bf83b test: fix related test cases 2023-10-09 20:34:05 +05:30
Navin Karkera
c70679da54 fix: make max attempts setting fallback to default
The max attempts setting for a problem xblock should be set to null for
course default max attempt setting to take effect. This makes sure that
xblock setting is updated if course default is updated.
2023-10-06 20:35:53 +05:30
Abdullah Waheed
e474a6fc91 feat: babel-plugin-react-intl to babel-plugin-formatjs migration 2023-10-04 22:17:12 +05:00
Kristin Aoki
564d724d5b feat: remove footer component (#397) 2023-10-02 10:29:37 -04:00
Kristin Aoki
a0089eb1be fix: typeahead sort and styling (#396) 2023-09-27 12:09:27 -04:00
kenclary
eb320abfed Merge pull request #386 from open-craft/navin/partial-credit
fix: switch to advanced editor for partial credit support
2023-09-20 11:58:52 -04:00
Kristin Aoki
773812c3e1 fix: block url conditional (#393) 2023-09-15 11:23:01 -04:00
Kristin Aoki
9eefc07832 fix: empty v2 library studio view (#394) 2023-09-15 09:05:51 -04:00
Kristin Aoki
bc25f9c21b fix: v2 libraries default open to advanced editor (#392) 2023-09-14 11:41:14 -04:00
kenclary
4cf99ab930 Merge pull request #388 from open-craft/farhaan/bb-7835-fix-styling
fix: Fix styling for components in dropzone
2023-09-14 11:37:47 -04:00
Farhaan Bukhsh
db8929d1a8 fix: Fix styling for components in dropzone
Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
2023-09-14 12:52:26 +05:30
Kristin Aoki
126e662d80 feat: remove replace video button for libs (#390) 2023-09-13 13:35:42 -04:00
Kristin Aoki
39aa5aa749 feat: update isLibrary check to include v2 libs (#389) 2023-09-13 13:13:18 -04:00
Kristin Aoki
73af4317f6 fix: name of blank problems (#391) 2023-09-13 10:55:28 -04:00
Kristin Aoki
4f76b7c85e fix: sort items in typeahead dropdown (#387) 2023-09-12 09:48:43 -04:00
Syed Ali Abbas Zaidi
c44c72cec0 feat: upgrade react router to v6 (#280) 2023-09-12 09:04:42 -04:00
Navin Karkera
e3f5bbfe0c fix: switch to advanced editor for partial credit support
This commit reverts to advanced editor when partial_credit attribute is
added to multichoice, single select and numerical problems. Without this
change, the partial_credit attribute is removed from the problem on the
next edit.
2023-09-11 20:14:04 +02:00
Mohamed Akram
25e4e39953 fix: preformatted content being re-formatted (#376)
The issue had to do with how Firefox handles pasting newlines inside a <pre
contenteditable> tag (TinyMCE's editor works via contenteditable) and
fast-xml-parser's parsing. In Firefox, newlines are converted to <br> when
pasted, while Chrome preserves them. The parser by default trims spaces in text
nodes. In Firefox, the parser creates individual text nodes between the <br>
elements, and those have leading spaces in the example. In Chrome, there are no
<br> elements and the entire content is a single text node as-is. Setting
trimValues to false disables the trimming and resolves this issue in Firefox.

While investigating this, I noticed the builder also mishandles <br /> tags
emitted by the editor, converting them to <br></br>. The unpairedTags option in
the builder ensures they are output correctly as a single tag, and setting
suppressUnpairedNode to false ensures that single tag is <br/> rather than <br>
to remain XML compatible.

While trying to resolve this, I was looking into the paste plugin in TinyMCE.
It changes the behavior of pasting, making it more consistent between Chrome
and Firefox (i.e. both emit <br>) and is incorporated into TinyMCE 6 core.
Unfortunately, it seems to mangle pasting inside a <pre> tag by inserting
redundant nbsp characters (tinymce/tinymce#9017). TinyMCE 6 also outputs <br>
rather than <br /> - adding unpairedTags to the parser options is meant to
handle this, but it does not seem to behave entirely correct
(NaturalIntelligence/fast-xml-parser#609). These should be kept in mind if/when
upgrading to TinyMCE 6 (the different behaviors can be seen easily at
https://fiddle.tiny.cloud).
2023-09-11 10:47:04 -04:00
Kristin Aoki
9ebe187029 fix: undefined set selection for image modal (#384) 2023-09-06 16:48:21 -04:00
Jesper Hodge
8fe8bc1587 docs: document jest troubleshooting (#382) 2023-08-28 12:05:47 -04:00
mashal-m
e23a0887ce refactor: update lock file version 2023-08-28 13:54:54 +05:00
kenclary
8e659527f0 Merge pull request #366 from open-craft/farhaan/fix-drag-drop-component
Re-write the dropzone component and fix styling issues
2023-08-25 12:50:24 -04:00
kenclary
45e4bc5376 Merge pull request #368 from open-craft/kshitij/fix-video-sort-filter
fix: Video Gallery filters and sorting
2023-08-23 06:43:56 -07:00
kenclary
259b9f3d1f fix: don't get returnUrl for v2 blocks. (#380) 2023-08-21 19:57:08 -04:00
Jesper Hodge
e691df9cb5 fix: answer text flipped (#379)
This fixes a bug where an answer text was flipped in terms of the character order when typing (TNL-10980). One of the prop names of the TinyMceWidget that is imported in course-authoring had to be changed, so this goes together with https://github.com/openedx/frontend-app-course-authoring/pull/575.
2023-08-21 16:43:46 -04:00
Farhaan Bukhsh
b7a04e17da fix: Fixing the accessing of undefined variables in video
Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
2023-08-21 10:11:56 +05:30
Farhaan Bukhsh
f822d95d6a fix: Used Dropzone instead of having custom component
This PR fixes style component and remove any new component introduced.
We introduce a new thumbnail for setting page as well.

Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
2023-08-21 10:11:56 +05:30
kenclary
12266836eb Merge pull request #378 from openedx/kenclary/supplemental
fix: revert to blank-url version of error handling, for now
2023-08-18 14:09:29 -07:00
Ken Clary
3c1f870aac fix: revert to blank-url version of error handling, for now 2023-08-18 13:46:57 -07:00
kenclary
6de926ce7e Merge pull request #377 from openedx/kenclary/supplimental
fix: don't even bother fetching block ancestor in v2.
2023-08-17 17:37:31 -04:00
Ken Clary
9079196309 fix: don't even bother fetching block ancestor in v2. 2023-08-17 14:23:13 -07:00
Kshitij Sobti
fb7caffdd5 feat: Allow selecting my multiple filters in video gallery
The sort and filter UI of the video gallery was not working, this fixes that
issue, and also adds a new UI for filering videos that allows filtering videos
to include more than one status.

It also fixes the hooks related to VideoGallery to avoid potential bugs in the
future and updates tests to use react testing library instead of enzyme.

It also reduces the padding in gallery page.
2023-08-17 13:21:47 +05:30
Kristin Aoki
9438a5b89a feat: add typeahead component (#375) 2023-08-16 18:18:06 -04:00
Kristin Aoki
e9c0f6cc82 fix: selectedVideo undefined error (#374) 2023-08-11 14:05:07 -04:00
Raymond Zhou
a18c45f0db feat: call failRequest on fetch failure (#373) 2023-08-10 12:58:14 -04:00
Kristin Aoki
669fbfb3d2 fix: blockId checks for v1 or v2 libraries (#372) 2023-08-09 14:55:46 -04:00
Kristin Aoki
918370f743 fix: error return while editor loading (#369) 2023-08-08 12:41:15 -04:00
ruzniaievdm
d25ae09273 feat: Add TinyMceWidget on export (#365) 2023-08-03 12:44:07 -04:00
kenclary
38b85f70ac Merge pull request #343 from Mashal-m/mashal-m/react-upgrade-to-v17
feat: update react & react-dom to v17
2023-07-31 14:54:39 -04:00
mashal-m
cc4a7cc83d build: update lock file 2023-07-31 16:52:05 +05:00
mashal-m
3f98349f94 build: update lock file 2023-07-31 16:47:50 +05:00
mashal-m
ed7e98b6ea Merge branch 'main' of https://github.com/openedx/frontend-lib-content-components into mashal-m/react-upgrade-to-v17 2023-07-31 16:23:46 +05:00
kenclary
a935d296c9 Merge pull request #355 from openedx/kenclary/TNL-10743
feat: more/correct v2 url handling. TNL-10742
2023-07-20 15:31:33 -04:00
Jesper Hodge
3565741839 fix image resize (#299)
Description:
This is a bug where the image resizing in text editor and problem editor was completely broken. Putting in a text value when the aspect ratio lock was enabled would change both values but not to the size you wanted. If you disabled the lock, not just one but both values would change.

This is a problem that mostly affects images that are rectangular, not square. There's an example image below which is one that caused problems on prod.

Main fixes:
when I keep the image ratio locked, I can change one value (like width) and the other will jump to the proportionate value, but rounded to full pixels.
when I unlock the aspect ratio and change a value, then click save on the image dimension modal, only the one value will change, which will stretch the image in whatever direction. This is reflected in the tinymce image and then the updated value will appear when I reopen the image dimension modal. It is not possible to reset the image to the original dimensions any longer. The new values are saved.
The image dimensions in the edit image settings modal should always reflect the actual dimensions of the image when I look at it e.g. in the course outline. (Otherwise I may click save and the image is squished.)
There was a problem with deselecting an image: when you edit image dimensions and then save or press cancel, the "edit image" button will not disappear, but the image is not selected anymore. When you do not click anything else but immediately click on this button, sometimes (at least the second or third time you do this) this will throw an error. I fixed it so it will just open the default "select image" modal.
Other requirements:
Resizing the image means that when I open the dimensions update, I see the new dimensions.
Images in the editor are now displayed with the correct dimensions, proportional or stretched, if those dimensions don't exceed the size of the editor.
A known smaller bug emerging from this is that when you have more than one instance of the same image in the same editor, you cannot get or set its dimensions correctly. I believe I have gotten it into the following state: When you click one of the copies, you will either get the correct dimensions of the selected copy, or if not, it will display the original image dimensions. When you edit the dimensions, the correct copy of the image will be updated.
Out of Scope:
This cannot handle more than one instance of the same image properly. There will be a separate bug issue for this.
Sometimes, when you edit image dimensions and then reopen the image dimension modal, the dimensions will be null and thus just not appear in the modal - randomly. This is a bug as well.
2023-07-20 14:52:21 -04:00
Ken Clary
7178e5e4c9 feat: more/correct v2 url handling. TNL-10742 2023-07-20 14:37:22 -04:00
Raymond Zhou
4a5eaaf15e feat: setup game editor work (#363) 2023-07-20 04:59:54 -04:00
Kristin Aoki
7939af4737 fix: partner portal typo (#362) 2023-07-11 14:10:04 -04:00
Kristin Aoki
3586307ee7 feat: react based studio footer (#359) 2023-07-11 10:30:52 -04:00
Ghassan Maslamani
2bc447fab0 fix: resolve #360 make style consistent across outlines
This changes make the style consistent across the first three
 headline line levels

 1. The first level add CSS prop initial
 2. The second level change prop from capital to inital
 3. No change
2023-07-11 14:50:29 +03:00
Jesper Hodge
f942ef9594 fix enable rules of hooks (#329)
This is a PR enabling eslint "rules-of-hooks".

This lint rule catches some very annoying bugs and enforces you to use correct naming for custom hooks (prepend with "use"), which is a mandatory react rule and important for a number of reasons.

I added eslint-disable statements wherever the rules are broken, and if this is merged, I would expect new code not to break the rules any longer.

I strongly suggest that the much better way to extract and reuse hooks and logic from components is the way the community does it and the React docs suggest. The new React docs are really fantastic in this regard and you can use the patterns found there very well to have an excellent application. https://react.dev/learn/reusing-logic-with-custom-hooks
2023-07-05 15:11:07 -04:00
mashal-m
505704e8f3 build: update edx pkgs and peer Dep 2023-07-05 16:44:24 +05:00
kenclary
c09faa3b09 Merge pull request #354 from open-craft/farhaan/bb-7522-fix-spinner-for-video
feat: Add loading spinner to the video upload page
2023-06-30 11:10:50 -04:00
kenclary
2ab7aa5cea Merge pull request #350 from open-craft/navin/hide-hide-option
refactor: hide switch to hide selected videos
2023-06-30 11:10:42 -04:00
Raymond Zhou
436fdfc470 feat: parse out explanation text (#358) 2023-06-28 14:05:31 -04:00
Raymond Zhou
86b67022ba feat: parser changes (#356) 2023-06-27 12:50:07 -04:00
Navin Karkera
7a53de4f2d refactor: hide switch to hide selected videos
The backend for hiding selected videos is not implemented and it is currently not required, so this commit hides the option.
2023-06-24 19:39:38 +05:30
Farhaan Bukhsh
ab640fb561 refactor: Moved the function to hooks in order to keep the components
dumb

It is done to make sure the business logic is not in a component and can
be individually tested.

Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
2023-06-23 20:01:33 +05:30
Farhaan Bukhsh
4d684d620e fix: Added tests for video upload
Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
2023-06-23 20:01:33 +05:30
Kristin Aoki
714c946f0f fix: persisting title from previous editor load (#353) 2023-06-22 19:22:40 -04:00
kenclary
769cdb08fb Merge pull request #344 from jansenk/events
feat: send event on checkbox change
2023-06-22 10:37:20 -04:00
jansenk
1a0cc2db2a style: rename function 2023-06-22 09:26:11 -04:00
Farhaan Bukhsh
a86b844208 feat: Add spinner to video element to load
Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
2023-06-22 13:46:08 +05:30
Kristin Aoki
c8e85fae0b fix: failure toast and close modal bugs (#352) 2023-06-21 13:48:54 -04:00
mashal-m
42210e7c89 build: update lock file 2023-06-21 14:16:10 +05:00
mashal-m
ef662f9ceb Merge branch 'main' of https://github.com/openedx/frontend-lib-content-components into mashal-m/react-upgrade-to-v17 2023-06-21 14:10:01 +05:00
Mashal Malik
8a2c725eda chore: update lock version file (#351) 2023-06-21 05:03:50 -04:00
mashal-m
530183a297 build: update paragon version 2023-06-19 15:55:53 +05:00
Kristin Aoki
b0fef766eb feat: add ErrorAlert to exports (#349) 2023-06-15 15:28:12 -04:00
Raymond Zhou
83f034e500 feat: save spacing for richText parser (#348) 2023-06-14 12:04:44 -04:00
kenclary
ac2444c258 Merge pull request #347 from openedx/kenclary/TNL-10742
feat: v2 xblocks should use v2 url. TNL-10742
2023-06-13 16:32:44 -04:00
Kristin Aoki
665a53a713 feat: add draggable list (#342) 2023-06-13 16:31:17 -04:00
Kristin Aoki
8eb10b7b12 feat: update returnToUnit to include api response (#346) 2023-06-13 15:29:04 -04:00
Ken Clary
ffd311881a feat: v2 xblocks should use v2 url. TNL-10742 2023-06-13 15:09:04 -04:00
jansenk
491d870cd2 style: quality 2023-06-12 10:25:04 -04:00
jansenk
e2535b2467 feat: send event on checkbox change 2023-06-12 09:56:32 -04:00
jansenk
0111d1c2f5 fix: remove param from end of video features url 2023-06-12 09:56:07 -04:00
mashal-m
86b0c4da82 feat: update react & react-dom to v17 2023-06-12 18:13:45 +05:00
Kristin Aoki
82b0f67f11 feat: add returnUrl prop to editors (#341) 2023-06-08 13:32:53 -04:00
Kristin Aoki
f3c4669604 fix: doc typos (#340) 2023-06-06 11:00:37 -04:00
kenclary
43b6ec7708 Merge pull request #339 from openedx/revert-338-kenclary/update-react
Revert "chore: update react to 17, etc. TNL-10715"
2023-06-05 16:43:00 -04:00
kenclary
6317c46120 Revert "chore: update react to 17, etc. TNL-10715" 2023-06-05 16:38:58 -04:00
Kristin Aoki
831c6096cb fix: choice parsing for answers with multi lines (#337) 2023-06-02 11:13:33 -04:00
kenclary
dd79d49533 Merge pull request #338 from openedx/kenclary/update-react
chore: update react to 17, etc. TNL-10715
2023-06-02 09:17:51 -04:00
Ken Clary
648e700818 chore: update react to 17, etc. TNL-10715 2023-06-01 16:11:58 -04:00
Kristin Aoki
88629d6df1 fix: olx parsers with formatted text (#336) 2023-05-30 11:42:59 -04:00
Bilal Qamar
2199a24dd7 feat: upgraded to node v18, added .nvmrc and updated workflows (#281)
Co-authored-by: Abdullah Waheed <abdullah.waheed@arbisoft.com>
2023-05-26 09:52:56 -04:00
Kristin Aoki
d80b6faaad feat: replace canvas with jest-canvas-mock (#335) 2023-05-24 09:56:39 -04:00
Kristin Aoki
e0c0c918d0 fix: feedback clearing on type change (#334) 2023-05-22 09:57:22 -04:00
kenclary
9239d2b8b1 Merge pull request #333 from open-craft/chris/video-editor-flow-fix
fix: Temporal testing line deleted from VideoUploadEditor::hooks.js
2023-05-18 12:42:39 -04:00
XnpioChV
3bdafd6e36 fix: Temporal testing line deleted from VideoUploadEditor::hooks.js 2023-05-18 11:31:35 -05:00
kenclary
aee971924f Merge pull request #326 from open-craft/chris/FAL-3383-new-video-editor-flow
[FAL-3383] Implement new video UX flow on new video editor
2023-05-18 11:49:10 -04:00
Raymond Zhou
741b83bdf2 fix: delete answers without changing expandable (#328) 2023-05-17 14:22:51 -04:00
Kristin Aoki
be8f9ecc86 feat: add raw olx settings parser (#332) 2023-05-15 15:12:32 -04:00
Mashal Malik
084d61ffa1 Update codecov and add browserslist config (#209)
* refactor: update code cov and add browserlist config
2023-05-11 14:44:48 -04:00
Kristin Aoki
99cd3bf1d9 chore: refactor OLXParser and related doc strings (#330) 2023-05-11 13:30:47 -04:00
Jesper Hodge
8cd222b9fa Add ADR for organizing our folder structure in a feature-based manner (#296)
* docs: add feature based application organization adr

* Update 0006-feature-based-application-organization.rst

* docs: update adr
2023-05-11 12:06:11 -04:00
Kristin Aoki
1d66a9d14d feat: remove matlab api widget and refs (#331) 2023-05-10 15:17:16 -04:00
Kristin Aoki
109334a9bf fix: show setting note for course set social share (#327) 2023-05-09 09:27:32 -04:00
Jesper Hodge
003f33152d docs: add adr with test naming conventions (#320)
* docs: add adr with test naming conventions

* docs: fix rst

* docs: add further reading section

* Update docs/decisions/0006-test-names.rst
2023-05-05 16:20:19 -04:00
XnpioChV
5c432a03db test: Adding missing test to reach coverage/patch 2023-05-05 14:10:18 -05:00
XnpioChV
15393f3da1 style: Fixing styles on gallery, editor and uploader video page 2023-05-04 18:00:06 -05:00
XnpioChV
135e0d7859 feat: Adding navigation on the url input of the video uploader page 2023-05-04 17:31:56 -05:00
XnpioChV
e20dedd0a5 feat: Allow to import transcripts from selected video 2023-05-04 17:31:55 -05:00
Pooja Kulkarni
359a5fd505 feat: Create new editor page for video upload 2023-05-04 17:31:54 -05:00
XnpioChV
da00ad7539 chore: All selection and save flow added 2023-05-04 17:01:42 -05:00
XnpioChV
23593b44fe chore: Error message on unselected video added & replace video button navigation added 2023-05-04 16:59:31 -05:00
XnpioChV
d2b3edad57 feat: Adding blockId to the Gallery. Adding cancel and next navigation 2023-05-04 16:58:36 -05:00
Raymond Zhou
adc21735fc fix: expandable textarea should save on blur (#325) 2023-05-04 17:17:14 -04:00
Kristin Aoki
34d6fcc552 feat: allow social share widget in libraries (#324) 2023-05-04 13:25:28 -04:00
Kristin Aoki
c49779a293 feat: add a button to return to studio (#322) 2023-05-03 10:35:02 -04:00
Kristin Aoki
6aaedfc500 feat: add social share widget (#323) 2023-05-03 09:55:31 -04:00
Raymond Zhou
d68bdf9dc6 feat: page errors indefinitely with no ancestor (#321) 2023-04-27 14:38:59 -04:00
kenclary
76ad7d8bda Merge pull request #262 from open-craft/pooja/bb7157-add-video-upload-feature
[BB-7157] Create new editor page for video upload
2023-04-26 13:41:37 -04:00
Pooja Kulkarni
bef6813d2c feat: Create new editor page for video upload 2023-04-26 11:36:26 -04:00
Kristin Aoki
bade92f613 feat: remove custom css with paragon upgrade (#319) 2023-04-26 09:55:40 -04:00
Kristin Aoki
21841fe09f fix: editable header width (#318) 2023-04-26 09:13:04 -04:00
Raymond Zhou
8676ba257c feat: default randomization to never (#317) 2023-04-25 16:14:40 -04:00
kenclary
eaab798da2 Merge pull request #278 from open-craft/chris/FAL-3375-video-selection-gallery
[FAL-3375] Feat: Video selection gallery page
2023-04-25 15:54:05 -04:00
XnpioChV
5695f92127 chore: Padding on gallery fixed 2023-04-21 18:06:10 -05:00
XnpioChV
36e56588cb test: Adding test for VideoGallery and SelectionModal 2023-04-21 18:06:09 -05:00
XnpioChV
b3bced9875 feat: New screens for loading, no videos and error states. Also tests added 2023-04-21 18:06:08 -05:00
XnpioChV
71efe876d3 style: adding more styles on the selection modal 2023-04-21 18:04:06 -05:00
XnpioChV
3b69958427 feat: Search and filters added 2023-04-21 18:04:05 -05:00
XnpioChV
b78e58cd2a feat: New request hook to fetch videos 2023-04-21 18:04:05 -05:00
XnpioChV
14504073e0 feat: Video selection page created
The SelectImageModal component has been refactored so that it can also be used on the video selection page; and all its child components.
Now this component is called SelectionModal and is used both for the image selector and in this new video selection screen.
The assets api has been used to get the videos.
2023-04-21 18:04:04 -05:00
Raymond Zhou
2a5f6795d3 feat: tinyMCE formatting and parsing (#311) 2023-04-21 11:42:10 -04:00
connorhaugh
802d328f4a feat: remove layered button (#314) 2023-04-21 11:04:23 -04:00
Kristin Aoki
c37e6957f6 fix: advanced editor not saving (#315) 2023-04-21 10:25:01 -04:00
Kristin Aoki
492ee27d8e fix: settings helper text font size (#313) 2023-04-21 09:19:39 -04:00
Raymond Zhou
80461755d1 feat: hint trash button should not be squished (#312) 2023-04-20 16:49:43 -04:00
Kristin Aoki
b674cd0cb0 feat: add no answer confirmation alert (#310) 2023-04-20 12:49:07 -04:00
Kristin Aoki
8f15480c28 feat: update problem descriptions (#309) 2023-04-18 13:23:18 -04:00
Kristin Aoki
4f1dc98ecc fix: settings font size and spacing (#308) 2023-04-18 11:56:20 -04:00
Kristin Aoki
405003045c fix: textArr join error in syntaxChecker (#307) 2023-04-14 16:28:16 -04:00
Kristin Aoki
1d2a4c212d feat: add xml linter to code mirror (#306) 2023-04-14 11:58:49 -04:00
Raymond Zhou
4b7b1c91ec feat: further number parse changes (#305) 2023-04-13 17:31:03 -04:00
Raymond Zhou
286d2209cb feat: XMLBuilder and XMLParser performing unwanted processing in encoding / parsing (#304) 2023-04-13 12:25:43 -04:00
Raymond Zhou
1e6d8b51e4 feat: show reset for advanced problem editor (#302) 2023-04-11 12:53:53 -04:00
connorhaugh
73a4b893f7 Feat parse solution as sibling (#303)
* fear: parse solution as siblings

* feat: add error resliancy to solution check.
2023-04-11 09:23:02 -04:00
connorhaugh
d58f349e1f feat: parse solution as siblings (#301)
this creates the ability for explanations to work if they are:

Not a child of a response type
Use an h2 tag for the explanation title
do not use the "Explanation" title.
2023-04-10 15:37:02 -04:00
connorhaugh
8a7dbdf4be fix: parse description/label as children (#300)
* fix: parse description/label as children

* fix: bounce problem tag attributes to advanced
2023-04-10 10:38:30 -04:00
Kristin Aoki
284139e247 feat: add check to sanitize answer ranges (#298) 2023-04-07 09:04:15 -04:00
Raymond Zhou
9a19711755 feat: revert group feedback expanded text field (#297) 2023-04-06 13:40:13 -04:00
Kristin Aoki
4cfc5a6ea6 feat: add alert to notify video id changes (#295) 2023-04-06 12:34:07 -04:00
connorhaugh
82cfa9897c feat: default scoring to 1, not zero. (#294)
Since every course has graded problems, every course author will be editing or creating problems, and every learner will need to receive points for any problem in a graded assignment in order to earn a passing grade. So if what I encountered and am reporting here is reproducible, this should probably be addressed before the problem editor feature is released.
2023-04-05 09:36:20 -04:00
Kristin Aoki
bd964854de fix: misspelling of explanation in description (#293) 2023-04-03 13:56:50 -04:00
Kristin Aoki
f99421f493 feat: add catch for script tags in question (#292) 2023-04-03 11:50:35 -04:00
connorhaugh
c2b67429d3 feat: add answer range (#291)
* feat: add answer range

* feat: add margin for doropdown

* fix: improve test converage
2023-03-30 10:34:45 -04:00
Omar Al-Ithawi
98ec415e2b fix: let make extract_translations find messages (#290)
Otherwise it'll complain for not finding any message.

`defineMessage` ensures that React i18n static code collector is able to
find the messages.

References
----------

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).

Check the links above for full information about the overall project.
2023-03-29 10:17:25 -04:00
kenclary
e7d69f4e5d Merge pull request #289 from openedx/kenclary/TNL-10535
fix: ErrorPage rewritten as functional component with injected i18n. TNL-10535
2023-03-24 16:40:10 -04:00
Ken Clary
f2ad93789f fix: ErrorPage rewritten as functional component with injected i18n. TNL-10535 2023-03-24 16:22:32 -04:00
connorhaugh
3bfa83220f feat: error on funky multiple choice tags. (#288)
This change increases the frequency at which odd tags (like shuffle) on multiple choice problems don't go to the visual editor.
Instead, they will now divert to the advanced editor. There might be other places where we need to follow a similar pattern, but we don't know those yet.
2023-03-24 10:05:21 -04:00
Kristin Aoki
7ef1963327 feat: add default advanced setting ui callouts (#285) 2023-03-23 17:37:13 -04:00
Ken Clary
4410f0a544 Merge branch 'keith/video-preview-widget' 2023-03-23 14:59:56 -04:00
Ken Clary
ed0aa88841 chore: fixup from rebase 2023-03-23 14:59:38 -04:00
Ken Clary
7080189a65 chore: fixup from rebase 2023-03-23 14:56:49 -04:00
Ken Clary
7a27b65a8c Merge branch 'keith/video-preview-widget' 2023-03-23 14:19:24 -04:00
Keith Grootboom
57a558f258 chore: use Hyperlink instead 2023-03-23 14:18:16 -04:00
Keith Grootboom
475c32463a refactor: review changes to use existing youtube function 2023-03-23 14:18:16 -04:00
Keith Grootboom
b4fb88c73c feat: add video preview widget to settings modal 2023-03-23 14:18:10 -04:00
kenclary
c7c0d5e100 Merge pull request #258 from open-craft/0x29a/video-duration-widget-improvements
feat: video duration section improvements [BD-12]
2023-03-23 11:47:31 -04:00
kenclary
21e01d1b77 Merge pull request #284 from open-craft/maxim/transcripts-section-improvements
feat: offer to import youtube transcripts dynamically
2023-03-23 11:18:31 -04:00
connorhaugh
df5af3efd9 feat: tolerance Setting Widget (#286)
* feat: tolerance Setting Widget

* fix: tolerance position and percent summary
2023-03-22 14:31:02 -04:00
Kristin Aoki
16003a7f4a feat: move explanation to main body of editor (#287) 2023-03-22 09:36:01 -04:00
Maxim Beder
6c8fca8113 test: add tests for VideoSettingsModal 2023-03-20 15:26:45 +01:00
Maxim Beder
363df38b1f feat: offer to import youtube transcripts dynamically
Before this commit, the popup message which offers to import transcripts
from YouTube would only appear after saving the video settings, and then
reopenning the editor.

With this commit, the popup appears dynamically, i.e. whenever a URL is
changed to a YouTube one, certain validations and check take place,
after which, if possible to do so, user will be offered to import
transcripts from the YouTube video.
2023-03-20 14:04:38 +01:00
Raymond Zhou
da9cb6054c Revert "feat: update switch to Advanced Editor warning (#259)" (#282)
This reverts commit 4a24d25f22.
2023-03-16 13:44:41 -04:00
Kristin Aoki
fa14365d54 feat: update text areas to expandable text areas (#274) 2023-03-16 13:17:01 -04:00
kenclary
84b9dd7e88 Merge pull request #277 from jansenk/jkantor/video-public-allowed-gate
feat: don't show video sharing checkbox unless waffle from studio is active
2023-03-15 16:21:03 -04:00
jansenk
97d0a74fef feat: call video_features cms endpoint for waffle status 2023-03-15 14:39:15 -04:00
jansenk
a895c28c4c feat: hide checkbox when video share not enabled for course 2023-03-15 14:39:15 -04:00
connorhaugh
2dc42e6a46 fix: show answer attempts spacing (#276) 2023-03-14 12:29:25 -04:00
Raymond Zhou
56621ca575 feat: remove general and group feedback (#273) 2023-03-13 12:25:38 -04:00
Mashal Malik
2ea3efed4b Update transifex api from v2 to v3 (#264) 2023-03-13 12:25:12 -04:00
connorhaugh
18fd63ab69 feat: expanding complex text area (#257) 2023-03-13 09:21:17 -04:00
kenclary
b917586fd8 Merge pull request #268 from openedx/kenclary/TNL-10507-1
fix: ProblemEditor useEffect at beginning of component; message for block failed to load. TNL-10507
2023-03-10 18:19:25 -05:00
Ken Clary
55b1e41898 fix: ProblemEditor useEffect at beginning of component; message for block failed to load. TNL-10507 2023-03-10 15:01:39 -05:00
Jesper Hodge
0ce9e4dfd3 fix: answer button accessibility (#271) 2023-03-10 14:18:21 -05:00
kenclary
b4edfe0bcb Merge pull request #270 from jansenk/jkantor/video-public
feat: Add "allow sharing" checkbox to video editor
2023-03-09 14:28:56 -05:00
jansenk
4467590a65 test: code review 2023-03-09 13:08:09 -05:00
jansenk
2be52871aa test: update snapshot 2023-03-09 11:38:17 -05:00
jansenk
968f48c55a feat: add checkbox for public video sharing field 2023-03-09 11:38:17 -05:00
Jeremy Ristau
54d4d2cca2 Merge pull request #269 from openedx/maintainership-phase1
chore: add missing maintainership files
2023-03-09 10:22:27 -05:00
Jeremy Ristau
07a84bc133 chore: add CODEOWNERS file to repo, point to tnl
This is related to Maintainership Pilot expectations. This CODEOWNERS file will notify teaching-and-learning team members of PR submissions, but there are currently no additional branch protections related to this ownership.
2023-03-09 09:58:32 -05:00
Jeremy Ristau
7fc149b882 chore: add catalog-info file for Open edX Backstage
This file populates Backstage info for the Open edX community. It helps identify that tnl is the owner of this component. This is in relation to Maintainership OEP-55.
2023-03-09 09:53:39 -05:00
Raymond Zhou
e6b532c71e Feat allow not select feedback for only multi select problem type (#267) 2023-03-08 15:18:57 -05:00
Raymond Zhou
b0c1e4d754 feat: clear save failed status when closing error (#266) 2023-03-07 13:27:55 -05:00
Raymond Zhou
b84c9c006e feat: fix time between attempts label (#263) 2023-03-02 16:46:05 -05:00
Kristin Aoki
5d77dddaf6 feat: add labels and blockquotes to clear format (#261) 2023-03-02 11:43:49 -05:00
connorhaugh
77f030c3fe fix: remove reset widget from advnaced editor 2023-03-02 10:20:22 -05:00
connorhaugh
7a8a182d5a fix: explantion data parse (#260) 2023-03-02 09:20:37 -05:00
Raymond Zhou
4a24d25f22 feat: update switch to Advanced Editor warning (#259) 2023-03-01 16:06:49 -05:00
Raymond Zhou
493ef9026e feat: numeric input UI to allow only correct (#256) 2023-03-01 13:02:27 -05:00
0x29a
897c440f26 test: test the new message, update the snapshot 2023-03-01 17:15:54 +01:00
0x29a
5b543ea93e feat: show "Custom" instead of "Total" when the widget is collapsed 2023-03-01 17:15:41 +01:00
0x29a
0fa18e4199 feat: outline and align right the total label 2023-03-01 16:31:20 +01:00
Kristin Aoki
c65f60ec10 feat: refactor tinymce editor to sharedComponents (#255) 2023-02-28 16:37:52 -05:00
Raymond Zhou
e0c5573c8d feat: tinyMCE config changes (#253) 2023-02-27 13:48:04 -05:00
connorhaugh
3c3361c765 fix: file upload on safari (#254)
* fix: file upload on safari

* fix: lint fix
2023-02-24 10:40:56 -05:00
Feanil Patel
a184ac981c Update standard workflow files. (#252)
* 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.

* build: Creating 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.

* 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.

* build: Updating a missing workflow file `commitlint.yml`.

The .github/workflows/commitlint.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-24 10:40:43 -05:00
Kristin Aoki
76aae38d3a fix: check for if an answer changes to false (#250) 2023-02-23 10:02:22 -05:00
Raymond Zhou
f18353e5fc feat: fix initial advanced problem type olx (#251) 2023-02-22 17:59:27 -05:00
connorhaugh
316f6f2850 feat: reset card link works (#249) 2023-02-17 13:53:09 -05:00
Kristin Aoki
70c0fc6dcf fix: settings col width in advanced view (#233) 2023-02-15 16:37:55 -05:00
Raymond Zhou
6156798e02 feat: move solution tag inside problem type tag (#248) 2023-02-15 12:53:02 -05:00
Raymond Zhou
3f9fc513cf feat: remove Hints widget from advanced editor (#247) 2023-02-15 12:52:52 -05:00
connorhaugh
61c99b9b40 feat: add error boundary (#246)
* feat: add error boundary
2023-02-14 15:21:43 -05:00
Raymond Zhou
529ec8ddf2 feat: fix checkbox colors for feedback (#244) 2023-02-14 12:34:55 -05:00
connorhaugh
b4f1676acf feat: add feedback link (#245)
For Problem Editor Beta
2023-02-14 10:20:26 -05:00
Kristin Aoki
eeaa0e3f68 fix: getGeneralFeedback selectedFeedback error (#243) 2023-02-10 14:54:56 -05:00
kenclary
0367ef776e Merge pull request #240 from openedx/kenclary/TNL-10433
fix: more correct parsing of settings, for scoring; use empty string instead of null for empty attempts. TNL-10433.
2023-02-10 12:01:10 -05:00
Raymond Zhou
eff3df7115 Feat allow singleselect to accept multiple correct answers (#241) 2023-02-10 11:31:52 -05:00
Kristin Aoki
a22ad54502 fix: update problem description in preview block (#242) 2023-02-10 11:00:49 -05:00
Ken Clary
38e262eee0 fix: more correct parsing of settings, for scoring; use empty string instead of null for empty attempts. TNL-10433. 2023-02-10 09:17:44 -05:00
connorhaugh
d69d3e1ce7 feat: Group, General Feedback Settings, Randomization
This Ticket adds three new settings widgets to the Problem Editor:
Randomization: This is a setting for advanced problems only which deals with python scripts.
General Feedback: This is feedback which is only applied to certain problem types for mass-adding feedback to incorrect problems.
Group Feedback: For certain problems, the user can provide specific feedback for a combination of specific answers.
2023-02-10 08:50:32 -05:00
kenclary
7c0309189f Merge pull request #238 from openedx/kenclary/TNL-10426
feat: multiple numericalresponse tags no longer special-cased against going to the advanced editor. TNL-10426.
2023-02-09 18:40:59 -05:00
Raymond Zhou
1282a72acf feat: green radio+checkbox only for valid Checker (#239) 2023-02-09 18:33:20 -05:00
Ken Clary
746cd7cc28 feat: multiple numericalresponse tags no longer special-cased against going to the advanced editor. TNL-10426. 2023-02-09 14:47:29 -05:00
Raymond Zhou
46427ee156 feat: make radio and checkbox green (#234) 2023-02-08 14:41:36 -05:00
Kristin Aoki
87aaa7f3ff fix: add empty answer to problem without answers (#235) 2023-02-07 20:04:16 -05:00
Kristin Aoki
613b8d16ae feat: update question parser to preserve text structure (#232) 2023-02-07 14:31:41 -05:00
Raymond Zhou
7e8f9a2f0c feat: change title when problem type changes (#231) 2023-02-06 13:11:59 -05:00
kenclary
65b663bfc6 Merge pull request #229 from openedx/kenclary/TNL-10413
fix: correct question parsing/building after use of styling. TNL-10413.
2023-02-06 10:17:02 -05:00
Ken Clary
ea6c2c6658 fix: correct question parsing/building after use of styling. TNL-10413. 2023-02-03 11:28:20 -05:00
Raymond Zhou
d978725c35 feat: react to OLX parser process number answers (#230) 2023-02-02 15:30:05 -05:00
Kristin Aoki
57dd03f40f feat: fix feedback box bugs (#227) 2023-02-02 13:51:58 -05:00
Kristin Aoki
796dd388f7 fix: selectTypeModal header z-index (#228) 2023-02-02 13:43:49 -05:00
Kristin Aoki
74b2b76beb fix: add check for question length for parser (#226) 2023-02-01 15:00:03 -05:00
kenclary
2f1072812d Merge pull request #224 from openedx/kenclary/TNL-10390
fix: correct css for text margins in question tinymce. TNL-10390.
2023-02-01 13:58:38 -05:00
Jesper Hodge
861b47b772 feat add olx solution support (#225)
This adds support for the tag in OLX and maps it to the description in the settings options on the ShowAnswer card.
https://2u-internal.atlassian.net/browse/TNL-10397
2023-02-01 13:28:14 -05:00
Ken Clary
b1201cdcef fix: correct css for text margins in question tinymce. TNL-10390. 2023-02-01 12:49:38 -05:00
Kristin Aoki
83d45a249a feat: add label button to question tinyMCE (#221) 2023-02-01 11:35:15 -05:00
kenclary
09d5ce35f3 Merge pull request #219 from openedx/kenclary/TNL-10395
fix: question field uses real placeholder instead of template. fixed blank question handling. TNL-10395, TNL-10411.
2023-01-31 13:31:36 -05:00
Kristin Aoki
787c4068f2 feat: add margin to prevent footer blocking content (#222) 2023-01-31 12:12:38 -05:00
Ken Clary
80f2689cc2 fix: question field uses real placeholder instead of template. fixed blank question handling. TNL-10395, TNL-10411. 2023-01-30 19:06:53 -05:00
kenclary
4a1bac3bdb Merge pull request #218 from openedx/TNL-10400
fix: give QuestionWidget Editor a minimum height. TNL-10400.
2023-01-27 10:37:04 -05:00
Ken Clary
84fe6605c2 fix: give QuestionWidget Editor a minimum height. TNL-10400. 2023-01-26 16:48:21 -05:00
kenclary
fa2387ae00 Merge pull request #217 from openedx/kenclary/TNL-10401
fix: multiple non-numeric problems of the same type should also route to the advanced editor. TNL-10401.
2023-01-26 15:57:21 -05:00
Ken Clary
3b9681618c fix: multiple non-numeric problems of the same type should also route to the advanced editor. TNL-10401. 2023-01-26 12:28:55 -05:00
Kristin Aoki
afec2865c0 fix: separate feedback onchange for each field (#214) 2023-01-26 09:48:43 -05:00
Jesper Hodge
83acc741f5 fix remove problem placeholder answer text (#215)
* refactor: rename hook correctly

* fix: problem templates
2023-01-25 15:02:35 -05:00
Kristin Aoki
2d669cbe3e feat: update styling in advanced problem editor (#216) 2023-01-25 10:42:30 -05:00
Kristin Aoki
656e8f8568 feat: update answer helper text (#213) 2023-01-25 10:10:08 -05:00
Kristin Aoki
be6aca8e8e feat: add function to remove empty hints (#211) 2023-01-24 13:12:41 -05:00
Jesper Hodge
1a2f175989 fix: problem editor styling (#212)
* fix: test name

* fix: make horizontal paddings 24px

* fix: space between widgets

* fix: remove settings heading

* fix: remove button hover effects

* fix: font size

* fix: make buttons small

* fix: change theme

* fix: reset buttons

* refactor: add Button component

* fix: hints widget

* fix: hints widget

* fix: tooltip

* fix: make settings fixed width

* fix: modal heading

* fix: center header text

* fix: modal header

* fix: settings fonts

* fix: settings fonts

* fix: fonts

* fix: padding

* fix: alignments

* fix: package.json

* fix: package.json

* fix: lint
2023-01-24 13:00:38 -05:00
Kristin Aoki
77afb7465b feat: update onclick to close modal + top scroll (#207) 2023-01-24 11:34:55 -05:00
Raymond Zhou
f135bd2b4a feat: align files with commit 5d52a28 and f9dff0 (#210)
This PR aims to fix the commit mistakes I made when trying to merge with a refactored fork. This will keep the changes I made in the refactor.
2023-01-24 09:43:01 -05:00
rayzhou-bit
acee24eaa7 Merge branch 'main' of https://github.com/openedx/frontend-lib-content-components 2023-01-23 15:42:18 -05:00
rayzhou-bit
b7c654399b fix: fix revert 2023-01-23 15:42:13 -05:00
rayzhou-bit
1557fabf9e Revert "Merge branch 'main' of github.com:rayzhou-bit/frontend-lib-content-components into rayzhou-bit-main"
This reverts commit f9dff0df85, reversing
changes made to 5d52a289dc.
2023-01-23 15:12:32 -05:00
rayzhou-bit
bafc3c8de8 Revert "feat: merge conflicts"
This reverts commit 73ec807dd3, reversing
changes made to 62cfecc456.
2023-01-23 14:51:21 -05:00
rayzhou-bit
73ec807dd3 feat: merge conflicts 2023-01-23 13:49:25 -05:00
rayzhou-bit
f9dff0df85 Merge branch 'main' of github.com:rayzhou-bit/frontend-lib-content-components into rayzhou-bit-main 2023-01-23 13:42:15 -05:00
kenclary
5d52a289dc Merge pull request #200 from openedx/kenclary/TNL-10332
fix: various style and UX fixes. TNL-10332.
2023-01-23 13:01:26 -05:00
Ken Clary
d3be3d4240 fix: Correct summary of number of attempts; new separator between attempts summary and points summary; hint text for both attempts and points settings; fixed some widget paddings; advanced problems do not show type setting, and type setting menu does not show advanced problems. TNL-10332. 2023-01-23 12:34:43 -05:00
Jesper Hodge
5aca835a4b Fix problem editor margins and borders (#203)
* fix: fix border and allow customizing of tinymce style

* fix: make tinymce widget look like on figma

* fix: update settingsoptions card border

* fix: header typography

* fix: spacings

* chore: update snapshots

* Update src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.jsx

Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>

* Update src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.jsx

Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>

* Update src/editors/containers/ProblemEditor/components/EditProblemView/index.jsx

Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>

* Update src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx

Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>

* Update src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx

Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>

* Update src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx

Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>

* fix: html and react problems in problem editor

* chore: update snapshots

* chore: apply pr suggestions

* chore: fix test coverage

* chore: fix lint

* chore: fix tests

* chore: fix lint

Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>
2023-01-20 15:59:30 -05:00
Kristin Aoki
d6d3363866 feat: make problem select and preview a fixed size (#204) 2023-01-20 15:05:53 -05:00
Kristin Aoki
f08a662136 feat: remove drag and drop from advanced problems (#206)
Drag and drop V2 is still available in studio via the "Advanced" component.
2023-01-20 14:22:33 -05:00
Raymond Zhou
9c4077f32d feat: set videoId to '' instead of null on load (#205) 2023-01-20 11:22:18 -05:00
rayzhou-bit
317cb48dbe feat: fix to updateDuration call 2023-01-20 05:44:22 -05:00
rayzhou-bit
62cfecc456 feat: fix input for updateDuration call 2023-01-19 16:25:08 -05:00
rayzhou-bit
f64d1bb127 feat: package-lock 2023-01-18 18:18:39 -05:00
rayzhou-bit
af94e15ffb feat: name changes 2023-01-18 18:08:07 -05:00
Kristin Aoki
5e037a7209 feat: change editor footer from sticky to fixed (#202) 2023-01-18 14:39:46 -05:00
Kristin Aoki
adb24ef9ea feat: change default question text (#199) 2023-01-18 12:50:26 -05:00
Jesper Hodge
9a8307001f add testability adr (#201)
* chore: hook ADR round 1

* chore: add adr number

* chore: revert changes that are not docs-related

* chore: revert changes

Co-authored-by: Ben Warzeski <bwarzeski@edx.org>
2023-01-18 11:44:50 -05:00
rayzhou-bit
34b7b3314c feat: revert to connect 2023-01-18 06:12:49 -05:00
Kristin Aoki
7d21a3d4c9 feat: change feedback and delete icons to outline variants (#198) 2023-01-17 15:41:11 -05:00
Jesper Hodge
b7c24d1e1a Fix answer box styling. TNL-10333 (#197)
* fix: use feedback icon with correct hover color

* fix: problem answer layout squishes delete button background

* fix: remove borders from textarea

* fix: textarea resize

* refactor: remove renderThing-antipattern in answer option

* fix: answer option feedback color

* fix: add second feedback box to all problem types

* refactor: move extra components out of answer option file

* fix: icon disappearing on hover when active

* fix: update snapshot

* fix: lint

* fix: add tests

* fix: add tests

* fix: snapshots

* Update src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx

Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>

* fix: resolve discussions from PR

Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>
2023-01-13 17:00:56 -05:00
connorhaugh
95ae45cce8 fix: update title on type select (#196)
* fix: update title on type select

* fix: lint fix

* fix: add test
2023-01-13 14:37:52 -05:00
Kristin Aoki
1a370c12d9 feat: update problem type titles + small ui fixes (#195) 2023-01-13 10:04:01 -05:00
Kristin Aoki
990e35bdc2 feat: remove question box branding + menu (#192)
This PR address the console.log errors from the question box tinyMCE, removing the tinyMCE branding and menu.
2023-01-12 15:30:06 -05:00
connorhaugh
2a9851544e Fix: advanced problem template reference (#194)
* fix: correctly reference advanced problem templates

* fix: remove console log
2023-01-12 13:23:02 -05:00
Raymond Zhou
aad7a6b706 feat: video editor fix to disappearing transcript (#178)
* feat: video editor fix to disappearing transcript
2023-01-12 12:51:56 -05:00
Jesper Hodge
574c2cc76a fix: cannot open problem editor because of typeerror undefined (#193)
* fix: cannot open problem editor because of typeerror

* fix: snapshots
2023-01-12 12:25:18 -05:00
kenclary
6d823e4e7c Merge pull request #187 from openedx/kenclary/TNL-10324
fix: match new frontend behavior with legacy behavior (zero problem attempts is zero attempts, null attempts is infinite); negative values disallowed and forced to zero. TNL-10324.
2023-01-12 10:40:47 -05:00
Ken Clary
390d620664 fix: match new frontend behavior with legacy behavior (zero problem attempts is zero attempts, null attempts is infinite); negative values disallowed and forced to zero. TNL-10324. 2023-01-12 10:31:13 -05:00
connorhaugh
6b2b5ac455 Update workflow 2023-01-12 09:56:59 -05:00
connorhaugh
70f5bb1080 build: pin semantic release to unblock pipeline (#191)
I saw that the release CI https://github.com/openedx/frontend-lib-content-components/actions/runs/3897027405/jobs/6654318273 was failing the release on [semantic-release]: node version >=18 is required. Found v16.19.0.

from https://github.com/semantic-release/semantic-release/releases/tag/v20.0.0 we learn that node v18 is now the minimum required version of node.

The version of semantic-release that runs in a repo is usually based on the relevant Github Acton workflow file for the release, defined in the repo itself.

I am pinning that version to 19.0.5 until the next node upgrade, as it seems we recently upgrade to node 16.
2023-01-12 09:31:31 -05:00
Kristin Aoki
5f5dc911da fix: change # destination to advance settings url (#189) 2023-01-12 09:22:37 -05:00
rayzhou-bit
e66863795c feat: tests argh 2023-01-11 20:14:03 -05:00
connorhaugh
9b2e284ee3 fix: remove test (#188) 2023-01-11 16:53:16 -05:00
Kristin Aoki
d23a790ad2 feat: allow feedback to copy when problem changed (#184) 2023-01-11 16:40:36 -05:00
connorhaugh
cf1daa3ba5 Feat add templates for default problems after problem select (#185)
https://2u-internal.atlassian.net/browse/TNL-10316 is the relevant bug.

Problems have default values when created using the select type page.
2023-01-11 14:26:46 -05:00
Jesper Hodge
2c6679fe06 Feat raw olx editing. TNL-10218 (#182)
* refactor: move CodeEditor to shared components and remove circular dependency

* feat: add code editor to problem editor

* fix: typo

* feat: add save function to raw olx editor and add highlighting

* feat: simplify and add tests to edit problem view

* feat: add tests to problem edit view

* fix: update raw editor tests

* fix: code editor tests

* fix: package-lock

* fix: lint
2023-01-11 14:23:06 -05:00
connorhaugh
f81b0ee925 docs: add period to module.config.js (#183) 2023-01-11 10:25:25 -05:00
kenclary
6a4ac3525f Merge pull request #180 from openedx/kenclary/TNL-10280
feat: confirmation dialog for closing any editor. TNL-10280.
2023-01-11 10:07:46 -05:00
Ken Clary
9ba0da04c3 feat: confirmation dialog for closing any editor. TNL-10280. 2023-01-11 09:58:43 -05:00
Kristin Aoki
af4cd55390 feat: unselect multiple choices type multi->single (#181) 2023-01-10 13:25:19 -05:00
connorhaugh
880d205cbb Feat: raw editor ingress and egress logic (#179)
* feat: conditional rendering of olx editor.

* fix: open the raw editor if advanced is chosen

* fix: add test fix

* feat: add button to switch visual->advanced

* fix: add tests + lint for visual->advanced button

* feat: revert to advanced if parser fails

* fix: improve coverage

* feat: add confirm dialog to switch

* fix: load settings with advanced

* fix: refactor + lint fix
2023-01-10 09:42:44 -05:00
rayzhou-bit
e946fb8711 feat: duration change first pass 2023-01-02 20:52:16 -05:00
Kristin Aoki
09bb1dab2b feat: add import transcripts from youtube (#176) 2022-12-23 10:54:07 -05:00
connorhaugh
2896393c53 feat: add problem type select
Co-authored-by: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>
Co-authored-by: Raymond Zhou <56318341+rayzhou-bit@users.noreply.github.com>
2022-12-22 16:52:21 -05:00
connorhaugh
83cbac6270 feat: doc updates for problem editor release 2022-12-20 15:31:14 -05:00
connorhaugh
8dea72de99 feat:problem editor
Co-authored-by: Farhaan Bukhsh <farhaan@opencraft.com>
Co-authored-by: Navin Karkera <navin@disroot.org>
Co-authored-by: Kaustav Banerjee <kaustav@opencraft.com>
2022-12-20 14:52:20 -05:00
connorhaugh
6f82e87574 feat: make delete and info icons outlines (#150)
* feat: make delete and info icons outlines

* feat:upgrade paragon
2022-12-14 11:44:41 -05:00
Kristin Aoki
f85d86f796 fix: left and right alignment (#167) 2022-12-13 15:04:53 -05:00
Zubair Shakoor
128b112af7 fix: -t flag added in pull translation command (#142) 2022-12-13 13:23:24 -05:00
Kristin Aoki
7daa2c2dba fix: vertical spacing between items (#166) 2022-12-13 13:20:15 -05:00
Kristin Aoki
b5be6f441c fix: add check if field is cleared (#165) 2022-12-12 14:18:25 -05:00
Kristin Aoki
07202c0518 feat: separate video id and url fields into two (#164) 2022-12-12 10:55:32 -05:00
Raymond Zhou
bcb3c3f7fb feat: parseTranscript to work with all languages (#162)
* feat: parseTranscript to work with all languages
2022-12-09 11:05:50 -05:00
Raymond Zhou
cc61e2944c feat: header overlap content when scrolling down (#161)
* feat: header overlap content when scrolling down
2022-12-07 15:24:48 -05:00
Kristin Aoki
01c3a42eb2 fix: transcript styling (#159) 2022-12-07 11:16:02 -05:00
kenclary
a15b894ec1 Merge pull request #160 from openedx/kenclary/TNL-10236
fix: editor title editing no longer tries to scale with input size. TNL-10236.
2022-12-07 11:10:21 -05:00
kenclary
014523731e Merge pull request #158 from openedx/kenclary/TNL-10235
fix: editor container titles are the same height whether displaying or editing. TNL-10235.
2022-12-07 11:01:38 -05:00
Ken Clary
f6574c6849 fix: editor title editing no longer tries to scale with input size. TNL-10236. 2022-12-07 10:31:29 -05:00
Ken Clary
3239810a7f fix: editor container titles are the same height whether displaying or editing. TNL-10235. 2022-12-07 10:05:33 -05:00
Kristin Aoki
6368ccf5ac feat: show view license link at all levels (#157) 2022-12-05 12:43:14 -05:00
Kristin Aoki
0b199b1f5d feat: add black canvas when current thumbnail is deleted (#156) 2022-12-02 16:47:00 -05:00
Raymond Zhou
73150817ca feat: update paragon to v20.21.0 (#155) 2022-12-02 12:54:45 -05:00
Kristin Aoki
f824ef0551 fix: license styling (#154) 2022-12-01 15:14:44 -05:00
connorhaugh
35b58a42b5 feat: left align widget "add" buttons (#153) 2022-12-01 12:20:29 -05:00
Kristin Aoki
6a2bafb402 fix: font/icon size and color (#152) 2022-11-30 15:31:39 -05:00
connorhaugh
e70800543a feat: increase spacing between video settings (#149) 2022-11-30 14:12:03 -05:00
kenclary
1360994fc5 Merge pull request #151 from edx/kenclary/TNL-10240
fix: correct various strings, including making them sentence-case. TNL-10240.
2022-11-30 12:45:04 -05:00
Ken Clary
c4a7b97b63 fix: correct various strings, including making them sentence-case. TNL-10240. 2022-11-30 12:36:42 -05:00
Kristin Aoki
7a356175e7 feat: update onBlur to set state to default values (#148) 2022-11-29 15:23:14 -05:00
Kristin Aoki
f38ae87c95 fix: length error on undefined fallback videos (#147) 2022-11-29 12:44:56 -05:00
Jeremy Ristau
08b5475548 feat: add CODEOWNERS file
feat: add CODEOWNERS file
2022-11-17 11:48:04 -05:00
Jeremy Ristau
f00f6174ac feat: add CODEOWNERS file
The repo should have a CODEOWNERS file, but this effort is specifically to help test a need to make an edx-platform file notify T&L when changes are made.  We are doing the testing on this edx repo that we own to minimize the churn and impact on edx-platform.

The scope of this effort includes:
# Create a CODEOWNERS file in this repo that calls out a single file as owned by a team.
# Submit a no-change PR to that file and ensure the team is notified
# Submit a no-change PR to another file in the repo and ensure the team is NOT notified
# Update the CODEOWNERS file to have T&L team as owners of the whole repo, instead of just one file (long term desired state)
2022-11-17 10:29:16 -05:00
Raymond Zhou
6c574ac18e feat: duration entree features (#143) 2022-11-15 16:22:29 -05:00
connorhaugh
ea50afc165 feat: update readme
adding this messaging to improve quality and trigger a release.
2022-11-15 12:17:30 -05:00
connorhaugh
3506db7c14 Feat improve transcript flow (#141)
https://2u-internal.atlassian.net/browse/TNL-10199
Rewrite of Transcripts widget to improve flow.
2022-11-15 12:03:04 -05:00
Kristin Aoki
8eab620b65 feat: auto-resize width of input and allow save onBlur (#144) 2022-11-14 13:24:11 -05:00
Kristin Aoki
af6e21e1fe fix: non-blocking UI bugs for video settings (#140) 2022-11-09 12:32:36 -05:00
Raymond Zhou
b4b31794af feat: allow license library content edit (#139)
* feat: allow license library content edit
2022-11-03 19:58:22 -04:00
kenclary
5f5250fd2c Merge pull request #131 from edx/kenclary/TNL-9823
feat: duration widget for video settings. TNL-9823.
2022-11-03 18:44:12 -04:00
Kristin Aoki
4187f6a884 feat: remove thumbnail widget from content libraries (#138) 2022-11-03 18:23:34 -04:00
Kristin Aoki
e5932ced27 feat: remove handout widget for content libraries (#137) 2022-11-03 18:16:04 -04:00
Ken Clary
a4f0a8f162 feat: duration widget for video settings. TNL-9823. 2022-11-03 17:55:05 -04:00
Raymond Zhou
79ae64b562 feat: license widget (#132) 2022-11-02 10:41:40 -04:00
kenclary
9c397d8802 Merge pull request #136 from edx/kenclary/TNL-10183
fix: filter for images in a null-safe/undefined-safe way. Fixes TNL-10183.
2022-10-27 10:52:40 -04:00
Ken Clary
c89ad83ed5 fix: filter for images in a null-safe/undefined-safe way. Fixes TNL-10183. 2022-10-26 20:32:52 -04:00
connorhaugh
bfb4de6b1a Fix: temp remove video preview text from settings editor (#134)
* fix: remove preview

* fix: unrelated remove removed fetchImages
2022-10-25 11:44:39 -04:00
Kristin Aoki
ca5846f1f6 fix: text editor save to use assets array instead of object 2022-10-25 10:42:26 -04:00
Kristin Aoki
8e55081ce1 feat: revert selection.url change and replaced with getting the relative path substring from the absolute url 2022-10-24 16:49:47 -04:00
Kristin Aoki
e6101ed3ac feat: update setAssetToStaticUrl to include all assets 2022-10-24 13:44:33 -04:00
Kristin Aoki
cb01ff17a0 feat: add handout widget 2022-10-19 12:17:59 -04:00
Kristin Aoki
8a2c337170 feat: update edx packages: pargon, frontend-platform,browserslist-config (#129) 2022-10-18 12:12:38 -04:00
Kristin Aoki
84f35dad40 feat: add automatic thumbnail resampling for thumbnail widget 2022-10-13 15:07:08 -04:00
Kristin Aoki
e9a123c16b feat: limit xblock title display 2022-10-13 12:44:56 -04:00
Kristin Aoki
36576903ea feat: thumbnail widget 2022-10-12 15:42:38 -04:00
Raymond Zhou
b035725344 feat: bump version (#127) 2022-10-12 15:11:29 -04:00
rayzhou-bit
72aa2dbe92 feat: bump version 2022-10-12 15:00:16 -04:00
Raymond Zhou
d2f07045f0 Feat video source integration (#125)
* feat: video source integration

Co-authored-by: KristinAoki <kaoki@2u.com>
2022-10-12 12:38:44 -04:00
kenclary
a7abab1236 Convert video settings from xblock metadata into the redux store. In-progress draft. TNL-10009. (#119)
* feat: Convert video settings from xblock metadata into the redux store. In-progress draft. TNL-10009.

Co-authored-by: rayzhou-bit <rzhou@2u.com>
2022-10-04 14:59:22 -04:00
Raymond Zhou
cc3a2d8b85 feat: videosource to backend (#118)
* feat: videosource to backend
2022-09-30 11:00:06 -04:00
Kristin Aoki
79ceaca8cc feat: update UI for video source widget (#120) 2022-09-28 11:34:56 -04:00
connorhaugh
45215ba504 Feat: full transcript widget (#117) 2022-09-27 14:09:29 -04:00
Kristin Aoki
ff636837cf feat: transcript parent widget component 2022-09-14 11:07:20 -04:00
connorhaugh
3f303a718d feat: unescape alphanumerics in code Editor (#112)
* feat: unescape alphanumerics in code Editor

* fix: replace disable with not render
2022-09-09 11:09:53 -04:00
Kristin Aoki
03a609ea98 feat: allow .ico image file types 2022-09-08 12:36:34 -04:00
Raymond Zhou
54d773a19a Feat shared widget componentries and layout (#107) 2022-09-07 12:22:27 -04:00
connorhaugh
720b41193f fix: intermittent raw loading error (#109)
As sometimes the html components are rendered downstream before the block is loaded, we need to handle the case of no block value being provided to the raw editor at the time of first render. Subsequent thunk actions will trigger re-renders to display the block.
2022-09-01 14:35:44 -04:00
Kristin Aoki
e5ea0a096c feat: change image absolute urls to relative urls 2022-08-31 12:03:07 -04:00
Kristin Aoki
2d427da80f feat: add tinyMCE functionality for drag resizing of images 2022-08-31 09:18:36 -04:00
Kristin Aoki
4e69fffbef feat: remove the ability to use image tools for content libraries 2022-08-30 16:40:17 -04:00
Kristin Aoki
36380edce4 feat: add codeMirror lineWrapping extension 2022-08-29 09:39:46 -04:00
Kristin Aoki
2b49304ecc feat: change static url to asset url in editor 2022-08-24 12:53:18 -04:00
Raymond Zhou
09110ec0b0 feat: run onImgLoad even on broken images (#102)
* feat: run onImgLoad even on broken images
2022-08-23 06:00:46 -04:00
connorhaugh
564dcb8ebc feat: improve raw HTML editing Experince. (#101)
* feat: add contents

* feat: add codemirror support to raw HTML editing

* feat: add test coverage

* fix: error

* fix: update codeeditor file path

* fix: update messages
2022-08-22 15:19:21 -04:00
Kristin Aoki
617f316f37 feat: allow relative urls for assets 2022-08-18 09:04:44 -04:00
Farhaan Bukhsh
405c3cf7e3 chore: Update the Readme for project (#98)
Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>

Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
2022-08-17 11:13:40 -04:00
Kristin Aoki
d68c357a86 feat: resolve console errors regarding skin.css 2022-08-15 11:26:39 -04:00
Kristin Aoki
f86e1fe97e feat: update editor text to match studio styling 2022-08-12 10:47:11 -04:00
Raymond Zhou
476c450e6c Feat updates to code block button (#93)
* feat: updates to code block button

* feat: updates to code block button
2022-08-10 12:59:03 -04:00
Kristin Aoki
1b180de468 feat: add altText and isDecorative persistence for image editing 2022-08-10 09:17:35 -04:00
Kristin Aoki
d739bcbdb5 feat: Prevent image uploads larger than 10 MB and add spinner 2022-08-08 15:44:59 -04:00
Kristin Aoki
9b23731acc feat: Add functionality to resize image based on percentage (#94)
* feat: add image resizing with percents
2022-08-05 12:13:57 -04:00
Kristin Aoki
3821378dc1 Merge pull request #92 from edx/KristinAoki/tinymce-underline
fix: added underline option to toolbar. TNL-10003
2022-08-01 10:29:21 -04:00
KristinAoki
6be7433567 Merge branch 'KristinAoki/tinymce-underline' of https://github.com/edx/frontend-lib-content-components into KristinAoki/tinymce-underline 2022-08-01 09:15:35 -04:00
KristinAoki
cc7e502011 fix: added underline option to toolbar. TNL-10003 2022-08-01 09:11:01 -04:00
KristinAoki
a918da46c2 Add underline option to editor toolbar 2022-07-29 12:02:08 -04:00
Raymond Zhou
80dfc6ba15 feat: www gallery raw selection (#88)
* feat: www gallery raw selection
2022-07-22 10:58:55 -04:00
connorhaugh
224720c32e feat: reorganize dependancies (#91) 2022-07-11 16:19:31 -04:00
connorhaugh
9829a5d4ef feat: No - OP (#90) 2022-07-07 08:47:56 -04:00
connorhaugh
2473c9a875 chore: upgrade paragon dep (#89)
* chore: upgrade paragon dep

* fix: eslint config
2022-07-05 09:08:15 -04:00
Raymond Zhou
b047f7a2a8 feat: raw html editor (#86)
raw html editor
2022-06-28 14:25:09 -04:00
connorhaugh
b2fec70702 feat: swap relative Urls bool (#85) 2022-06-10 10:46:34 -04:00
connorhaugh
728dc58ac4 fix: Remove addition to URLs in text editor (#84) 2022-06-09 09:43:23 -04:00
connorhaugh
81fc4fca6f docs: adopt ADR 4 (#79) 2022-06-09 09:41:56 -04:00
connorhaugh
cc4e19cd2a fix: redirect to correct learning context (#83)
For https://2u-internal.atlassian.net/browse/TNL-9955
there are multiple instantiations of the text editor in different contexts, so we need to handle them upfront to not break either experience flow” or something along those lines…
2022-06-09 09:41:31 -04:00
Raymond Zhou
ca9f788838 feat: toolbar stays visible when scrolling (#82) 2022-05-27 12:40:20 -04:00
kenclary
0e523feb09 Merge pull request #81 from edx/kenclary/TNL-9943
fix: allow style tags inside html body, to match old editor behavior. TNL-9943.
2022-05-26 13:44:41 -04:00
kenclary
c02bb9df7f Merge branch 'main' into kenclary/TNL-9943 2022-05-25 17:23:07 -04:00
Ken Clary
5922e25b3d fix: allow style tags inside html body, to match old editor behavior. TNL-9943. 2022-05-25 15:15:43 -04:00
connorhaugh
3b859734fd feat: add simple code block and blockquote buttons (#80)
* feat: add simple code block and blockquote buttons

* fix: readaad context toolbar
2022-05-25 13:58:11 -04:00
connorhaugh
a74b2f2272 docs: V2 Content Editors ADR (#72)
This PR adds an overarching ADR for the V2 Content Editors framework, as well as several other, smaller, ADRs related to architectural abstractions.
2022-05-19 10:05:52 -04:00
connorhaugh
a3c50b2723 feat: allow all html tags (#77)
* feat: allow all html tags.
2022-05-18 13:24:13 -04:00
connorhaugh
94009e6ed7 fix: delete z index css (#78)
* fix: delete z index css

* fix: remove from index.css
2022-05-17 13:50:41 -04:00
connorhaugh
5aea213b8c feat: add autocreate new xblock (#67)
This PR adds an automated script for generating the boilerplate code for adding a new xblock editor. As well as documentation for how to do so.
2022-05-16 16:14:18 -04:00
kenclary
0d51b45636 Merge pull request #75 from edx/kenclary/TNL-9879
chore: npm update, using node 16 / npm 8. TNL-9879.
2022-05-15 10:18:28 -04:00
Ken Clary
d74f2b8ba9 chore: npm update, using node 16 / npm 8. TNL-9879. 2022-05-15 09:57:10 -04:00
Raymond Zhou
76dcd1a920 Feat alert users with feedback instead of disabling next/save buttons (#68)
* feat: implemented user feedback ErrorAlerts
2022-05-13 15:23:42 -04:00
Jawayria
b5480beaf8 feat: Add package-lock file version check (#73) 2022-05-13 14:55:29 -04:00
Tim McCormack
18e3012462 fix: Fix pull_translations by using correct CLI flag for languages (#74)
Docs: https://developers.transifex.com/docs/using-the-client

Apparently this CLI option changed from singular to plural at some point.
2022-05-13 13:03:26 -04:00
Ben Warzeski
564b953860 feat: video skeleton hooks (#65)
* feat: video skeleton hooks

* fix: lint

* Update src/editors/containers/VideoEditor/components/VideoSettingsModal/components/CollapsibleFormWidget.jsx

Co-authored-by: connorhaugh <49422820+connorhaugh@users.noreply.github.com>

Co-authored-by: connorhaugh <49422820+connorhaugh@users.noreply.github.com>
2022-05-09 14:23:21 -04:00
bszabo
964f00e563 Merge pull request #71 from edx/TNL-9888-text-editor-ADR
docs: ADR for text editor decisions May 2022
2022-05-06 11:39:56 -04:00
Bernard Szabo
46458b0f58 docs: TNL-9888 ADR for text editor decisions May 2022
Mostly notes on how to use TinyMCE to meet product requirements
Includes pull request feedback
Co-authored-by: Ben Warzeski <bwarzeski@2u.com>
2022-05-06 11:38:59 -04:00
Bernard Szabo
da6bdad9f0 docs: TNL-9888 ADR for text editor decisions May 2022
Mostly notes on how to use TinyMCE to meet product requirements
Includes pull request feedback
Co-authored-by: Ben Warzeski <bwarzeski@2u.com>
2022-05-06 11:24:18 -04:00
kenclary
121f28c535 Merge pull request #70 from edx/kenclary/TNL-9876
fix: code plugin uses 'HTML' label instead of icon. Fixes TNL-9876.
2022-05-04 18:25:12 -04:00
Ken Clary
91be5db424 fix: code plugin uses 'HTML' label instead of icon. Fixes TNL-9876. 2022-05-04 16:50:07 -04:00
Bernard Szabo
7b6bd31475 docs: fix typo and clarify no feature loss requirement
per Ray Zhou's PR feedback
2022-05-04 15:24:13 -04:00
Raymond Zhou
51f89bdc1e feat: The X Button in the Top Right Doesn't do anything. (#66)
* fix: tests

* fix: onClose test case
2022-05-04 14:20:23 -04:00
Bernard Szabo
5920096306 docs: ADR for text editor decisions May 2022
Mostly how to use and extended tinyMCE
2022-05-04 10:52:44 -04:00
connorhaugh
0d4688ce75 feat: remove codesample add code plugin (#64) 2022-04-19 12:53:33 -04:00
connorhaugh
081129b639 feat: no-op commit update readme (#63)
this is for the release to stage.
2022-04-19 11:54:25 -04:00
Raymond Zhou
5200897e1b Fix change to go back to 'fake' modal (#62)
* fix: rebase

* fix: tests

* fix: remove broken code button

* fix: test case with iff
2022-04-19 11:25:01 -04:00
kenclary
be12d11027 Merge pull request #61 from edx/kenclary/TNL-9874
fix: rearrange and add several tinymce toolbar items. Addresses TNL-9874.
2022-04-18 16:43:00 -04:00
Ken Clary
1999041cdf fix: rearrange and add several tinymce toolbar items. Addresses TNL-9874. 2022-04-18 15:37:47 -04:00
Julia Eskew
51558fd17c Add events sent to Segment for the save and cancel clicks for content editors. (#44)
* feat: Add events sent to Segment for the save and cancel clicks for a content editor.

Co-authored-by: rayzhou-bit <rzhou@edx.org>
2022-04-18 13:44:27 -04:00
kenclary
3620cac421 Merge pull request #60 from edx/kclary/TNL-9855
fix: enable ordered and unordered lists in text editor. Fixes TNL-9855.
2022-04-14 16:05:04 -04:00
Ken Clary
24baf8cbeb fix: enable ordered and unordered lists in text editor. Fixes TNL-9855. 2022-04-14 15:20:31 -04:00
Ben Warzeski
cb1c00bf3c Feat: Video skeleton (#58)
* pt1

* feat: video skeleton

* fix: update tests

* chore: update snapshots and linting

* fix: fix image context button

* feat: re-usable editor pattern

* fix: css and bad hook
2022-04-14 15:01:04 -04:00
bszabo
0edee6b4e0 Merge pull request #57 from edx/TNL-9804-make-small-code-stewardship-changes-to-frontend-lib-content-components
Tnl 9804 make small code stewardship changes to frontend lib content components
2022-04-11 18:12:19 -04:00
Bernard Szabo
0d60cd97a0 refactor: Fix footer aria descriptions
'screensaver' in Aria description messages changed to 'screen reader'
2022-04-11 16:33:19 -04:00
Raymond Zhou
553e4d8c04 fix: editor has double scrollbars (#59) 2022-04-11 12:26:39 -04:00
Bernard Szabo
48fcfb0e00 refactor: Preserve button default messages
description for aria labels may explicitly reference intended screensaver use, but label names and ids should remain unchanged
2022-04-08 16:55:14 -04:00
connorhaugh
33b2c6a660 feat: image context toolbar (#55)
Note: this removes the crop and rotate functionality from the toolbar, as it requires an image_proxy server or tinymce cloud. https://www.tiny.cloud/docs-4x/plugins/imagetools/#imagetools_proxy. We also need to create a follow up ticket to handle right click behavior.
This is that follow up ticket
2022-04-08 13:23:42 -04:00
Raymond Zhou
ef6ea6b617 fix: saving block title (#50)
* fix: saving block title

* fix: ben's suggestions
2022-04-08 12:45:49 -04:00
Bernard Szabo
d79ee29b96 refactor: consistent naming and default message for saveButton label
Prior to this change Aria message and default message were different
2022-04-07 16:12:13 -04:00
Bernard Szabo
26c0c78660 refactor: use consistent ordering for header/footer attributes 2022-04-07 16:12:13 -04:00
kenclary
bc3ef37dcf Merge pull request #53 from edx/kenclary/TNL-9832
fix: remove spurious hard-coded height for img-settings-form-container class. Fixes TNL-9832.
2022-04-07 15:49:06 -04:00
Ken Clary
e3236e9d95 fix: remove spurious hard-coded height for img-settings-form-container class. Fixes TNL-9832. 2022-04-07 15:44:47 -04:00
connorhaugh
c817e17d8a fix: update texteditor spacing (#49)
footer is now locked to bottom of page, and that text editor content scrolls, and that this works on resize of page.
2022-04-07 14:49:15 -04:00
Raymond Zhou
8104aa3152 fix: load block title (#51) 2022-04-07 12:47:35 -04:00
connorhaugh
c3d9109211 fix: remove merge artifiact (#48)
For repo health
2022-04-06 10:50:08 -04:00
Raymond Zhou
45758612a4 feat: empty gallery (#46)
Adds a new option to the behavior for when the gallery has no images in it.
2022-04-05 11:43:40 -04:00
connorhaugh
049b6a9211 Fix: release ci (#47)
* feat: add capabilities

* chore: more tests

* fix: use correct hook source for getDispatch

* fix: fix fetchImages data contract

* fix: make onClose method a callback for ImageUploadModal

* chore: lint and test updates

* chore: clean up propType warning

* fix: upload of file

* fix: error notifcations

* fix: improve test coverage

* fix: lint fixes

* fix: lint fix

* rebase: stept 1

* rebase: step 2

* fix: use correct hook source for getDispatch

* rebase: step 3

* rebase: step 4

* chore: clean up propType warning

* fix: upload of file

* rebase: step 5

* fix: improve test coverage

* fix: lint fixes

* fix: release CI

Co-authored-by: Ben Warzeski <bwarzeski@edx.org>
2022-04-04 09:17:34 -04:00
connorhaugh
fd35c1cb18 Feat: Add Request Alerts and upload file (#43)
Fixes to Upload data type, as well as adding in of two error alerts for upload and fetch.
Co-authored-by: Ben Warzeski <bwarzeski@edx.org>
Co-authored-by: Raymond Zhou <56318341+rayzhou-bit@users.noreply.github.com
2022-04-04 08:33:31 -04:00
Raymond Zhou
28516a0389 fix: text editor save (#45)
* fix: text editor save

* fix: update snapshot
2022-04-01 17:01:12 -04:00
Raymond Zhou
dca18b9b97 chore: i18n complete (#37)
* chore: i18n
2022-03-31 16:14:29 -04:00
Ben Warzeski
0f87a61639 feat: Select img api (#41)
* feat: add capabilities

* chore: more tests

* fix: use correct hook source for getDispatch

* fix: fix fetchImages data contract

* fix: make onClose method a callback for ImageUploadModal

* chore: lint and test updates

* chore: clean up propType warning

Co-authored-by: connorhaugh <chaugh21@amherst.edu>
2022-03-30 15:13:19 -04:00
Ben Warzeski
1a5497a5ae Feat select image modal (#38)
* feat: select image modal

* chore: fix module config
2022-03-24 16:16:38 -04:00
Ben Warzeski
09e9d865c2 Chore: Test coverage hunt (#36)
* chore: add brand mocking in gallery view

* feat: dev gallery app

* chore: link mock block ids to real block type api

* feat: image settings page features

* chore: more tests

* chore: keystore util and more testing

* chore: more tests

* chore: re-install lint plugin...

* chore: lint fixes

* chore: moar tests

* chore: remove brand from module.config and link gallery to edx.org brand
2022-03-24 11:15:32 -04:00
Ben Warzeski
284601d6d2 feat: image dimension lock logic update (#34) 2022-03-22 10:03:26 -04:00
Ben Warzeski
3b8a7780ac I18n example (#33)
* feat: i18n pt 1

* fix: prevent float calculations when updating dimensions
2022-03-17 14:08:46 -04:00
Ben Warzeski
a79da4cb2d feat: useState test util (#31) 2022-03-16 11:27:08 -04:00
Jawayria
9e84e0ecf0 fix: update dependencies (#32)
* fix: update dependencies

Co-authored-by: M Umar Khan <umar.khan@arbisoft.com>
2022-03-16 09:45:35 -04:00
Ben Warzeski
32e4d5f7a1 feat: Image settings feature and design completeness (#30)
* feat: devgallery api mode

* feat: dev gallery app

* chore: link mock block ids to real block type api

* feat: image settings page features

* fix: update tests

* fix: console message cleanup

* fix: test fixes from code walkthrough with ray
2022-03-15 16:32:07 -04:00
connorhaugh
4ae2d1230b feat: insert images into text editor html (#29)
This work adds the functionality that when an image is selected ineither the select image step of the image upload modal, or by using the toolbar inside tinymce, the requisite image is loaded into the settings page, and on the click of the save button, it is inserted into tinymce html.
2022-03-15 10:53:56 -04:00
connorhaugh
5258e93972 Test add requests redux tests (#24)
Add redux tests as well as get save functionality working.
2022-03-07 19:43:46 -05:00
connorhaugh
c4cd0c44ce test: update editor-level tests (#26)
To complete https://openedx.atlassian.net/browse/TNL-9601
2022-03-07 15:03:13 -05:00
Ben Warzeski
ac0d261e89 Gallery app (#27)
* feat: devgallery api mode

* chore: update react version

* feat: dev gallery app

* chore: fix component tests

* chore: lint fixes

* chore: link mock block ids to real block type api
2022-03-07 13:35:28 -05:00
Raymond Zhou
6f0f6296e4 test: cms api tests + extra lint (#25) 2022-03-01 11:32:03 -05:00
Ben Warzeski
9c9d3c8fdf feat: image upload skeleton (#22) 2022-03-01 11:17:03 -05:00
Raymond Zhou
f3d80995c5 test: cms urls (#23) 2022-02-25 19:24:05 -05:00
connorhaugh
7ccba63a85 test: add TextEditor Tests (#21) 2022-02-25 15:06:12 -05:00
Raymond Zhou
042246be86 Test: editor header component (#20)
* test: header tests start

* test: EditableHeader test ready for review 1

* test: editor header tests complete

* test: fixing up nits

* test: ben's corrections
2022-02-25 12:15:13 -05:00
Ben Warzeski
1a1900f213 feat: redux tests pt 1 (#19)
* feat: redux tests pt 1

* chore: add app thunkAction tests

* chore: resolve lint issues

* Update src/editors/data/redux/app/reducer.test.js

Co-authored-by: connorhaugh <49422820+connorhaugh@users.noreply.github.com>

Co-authored-by: connorhaugh <49422820+connorhaugh@users.noreply.github.com>
2022-02-24 16:59:30 -05:00
Ben Warzeski
2b0346fe84 chore: add tests for EditorHeader hooks (#18) 2022-02-23 11:55:53 -05:00
connorhaugh
6ca93a7297 test: add EditorFooter tests (#16)
* test: add EditorFooter tests
2022-02-22 13:24:15 -05:00
Ben Warzeski
d2e89d7b28 chore: rename lms service to cms (#15)
* chore: rename lms service to cms

* fix: remove typo

* fix: remove old selector
2022-02-22 12:59:37 -05:00
Ben Warzeski
362139edd2 feat: mock paragon and i18n library for tests 2022-02-22 12:45:30 -05:00
Ben Warzeski
5a1d71a62c !refactor: Breaking Change refactor use Redux. No release 2022-02-18 13:16:36 -05:00
connorhaugh
eef30348fd feat: add plugins including image-upload (#12)
This adds the image upload "plugin" and all the desired built-in plugins.
Per the following two tickets
https://openedx.atlassian.net/browse/TNL-9367
https://openedx.atlassian.net/browse/TNL-9475

I need to add the requisite plugins, as well as a framework for the image upload modal.
2022-02-14 12:33:49 -05:00
connorhaugh
2f931b5bdb fix: dont encode with uri twice (#10) 2022-01-27 12:39:19 -05:00
connorhaugh
d8c6b8dddd feat: Text Editor and V2 Editor Framework (#9)
Text Editor and V2 Editor Framework. Documentation to come.
2022-01-25 14:04:57 -05:00
kenclary
c93c5e986a Merge pull request #8 from edx/kenclary/release-fix
fix: correct project links in package.json
2021-12-15 11:34:36 -05:00
Ken Clary
bb7360ac93 fix: correct project links in package.json 2021-12-15 11:31:46 -05:00
kenclary
f7935deea0 Merge pull request #7 from edx/kenclary/release-fix
fix: correct(?) configuration of main branch for semantic-release.
2021-12-15 11:01:48 -05:00
Ken Clary
b98fe329af fix: correct(?) configuration of main branch for semantic-release. 2021-12-15 10:52:22 -05:00
kenclary
2bd75952f0 Merge pull request #6 from edx/kenclary/security
fix: update dependencies for security.
2021-12-14 17:22:23 -05:00
Ken Clary
f44017e5f4 fix: update dependencies for security. 2021-12-14 17:12:22 -05:00
kenclary
621f39f8ca Merge pull request #4 from edx/kenclary/release
fix: base semantic-release on main branch.
2021-12-13 11:30:33 -05:00
Ken Clary
159ecc84c3 fix: base semantic-release on main branch. 2021-12-09 16:06:16 -05:00
kenclary
e5a1694c90 Merge pull request #3 from edx/kclary/node
fix: update node to 16, using .nvmrc file, to support later versions of semantic-release.
2021-12-03 16:48:58 -05:00
Ken Clary
b37db23e8f fix: update node to 16, using .nvmrc file, to support later versions of semantic-release. 2021-12-03 12:10:06 -05:00
kenclary
105c29a67a Merge pull request #2 from edx/kenclary-initial
feat: setup repo as NPM package with edX standards.
2021-12-01 20:09:26 -05:00
Ken Clary
a48eb0aaf4 feat: setup repo as NPM package with edX standards. 2021-12-01 12:41:54 -05:00
kenclary
7142f89211 Merge pull request #1 from edx/kenclary-adr
Create 0001-library-adr.rst
2021-11-23 09:02:46 -05:00
kenclary
f547e5ed1f Create 0001-library-adr.rst
Draft of ADR for repo.
2021-11-22 16:52:19 -05:00
David Joy
9ed78de9e2 Initial commit 2021-11-19 14:28:50 -05:00
2267 changed files with 183647 additions and 36687 deletions

15
.env
View File

@@ -1,3 +1,4 @@
APP_ID='authoring'
NODE_ENV='production'
ACCESS_TOKEN_COOKIE_NAME=''
BASE_URL=''
@@ -30,15 +31,23 @@ USER_INFO_COOKIE_NAME=''
ENABLE_ACCESSIBILITY_PAGE=false
ENABLE_PROGRESS_GRAPH_SETTINGS=false
ENABLE_TEAM_TYPE_SETTING=false
ENABLE_NEW_EDITOR_PAGES=true
ENABLE_UNIT_PAGE=false
ENABLE_ASSETS_PAGE=false
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN=false
ENABLE_TAGGING_TAXONOMY_PAGES=false
ENABLE_TAGGING_TAXONOMY_PAGES=true
ENABLE_CERTIFICATE_PAGE=true
ENABLE_COURSE_IMPORT_IN_LIBRARY=false
ENABLE_UNIT_PAGE_NEW_DESIGN=false
ENABLE_COURSE_OUTLINE_NEW_DESIGN=false
BBB_LEARN_MORE_URL=''
HOTJAR_APP_ID=''
HOTJAR_VERSION=6
HOTJAR_DEBUG=false
INVITE_STUDENTS_EMAIL_TO=''
AI_TRANSLATIONS_BASE_URL=''
ENABLE_CHECKLIST_QUALITY=''
# "Multi-level" blocks are unsupported in libraries
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder,library_content,itembank"
# Fallback in local style files
PARAGON_THEME_URLS={}
COURSE_TEAM_SUPPORT_EMAIL=''
ADMIN_CONSOLE_URL='http://localhost:2025/admin-console'

View File

@@ -1,3 +1,4 @@
APP_ID='authoring'
NODE_ENV='development'
ACCESS_TOKEN_COOKIE_NAME='edx-jwt-cookie-header-payload'
BASE_URL='http://localhost:2001'
@@ -32,15 +33,24 @@ USER_INFO_COOKIE_NAME='edx-user-info'
ENABLE_ACCESSIBILITY_PAGE=false
ENABLE_PROGRESS_GRAPH_SETTINGS=false
ENABLE_TEAM_TYPE_SETTING=false
ENABLE_NEW_EDITOR_PAGES=true
ENABLE_UNIT_PAGE=false
ENABLE_ASSETS_PAGE=false
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN=false
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN=true
ENABLE_CERTIFICATE_PAGE=true
ENABLE_COURSE_IMPORT_IN_LIBRARY=true
ENABLE_COURSE_OUTLINE_NEW_DESIGN=true
ENABLE_UNIT_PAGE_NEW_DESIGN=true
ENABLE_NEW_VIDEO_UPLOAD_PAGE=true
ENABLE_TAGGING_TAXONOMY_PAGES=true
BBB_LEARN_MORE_URL=''
HOTJAR_APP_ID=''
HOTJAR_VERSION=6
HOTJAR_DEBUG=true
INVITE_STUDENTS_EMAIL_TO="someone@domain.com"
AI_TRANSLATIONS_BASE_URL='http://localhost:18760'
ENABLE_CHECKLIST_QUALITY=true
# "Multi-level" blocks are unsupported in libraries
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder,library_content,itembank"
# Fallback in local style files
PARAGON_THEME_URLS={}
COURSE_TEAM_SUPPORT_EMAIL=''
ADMIN_CONSOLE_URL='http://localhost:2025/admin-console'

View File

@@ -1,3 +1,4 @@
APP_ID='authoring'
ACCESS_TOKEN_COOKIE_NAME='edx-jwt-cookie-header-payload'
BASE_URL='http://localhost:2001'
CREDENTIALS_BASE_URL='http://localhost:18150'
@@ -28,11 +29,18 @@ SUPPORT_URL='https://support.edx.org'
USER_INFO_COOKIE_NAME='edx-user-info'
ENABLE_PROGRESS_GRAPH_SETTINGS=false
ENABLE_TEAM_TYPE_SETTING=false
ENABLE_NEW_EDITOR_PAGES=true
ENABLE_UNIT_PAGE=true
ENABLE_ASSETS_PAGE=false
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN=true
ENABLE_CERTIFICATE_PAGE=true
ENABLE_COURSE_IMPORT_IN_LIBRARY=true
ENABLE_COURSE_OUTLINE_NEW_DESIGN=false
ENABLE_UNIT_PAGE_NEW_DESIGN=false
ENABLE_TAGGING_TAXONOMY_PAGES=true
BBB_LEARN_MORE_URL=''
INVITE_STUDENTS_EMAIL_TO="someone@domain.com"
ENABLE_CHECKLIST_QUALITY=true
# "Multi-level" blocks are unsupported in libraries
LIBRARY_UNSUPPORTED_BLOCKS="conditional,step-builder,problem-builder,library_content,itembank"
PARAGON_THEME_URLS=
COURSE_TEAM_SUPPORT_EMAIL='support@example.com'

View File

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

View File

@@ -11,8 +11,18 @@ module.exports = createConfig(
}],
'template-curly-spacing': 'off',
'react-hooks/exhaustive-deps': 'off',
indent: ['error', 2],
'no-restricted-exports': 'off',
// There is no reason to disallow this syntax anymore; we don't use regenerator-runtime in new browsers
'no-restricted-syntax': 'off',
'no-restricted-imports': ['error', {
patterns: [
{
group: ['@edx/frontend-platform/i18n'],
importNames: ['injectIntl'],
message: "Use 'useIntl' hook instead of injectIntl.",
},
],
}],
},
settings: {
// Import URLs should be resolved using aliases

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

@@ -2,26 +2,37 @@
Describe what this pull request changes, and why. Include implications for people using this change.
Design decisions and their rationales should be documented in the repo (docstring / ADR), per
[OEP-19](https://open-edx-proposals.readthedocs.io/en/latest/oep-0019-bp-developer-documentation.html), and can be linked here.
Useful information to include:
- Which edX user roles will this change impact? Common user roles are "Learner", "Course Author",
- Which user roles will this change impact? Common user roles are "Learner", "Course Author",
"Developer", and "Operator".
- Include screenshots for changes to the UI (ideally, both "before" and "after" screenshots, if applicable).
- Provide links to the description of corresponding configuration changes. Remember to correctly annotate these
changes.
## Supporting information
Link to other information about the change, such as Jira issues, GitHub issues, or Discourse discussions.
Link to other information about the change, such as GitHub issues, or Discourse discussions.
Be sure to check they are publicly readable, or if not, repeat the information here.
## Testing instructions
Please provide detailed step-by-step instructions for testing this change.
Please provide detailed step-by-step instructions for manually testing this change.
## Other information
Include anything else that will help reviewers and consumers understand the change.
- Does this change depend on other changes elsewhere?
- Any special concerns or limitations? For example: deprecations, migrations, security, or accessibility.
- Any special concerns or limitations? For example: deprecations, migrations, security, or accessibility.
## Best Practices Checklist
We're trying to move away from some deprecated patterns in this codebase. Please
check if your PR meets these recommendations before asking for a review:
- [ ] Any _new_ files are using TypeScript (`.ts`, `.tsx`).
- [ ] Avoid `propTypes` and `defaultProps` in any new or modified code.
- [ ] Tests should use the helpers in `src/testUtils.tsx` (specifically `initializeMocks`)
- [ ] Do not add new fields to the Redux state/store. Use React Context to share state among multiple components.
- [ ] Use React Query to load data from REST APIs. See any `apiHooks.ts` in this repo for examples.
- [ ] All new i18n messages in `messages.ts` files have a `description` for translators to use.
- [ ] Avoid using `../` in import paths. To import from parent folders, use `@src`, e.g. `import { initializeMocks } from '@src/testUtils';` instead of `from '../../../../testUtils'`

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 }}

15
.github/workflows/add-to-cc-board.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Trigger to add Issue or PR to a Core Contributor project board
on:
issues:
types: [labeled]
pull_request:
types: [labeled]
jobs:
add-to-cc-board:
if: github.event.label.name == 'Core Contributor assignee'
uses: openedx/.github/.github/workflows/add-to-cc-board.yml@master
with:
board_name: cc-frontend-apps
secrets:
projects_access_token: ${{ secrets.PROJECTS_TOKEN }}

View File

@@ -9,15 +9,31 @@ on:
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Nodejs Env
run: echo "NODE_VER=`cat .nvmrc`" >> $GITHUB_ENV
- uses: actions/setup-node@v3
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VER }}
node-version-file: '.nvmrc'
- run: make validate.ci
- name: Archive code coverage results
uses: actions/upload-artifact@v7
with:
name: code-coverage-report
path: coverage/*.*
coverage:
runs-on: ubuntu-latest
needs: tests
steps:
- uses: actions/checkout@v6
- name: Download code coverage results
uses: actions/download-artifact@v8
with:
pattern: code-coverage-report
path: coverage
merge-multiple: true
- name: Upload coverage
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v5
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}

4
.gitignore vendored
View File

@@ -1,6 +1,7 @@
.DS_Store
.eslintcache
.idea
.run
node_modules
npm-debug.log
coverage
@@ -26,3 +27,6 @@ temp/babel-plugin-react-intl
# Messages .json files fetched by atlas
src/i18n/messages/
# environment js config
env.config.jsx

2
.nvmrc
View File

@@ -1 +1 @@
18
24

23
.oxlintrc.json Normal file
View File

@@ -0,0 +1,23 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"categories": {
"correctness": "warn"
},
"rules": {
"eslint/no-unused-vars": "off",
"typescript/unbound-method": "off", // 🛑 TEMPORARY
"typescript/no-floating-promises": ["error", {
"allowForKnownSafeCalls": [
// queryClient.invalidateQueries returns a promise that can be awaited
// if you want to do something after all the subsequent refetches are
// complete, but we rarely if ever want that; we usually want to
// continue invalidating more things immediately. So we don't usually
// want to await this.
"invalidateQueries",
]
}]
},
"ignorePatterns": [
"webpack.dev-tutor.config.js",
]
}

View File

@@ -26,6 +26,7 @@
"scss/at-rule-no-unknown": true,
"scss/at-import-partial-extension": null,
"scss/comment-no-empty": null,
"import-notation": "string",
"property-no-unknown": [true, {
"ignoreProperties": ["xs", "sm", "md", "lg", "xl", "xxl"]
}],

View File

@@ -1,2 +0,0 @@
# The following users are the maintainers of all frontend-app-course-authoring files
* @openedx/2u-tnl

View File

@@ -35,13 +35,12 @@ pull_translations:
cd src/i18n/messages \
&& atlas pull $(ATLAS_OPTIONS) \
translations/frontend-component-ai-translations/src/i18n/messages:frontend-component-ai-translations \
translations/frontend-lib-content-components/src/i18n/messages:frontend-lib-content-components \
translations/frontend-platform/src/i18n/messages:frontend-platform \
translations/paragon/src/i18n/messages:paragon \
translations/frontend-component-footer/src/i18n/messages:frontend-component-footer \
translations/frontend-app-course-authoring/src/i18n/messages:frontend-app-course-authoring
$(intl_imports) frontend-component-ai-translations frontend-lib-content-components frontend-platform paragon frontend-component-footer frontend-app-course-authoring
$(intl_imports) frontend-component-ai-translations frontend-platform paragon frontend-component-footer frontend-app-course-authoring
# This target is used by Travis.
validate-no-uncommitted-package-lock-changes:
@@ -52,9 +51,11 @@ validate-no-uncommitted-package-lock-changes:
validate:
make validate-no-uncommitted-package-lock-changes
npm run i18n_extract
npm run lint -- --max-warnings 0
# We are trying out oxlint. Now that it's been working well for a while with both oxlint and eslint, we have disabled
# eslint, and after a few weeks we'll evaluate whether any problems are slipping through if only oxlint is used.
npm run oxlint
npm run types
npm run test
npm run test:ci
npm run build
.PHONY: validate.ci

View File

@@ -1,5 +1,5 @@
frontend-app-course-authoring
#############################
frontend-app-authoring
######################
|license-badge| |status-badge| |codecov-badge|
@@ -7,9 +7,9 @@ frontend-app-course-authoring
Purpose
*******
This is the Course Authoring micro-frontend, currently under development by `2U <https://2u.com>`_.
This implements most of the frontend for **Open edX Studio**, allowing authors to create and edit courses, libraries, and their learning components.
Its purpose is to provide both a framework and UI for new or replacement React-based authoring features outside ``edx-platform``. You can find the current set described below.
A few parts of Studio still default to the `"legacy" pages defined in edx-platform <https://github.com/openedx/edx-platform/tree/master/cms>`_, but those are rapidly being deprecated and replaced with the React- and Paragon-based pages defined here.
Getting Started
@@ -18,51 +18,87 @@ Getting Started
Prerequisites
=============
The `devstack`_ is currently recommended as a development environment for your
new MFE. If you start it with ``make dev.up.lms`` that should give you
everything you need as a companion to this frontend.
Note that it is also possible to use `Tutor`_ to develop an MFE. You can refer
to the `relevant tutor-mfe documentation`_ to get started using it.
.. _Devstack: https://github.com/openedx/devstack
`Tutor`_ is currently recommended as a development environment for the Authoring
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
Configuration
=============
All features that integrate into the edx-platform CMS require that the ``COURSE_AUTHORING_MICROFRONTEND_URL`` Django setting is set in the CMS environment and points to this MFE's deployment URL. This should be done automatically if you are using devstack or tutor-mfe.
Cloning and Setup
=================
Cloning and Startup
===================
1. Clone your new repo:
.. code-block:: bash
1. Clone the repo:
git clone https://github.com/openedx/frontend-app-authoring.git
``git clone https://github.com/openedx/frontend-app-course-authoring.git``
2. Use the version of Node specified in the ``.nvmrc`` file.
2. Use node v18.x.
The current version of the micro-frontend build scripts supports the version of Node found 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>`_.
The current version of the micro-frontend build scripts support node 18.
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 use`_.
3. Stop the Tutor devstack, if it's running: ``tutor dev stop``
3. Install npm dependencies:
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:
``cd frontend-app-course-authoring && npm install``
.. code-block:: bash
tutor mounts add /path/to/frontend-app-authoring
4. Start the dev server:
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 Authoring MFE, which we're going to run on the host instead of in a
container managed by Tutor. Run:
``npm start``
.. code-block:: bash
tutor dev start lms cms mfe
The dev server is running at `http://localhost:2001 <http://localhost:2001>`_.
or whatever port you setup.
Startup
=======
1. Install npm dependencies:
.. code-block:: bash
cd frontend-app-authoring && npm ci
2. Start the dev server:
.. code-block:: bash
npm run dev
Then you can access the app at http://apps.local.openedx.io:2001/course-authoring/home
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 authoring # We will run this MFE on the host
* If tutor-mfe is not starting the authoring MFE in development mode (eg. `tutor dev start authoring` fails), it may be due to
using a tutor version that expects the MFE name to be frontend-app-course-authoring (the previous name of this repo). To fix
this, you can rename the cloned repo directory to frontend-app-course-authoring. More information can be found in
`this forum post <https://discuss.openedx.org/t/repo-rename-frontend-app-course-authoring-frontend-app-authoring/13930/2>`__.
Features
@@ -129,32 +165,7 @@ Feature: New React XBlock Editors
.. image:: ./docs/readme-images/feature-problem-editor.png
This allows an operator to enable the use of new React editors for the HTML, Video, and Problem XBlocks, all of which are provided here.
Requirements
------------
* ``edx-platform`` Waffle flags:
* ``new_core_editors.use_new_text_editor``: must be enabled for the new HTML Xblock editor to be used in Studio
* ``new_core_editors.use_new_video_editor``: must be enabled for the new Video Xblock editor to be used in Studio
* ``new_core_editors.use_new_problem_editor``: must be enabled for the new Problem Xblock editor to be used in Studio
Configuration
-------------
In additional to the standard settings, the following local configuration item is required:
* ``ENABLE_NEW_EDITOR_PAGES``: must be enabled in order to actually present the new XBlock editors (on by default)
Feature Description
-------------------
When a corresponding waffle flag is set, upon editing a block in Studio, the view is rendered by this MFE instead of by the XBlock's authoring view. The user remains in Studio.
.. note::
The new editors themselves are currently implemented in a repository outside ``openedx``: `frontend-lib-content-components <https://github.com/edx/frontend-lib-content-components/>`_, a dependency of this MFE. This repository is slated to be moved to the ``openedx`` org, however.
New React editors for the HTML, Video, and Problem XBlocks are provided here and are rendered by this MFE instead of by the XBlock's authoring view.
Feature: New Proctoring Exams View
==================================
@@ -164,14 +175,6 @@ Feature: New Proctoring Exams View
Requirements
------------
* ``edx-platform`` Django settings:
* ``ZENDESK_*``: necessary if automatic ZenDesk ticket creation is desired
* ``edx-platform`` Feature flags:
* ``ENABLE_EXAM_SETTINGS_HTML_VIEW``: this feature flag must be enabled for the link to the settings view to be shown
* `edx-exams <https://github.com/edx/edx-exams>`_: for this feature to work, the ``edx-exams`` IDA must be deployed and its API accessible by the browser
Configuration
@@ -189,23 +192,12 @@ In Studio, a new item ("Proctored Exam Settings") is added to "Other Course Sett
* Enable proctored exams for the course
* Allow opting out of proctored exams
* Select a proctoring provider
* Enable automatic creation of Zendesk tickets for "suspicious" proctored exam attempts
Feature: Advanced Settings
==========================
.. image:: ./docs/readme-images/feature-advanced-settings.png
Requirements
------------
* ``edx-platform`` Waffle flags:
* ``contentstore.new_studio_mfe.use_new_advanced_settings_page``: this feature flag must be enabled for the link to the settings view to be shown. It can be enabled on a per-course basis.
Feature Description
-------------------
In Studio, the "Advanced Settings" page for each enabled course will now be served by this frontend, instead of the UI built into edx-platform. The advanced settings page holds many different settings for the course, such as what features or XBlocks are enabled.
Feature: Files & Uploads
@@ -213,16 +205,6 @@ Feature: Files & Uploads
.. image:: ./docs/readme-images/feature-files-uploads.png
Requirements
------------
* ``edx-platform`` Waffle flags:
* ``contentstore.new_studio_mfe.use_new_files_uploads_page``: this feature flag must be enabled for the link to the Files & Uploads page to go to the MFE. It can be enabled on a per-course basis.
Feature Description
-------------------
In Studio, the "Files & Uploads" page for each enabled course will now be served by this frontend, instead of the UI built into edx-platform. This page allows managing static asset files like PDFs, images, etc. used for the course.
Feature: Course Updates
@@ -230,26 +212,11 @@ Feature: Course Updates
.. image:: ./docs/readme-images/feature-course-updates.png
Requirements
------------
* ``edx-platform`` Waffle flags:
* ``contentstore.new_studio_mfe.use_new_updates_page``: this feature flag must be enabled.
Feature: Import/Export Pages
============================
.. image:: ./docs/readme-images/feature-export.png
Requirements
------------
* ``edx-platform`` Waffle flags:
* ``contentstore.new_studio_mfe.use_new_export_page``: this feature flag will change the CMS to link to the new export page.
* ``contentstore.new_studio_mfe.use_new_import_page``: this feature flag will change the CMS to link to the new import page.
Feature: Tagging/Taxonomy Pages
================================
@@ -267,13 +234,30 @@ Configuration
In additional to the standard settings, the following local configuration items are required:
* ``ENABLE_TAGGING_TAXONOMY_PAGES``: must be enabled in order to actually present the new Tagging/Taxonomy pages.
* ``ENABLE_TAGGING_TAXONOMY_PAGES``: must be enabled (which it is by default) in order to actually enable/show the new
Tagging/Taxonomy functionality.
Feature: Libraries V2/Legacy Tabs
=================================
Configuration
-------------
In additional to the standard settings, the following local configurations can be set to switch between different library modes:
* ``MEILISEARCH_ENABLED``: Studio setting which is enabled when the `meilisearch plugin`_ is installed.
* ``edx-platform`` Waffle flags:
* ``contentstore.new_studio_mfe.disable_legacy_libraries``: this feature flag must be OFF to show legacy Libraries V1
* ``contentstore.new_studio_mfe.disable_new_libraries``: this feature flag must be OFF to show Content Libraries V2
.. _meilisearch plugin: https://github.com/open-craft/tutor-contrib-meilisearch
Developing
**********
`Devstack <https://edx.readthedocs.io/projects/edx-installing-configuring-and-running/en/latest/installation/index.html>`_. If you start Devstack with ``make dev.up.studio`` that should give you everything you need as a companion to this frontend.
`Tutor <https://docs.tutor.edly.io/>`_ is the community-supported Open edX development environment. See the `tutor-mfe plugin README <https://github.com/overhangio/tutor-mfe?tab=readme-ov-file#mfe-development>`_ for more information.
If your devstack includes the default Demo course, you can visit the following URLs to see content:
@@ -284,7 +268,7 @@ Troubleshooting
========================
* ``npm ERR! gyp ERR! build error`` while running npm install on Macs with M1 processors: Probably due to a compatibility issue of node-canvas with M1.
Run ``brew install pkg-config pixman cairo pango libpng jpeg giflib librsvg`` before ``npm install`` to get the correct versions of the dependencies.
If there is still an error, look for "no package [...] found" in the error message and install missing package via brew.
(https://github.com/Automattic/node-canvas/issues/1733)
@@ -302,8 +286,8 @@ The production build is created with ``npm run build``.
:target: https://travis-ci.com/edx/frontend-app-course-authoring
.. |Codecov| image:: https://codecov.io/gh/edx/frontend-app-course-authoring/branch/master/graph/badge.svg
:target: https://codecov.io/gh/edx/frontend-app-course-authoring
.. |license| image:: https://img.shields.io/npm/l/@edx/frontend-app-course-authoring.svg
:target: @edx/frontend-app-course-authoring
.. |license| image:: https://img.shields.io/npm/l/@edx/frontend-app-authoring.svg
:target: @edx/frontend-app-authoring
Internationalization
====================
@@ -338,6 +322,20 @@ For more information about these options, see the `Getting Help`_ page.
.. _Getting Help: https://openedx.org/community/connect
Legacy Studio
*************
If you would like to use legacy studio for certain features, you can set the following waffle flags in ``edx-platform``:
* ``legacy_studio.text_editor``: loads the legacy HTML Xblock editor when editing a text block
* ``legacy_studio.video_editor``: loads the legacy Video editor when editing a video block
* ``legacy_studio.problem_editor``: loads the legacy Problem editor when editing a problem block
* ``legacy_studio.advanced_settings``: Advanced Settings page
* ``legacy_studio.updates``: Updates page
* ``legacy_studio.export``: Export page
* ``legacy_studio.import``: Import page
* ``legacy_studio.files_uploads``: Files page
* ``legacy_studio.exam_settings``: loads the legacy Exam Settings
License
*******

View File

@@ -4,15 +4,16 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: 'frontend-app-course-authoring'
description: "The frontend (MFE) for Open edX Course Authoring (aka Studio)"
name: 'frontend-app-authoring'
description: "The frontend (MFE) for Open edX Authoring (aka Studio)"
links:
- url: "https://github.com/openedx/frontend-app-course-authoring"
title: "Frontend app course authoring"
- url: "https://github.com/openedx/frontend-app-authoring"
title: "Frontend app authoring"
icon: "Web"
annotations:
openedx.org/arch-interest-groups: ""
openedx.org/release: "master"
spec:
owner: group:2u-tnl
owner: user:bradenmacdonald
type: 'website'
lifecycle: 'production'

View File

@@ -10,4 +10,6 @@ coverage:
threshold: 0%
ignore:
- "src/grading-settings/grading-scale/react-ranger.js"
- "src/generic/DraggableList/verticalSortableList.ts"
- "src/container-comparison/data/api.mock.ts"
- "src/index.js"

View File

@@ -0,0 +1,80 @@
Override External URLs
======================
What is getExternalLinkUrl?
---------------------------
The `getExternalLinkUrl` function is a utility from `@edx/frontend-platform` that allows for centralized management of external URLs. It enables the override of external links through configuration, making it possible to customize external references without modifying the source code directly.
URLs wrapped with getExternalLinkUrl
------------------------------------
Use cases:
1. **Accessibility Page** (`src/accessibility-page/AccessibilityPage.jsx`)
- `COMMUNITY_ACCESSIBILITY_LINK` - Points to community accessibility resources: https://www.edx.org/accessibility
2. **Course Outline** (if applicable)
- Documentation links
- Help resources
3. **Other pages** (search for `getExternalLinkUrl` usage across the codebase)
- Help documentation
- External tool integrations
Following external URLs are wrapped with `getExternalLinkUrl` in the authoring application:
- 'https://www.edx.org/accessibility'
- 'https://docs.openedx.org/en/latest/educators/concepts/exercise_tools/about_multi_select.html'
- 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_multi_select.html'
- 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_dropdown.html'
- 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/manage_numerical_input_problem.html'
- 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/add_text_input.html'
- 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/social_sharing.html'
- 'https://docs.openedx.org/en/latest/educators/references/course_development/exercise_tools/guide_problem_types.html#advanced-problem-types'
- 'https://docs.openedx.org/en/latest/educators/references/course_development/parent_child_components.html'
- 'https://openai.com/api-data-privacy'
- 'https://docs.openedx.org/en/latest/educators/how-tos/course_development/create_new_library.html'
- 'https://bigbluebutton.org/privacy-policy/'
- 'https://creativecommons.org/about'
Note: as new external URLs are added to the codebase, more URLs will be wrapped with `getExternalLinkUrl` and this list may not always be up to date.
How to Override External URLs
-----------------------------
To override external URLs, you can use the frontend platform's configuration system.
This object should be added to the config object defined in the env.config.[js,jsx,ts,tsx], and must be named externalLinkUrlOverrides.
1. **Environment Configuration**
Add the URL overrides to your environment configuration:
.. code-block:: javascript
const config = {
// Other config options...
externalLinkUrlOverrides: {
'https://www.edx.org/accessibility': 'https://your-custom-domain.com/accessibility',
// Add other URL overrides here
}
};
Examples
--------
**Original URL:** Default community accessibility link
**Override:** Your institution's accessibility policy page
.. code-block:: javascript
// In your app configuration
getExternalLinkUrl('https://www.edx.org/accessibility')
// Returns: 'https://your-custom-domain.com/accessibility'
// Instead of the default Open edX community link
Benefits
--------
- **Customization**: Institutions can point to their own resources
- **Maintainability**: URLs can be changed without code modifications
- **Consistency**: Centralized URL management across the application
- **Flexibility**: Different environments can have different external links

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

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

View File

@@ -11,9 +11,11 @@ module.exports = createConfig('jest', {
],
moduleNameMapper: {
'^lodash-es$': 'lodash',
// This alias is for any code in the src directory that wants to avoid '../../' style relative imports:
'^@src/(.*)$': '<rootDir>/src/$1',
// This alias is used for plugins in the plugins/ folder only.
'^CourseAuthoring/(.*)$': '<rootDir>/src/$1',
},
modulePathIgnorePatterns: [
'/src/pages-and-resources/utils.test.jsx',
],
});

View File

@@ -1,11 +0,0 @@
# This file describes this Open edX repo, as described in OEP-2:
# http://open-edx-proposals.readthedocs.io/en/latest/oeps/oep-0002.html#specification
nick: cath
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

20415
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,59 +1,57 @@
{
"name": "@edx/frontend-app-course-authoring",
"name": "@edx/frontend-app-authoring",
"version": "0.1.0",
"description": "Frontend application template",
"repository": {
"type": "git",
"url": "git+https://github.com/openedx/frontend-app-course-authoring.git"
"url": "git+https://github.com/openedx/frontend-app-authoring.git"
},
"browserslist": [
"extends @edx/browserslist-config"
],
"scripts": {
"build": "fedx-scripts webpack",
"i18n_extract": "fedx-scripts formatjs extract",
"stylelint": "stylelint \"src/**/*.scss\" \"scss/**/*.scss\" --config .stylelintrc.json",
"lint": "npm run stylelint && fedx-scripts eslint --ext .js --ext .jsx .",
"lint:fix": "npm run stylelint && fedx-scripts eslint --ext .js --ext .jsx . --fix",
"snapshot": "TZ=UTC fedx-scripts jest --updateSnapshot",
"i18n_extract": "fedx-scripts formatjs extract --include=plugins",
"stylelint": "stylelint \"plugins/**/*.scss\" \"src/**/*.scss\" \"scss/**/*.scss\" --config .stylelintrc.json",
"lint": "npm run stylelint && fedx-scripts eslint --ext .js --ext .jsx --ext .ts --ext .tsx .",
"oxlint": "oxlint --type-aware --deny-warnings",
"lint:fix": "npm run stylelint -- --fix && fedx-scripts eslint --fix --ext .js --ext .jsx --ext .ts --ext .tsx .",
"start": "fedx-scripts webpack-dev-server --progress",
"start:with-theme": "paragon install-theme && npm start && npm install",
"dev": "PUBLIC_PATH=/authoring/ MFE_CONFIG_API_URL='http://localhost:8000/api/mfe_config/v1' fedx-scripts webpack-dev-server --progress --host apps.local.openedx.io",
"test": "TZ=UTC fedx-scripts jest --coverage --passWithNoTests",
"test:ci": "TZ=UTC fedx-scripts jest --silent --coverage --passWithNoTests",
"types": "tsc --noEmit"
},
"husky": {
"hooks": {
"pre-commit": "npm run lint"
}
},
"author": "edX",
"license": "AGPL-3.0",
"homepage": "https://github.com/openedx/frontend-app-course-authoring#readme",
"homepage": "https://github.com/openedx/frontend-app-authoring#readme",
"publishConfig": {
"access": "public"
},
"bugs": {
"url": "https://github.com/openedx/frontend-app-course-authoring/issues"
"url": "https://github.com/openedx/frontend-app-authoring/issues"
},
"dependencies": {
"@codemirror/lang-html": "^6.0.0",
"@codemirror/lang-markdown": "^6.0.0",
"@codemirror/lang-xml": "^6.0.0",
"@codemirror/lint": "^6.2.1",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/modifiers": "^7.0.0",
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
"@edx/frontend-component-ai-translations": "^2.0.0",
"@edx/frontend-component-footer": "^13.0.2",
"@edx/frontend-component-header": "^5.0.2",
"@edx/frontend-enterprise-hotjar": "^2.0.0",
"@edx/frontend-lib-content-components": "^2.1.4",
"@edx/frontend-platform": "7.0.1",
"@edx/openedx-atlas": "^0.6.0",
"@fortawesome/fontawesome-svg-core": "1.2.36",
"@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.2.0",
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.3",
"@edx/browserslist-config": "1.5.1",
"@edx/frontend-component-footer": "^14.9.0",
"@edx/frontend-component-header": "^8.1.0",
"@edx/frontend-enterprise-hotjar": "^7.2.0",
"@edx/frontend-platform": "^8.4.0",
"@edx/openedx-atlas": "^0.7.0",
"@openedx-plugins/course-app-calculator": "file:plugins/course-apps/calculator",
"@openedx-plugins/course-app-dates": "file:plugins/course-apps/dates",
"@openedx-plugins/course-app-edxnotes": "file:plugins/course-apps/edxnotes",
"@openedx-plugins/course-app-learning_assistant": "file:plugins/course-apps/learning_assistant",
"@openedx-plugins/course-app-live": "file:plugins/course-apps/live",
@@ -63,59 +61,66 @@
"@openedx-plugins/course-app-teams": "file:plugins/course-apps/teams",
"@openedx-plugins/course-app-wiki": "file:plugins/course-apps/wiki",
"@openedx-plugins/course-app-xpert_unit_summary": "file:plugins/course-apps/xpert_unit_summary",
"@openedx/paragon": "^21.5.7",
"@reduxjs/toolkit": "1.9.7",
"@tanstack/react-query": "4.36.1",
"broadcast-channel": "^7.0.0",
"classnames": "2.2.6",
"core-js": "3.8.1",
"@openedx/frontend-build": "^14.6.2",
"@openedx/frontend-plugin-framework": "^1.8.0",
"@openedx/paragon": "^23.5.0",
"@redux-devtools/extension": "^3.3.0",
"@reduxjs/toolkit": "2.11.2",
"@tanstack/react-query": "5.90.21",
"@tinymce/tinymce-react": "^6.0.0",
"classnames": "2.5.1",
"codemirror": "^6.0.0",
"email-validator": "2.0.4",
"fast-xml-parser": "^5.0.0",
"file-saver": "^2.0.5",
"formik": "2.2.6",
"formik": "2.4.9",
"frontend-components-tinymce-advanced-plugins": "^1.0.3",
"jszip": "^3.10.1",
"lodash": "4.17.21",
"moment": "2.29.4",
"prop-types": "15.7.2",
"react": "17.0.2",
"react-datepicker": "^4.13.0",
"react-dom": "17.0.2",
"lodash": "4.17.23",
"meilisearch": "^0.41.0",
"moment": "2.30.1",
"moment-shortformat": "^2.1.0",
"prop-types": "^15.8.1",
"react": "^18.3.1",
"react-datepicker": "^8.10.0",
"react-dom": "^18.3.1",
"react-error-boundary": "^4.0.13",
"react-helmet": "^6.1.0",
"react-onclickoutside": "^6.13.0",
"react-redux": "7.2.9",
"react-responsive": "9.0.2",
"react-router": "6.16.0",
"react-router-dom": "6.16.0",
"react-select": "5.8.0",
"react-textarea-autosize": "^8.4.1",
"react-responsive": "10.0.1",
"react-router": "6.30.3",
"react-router-dom": "6.30.3",
"react-select": "5.10.2",
"react-textarea-autosize": "^8.5.3",
"react-transition-group": "4.4.5",
"redux": "4.0.5",
"regenerator-runtime": "0.13.7",
"universal-cookie": "^4.0.4",
"uuid": "^3.4.0",
"yup": "0.31.1"
"redux": "4.2.1",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.4.1",
"reselect": "^4.1.5",
"tinymce": "^5.10.4",
"universal-cookie": "^8.0.0",
"uuid": "^11.1.0",
"xmlchecker": "^0.1.0",
"yup": "0.32.11"
},
"devDependencies": {
"@edx/browserslist-config": "1.2.0",
"@edx/react-unit-test-utils": "^2.0.0",
"@edx/reactifex": "^1.0.3",
"@edx/stylelint-config-edx": "2.3.0",
"@edx/stylelint-config-edx": "2.3.3",
"@edx/typescript-config": "^1.0.1",
"@openedx/frontend-build": "13.0.27",
"@testing-library/jest-dom": "5.17.0",
"@testing-library/react": "12.1.5",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^13.2.1",
"axios": "^0.27.2",
"axios-mock-adapter": "1.22.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.1",
"@types/lodash": "^4.17.17",
"@types/react": "^18",
"@types/react-dom": "^18",
"axios-mock-adapter": "2.1.0",
"eslint-import-resolver-webpack": "^0.13.8",
"glob": "7.2.3",
"husky": "7.0.4",
"fetch-mock-jest": "^1.5.1",
"jest-canvas-mock": "^2.5.2",
"jest-expect-message": "^1.1.3",
"react-test-renderer": "17.0.2",
"reactifex": "1.1.1",
"ts-loader": "^9.5.0"
},
"peerDependencies": {
"decode-uri-component": ">=0.2.2"
"oxlint": "^1.42.0",
"oxlint-tsgolint": "^0.16.0",
"react-test-renderer": "^18.3.1",
"redux-mock-store": "^1.5.4"
}
}

View File

@@ -3,14 +3,14 @@
"version": "0.1.0",
"description": "Calculator configuration for courses using it",
"peerDependencies": {
"@edx/frontend-app-course-authoring": "*",
"@edx/frontend-app-authoring": "*",
"@edx/frontend-platform": "*",
"@openedx/paragon": "*",
"prop-types": "*",
"react": "*"
},
"peerDependenciesMeta": {
"@edx/frontend-app-course-authoring": {
"@edx/frontend-app-authoring": {
"optional": true
}
}

View File

@@ -0,0 +1,29 @@
import React from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import AppSettingsModal from 'CourseAuthoring/pages-and-resources/app-settings-modal/AppSettingsModal';
import messages from './messages';
type DatesSettingsProps = {
onClose: () => void;
};
const DatesSettings: React.FC<DatesSettingsProps> = ({ onClose }) => {
const intl = useIntl();
return (
<AppSettingsModal
appId="dates"
title={intl.formatMessage(messages.heading)}
enableAppHelp={intl.formatMessage(messages.enableAppHelp)}
enableAppLabel={intl.formatMessage(messages.enableAppLabel)}
learnMoreText={intl.formatMessage(messages.learnMore)}
onClose={onClose}
validationSchema={{}}
initialValues={{}}
onSettingsSave={async () => true}
/>
);
};
export default DatesSettings;

View File

@@ -0,0 +1,26 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
heading: {
id: 'course-authoring.pages-resources.dates.heading',
defaultMessage: 'Configure dates',
description: 'Heading for the Dates settings modal shown in Pages & Resources.',
},
enableAppLabel: {
id: 'course-authoring.pages-resources.dates.enable-app.label',
defaultMessage: 'Dates',
description: 'Label for the toggle that enables the Dates experience.',
},
enableAppHelp: {
id: 'course-authoring.pages-resources.dates.enable-app.help',
defaultMessage: 'Show the Dates tab in course navigation, where learners can view important course dates.',
description: 'Helper text explaining what enabling the Dates experience does.',
},
learnMore: {
id: 'course-authoring.pages-resources.dates.learn-more',
defaultMessage: 'Learn more about dates',
description: 'Link text that leads to documentation about the Dates experience.',
},
});
export default messages;

View File

@@ -0,0 +1,17 @@
{
"name": "@openedx-plugins/course-app-dates",
"version": "0.1.0",
"description": "Dates configuration for courses using it",
"peerDependencies": {
"@edx/frontend-app-authoring": "*",
"@edx/frontend-platform": "*",
"@openedx/paragon": "*",
"prop-types": "*",
"react": "*"
},
"peerDependenciesMeta": {
"@edx/frontend-app-authoring": {
"optional": true
}
}
}

View File

@@ -3,14 +3,14 @@
"version": "0.1.0",
"description": "edxnotes configuration for courses using it",
"peerDependencies": {
"@edx/frontend-app-course-authoring": "*",
"@edx/frontend-app-authoring": "*",
"@edx/frontend-platform": "*",
"@openedx/paragon": "*",
"prop-types": "*",
"react": "*"
},
"peerDependenciesMeta": {
"@edx/frontend-app-course-authoring": {
"@edx/frontend-app-authoring": {
"optional": true
}
}

View File

@@ -2,16 +2,12 @@ import React from 'react';
import { screen, waitFor } from '@testing-library/react';
import { RequestStatus } from 'CourseAuthoring/data/constants';
import { render } from 'CourseAuthoring/pages-and-resources/utils.test';
import { initializeMocks, render } from 'CourseAuthoring/testUtils';
import LearningAssistantSettings from './Settings';
const onClose = () => { };
describe('Learning Assistant Settings', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('renders', async () => {
const initialState = {
models: {
@@ -38,14 +34,8 @@ describe('Learning Assistant Settings', () => {
},
};
render(
<LearningAssistantSettings
onClose={onClose}
/>,
{
preloadedState: initialState,
},
);
initializeMocks({ initialState });
render(<LearningAssistantSettings onClose={onClose} />);
const toggleDescription = 'Reinforce learning concepts by sharing text-based course content '
+ 'with OpenAI (via API) to power an in-course Learning Assistant. Learners can leave feedback about the quality '

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"description": "Learning Assistant configuration for courses using it",
"peerDependencies": {
"@edx/frontend-app-course-authoring": "*",
"@edx/frontend-app-authoring": "*",
"@edx/frontend-platform": "*",
"@openedx/paragon": "*",
"prop-types": "*",
@@ -11,7 +11,7 @@
"yup": "*"
},
"peerDependenciesMeta": {
"@edx/frontend-app-course-authoring": {
"@edx/frontend-app-authoring": {
"optional": true
}
}

View File

@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import { getConfig } from '@edx/frontend-platform';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { getConfig, getExternalLinkUrl } from '@edx/frontend-platform';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import { Form, Hyperlink } from '@openedx/paragon';
import PropTypes from 'prop-types';
import AppConfigFormDivider from 'CourseAuthoring/pages-and-resources/discussions/app-config-form/apps/shared/AppConfigFormDivider';
@@ -11,10 +11,10 @@ import LiveCommonFields from './LiveCommonFields';
import messages from './messages';
const BbbSettings = ({
intl,
values,
setFieldValue,
}) => {
const intl = useIntl();
const [bbbPlan, setBbbPlan] = useState(values.tierType);
useEffect(() => {
@@ -93,7 +93,7 @@ const BbbSettings = ({
<span data-testid="free-plan-message">
{intl.formatMessage(messages.freePlanMessage)}
<Hyperlink
destination="https://bigbluebutton.org/privacy-policy/"
destination={getExternalLinkUrl('https://bigbluebutton.org/privacy-policy/')}
target="_blank"
rel="noopener noreferrer"
showLaunchIcon
@@ -107,12 +107,10 @@ const BbbSettings = ({
)}
</>
</>
);
};
BbbSettings.propTypes = {
intl: intlShape.isRequired,
values: PropTypes.shape({
consumerKey: PropTypes.string,
consumerSecret: PropTypes.string,
@@ -127,4 +125,4 @@ BbbSettings.propTypes = {
setFieldValue: PropTypes.func.isRequired,
};
export default injectIntl(BbbSettings);
export default BbbSettings;

View File

@@ -4,21 +4,16 @@ import {
getByRole,
getAllByRole,
waitForElementToBeRemoved,
} from '@testing-library/react';
initializeMocks,
} from 'CourseAuthoring/testUtils';
import ReactDOM from 'react-dom';
import { Routes, Route, MemoryRouter } from 'react-router-dom';
import { initializeMockApp } from '@edx/frontend-platform';
import MockAdapter from 'axios-mock-adapter';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider, PageWrap } from '@edx/frontend-platform/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import userEvent from '@testing-library/user-event';
import initializeStore from 'CourseAuthoring/store';
import { executeThunk } from 'CourseAuthoring/utils';
import PagesAndResourcesProvider from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
import { CourseAuthoringProvider } from 'CourseAuthoring/CourseAuthoringContext';
import LiveSettings from './Settings';
import {
generateLiveConfigurationApiResponse,
@@ -40,17 +35,20 @@ ReactDOM.createPortal = jest.fn(node => node);
const renderComponent = () => {
const wrapper = render(
<IntlProvider locale="en">
<AppProvider store={store} wrapWithRouter={false}>
<PagesAndResourcesProvider courseId={courseId}>
<MemoryRouter initialEntries={[liveSettingsUrl]}>
<Routes>
<Route path={liveSettingsUrl} element={<PageWrap><LiveSettings onClose={() => {}} /></PageWrap>} />
</Routes>
</MemoryRouter>
</PagesAndResourcesProvider>
</AppProvider>
</IntlProvider>,
<CourseAuthoringProvider courseId={courseId}>
<PagesAndResourcesProvider courseId={courseId}>
<LiveSettings onClose={() => {}} />
</PagesAndResourcesProvider>
</CourseAuthoringProvider>,
{
path: liveSettingsUrl,
routerProps: {
initialEntries: [liveSettingsUrl],
},
params: {
courseId,
},
},
);
container = wrapper.container;
};
@@ -74,16 +72,9 @@ const mockStore = async ({
describe('BBB Settings', () => {
beforeEach(async () => {
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: false,
roles: [],
},
});
store = initializeStore(initialState);
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
const mocks = initializeMocks({ initialState });
store = mocks.reduxStore;
axiosMock = mocks.axiosMock;
});
test('Plan dropdown to be visible and enabled in UI', async () => {
@@ -124,12 +115,13 @@ describe('BBB Settings', () => {
);
test('free plans message is visible when free plan is selected', async () => {
const user = userEvent.setup();
await mockStore({ emailSharing: true, isFreeTier: true });
renderComponent();
const spinner = getByRole(container, 'status');
await waitForElementToBeRemoved(spinner);
const dropDown = container.querySelector('select[name="tierType"]');
userEvent.selectOptions(
await user.selectOptions(
dropDown,
getByRole(dropDown, 'option', { name: 'Free' }),
);

View File

@@ -1,42 +1,43 @@
import React from 'react';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import FormikControl from 'CourseAuthoring/generic/FormikControl';
import messages from './messages';
const LiveCommonFields = ({
intl,
values,
}) => (
<>
<p className="pb-2">{intl.formatMessage(messages.formInstructions)}</p>
<FormikControl
name="consumerKey"
value={values.consumerKey}
floatingLabel={intl.formatMessage(messages.consumerKey)}
className="pb-1"
type="input"
/>
<FormikControl
name="consumerSecret"
value={values.consumerSecret}
floatingLabel={intl.formatMessage(messages.consumerSecret)}
className="pb-1"
type="password"
/>
<FormikControl
name="launchUrl"
value={values.launchUrl}
floatingLabel={intl.formatMessage(messages.launchUrl)}
className="pb-1"
type="input"
/>
</>
);
}) => {
const intl = useIntl();
return (
<>
<p className="pb-2">{intl.formatMessage(messages.formInstructions)}</p>
<FormikControl
name="consumerKey"
value={values.consumerKey}
floatingLabel={intl.formatMessage(messages.consumerKey)}
className="pb-1"
type="input"
/>
<FormikControl
name="consumerSecret"
value={values.consumerSecret}
floatingLabel={intl.formatMessage(messages.consumerSecret)}
className="pb-1"
type="password"
/>
<FormikControl
name="launchUrl"
value={values.launchUrl}
floatingLabel={intl.formatMessage(messages.launchUrl)}
className="pb-1"
type="input"
/>
</>
);
};
LiveCommonFields.propTypes = {
intl: intlShape.isRequired,
values: PropTypes.shape({
consumerKey: PropTypes.string,
consumerSecret: PropTypes.string,
@@ -45,4 +46,4 @@ LiveCommonFields.propTypes = {
}).isRequired,
};
export default injectIntl(LiveCommonFields);
export default LiveCommonFields;

View File

@@ -1,16 +1,18 @@
// oxlint-disable unicorn/no-thenable
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { camelCase } from 'lodash';
import { Icon } from '@openedx/paragon';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { SelectableBox } from '@edx/frontend-lib-content-components';
import { useIntl } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import * as Yup from 'yup';
import { useNavigate } from 'react-router-dom';
import SelectableBox from 'CourseAuthoring/editors/sharedComponents/SelectableBox';
import AppSettingsModal from 'CourseAuthoring/pages-and-resources/app-settings-modal/AppSettingsModal';
import { useModel } from 'CourseAuthoring/generic/model-store';
import Loading from 'CourseAuthoring/generic/Loading';
import { RequestStatus } from 'CourseAuthoring/data/constants';
import { useCourseAuthoringContext } from 'CourseAuthoring/CourseAuthoringContext';
import { fetchLiveData, saveLiveConfiguration, saveLiveConfigurationAsDraft } from './data/thunks';
import { selectApp } from './data/slice';
@@ -20,12 +22,12 @@ import ZoomSettings from './ZoomSettings';
import BBBSettings from './BBBSettings';
const LiveSettings = ({
intl,
onClose,
}) => {
const intl = useIntl();
const navigate = useNavigate();
const dispatch = useDispatch();
const courseId = useSelector(state => state.courseDetail.courseId);
const { courseId } = useCourseAuthoringContext();
const availableProviders = useSelector((state) => state.live.appIds);
const {
piiSharingAllowed, selectedAppId, enabled, status,
@@ -71,6 +73,7 @@ const LiveSettings = ({
};
const handleSettingsSave = async (values) => {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
await dispatch(saveLiveConfiguration(courseId, values, navigate));
};
@@ -130,8 +133,7 @@ const LiveSettings = ({
};
LiveSettings.propTypes = {
intl: intlShape.isRequired,
onClose: PropTypes.func.isRequired,
};
export default injectIntl(LiveSettings);
export default LiveSettings;

View File

@@ -8,20 +8,14 @@ import {
queryByText,
getByRole,
waitForElementToBeRemoved,
} from '@testing-library/react';
initializeMocks,
} from 'CourseAuthoring/testUtils';
import ReactDOM from 'react-dom';
import { Routes, Route, MemoryRouter } from 'react-router-dom';
import { initializeMockApp } from '@edx/frontend-platform';
import MockAdapter from 'axios-mock-adapter';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider, PageWrap } from '@edx/frontend-platform/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import initializeStore from 'CourseAuthoring/store';
import { executeThunk } from 'CourseAuthoring/utils';
import PagesAndResourcesProvider from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
import { CourseAuthoringProvider } from 'CourseAuthoring/CourseAuthoringContext';
import LiveSettings from './Settings';
import {
generateLiveConfigurationApiResponse,
@@ -44,17 +38,20 @@ ReactDOM.createPortal = jest.fn(node => node);
const renderComponent = () => {
const wrapper = render(
<IntlProvider locale="en">
<AppProvider store={store} wrapWithRouter={false}>
<PagesAndResourcesProvider courseId={courseId}>
<MemoryRouter initialEntries={[liveSettingsUrl]}>
<Routes>
<Route path={liveSettingsUrl} element={<PageWrap><LiveSettings onClose={() => {}} /></PageWrap>} />
</Routes>
</MemoryRouter>
</PagesAndResourcesProvider>
</AppProvider>
</IntlProvider>,
<PagesAndResourcesProvider courseId={courseId}>
<CourseAuthoringProvider>
<LiveSettings onClose={() => {}} />
</CourseAuthoringProvider>
</PagesAndResourcesProvider>,
{
path: liveSettingsUrl,
routerProps: {
initialEntries: [liveSettingsUrl],
},
params: {
courseId,
},
},
);
container = wrapper.container;
};
@@ -77,16 +74,11 @@ const mockStore = async ({
describe('LiveSettings', () => {
beforeEach(async () => {
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: false,
roles: [],
},
const mocks = initializeMocks({
initialState,
});
store = initializeStore(initialState);
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
store = mocks.reduxStore;
axiosMock = mocks.axiosMock;
});
test('Live Configuration modal is visible', async () => {

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import FormikControl from 'CourseAuthoring/generic/FormikControl';
@@ -8,37 +8,38 @@ import { providerNames } from './constants';
import LiveCommonFields from './LiveCommonFields';
const ZoomSettings = ({
intl,
values,
}) => (
// eslint-disable-next-line react/jsx-no-useless-fragment
<>
{!values.piiSharingEnable ? (
<p data-testid="request-pii-sharing">
{intl.formatMessage(messages.requestPiiSharingEnable, { provider: providerNames[values.provider] })}
</p>
) : (
<>
{(values.piiSharingEmail || values.piiSharingUsername)
&& (
<p data-testid="helper-text">
{intl.formatMessage(messages.providerHelperText, { providerName: providerNames[values.provider] })}
</p>
)}
<LiveCommonFields values={values} />
<FormikControl
name="launchEmail"
value={values.launchEmail}
floatingLabel={intl.formatMessage(messages.launchEmail)}
type="input"
/>
</>
)}
</>
);
}) => {
const intl = useIntl();
return (
// eslint-disable-next-line react/jsx-no-useless-fragment
<>
{!values.piiSharingEnable ? (
<p data-testid="request-pii-sharing">
{intl.formatMessage(messages.requestPiiSharingEnable, { provider: providerNames[values.provider] })}
</p>
) : (
<>
{(values.piiSharingEmail || values.piiSharingUsername)
&& (
<p data-testid="helper-text">
{intl.formatMessage(messages.providerHelperText, { providerName: providerNames[values.provider] })}
</p>
)}
<LiveCommonFields values={values} />
<FormikControl
name="launchEmail"
value={values.launchEmail}
floatingLabel={intl.formatMessage(messages.launchEmail)}
type="input"
/>
</>
)}
</>
);
};
ZoomSettings.propTypes = {
intl: intlShape.isRequired,
values: PropTypes.shape({
consumerKey: PropTypes.string,
consumerSecret: PropTypes.string,
@@ -51,4 +52,4 @@ ZoomSettings.propTypes = {
}).isRequired,
};
export default injectIntl(ZoomSettings);
export default ZoomSettings;

View File

@@ -3,19 +3,14 @@ import {
queryByTestId,
getByRole,
waitForElementToBeRemoved,
} from '@testing-library/react';
initializeMocks,
} from 'CourseAuthoring/testUtils';
import ReactDOM from 'react-dom';
import { Routes, Route, MemoryRouter } from 'react-router-dom';
import { initializeMockApp } from '@edx/frontend-platform';
import MockAdapter from 'axios-mock-adapter';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider, PageWrap } from '@edx/frontend-platform/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import initializeStore from 'CourseAuthoring/store';
import { executeThunk } from 'CourseAuthoring/utils';
import PagesAndResourcesProvider from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
import { CourseAuthoringProvider } from 'CourseAuthoring/CourseAuthoringContext';
import LiveSettings from './Settings';
import {
generateLiveConfigurationApiResponse,
@@ -38,17 +33,20 @@ ReactDOM.createPortal = jest.fn(node => node);
const renderComponent = () => {
const wrapper = render(
<IntlProvider locale="en">
<AppProvider store={store} wrapWithRouter={false}>
<PagesAndResourcesProvider courseId={courseId}>
<MemoryRouter initialEntries={[liveSettingsUrl]}>
<Routes>
<Route path={liveSettingsUrl} element={<PageWrap><LiveSettings onClose={() => {}} /></PageWrap>} />
</Routes>
</MemoryRouter>
</PagesAndResourcesProvider>
</AppProvider>
</IntlProvider>,
<CourseAuthoringProvider courseId={courseId}>
<PagesAndResourcesProvider courseId={courseId}>
<LiveSettings onClose={() => {}} />
</PagesAndResourcesProvider>
</CourseAuthoringProvider>,
{
path: liveSettingsUrl,
routerProps: {
initialEntries: [liveSettingsUrl],
},
params: {
courseId,
},
},
);
container = wrapper.container;
};
@@ -71,16 +69,9 @@ const mockStore = async ({
describe('Zoom Settings', () => {
beforeEach(async () => {
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: false,
roles: [],
},
});
store = initializeStore(initialState);
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
const mocks = initializeMocks({ initialState });
store = mocks.reduxStore;
axiosMock = mocks.axiosMock;
});
test('LTI fields are visible when pii sharing is enabled', async () => {

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { ensureConfig, getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { bbbPlanTypes } from '../constants';

View File

@@ -3,8 +3,7 @@
"version": "0.1.0",
"description": "Live course configuration for courses using it",
"peerDependencies": {
"@edx/frontend-app-course-authoring": "*",
"@edx/frontend-lib-content-components": "*",
"@edx/frontend-app-authoring": "*",
"@edx/frontend-platform": "*",
"@openedx/paragon": "*",
"@reduxjs/toolkit": "*",
@@ -16,7 +15,7 @@
"yup": "*"
},
"peerDependenciesMeta": {
"@edx/frontend-app-course-authoring": {
"@edx/frontend-app-authoring": {
"optional": true
}
}

View File

@@ -1,69 +1,177 @@
import React from 'react';
import { useEffect, useState, useRef } from 'react';
import PropTypes from 'prop-types';
import * as Yup from 'yup';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useDispatch, useSelector } from 'react-redux';
import { Hyperlink } from '@openedx/paragon';
import { useModel } from 'CourseAuthoring/generic/model-store';
import {
ActionRow, Alert, Badge, Form, Hyperlink, ModalDialog, StatefulButton,
} from '@openedx/paragon';
import { Info } from '@openedx/paragon/icons';
import { updateModel, useModel } from 'CourseAuthoring/generic/model-store';
import { RequestStatus } from 'CourseAuthoring/data/constants';
import FormSwitchGroup from 'CourseAuthoring/generic/FormSwitchGroup';
import { useAppSetting } from 'CourseAuthoring/utils';
import AppSettingsModal from 'CourseAuthoring/pages-and-resources/app-settings-modal/AppSettingsModal';
import Loading from 'CourseAuthoring/generic/Loading';
import PermissionDeniedAlert from 'CourseAuthoring/generic/PermissionDeniedAlert';
import ConnectionErrorAlert from 'CourseAuthoring/generic/ConnectionErrorAlert';
import { useAppSetting, useIsMobile } from 'CourseAuthoring/utils';
import { getLoadingStatus, getSavingStatus } from 'CourseAuthoring/pages-and-resources/data/selectors';
import { updateSavingStatus } from 'CourseAuthoring/pages-and-resources/data/slice';
import messages from './messages';
const ORASettings = ({ intl, onClose }) => {
const ORASettings = ({ onClose }) => {
const dispatch = useDispatch();
const { formatMessage } = useIntl();
const alertRef = useRef(null);
const updateSettingsRequestStatus = useSelector(getSavingStatus);
const loadingStatus = useSelector(getLoadingStatus);
const isMobile = useIsMobile();
const modalVariant = isMobile ? 'dark' : 'default';
const appId = 'ora_settings';
const appInfo = useModel('courseApps', appId);
const [enableFlexiblePeerGrade, saveSetting] = useAppSetting(
'forceOnFlexiblePeerOpenassessments',
);
const initialFormValues = { enableFlexiblePeerGrade };
const [formValues, setFormValues] = useState(initialFormValues);
const [saveError, setSaveError] = useState(false);
const submitButtonState = updateSettingsRequestStatus === RequestStatus.IN_PROGRESS ? 'pending' : 'default';
const handleSettingsSave = (values) => saveSetting(values.enableFlexiblePeerGrade);
const title = (
<div>
<p>{intl.formatMessage(messages.heading)}</p>
<div className="pt-3">
<Hyperlink
className="text-primary-500 small"
destination={appInfo.documentationLinks?.learnMoreConfiguration}
target="_blank"
rel="noreferrer noopener"
>
{intl.formatMessage(messages.ORASettingsHelpLink)}
</Hyperlink>
</div>
</div>
);
const handleSubmit = async (event) => {
let success = true;
event.preventDefault();
success = success && await handleSettingsSave(formValues);
setSaveError(!success);
if ((initialFormValues.enableFlexiblePeerGrade !== formValues.enableFlexiblePeerGrade) && success) {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
success = await dispatch(updateModel({
modelType: 'courseApps',
model: {
id: appId, enabled: formValues.enableFlexiblePeerGrade,
},
}));
}
!success && alertRef?.current.scrollIntoView(); // eslint-disable-line @typescript-eslint/no-unused-expressions
};
const handleChange = (e) => {
setFormValues({ enableFlexiblePeerGrade: e.target.checked });
};
useEffect(() => {
if (updateSettingsRequestStatus === RequestStatus.SUCCESSFUL) {
dispatch(updateSavingStatus({ status: '' }));
onClose();
}
}, [updateSettingsRequestStatus]);
const renderBody = () => {
switch (loadingStatus) {
case RequestStatus.SUCCESSFUL:
return (
<>
{saveError && (
<Alert variant="danger" icon={Info} ref={alertRef}>
<Alert.Heading>
{formatMessage(messages.errorSavingTitle)}
</Alert.Heading>
{formatMessage(messages.errorSavingMessage)}
</Alert>
)}
<FormSwitchGroup
id="enable-flexible-peer-grade"
name="enableFlexiblePeerGrade"
label={(
<div className="d-flex align-items-center">
{formatMessage(messages.enableFlexPeerGradeLabel)}
{formValues.enableFlexiblePeerGrade && (
<Badge className="ml-2" variant="success" data-testid="enable-badge">
{formatMessage(messages.enabledBadgeLabel)}
</Badge>
)}
</div>
)}
helpText={(
<div>
<p>{formatMessage(messages.enableFlexPeerGradeHelp)}</p>
<span className="py-3">
<Hyperlink
className="text-primary-500 small"
destination={appInfo.documentationLinks?.learnMoreConfiguration}
target="_blank"
rel="noreferrer noopener"
>
{formatMessage(messages.ORASettingsHelpLink)}
</Hyperlink>
</span>
</div>
)}
onChange={handleChange}
checked={formValues.enableFlexiblePeerGrade}
/>
</>
);
case RequestStatus.DENIED:
return <PermissionDeniedAlert />;
case RequestStatus.FAILED:
return <ConnectionErrorAlert />;
default:
return <Loading />;
}
};
return (
<AppSettingsModal
appId={appId}
title={title}
<ModalDialog
title={formatMessage(messages.heading)}
isOpen
onClose={onClose}
initialValues={{ enableFlexiblePeerGrade }}
validationSchema={{ enableFlexiblePeerGrade: Yup.boolean() }}
onSettingsSave={handleSettingsSave}
hideAppToggle
size="lg"
variant={modalVariant}
hasCloseButton={isMobile}
isFullscreenScroll
isFullscreenOnMobile
>
{({ values, handleChange, handleBlur }) => (
<FormSwitchGroup
id="enable-flexible-peer-grade"
name="enableFlexiblePeerGrade"
label={intl.formatMessage(messages.enableFlexPeerGradeLabel)}
helpText={intl.formatMessage(messages.enableFlexPeerGradeHelp)}
onChange={handleChange}
onBlur={handleBlur}
checked={values.enableFlexiblePeerGrade}
/>
)}
</AppSettingsModal>
<Form onSubmit={handleSubmit} data-testid="proctoringForm">
<ModalDialog.Header>
<ModalDialog.Title>
{formatMessage(messages.heading)}
</ModalDialog.Title>
</ModalDialog.Header>
<ModalDialog.Body>
{renderBody()}
</ModalDialog.Body>
<ModalDialog.Footer className="p-4">
<ActionRow>
<ModalDialog.CloseButton variant="tertiary">
{formatMessage(messages.cancelLabel)}
</ModalDialog.CloseButton>
<StatefulButton
labels={{
default: formatMessage(messages.saveLabel),
pending: formatMessage(messages.pendingSaveLabel),
}}
description="Form save button"
data-testid="submissionButton"
disabled={submitButtonState === RequestStatus.IN_PROGRESS}
state={submitButtonState}
type="submit"
/>
</ActionRow>
</ModalDialog.Footer>
</Form>
</ModalDialog>
);
};
ORASettings.propTypes = {
intl: intlShape.isRequired,
onClose: PropTypes.func.isRequired,
};
export default injectIntl(ORASettings);
export default ORASettings;

View File

@@ -1,33 +1,155 @@
import { shallow } from '@edx/react-unit-test-utils';
import {
render,
screen,
waitFor,
within,
} from '@testing-library/react';
import ReactDOM from 'react-dom';
import { Routes, Route, MemoryRouter } from 'react-router-dom';
import { initializeMockApp } from '@edx/frontend-platform';
import MockAdapter from 'axios-mock-adapter';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider, PageWrap } from '@edx/frontend-platform/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import initializeStore from 'CourseAuthoring/store';
import { executeThunk } from 'CourseAuthoring/utils';
import PagesAndResourcesProvider from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
import { getCourseAppsApiUrl, getCourseAdvancedSettingsApiUrl } from 'CourseAuthoring/pages-and-resources/data/api';
import { fetchCourseApps, fetchCourseAppSettings } from 'CourseAuthoring/pages-and-resources/data/thunks';
import ORASettings from './Settings';
import messages from './messages';
import {
courseId,
inititalState,
} from './factories/mockData';
jest.mock('@edx/frontend-platform/i18n', () => ({
...jest.requireActual('@edx/frontend-platform/i18n'), // use actual for all non-hook parts
injectIntl: (component) => component,
intlShape: {},
}));
jest.mock('yup', () => ({
boolean: jest.fn().mockReturnValue('Yub.boolean'),
}));
jest.mock('CourseAuthoring/generic/model-store', () => ({
useModel: jest.fn().mockReturnValue({ documentationLinks: { learnMoreConfiguration: 'https://learnmore.test' } }),
}));
jest.mock('CourseAuthoring/generic/FormSwitchGroup', () => 'FormSwitchGroup');
jest.mock('CourseAuthoring/utils', () => ({
useAppSetting: jest.fn().mockReturnValue(['abitrary value', jest.fn().mockName('saveSetting')]),
}));
jest.mock('CourseAuthoring/pages-and-resources/app-settings-modal/AppSettingsModal', () => 'AppSettingsModal');
let axiosMock;
let store;
const oraSettingsUrl = `/course/${courseId}/pages-and-resources/live/settings`;
const props = {
onClose: jest.fn().mockName('onClose'),
intl: {
formatMessage: (message) => message.defaultMessage,
},
// Modal creates a portal. Overriding ReactDOM.createPortal allows portals to be tested in jest.
ReactDOM.createPortal = jest.fn(node => node);
const renderComponent = () => (
render(
<IntlProvider locale="en">
<AppProvider store={store} wrapWithRouter={false}>
<PagesAndResourcesProvider courseId={courseId}>
<MemoryRouter initialEntries={[oraSettingsUrl]}>
<Routes>
<Route path={oraSettingsUrl} element={<PageWrap><ORASettings onClose={jest.fn()} /></PageWrap>} />
</Routes>
</MemoryRouter>
</PagesAndResourcesProvider>
</AppProvider>
</IntlProvider>,
)
);
const mockStore = async ({
apiStatus,
enabled,
}) => {
const settings = ['forceOnFlexiblePeerOpenassessments'];
const fetchCourseAppsUrl = `${getCourseAppsApiUrl()}/${courseId}`;
const fetchAdvancedSettingsUrl = `${getCourseAdvancedSettingsApiUrl()}/${courseId}`;
axiosMock.onGet(fetchCourseAppsUrl).reply(
200,
[{
allowed_operations: { enable: false, configure: true },
description: 'setting',
documentation_links: { learnMoreConfiguration: '' },
enabled,
id: 'ora_settings',
name: 'Flexible Peer Grading for ORAs',
}],
);
axiosMock.onGet(fetchAdvancedSettingsUrl).reply(
apiStatus,
{ force_on_flexible_peer_openassessments: { value: enabled } },
);
await executeThunk(fetchCourseApps(courseId), store.dispatch);
await executeThunk(fetchCourseAppSettings(courseId, settings), store.dispatch);
};
describe('ORASettings', () => {
it('should render', () => {
const wrapper = shallow(<ORASettings {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
beforeEach(async () => {
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: false,
roles: [],
},
});
store = initializeStore(inititalState);
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
});
it('Flexible peer grading configuration modal is visible', async () => {
renderComponent();
expect(screen.getByRole('dialog')).toBeVisible();
});
it('Displays "Configure Flexible Peer Grading" heading', async () => {
renderComponent();
const headingElement = screen.getByText(messages.heading.defaultMessage);
expect(headingElement).toBeVisible();
});
it('Displays loading component', () => {
renderComponent();
const loadingElement = screen.getByRole('status');
expect(within(loadingElement).getByText('Loading...')).toBeInTheDocument();
});
it('Displays Connection Error Alert', async () => {
await mockStore({ apiStatus: 404, enabled: true });
renderComponent();
const errorAlert = screen.getByRole('alert');
expect(within(errorAlert).getByText('We encountered a technical error when loading this page.', { exact: false })).toBeVisible();
});
it('Displays Permissions Error Alert', async () => {
await mockStore({ apiStatus: 403, enabled: true });
renderComponent();
const errorAlert = screen.getByRole('alert');
expect(within(errorAlert).getByText('You are not authorized to view this page', { exact: false })).toBeVisible();
});
it('Displays title, helper text and badge when flexible peer grading button is enabled', async () => {
await mockStore({ apiStatus: 200, enabled: true });
renderComponent();
const checkbox = screen.getByRole('checkbox', { name: /Flex Peer Grading/ });
expect(checkbox).toBeChecked();
await waitFor(() => {
const label = screen.getByText(messages.enableFlexPeerGradeLabel.defaultMessage);
const enableBadge = screen.getByTestId('enable-badge');
expect(label).toBeVisible();
expect(enableBadge).toHaveTextContent('Enabled');
});
});
it('Displays title, helper text and hides badge when flexible peer grading button is disabled', async () => {
renderComponent();
await mockStore({ apiStatus: 200, enabled: false });
const label = await screen.findByText(messages.enableFlexPeerGradeLabel.defaultMessage);
const enableBadge = screen.queryByTestId('enable-badge');
expect(label).toBeVisible();
expect(enableBadge).toBeNull();
});
});

View File

@@ -1,41 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ORASettings should render 1`] = `
<AppSettingsModal
appId="ora_settings"
hideAppToggle={true}
initialValues={
Object {
"enableFlexiblePeerGrade": "abitrary value",
}
}
onClose={[MockFunction onClose]}
onSettingsSave={[Function]}
title={
<div>
<p>
Configure open response assessment
</p>
<div
className="pt-3"
>
<withDeprecatedProps(Hyperlink)
className="text-primary-500 small"
destination="https://learnmore.test"
rel="noreferrer noopener"
target="_blank"
>
Learn more about open response assessment settings
</withDeprecatedProps(Hyperlink)>
</div>
</div>
}
validationSchema={
Object {
"enableFlexiblePeerGrade": "Yub.boolean",
}
}
>
[Function]
</AppSettingsModal>
`;

View File

@@ -0,0 +1,32 @@
export const courseId = 'course-v1:org+num+run';
export const inititalState = {
courseDetail: {
courseId,
status: 'successful',
},
pagesAndResources: {
courseAppIds: ['ora_settings'],
loadingStatus: 'in-progress',
savingStatus: '',
courseAppsApiStatus: {},
courseAppSettings: {},
},
models: {
courseApps: {
ora_settings: {
id: 'ora_settings',
name: 'Flexible Peer Grading',
enabled: true,
description: 'Enable flexible peer grading',
allowedOperations: {
enable: false,
configure: true,
},
documentationLinks: {
learnMoreConfiguration: '',
},
},
},
},
};

View File

@@ -1,22 +0,0 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
heading: {
id: 'course-authoring.pages-resources.ora.heading',
defaultMessage: 'Configure open response assessment',
},
ORASettingsHelpLink: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.link',
defaultMessage: 'Learn more about open response assessment settings',
},
enableFlexPeerGradeLabel: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.label',
defaultMessage: 'Flex Peer Grading',
},
enableFlexPeerGradeHelp: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.help',
defaultMessage: 'Turn on Flexible Peer Grading for all open response assessments in the course with peer grading.',
},
});
export default messages;

View File

@@ -0,0 +1,54 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
heading: {
id: 'course-authoring.pages-resources.ora.heading',
defaultMessage: 'Configure Flexible Peer Grading',
description: 'Title for the modal dialog header',
},
ORASettingsHelpLink: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.link',
defaultMessage: 'Learn more about open response assessment settings',
description: 'Descriptive text for the hyperlink to the docs site',
},
enableFlexPeerGradeLabel: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.label',
defaultMessage: 'Flex Peer Grading',
description: 'Label for form switch',
},
enableFlexPeerGradeHelp: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.help',
defaultMessage: 'Turn on Flexible Peer Grading for all open response assessments in the course with peer grading.',
description: 'Help text describing what happens when the switch is enabled',
},
enabledBadgeLabel: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.enabled-badge.label',
defaultMessage: 'Enabled',
description: 'Label for badge that show users that a setting is enabled',
},
cancelLabel: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.cancel-button.label',
defaultMessage: 'Cancel',
description: 'Label for button that cancels user changes',
},
saveLabel: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.save-button.label',
defaultMessage: 'Save',
description: 'Label for button that saves user changes',
},
pendingSaveLabel: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.pending-save-button.label',
defaultMessage: 'Saving',
description: 'Label for button that has pending api save calls',
},
errorSavingTitle: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.save-error.title',
defaultMessage: 'We couldn\'t apply your changes.',
},
errorSavingMessage: {
id: 'course-authoring.pages-resources.ora.flex-peer-grading.save-error.message',
defaultMessage: 'Please check your entries and try again.',
},
});
export default messages;

View File

@@ -3,15 +3,16 @@
"version": "0.1.0",
"description": "Open Response Assessment configuration for courses using it",
"peerDependencies": {
"@edx/frontend-app-course-authoring": "*",
"@edx/frontend-app-authoring": "*",
"@edx/frontend-platform": "*",
"@openedx/paragon": "*",
"prop-types": "*",
"react": "*",
"react-redux": "*",
"yup": "*"
},
"peerDependenciesMeta": {
"@edx/frontend-app-course-authoring": {
"@edx/frontend-app-authoring": {
"optional": true
}
}

View File

@@ -8,7 +8,7 @@ import PropTypes from 'prop-types';
import { getConfig } from '@edx/frontend-platform';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import {
ActionRow, Alert, Badge, Form, Hyperlink, ModalDialog, StatefulButton,
} from '@openedx/paragon';
@@ -22,16 +22,17 @@ import { useModel } from 'CourseAuthoring/generic/model-store';
import PermissionDeniedAlert from 'CourseAuthoring/generic/PermissionDeniedAlert';
import { useIsMobile } from 'CourseAuthoring/utils';
import { PagesAndResourcesContext } from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
import { useCourseAuthoringContext } from 'CourseAuthoring/CourseAuthoringContext';
import messages from './messages';
const ProctoringSettings = ({ intl, onClose }) => {
const ProctoringSettings = ({ onClose }) => {
const intl = useIntl();
const initialFormValues = {
enableProctoredExams: false,
proctoringProvider: false,
escalationEmail: '',
allowOptingOut: false,
createZendeskTickets: false,
};
const [formValues, setFormValues] = useState(initialFormValues);
const [loading, setLoading] = useState(true);
@@ -40,6 +41,7 @@ const ProctoringSettings = ({ intl, onClose }) => {
const [loadingPermissionError, setLoadingPermissionError] = useState(false);
const [allowLtiProviders, setAllowLtiProviders] = useState(false);
const [availableProctoringProviders, setAvailableProctoringProviders] = useState([]);
const [requiresEscalationEmailProviders, setRequiresEscalationEmailProviders] = useState([]);
const [ltiProctoringProviders, setLtiProctoringProviders] = useState([]);
const [courseStartDate, setCourseStartDate] = useState('');
const [saveSuccess, setSaveSuccess] = useState(false);
@@ -64,6 +66,8 @@ const ProctoringSettings = ({ intl, onClose }) => {
}
const { courseId } = useContext(PagesAndResourcesContext);
const { courseDetails } = useCourseAuthoringContext();
const org = courseDetails?.org;
const appInfo = useModel('courseApps', 'proctoring');
const alertRef = React.createRef();
const saveStatusAlertRef = React.createRef();
@@ -75,18 +79,14 @@ const ProctoringSettings = ({ intl, onClose }) => {
const value = target.type === 'checkbox' ? target.checked : target.value;
const { name } = target;
if (['allowOptingOut', 'createZendeskTickets'].includes(name)) {
if (['allowOptingOut'].includes(name)) {
// Form.Radio expects string values, so convert back to a boolean here
setFormValues({ ...formValues, [name]: value === 'true' });
} else if (name === 'proctoringProvider') {
const newFormValues = { ...formValues, proctoringProvider: value };
if (value === 'proctortrack') {
setFormValues({ ...newFormValues, createZendeskTickets: false });
if (requiresEscalationEmailProviders.includes(value)) {
setFormValues({ ...newFormValues });
setShowEscalationEmail(true);
} else if (value === 'software_secure') {
setFormValues({ ...newFormValues, createZendeskTickets: true });
setShowEscalationEmail(false);
} else if (isLtiProvider(value)) {
setFormValues(newFormValues);
setShowEscalationEmail(true);
@@ -113,14 +113,13 @@ const ProctoringSettings = ({ intl, onClose }) => {
enable_proctored_exams: formValues.enableProctoredExams,
// lti providers are managed outside edx-platform, lti_external indicates this
proctoring_provider: isLtiProviderSelected ? 'lti_external' : selectedProvider,
create_zendesk_tickets: formValues.createZendeskTickets,
},
};
if (isEdxStaff) {
studioDataToPostBack.proctored_exam_settings.allow_proctoring_opt_out = formValues.allowOptingOut;
}
if (formValues.proctoringProvider === 'proctortrack') {
if (requiresEscalationEmailProviders.includes(formValues.proctoringProvider)) {
studioDataToPostBack.proctored_exam_settings.proctoring_escalation_email = formValues.escalationEmail === '' ? null : formValues.escalationEmail;
}
@@ -146,9 +145,9 @@ const ProctoringSettings = ({ intl, onClose }) => {
setSaveSuccess(true);
setSaveError(false);
setSubmissionInProgress(false);
}).catch(() => {
}).catch((error) => {
setSaveSuccess(false);
setSaveError(true);
setSaveError(error);
setSubmissionInProgress(false);
});
}
@@ -157,7 +156,7 @@ const ProctoringSettings = ({ intl, onClose }) => {
event.preventDefault();
const isLtiProviderSelected = isLtiProvider(formValues.proctoringProvider);
if (
(formValues.proctoringProvider === 'proctortrack' || isLtiProviderSelected)
(requiresEscalationEmailProviders.includes(formValues.proctoringProvider) || isLtiProviderSelected)
&& !EmailValidator.validate(formValues.escalationEmail)
&& !(formValues.escalationEmail === '' && !formValues.enableProctoredExams)
) {
@@ -384,29 +383,6 @@ const ProctoringSettings = ({ intl, onClose }) => {
</Form.Group>
</fieldset>
)}
{/* CREATE ZENDESK TICKETS */}
{ isEdxStaff && formValues.enableProctoredExams && !isLtiProviderSelected && (
<fieldset aria-describedby="createZendeskTicketsText">
<Form.Group controlId="formCreateZendeskTickets">
<Form.Label as="legend" className="font-weight-bold">
{intl.formatMessage(messages['authoring.proctoring.createzendesk.label'])}
</Form.Label>
<Form.RadioSet
name="createZendeskTickets"
value={formValues.createZendeskTickets.toString()}
onChange={handleChange}
>
<Form.Radio value="true" data-testid="createZendeskTicketsYes">
{intl.formatMessage(messages['authoring.proctoring.yes'])}
</Form.Radio>
<Form.Radio value="false" data-testid="createZendeskTicketsNo">
{intl.formatMessage(messages['authoring.proctoring.no'])}
</Form.Radio>
</Form.RadioSet>
</Form.Group>
</fieldset>
)}
</>
);
}
@@ -458,21 +434,32 @@ const ProctoringSettings = ({ intl, onClose }) => {
}
function renderSaveError() {
return (
<Alert
variant="danger"
data-testid="saveError"
tabIndex="-1"
ref={saveStatusAlertRef}
onClose={() => setSaveError(false)}
dismissible
>
let errorMessage = (
<FormattedMessage
id="authoring.proctoring.alert.error"
defaultMessage={`
We encountered a technical error while trying to save proctored exam settings.
This might be a temporary issue, so please try again in a few minutes.
If the problem persists, please go to the {support_link} for help.
`}
values={{
support_link: (
<Alert.Link href={getConfig().SUPPORT_URL}>
{intl.formatMessage(messages['authoring.proctoring.support.text'])}
</Alert.Link>
),
}}
/>
);
if (saveError?.response.status === 403) {
errorMessage = (
<FormattedMessage
id="authoring.examsettings.alert.error"
id="authoring.proctoring.alert.error.forbidden"
defaultMessage={`
We encountered a technical error while trying to save proctored exam settings.
This might be a temporary issue, so please try again in a few minutes.
If the problem persists, please go to the {support_link} for help.
You do not have permission to edit proctored exam settings for this course.
If you are a course team member and this problem persists,
please go to the {support_link} for help.
`}
values={{
support_link: (
@@ -482,6 +469,19 @@ const ProctoringSettings = ({ intl, onClose }) => {
),
}}
/>
);
}
return (
<Alert
variant="danger"
data-testid="saveError"
tabIndex="-1"
ref={saveStatusAlertRef}
onClose={() => setSaveError(false)}
dismissible
>
{errorMessage}
</Alert>
);
}
@@ -490,7 +490,7 @@ const ProctoringSettings = ({ intl, onClose }) => {
Promise.all([
StudioApiService.getProctoredExamSettingsData(courseId),
ExamsApiService.isAvailable() ? ExamsApiService.getCourseExamConfiguration(courseId) : Promise.resolve(),
ExamsApiService.isAvailable() ? ExamsApiService.getAvailableProviders() : Promise.resolve(),
ExamsApiService.isAvailable() ? ExamsApiService.getAvailableProviders(org) : Promise.resolve(),
])
.then(
([settingsResponse, examConfigResponse, ltiProvidersResponse]) => {
@@ -500,6 +500,7 @@ const ProctoringSettings = ({ intl, onClose }) => {
setSubmissionInProgress(false);
setCourseStartDate(settingsResponse.data.course_start_date);
setAvailableProctoringProviders(settingsResponse.data.available_proctoring_providers);
setRequiresEscalationEmailProviders(settingsResponse.data.requires_escalation_email_providers);
// The list of providers returned by studio settings are the default behavior. If lti_external
// is available as an option display the list of LTI providers returned by the exam service.
@@ -527,10 +528,11 @@ const ProctoringSettings = ({ intl, onClose }) => {
selectedProvider = proctoredExamSettings.proctoring_provider;
}
const isProctortrack = selectedProvider === 'proctortrack';
const requiresEscalationEmailProvidersList = settingsResponse.data.requires_escalation_email_providers;
const isEscalationEmailRequired = requiresEscalationEmailProvidersList.includes(selectedProvider);
const ltiProviderSelected = proctoringProvidersLti.some(p => p.name === selectedProvider);
if (isProctortrack || ltiProviderSelected) {
if (isEscalationEmailRequired || ltiProviderSelected) {
setShowEscalationEmail(true);
}
@@ -543,7 +545,6 @@ const ProctoringSettings = ({ intl, onClose }) => {
proctoringProvider: selectedProvider,
enableProctoredExams: proctoredExamSettings.enable_proctored_exams,
allowOptingOut: proctoredExamSettings.allow_proctoring_opt_out,
createZendeskTickets: proctoredExamSettings.create_zendesk_tickets,
// The backend API may return null for the proctoringEscalationEmail value, which is the default.
// In order to keep our email input component controlled, we use the empty string as the default
// and perform this conversion during GETs and POSTs.
@@ -626,10 +627,9 @@ const ProctoringSettings = ({ intl, onClose }) => {
};
ProctoringSettings.propTypes = {
intl: intlShape.isRequired,
onClose: PropTypes.func.isRequired,
};
ProctoringSettings.defaultProps = {};
export default injectIntl(ProctoringSettings);
export default ProctoringSettings;

View File

@@ -1,69 +1,73 @@
import React from 'react';
import {
render, screen, cleanup, waitFor, fireEvent, act,
} from '@testing-library/react';
import MockAdapter from 'axios-mock-adapter';
initializeMocks,
} from 'CourseAuthoring/testUtils';
import { initializeMockApp, mergeConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
import { AppProvider } from '@edx/frontend-platform/react';
import { mergeConfig } from '@edx/frontend-platform';
import StudioApiService from 'CourseAuthoring/data/services/StudioApiService';
import ExamsApiService from 'CourseAuthoring/data/services/ExamsApiService';
import initializeStore from 'CourseAuthoring/store';
import PagesAndResourcesProvider from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
import { CourseAuthoringProvider } from 'CourseAuthoring/CourseAuthoringContext';
import { getCourseDetailsUrl } from 'CourseAuthoring/data/api';
import ProctoredExamSettings from './Settings';
const courseId = 'course-v1%3AedX%2BDemoX%2BDemo_Course';
const defaultProps = {
courseId: 'course-v1%3AedX%2BDemoX%2BDemo_Course',
courseId,
onClose: () => {},
};
const IntlProctoredExamSettings = injectIntl(ProctoredExamSettings);
let store;
const intlWrapper = children => (
<AppProvider store={store}>
const renderComponent = children => (
<CourseAuthoringProvider courseId={defaultProps.courseId}>
<PagesAndResourcesProvider courseId={defaultProps.courseId}>
<IntlProvider locale="en">
{children}
</IntlProvider>
{children}
</PagesAndResourcesProvider>
</AppProvider>
</CourseAuthoringProvider>
);
let axiosMock;
describe('ProctoredExamSettings', () => {
function setupApp(isAdmin = true) {
/**
* @param {boolean} isAdmin
* @param {string | undefined} org
*/
function setupApp(isAdmin = true, org = undefined) {
mergeConfig({
EXAMS_BASE_URL: 'http://exams.testing.co',
}, 'CourseAuthoringConfig');
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: isAdmin,
roles: [],
},
});
store = initializeStore({
models: {
courseApps: {
proctoring: {},
const user = {
userId: 3,
username: 'abc123',
administrator: isAdmin,
roles: [],
};
const mocks = initializeMocks({
user,
initialState: {
models: {
courseApps: {
proctoring: {},
},
},
},
});
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
axiosMock.onGet(
`${ExamsApiService.getExamsBaseUrl()}/api/v1/providers`,
).reply(200, [
{
name: 'test_lti',
verbose_name: 'LTI Provider',
},
]);
axiosMock = mocks.axiosMock;
axiosMock
.onGet(getCourseDetailsUrl(courseId, user.username))
.reply(200, {
courseId,
name: 'Course Test',
start: Date(),
...(org ? { org } : {}),
});
axiosMock.onGet(`${ExamsApiService.getExamsBaseUrl()}/api/v1/providers`)
.reply(200, [{ name: 'test_lti', verbose_name: 'LTI Provider' }]);
if (org) {
axiosMock.onGet(`${ExamsApiService.getExamsBaseUrl()}/api/v1/providers?org=${org}`)
.reply(200, [{ name: 'test_lti', verbose_name: 'LTI Provider' }]);
}
axiosMock.onGet(
`${ExamsApiService.getExamsBaseUrl()}/api/v1/configs/course_id/${defaultProps.courseId}`,
).reply(200, {
@@ -78,60 +82,20 @@ describe('ProctoredExamSettings', () => {
allow_proctoring_opt_out: false,
proctoring_provider: 'mockproc',
proctoring_escalation_email: 'test@example.com',
create_zendesk_tickets: true,
},
available_proctoring_providers: ['software_secure', 'proctortrack', 'mockproc', 'lti_external'],
available_proctoring_providers: ['software_secure', 'mockproc', 'lti_external'],
requires_escalation_email_providers: ['test_lti'],
course_start_date: '2070-01-01T00:00:00Z',
});
}
afterEach(() => {
cleanup();
axiosMock.reset();
});
beforeEach(async () => {
setupApp();
});
describe('Field dependencies', () => {
beforeEach(async () => {
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
});
it('Updates Zendesk ticket field if proctortrack is provider', async () => {
await waitFor(() => {
screen.getByDisplayValue('mockproc');
});
const selectElement = screen.getByDisplayValue('mockproc');
await act(async () => {
fireEvent.change(selectElement, { target: { value: 'proctortrack' } });
});
const zendeskTicketInput = screen.getByTestId('createZendeskTicketsNo');
expect(zendeskTicketInput.checked).toEqual(true);
});
it('Updates Zendesk ticket field if software_secure is provider', async () => {
await waitFor(() => {
screen.getByDisplayValue('mockproc');
});
const selectElement = screen.getByDisplayValue('mockproc');
await act(async () => {
fireEvent.change(selectElement, { target: { value: 'software_secure' } });
});
const zendeskTicketInput = screen.getByTestId('createZendeskTicketsYes');
expect(zendeskTicketInput.checked).toEqual(true);
});
it('Does not update zendesk ticket field for any other provider', async () => {
await waitFor(() => {
screen.getByDisplayValue('mockproc');
});
const selectElement = screen.getByDisplayValue('mockproc');
await act(async () => {
fireEvent.change(selectElement, { target: { value: 'mockproc' } });
});
const zendeskTicketInput = screen.getByTestId('createZendeskTicketsYes');
expect(zendeskTicketInput.checked).toEqual(true);
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
});
it('Hides all other fields when enabledProctorExam is false when first loaded', async () => {
@@ -145,13 +109,13 @@ describe('ProctoredExamSettings', () => {
allow_proctoring_opt_out: false,
proctoring_provider: 'mockproc',
proctoring_escalation_email: 'test@example.com',
create_zendesk_tickets: true,
},
available_proctoring_providers: ['software_secure', 'proctortrack', 'mockproc'],
available_proctoring_providers: ['software_secure', 'mockproc'],
requires_escalation_email_providers: [],
course_start_date: '2070-01-01T00:00:00Z',
});
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
await waitFor(() => {
screen.getByText('Proctored exams');
});
@@ -160,8 +124,6 @@ describe('ProctoredExamSettings', () => {
expect(screen.queryByText('Allow Opting Out of Proctored Exams')).toBeNull();
expect(screen.queryByDisplayValue('mockproc')).toBeNull();
expect(screen.queryByTestId('escalationEmail')).toBeNull();
expect(screen.queryByTestId('createZendeskTicketsYes')).toBeNull();
expect(screen.queryByTestId('createZendeskTicketsNo')).toBeNull();
});
it('Hides all other fields when enableProctoredExams toggled to false', async () => {
@@ -171,21 +133,15 @@ describe('ProctoredExamSettings', () => {
expect(screen.queryByText('Allow opting out of proctored exams')).toBeDefined();
expect(screen.queryByDisplayValue('mockproc')).toBeDefined();
expect(screen.queryByTestId('escalationEmail')).toBeDefined();
expect(screen.queryByTestId('createZendeskTicketsYes')).toBeDefined();
expect(screen.queryByTestId('createZendeskTicketsNo')).toBeDefined();
let enabledProctoredExamCheck = screen.getAllByLabelText('Proctored exams', { exact: false })[0];
expect(enabledProctoredExamCheck.checked).toEqual(true);
await act(async () => {
fireEvent.click(enabledProctoredExamCheck, { target: { value: false } });
});
fireEvent.click(enabledProctoredExamCheck, { target: { value: false } });
enabledProctoredExamCheck = screen.getByLabelText('Proctored exams');
expect(enabledProctoredExamCheck.checked).toEqual(false);
expect(screen.queryByText('Allow opting out of proctored exams')).toBeNull();
expect(screen.queryByDisplayValue('mockproc')).toBeNull();
expect(screen.queryByTestId('escalationEmail')).toBeNull();
expect(screen.queryByTestId('createZendeskTicketsYes')).toBeNull();
expect(screen.queryByTestId('createZendeskTicketsNo')).toBeNull();
});
it('Hides unsupported fields when lti provider is selected', async () => {
@@ -193,17 +149,13 @@ describe('ProctoredExamSettings', () => {
screen.getByDisplayValue('mockproc');
});
const selectElement = screen.getByDisplayValue('mockproc');
await act(async () => {
fireEvent.change(selectElement, { target: { value: 'test_lti' } });
});
fireEvent.change(selectElement, { target: { value: 'test_lti' } });
expect(screen.queryByTestId('allowOptingOutRadio')).toBeNull();
expect(screen.queryByTestId('createZendeskTicketsYes')).toBeNull();
expect(screen.queryByTestId('createZendeskTicketsNo')).toBeNull();
});
});
describe('Validation with invalid escalation email', () => {
const proctoringProvidersRequiringEscalationEmail = ['proctortrack', 'test_lti'];
const proctoringProvidersRequiringEscalationEmail = ['test_lti'];
beforeEach(async () => {
axiosMock.onGet(
@@ -212,14 +164,21 @@ describe('ProctoredExamSettings', () => {
proctored_exam_settings: {
enable_proctored_exams: true,
allow_proctoring_opt_out: false,
proctoring_provider: 'proctortrack',
proctoring_provider: 'lti_external',
proctoring_escalation_email: 'test@example.com',
create_zendesk_tickets: true,
},
available_proctoring_providers: ['software_secure', 'proctortrack', 'mockproc', 'lti_external'],
available_proctoring_providers: ['software_secure', 'mockproc', 'lti_external'],
requires_escalation_email_providers: ['test_lti'],
course_start_date: '2070-01-01T00:00:00Z',
});
axiosMock.onGet(
`${ExamsApiService.getExamsBaseUrl()}/api/v1/configs/course_id/${defaultProps.courseId}`,
).reply(200, {
provider: 'test_lti',
escalation_email: 'test@example.com',
});
axiosMock.onPatch(
ExamsApiService.getExamConfigurationUrl(defaultProps.courseId),
).reply(204, {});
@@ -228,22 +187,18 @@ describe('ProctoredExamSettings', () => {
StudioApiService.getProctoredExamSettingsUrl(defaultProps.courseId),
).reply(200, {});
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
});
proctoringProvidersRequiringEscalationEmail.forEach(provider => {
it(`Creates an alert when no proctoring escalation email is provided with ${provider} selected`, async () => {
await waitFor(() => {
screen.getByDisplayValue('proctortrack');
screen.getByDisplayValue('LTI Provider');
});
const selectEscalationEmailElement = screen.getByDisplayValue('test@example.com');
await act(async () => {
fireEvent.change(selectEscalationEmailElement, { target: { value: '' } });
});
fireEvent.change(selectEscalationEmailElement, { target: { value: '' } });
const selectButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(selectButton);
});
fireEvent.click(selectButton);
// verify alert content and focus management
const escalationEmailError = screen.getByTestId('escalationEmailError');
@@ -252,31 +207,23 @@ describe('ProctoredExamSettings', () => {
// verify alert link links to offending input
const errorLink = screen.getByTestId('escalationEmailErrorLink');
await act(async () => {
fireEvent.click(errorLink);
});
fireEvent.click(errorLink);
const escalationEmailInput = screen.getByTestId('escalationEmail');
expect(document.activeElement).toEqual(escalationEmailInput);
});
it(`Creates an alert when invalid proctoring escalation email is provided with ${provider} selected`, async () => {
await waitFor(() => {
screen.getByDisplayValue('proctortrack');
screen.getByDisplayValue('LTI Provider');
});
const selectElement = screen.getByDisplayValue('proctortrack');
await act(async () => {
fireEvent.change(selectElement, { target: { value: provider } });
});
const selectElement = screen.getByDisplayValue('LTI Provider');
fireEvent.change(selectElement, { target: { value: provider } });
const selectEscalationEmailElement = screen.getByDisplayValue('test@example.com');
await act(async () => {
fireEvent.change(selectEscalationEmailElement, { target: { value: 'foo.bar' } });
});
const selectButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(selectButton);
});
fireEvent.change(selectEscalationEmailElement, { target: { value: 'foo.bar' } });
const proctoringForm = screen.getByTestId('proctoringForm');
fireEvent.submit(proctoringForm);
// verify alert content and focus management
const escalationEmailError = screen.getByTestId('escalationEmailError');
@@ -286,27 +233,21 @@ describe('ProctoredExamSettings', () => {
// verify alert link links to offending input
const errorLink = screen.getByTestId('escalationEmailErrorLink');
await act(async () => {
fireEvent.click(errorLink);
});
fireEvent.click(errorLink);
const escalationEmailInput = screen.getByTestId('escalationEmail');
expect(document.activeElement).toEqual(escalationEmailInput);
});
it('Creates an alert when invalid proctoring escalation email is provided with proctoring disabled', async () => {
await waitFor(() => {
screen.getByDisplayValue('proctortrack');
screen.getByDisplayValue('LTI Provider');
});
const selectEscalationEmailElement = screen.getByDisplayValue('test@example.com');
await act(async () => {
fireEvent.change(selectEscalationEmailElement, { target: { value: 'foo.bar' } });
});
fireEvent.change(selectEscalationEmailElement, { target: { value: 'foo.bar' } });
const enableProctoringElement = screen.getByText('Proctored exams');
await act(async () => fireEvent.click(enableProctoringElement));
fireEvent.click(enableProctoringElement);
const selectButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(selectButton);
});
fireEvent.click(selectButton);
// verify alert content and focus management
const escalationEmailError = screen.getByTestId('escalationEmailError');
@@ -317,78 +258,68 @@ describe('ProctoredExamSettings', () => {
it('Has no error when empty proctoring escalation email is provided with proctoring disabled', async () => {
await waitFor(() => {
screen.getByDisplayValue('proctortrack');
screen.getByDisplayValue('LTI Provider');
});
const selectEscalationEmailElement = screen.getByDisplayValue('test@example.com');
await act(async () => {
fireEvent.change(selectEscalationEmailElement, { target: { value: '' } });
});
fireEvent.change(selectEscalationEmailElement, { target: { value: '' } });
const enableProctoringElement = screen.getByText('Proctored exams');
await act(async () => fireEvent.click(enableProctoringElement));
fireEvent.click(enableProctoringElement);
const selectButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(selectButton);
});
fireEvent.click(selectButton);
// verify there is no escalation email alert, and focus has been set on save success alert
expect(screen.queryByTestId('escalationEmailError')).toBeNull();
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
await waitFor(() => {
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
});
});
it(`Has no error when valid proctoring escalation email is provided with ${provider} selected`, async () => {
await waitFor(() => {
screen.getByDisplayValue('proctortrack');
screen.getByDisplayValue('LTI Provider');
});
const selectEscalationEmailElement = screen.getByDisplayValue('test@example.com');
await act(async () => {
fireEvent.change(selectEscalationEmailElement, { target: { value: 'foo@bar.com' } });
});
fireEvent.change(selectEscalationEmailElement, { target: { value: 'foo@bar.com' } });
const selectButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(selectButton);
});
fireEvent.click(selectButton);
// verify there is no escalation email alert, and focus has been set on save success alert
expect(screen.queryByTestId('escalationEmailError')).toBeNull();
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
await waitFor(() => {
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
});
});
it(`Escalation email field hidden when proctoring backend is not ${provider}`, async () => {
await waitFor(() => {
screen.getByDisplayValue('proctortrack');
screen.getByDisplayValue('LTI Provider');
});
const proctoringBackendSelect = screen.getByDisplayValue('proctortrack');
const proctoringBackendSelect = screen.getByDisplayValue('LTI Provider');
const selectEscalationEmailElement = screen.getByTestId('escalationEmail');
expect(selectEscalationEmailElement.value).toEqual('test@example.com');
await act(async () => {
fireEvent.change(proctoringBackendSelect, { target: { value: 'software_secure' } });
});
fireEvent.change(proctoringBackendSelect, { target: { value: 'software_secure' } });
expect(screen.queryByTestId('escalationEmail')).toBeNull();
});
it(`Escalation email Field Show when proctoring backend is switched back to ${provider}`, async () => {
await waitFor(() => {
screen.getByDisplayValue('proctortrack');
screen.getByDisplayValue('LTI Provider');
});
const proctoringBackendSelect = screen.getByDisplayValue('proctortrack');
const proctoringBackendSelect = screen.getByDisplayValue('LTI Provider');
let selectEscalationEmailElement = screen.getByTestId('escalationEmail');
await act(async () => {
fireEvent.change(proctoringBackendSelect, { target: { value: 'software_secure' } });
});
fireEvent.change(proctoringBackendSelect, { target: { value: 'software_secure' } });
expect(screen.queryByTestId('escalationEmail')).toBeNull();
await act(async () => {
fireEvent.change(proctoringBackendSelect, { target: { value: 'proctortrack' } });
});
fireEvent.change(proctoringBackendSelect, { target: { value: provider } });
expect(screen.queryByTestId('escalationEmail')).toBeDefined();
selectEscalationEmailElement = screen.getByTestId('escalationEmail');
expect(selectEscalationEmailElement.value).toEqual('test@example.com');
@@ -396,15 +327,11 @@ describe('ProctoredExamSettings', () => {
it('Submits form when "Enter" key is hit in the escalation email field', async () => {
await waitFor(() => {
screen.getByDisplayValue('proctortrack');
screen.getByDisplayValue('LTI Provider');
});
const selectEscalationEmailElement = screen.getByDisplayValue('test@example.com');
await act(async () => {
fireEvent.change(selectEscalationEmailElement, { target: { value: '' } });
});
await act(async () => {
fireEvent.submit(selectEscalationEmailElement);
});
fireEvent.change(selectEscalationEmailElement, { target: { value: '' } });
fireEvent.submit(selectEscalationEmailElement);
// if the error appears, the form has been submitted
expect(screen.getByTestId('escalationEmailError')).toBeDefined();
});
@@ -418,9 +345,9 @@ describe('ProctoredExamSettings', () => {
allow_proctoring_opt_out: false,
proctoring_provider: 'mockproc',
proctoring_escalation_email: 'test@example.com',
create_zendesk_tickets: true,
},
available_proctoring_providers: ['software_secure', 'proctortrack', 'mockproc'],
available_proctoring_providers: ['software_secure', 'mockproc'],
requires_escalation_email_providers: [],
course_start_date: '2099-01-01T00:00:00Z',
};
@@ -430,9 +357,9 @@ describe('ProctoredExamSettings', () => {
allow_proctoring_opt_out: false,
proctoring_provider: 'mockproc',
proctoring_escalation_email: 'test@example.com',
create_zendesk_tickets: true,
},
available_proctoring_providers: ['software_secure', 'proctortrack', 'mockproc'],
available_proctoring_providers: ['software_secure', 'mockproc'],
requires_escalation_email_providers: [],
course_start_date: '2013-01-01T00:00:00Z',
};
@@ -444,8 +371,8 @@ describe('ProctoredExamSettings', () => {
const isAdmin = false;
setupApp(isAdmin);
mockCourseData(mockGetPastCourseData);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
const providerOption = screen.getByTestId('proctortrack');
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const providerOption = screen.getByTestId('software_secure');
expect(providerOption.hasAttribute('disabled')).toEqual(true);
});
@@ -453,8 +380,18 @@ describe('ProctoredExamSettings', () => {
const isAdmin = false;
setupApp(isAdmin);
mockCourseData(mockGetFutureCourseData);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
const providerOption = screen.getByTestId('proctortrack');
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const providerOption = screen.getByTestId('software_secure');
expect(providerOption.hasAttribute('disabled')).toEqual(false);
});
it('Sends the org to the proctoring provider endpoint', async () => {
const isAdmin = false;
const org = 'test-org';
setupApp(isAdmin, org);
mockCourseData(mockGetFutureCourseData);
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const providerOption = screen.getByTestId('software_secure');
expect(providerOption.hasAttribute('disabled')).toEqual(false);
});
@@ -462,8 +399,8 @@ describe('ProctoredExamSettings', () => {
const isAdmin = true;
setupApp(isAdmin);
mockCourseData(mockGetPastCourseData);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
const providerOption = screen.getByTestId('proctortrack');
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const providerOption = screen.getByTestId('software_secure');
expect(providerOption.hasAttribute('disabled')).toEqual(false);
});
@@ -471,18 +408,18 @@ describe('ProctoredExamSettings', () => {
const isAdmin = true;
setupApp(isAdmin);
mockCourseData(mockGetFutureCourseData);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
const providerOption = screen.getByTestId('proctortrack');
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const providerOption = screen.getByTestId('software_secure');
expect(providerOption.hasAttribute('disabled')).toEqual(false);
});
it('Does not include lti_external as a selectable option', async () => {
const courseData = {
...mockGetFutureCourseData,
available_proctoring_providers: ['lti_external', 'proctortrack', 'mockproc'],
available_proctoring_providers: ['lti_external', 'mockproc'],
};
mockCourseData(courseData);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
await waitFor(() => {
screen.getByDisplayValue('mockproc');
});
@@ -492,10 +429,10 @@ describe('ProctoredExamSettings', () => {
it('Includes lti proctoring provider options when lti_external is allowed by studio', async () => {
const courseData = {
...mockGetFutureCourseData,
available_proctoring_providers: ['lti_external', 'proctortrack', 'mockproc'],
available_proctoring_providers: ['lti_external', 'mockproc'],
};
mockCourseData(courseData);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
await waitFor(() => {
screen.getByDisplayValue('mockproc');
});
@@ -508,7 +445,7 @@ describe('ProctoredExamSettings', () => {
const isAdmin = true;
setupApp(isAdmin);
mockCourseData(mockGetFutureCourseData);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
await waitFor(() => {
screen.getByDisplayValue('mockproc');
});
@@ -522,18 +459,20 @@ describe('ProctoredExamSettings', () => {
EXAMS_BASE_URL: null,
}, 'CourseAuthoringConfig');
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
await waitFor(() => {
screen.getByDisplayValue('mockproc');
});
// only outgoing request should be for studio settings
expect(axiosMock.history.get.length).toBe(1);
// (1) for studio settings
// (2) waffle flags
// (3) for course details
expect(axiosMock.history.get.length).toBe(3);
expect(axiosMock.history.get[0].url.includes('proctored_exam_settings')).toEqual(true);
});
it('Selected LTI proctoring provider is shown on page load', async () => {
const courseData = { ...mockGetFutureCourseData };
courseData.available_proctoring_providers = ['lti_external', 'proctortrack', 'mockproc'];
courseData.available_proctoring_providers = ['lti_external', 'mockproc'];
courseData.proctored_exam_settings.proctoring_provider = 'lti_external';
mockCourseData(courseData);
axiosMock.onGet(
@@ -541,7 +480,7 @@ describe('ProctoredExamSettings', () => {
).reply(200, {
provider: 'test_lti',
});
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
await waitFor(() => {
screen.getByText('Proctoring provider');
});
@@ -552,29 +491,24 @@ describe('ProctoredExamSettings', () => {
});
describe('Toggles field visibility based on user permissions', () => {
it('Hides opting out and zendesk tickets for non edX staff', async () => {
it('Hides opting out for non edX staff', async () => {
setupApp(false);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
expect(screen.queryByTestId('allowOptingOutYes')).toBeNull();
expect(screen.queryByTestId('createZendeskTicketsYes')).toBeNull();
});
it('Shows opting out and zendesk tickets for edX staff', async () => {
it('Shows opting out for edX staff', async () => {
setupApp(true);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
expect(screen.queryByTestId('allowOptingOutYes')).not.toBeNull();
expect(screen.queryByTestId('createZendeskTicketsYes')).not.toBeNull();
});
});
describe('Connection states', () => {
it('Shows the spinner before the connection is complete', async () => {
await act(async () => {
render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />));
// This expectation is _inside_ the `act` intentionally, so that it executes immediately.
const spinner = screen.getByRole('status');
expect(spinner.textContent).toEqual('Loading...');
});
render(renderComponent(<ProctoredExamSettings {...defaultProps} />));
const spinner = await screen.findByRole('status');
expect(spinner.textContent).toEqual('Loading...');
});
it('Show connection error message when we suffer studio server side error', async () => {
@@ -582,7 +516,7 @@ describe('ProctoredExamSettings', () => {
StudioApiService.getProctoredExamSettingsUrl(defaultProps.courseId),
).reply(500);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const connectionError = screen.getByTestId('connectionErrorAlert');
expect(connectionError.textContent).toEqual(
expect.stringContaining('We encountered a technical error when loading this page.'),
@@ -594,7 +528,7 @@ describe('ProctoredExamSettings', () => {
`${ExamsApiService.getExamsBaseUrl()}/api/v1/providers`,
).reply(500);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const connectionError = screen.getByTestId('connectionErrorAlert');
expect(connectionError.textContent).toEqual(
expect.stringContaining('We encountered a technical error when loading this page.'),
@@ -606,7 +540,7 @@ describe('ProctoredExamSettings', () => {
StudioApiService.getProctoredExamSettingsUrl(defaultProps.courseId),
).reply(403);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const permissionError = screen.getByTestId('permissionDeniedAlert');
expect(permissionError.textContent).toEqual(
expect.stringContaining('You are not authorized to view this page'),
@@ -625,98 +559,104 @@ describe('ProctoredExamSettings', () => {
});
it('Disable button while submitting', async () => {
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
let submitButton = screen.getByTestId('submissionButton');
expect(screen.queryByTestId('saveInProgress')).toBeFalsy();
act(() => {
fireEvent.click(submitButton);
});
fireEvent.click(submitButton);
submitButton = screen.getByTestId('submissionButton');
expect(submitButton).toHaveAttribute('disabled');
});
it('Makes API call successfully with proctoring_escalation_email if proctortrack', async () => {
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
// Make a change to the provider to proctortrack and set the email
const selectElement = screen.getByDisplayValue('mockproc');
await act(async () => {
fireEvent.change(selectElement, { target: { value: 'proctortrack' } });
it('Makes API call successfully with proctoring_escalation_email if test_lti', async () => {
// Setup mock to include test_lti as available provider
axiosMock.onGet(
StudioApiService.getProctoredExamSettingsUrl(defaultProps.courseId),
).reply(200, {
proctored_exam_settings: {
enable_proctored_exams: true,
allow_proctoring_opt_out: false,
proctoring_provider: 'mockproc',
proctoring_escalation_email: 'test@example.com',
},
available_proctoring_providers: ['software_secure', 'mockproc', 'lti_external'],
requires_escalation_email_providers: ['test_lti'],
course_start_date: '2070-01-01T00:00:00Z',
});
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
// Make a change to the provider to test_lti and set the email
const selectElement = screen.getByDisplayValue('mockproc');
fireEvent.change(selectElement, { target: { value: 'test_lti' } });
const escalationEmail = screen.getByTestId('escalationEmail');
expect(escalationEmail.value).toEqual('test@example.com');
await act(async () => {
fireEvent.change(escalationEmail, { target: { value: 'proctortrack@example.com' } });
});
expect(escalationEmail.value).toEqual('proctortrack@example.com');
fireEvent.change(escalationEmail, { target: { value: 'test_lti@example.com' } });
expect(escalationEmail.value).toEqual('test_lti@example.com');
const submitButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(submitButton);
});
fireEvent.click(submitButton);
expect(axiosMock.history.post.length).toBe(1);
expect(JSON.parse(axiosMock.history.post[0].data)).toEqual({
proctored_exam_settings: {
enable_proctored_exams: true,
allow_proctoring_opt_out: false,
proctoring_provider: 'proctortrack',
proctoring_escalation_email: 'proctortrack@example.com',
create_zendesk_tickets: false,
proctoring_provider: 'lti_external',
proctoring_escalation_email: 'test_lti@example.com',
},
});
expect(axiosMock.history.patch.length).toBe(1);
expect(JSON.parse(axiosMock.history.patch[0].data)).toEqual({
provider: 'test_lti',
escalation_email: 'test_lti@example.com',
});
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
await waitFor(() => {
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
});
});
it('Makes API call successfully without proctoring_escalation_email if not proctortrack', async () => {
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
it('Makes API call successfully without proctoring_escalation_email if not requiring escalation email', async () => {
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
// make sure we have not selected proctortrack as the proctoring provider
// make sure we have not selected a provider requiring escalation email
expect(screen.getByDisplayValue('mockproc')).toBeDefined();
const submitButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(submitButton);
});
fireEvent.click(submitButton);
expect(axiosMock.history.post.length).toBe(1);
expect(JSON.parse(axiosMock.history.post[0].data)).toEqual({
proctored_exam_settings: {
enable_proctored_exams: true,
allow_proctoring_opt_out: false,
proctoring_provider: 'mockproc',
create_zendesk_tickets: true,
},
});
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
await waitFor(() => {
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
});
});
it('Successfully updates exam configuration and studio provider is set to "lti_external" for lti providers', async () => {
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
// Make a change to the provider to test_lti and set the email
const selectElement = screen.getByDisplayValue('mockproc');
await act(async () => {
fireEvent.change(selectElement, { target: { value: 'test_lti' } });
});
fireEvent.change(selectElement, { target: { value: 'test_lti' } });
const escalationEmail = screen.getByTestId('escalationEmail');
expect(escalationEmail.value).toEqual('test@example.com');
await act(async () => {
fireEvent.change(escalationEmail, { target: { value: 'test_lti@example.com' } });
});
fireEvent.change(escalationEmail, { target: { value: 'test_lti@example.com' } });
expect(escalationEmail.value).toEqual('test_lti@example.com');
const submitButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(submitButton);
});
fireEvent.click(submitButton);
// update exam service config
expect(axiosMock.history.patch.length).toBe(1);
@@ -732,23 +672,23 @@ describe('ProctoredExamSettings', () => {
enable_proctored_exams: true,
allow_proctoring_opt_out: false,
proctoring_provider: 'lti_external',
create_zendesk_tickets: true,
proctoring_escalation_email: 'test_lti@example.com',
},
});
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
await waitFor(() => {
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
});
});
it('Sets exam service provider to null if a non-lti provider is selected', async () => {
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const submitButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(submitButton);
});
fireEvent.click(submitButton);
// update exam service config
expect(axiosMock.history.patch.length).toBe(1);
expect(JSON.parse(axiosMock.history.patch[0].data)).toEqual({
@@ -762,15 +702,16 @@ describe('ProctoredExamSettings', () => {
enable_proctored_exams: true,
allow_proctoring_opt_out: false,
proctoring_provider: 'mockproc',
create_zendesk_tickets: true,
},
});
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
await waitFor(() => {
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
});
});
it('Does not update exam service if lti is not enabled in studio', async () => {
@@ -782,17 +723,15 @@ describe('ProctoredExamSettings', () => {
allow_proctoring_opt_out: false,
proctoring_provider: 'mockproc',
proctoring_escalation_email: 'test@example.com',
create_zendesk_tickets: true,
},
available_proctoring_providers: ['software_secure', 'proctortrack', 'mockproc'],
available_proctoring_providers: ['software_secure', 'mockproc'],
requires_escalation_email_providers: [],
course_start_date: '2070-01-01T00:00:00Z',
});
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const submitButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(submitButton);
});
fireEvent.click(submitButton);
// does not update exam service config
expect(axiosMock.history.patch.length).toBe(0);
// does update studio
@@ -802,15 +741,16 @@ describe('ProctoredExamSettings', () => {
enable_proctored_exams: true,
allow_proctoring_opt_out: false,
proctoring_provider: 'mockproc',
create_zendesk_tickets: true,
},
});
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
await waitFor(() => {
const errorAlert = screen.getByTestId('saveSuccess');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(errorAlert);
});
});
it('Makes studio API call generated error', async () => {
@@ -818,17 +758,17 @@ describe('ProctoredExamSettings', () => {
StudioApiService.getProctoredExamSettingsUrl(defaultProps.courseId),
).reply(500);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const submitButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(submitButton);
});
fireEvent.click(submitButton);
expect(axiosMock.history.post.length).toBe(1);
const errorAlert = screen.getByTestId('saveError');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('We encountered a technical error while trying to save proctored exam settings'),
);
expect(document.activeElement).toEqual(errorAlert);
await waitFor(() => {
const errorAlert = screen.getByTestId('saveError');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('We encountered a technical error while trying to save proctored exam settings'),
);
expect(document.activeElement).toEqual(errorAlert);
});
});
it('Makes exams API call generated error', async () => {
@@ -836,17 +776,35 @@ describe('ProctoredExamSettings', () => {
`${ExamsApiService.getExamsBaseUrl()}/api/v1/configs/course_id/${defaultProps.courseId}`,
).reply(500, 'error');
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const submitButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(submitButton);
});
fireEvent.click(submitButton);
expect(axiosMock.history.post.length).toBe(1);
const errorAlert = screen.getByTestId('saveError');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('We encountered a technical error while trying to save proctored exam settings'),
);
expect(document.activeElement).toEqual(errorAlert);
await waitFor(() => {
const errorAlert = screen.getByTestId('saveError');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('We encountered a technical error while trying to save proctored exam settings'),
);
expect(document.activeElement).toEqual(errorAlert);
});
});
test('Exams API permission error', async () => {
axiosMock.onPatch(
`${ExamsApiService.getExamsBaseUrl()}/api/v1/configs/course_id/${defaultProps.courseId}`,
).reply(403, 'error');
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const submitButton = screen.getByTestId('submissionButton');
fireEvent.click(submitButton);
expect(axiosMock.history.post.length).toBe(1);
await waitFor(() => {
const errorAlert = screen.getByTestId('saveError');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('You do not have permission to edit proctored exam settings for this course'),
);
expect(document.activeElement).toEqual(errorAlert);
});
});
it('Manages focus correctly after different save statuses', async () => {
@@ -855,57 +813,31 @@ describe('ProctoredExamSettings', () => {
StudioApiService.getProctoredExamSettingsUrl(defaultProps.courseId),
).reply(500);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
await act(async () => render(renderComponent(<ProctoredExamSettings {...defaultProps} />)));
const submitButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(submitButton);
});
fireEvent.click(submitButton);
expect(axiosMock.history.post.length).toBe(1);
const errorAlert = screen.getByTestId('saveError');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('We encountered a technical error while trying to save proctored exam settings'),
);
expect(document.activeElement).toEqual(errorAlert);
await waitFor(() => {
const errorAlert = screen.getByTestId('saveError');
expect(errorAlert.textContent).toEqual(
expect.stringContaining('We encountered a technical error while trying to save proctored exam settings'),
);
expect(document.activeElement).toEqual(errorAlert);
});
// now make a call that will allow for a successful save
axiosMock.onPost(
StudioApiService.getProctoredExamSettingsUrl(defaultProps.courseId),
).reply(200, 'success');
await act(async () => {
fireEvent.click(submitButton);
});
fireEvent.click(submitButton);
expect(axiosMock.history.post.length).toBe(2);
const successAlert = screen.getByTestId('saveSuccess');
expect(successAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(successAlert);
});
it('Include Zendesk ticket in post request if user is not an admin', async () => {
// use non-admin user for test
const isAdmin = false;
setupApp(isAdmin);
await act(async () => render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />)));
// Make a change to the proctoring provider
const selectElement = screen.getByDisplayValue('mockproc');
await act(async () => {
fireEvent.change(selectElement, { target: { value: 'proctortrack' } });
});
const submitButton = screen.getByTestId('submissionButton');
await act(async () => {
fireEvent.click(submitButton);
});
expect(axiosMock.history.post.length).toBe(1);
expect(JSON.parse(axiosMock.history.post[0].data)).toEqual({
proctored_exam_settings: {
enable_proctored_exams: true,
proctoring_provider: 'proctortrack',
proctoring_escalation_email: 'test@example.com',
create_zendesk_tickets: false,
},
await waitFor(() => {
const successAlert = screen.getByTestId('saveSuccess');
expect(successAlert.textContent).toEqual(
expect.stringContaining('Proctored exam settings saved successfully.'),
);
expect(document.activeElement).toEqual(successAlert);
});
});
});

View File

@@ -1,6 +1,11 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
'authoring.proctoring.alert.forbidden': {
id: 'authoring.proctoring.alert.forbidden',
defaultMessage: 'You do not have permission to edit proctored exam settings for this course. If you are a course team member and this problem persists, please go to the {support_link} for help.',
description: 'Alert message for proctoring settings permission error.',
},
'authoring.proctoring.no': {
id: 'authoring.proctoring.no',
defaultMessage: 'No',
@@ -76,11 +81,6 @@ const messages = defineMessages({
defaultMessage: 'Allow learners to opt out of proctoring on proctored exams',
description: 'Label for radio selection allowing proctored exam opt out',
},
'authoring.proctoring.createzendesk.label': {
id: 'authoring.proctoring.createzendesk.label',
defaultMessage: 'Create Zendesk tickets for suspicious attempts',
description: 'Label for Zendesk ticket creation radio select.',
},
'authoring.proctoring.error.single': {
id: 'authoring.proctoring.error.single',
defaultMessage: 'There is 1 error in this form.',

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"description": "Proctoring configuration for courses using it",
"peerDependencies": {
"@edx/frontend-app-course-authoring": "*",
"@edx/frontend-app-authoring": "*",
"@edx/frontend-platform": "*",
"@openedx/paragon": "*",
"classnames": "*",
@@ -13,7 +13,7 @@
"moment": "*"
},
"peerDependenciesMeta": {
"@edx/frontend-app-course-authoring": {
"@edx/frontend-app-authoring": {
"optional": true
}
}

View File

@@ -1,4 +1,4 @@
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import React from 'react';
import * as Yup from 'yup';
@@ -8,7 +8,8 @@ import { useAppSetting } from 'CourseAuthoring/utils';
import AppSettingsModal from 'CourseAuthoring/pages-and-resources/app-settings-modal/AppSettingsModal';
import messages from './messages';
const ProgressSettings = ({ intl, onClose }) => {
const ProgressSettings = ({ onClose }) => {
const intl = useIntl();
const [disableProgressGraph, saveSetting] = useAppSetting('disableProgressGraph');
const showProgressGraphSetting = getConfig().ENABLE_PROGRESS_GRAPH_SETTINGS.toString().toLowerCase() === 'true';
@@ -48,8 +49,7 @@ const ProgressSettings = ({ intl, onClose }) => {
};
ProgressSettings.propTypes = {
intl: intlShape.isRequired,
onClose: PropTypes.func.isRequired,
};
export default injectIntl(ProgressSettings);
export default ProgressSettings;

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"description": "Progress configuration for courses using it",
"peerDependencies": {
"@edx/frontend-app-course-authoring": "*",
"@edx/frontend-app-authoring": "*",
"@edx/frontend-platform": "*",
"@openedx/paragon": "*",
"prop-types": "*",
@@ -11,7 +11,7 @@
"yup": "*"
},
"peerDependenciesMeta": {
"@edx/frontend-app-course-authoring": {
"@edx/frontend-app-authoring": {
"optional": true
}
}

View File

@@ -1,4 +1,4 @@
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Button, Form, TransitionReplace } from '@openedx/paragon';
import PropTypes from 'prop-types';
import React, { useState } from 'react';
@@ -30,8 +30,9 @@ const TeamTypeNameMessage = {
};
const GroupEditor = ({
intl, group, onDelete, onChange, onBlur, fieldNameCommonBase, errors,
group, onDelete, onChange, onBlur, fieldNameCommonBase, errors,
}) => {
const intl = useIntl();
const [isDeleting, setDeleting] = useState(false);
const [isOpen, setOpen] = useState(group.id === null);
const initiateDeletion = () => setDeleting(true);
@@ -149,7 +150,6 @@ export const groupShape = PropTypes.shape({
});
GroupEditor.propTypes = {
intl: intlShape.isRequired,
fieldNameCommonBase: PropTypes.string.isRequired,
errors: PropTypes.shape({
name: PropTypes.string,
@@ -170,4 +170,4 @@ GroupEditor.defaultProps = {
},
};
export default injectIntl(GroupEditor);
export default GroupEditor;

View File

@@ -1,4 +1,4 @@
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Button, Form } from '@openedx/paragon';
import { Add } from '@openedx/paragon/icons';
@@ -17,15 +17,16 @@ import messages from './messages';
setupYupExtensions();
const TeamSettings = ({
intl,
onClose,
}) => {
const intl = useIntl();
const [teamsConfiguration, saveSettings] = useAppSetting('teamsConfiguration');
const blankNewGroup = {
name: '',
description: '',
type: GroupTypes.OPEN,
maxTeamSize: null,
userPartitionId: null,
id: null,
key: uuid(),
};
@@ -38,6 +39,7 @@ const TeamSettings = ({
type: group.type,
description: group.description,
max_team_size: group.maxTeamSize,
user_partition_id: group.userPartitionId,
}));
return saveSettings({
team_sets: groups,
@@ -105,6 +107,7 @@ const TeamSettings = ({
)
.when('enabled', {
is: true,
// oxlint-disable-next-line unicorn/no-thenable
then: Yup.array().min(1),
})
.default([])
@@ -164,8 +167,7 @@ const TeamSettings = ({
};
TeamSettings.propTypes = {
intl: intlShape.isRequired,
onClose: PropTypes.func.isRequired,
};
export default injectIntl(TeamSettings);
export default TeamSettings;

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"description": "Teams configuration for courses using it",
"peerDependencies": {
"@edx/frontend-app-course-authoring": "*",
"@edx/frontend-app-authoring": "*",
"@edx/frontend-platform": "*",
"@openedx/paragon": "*",
"formik": "*",
@@ -13,7 +13,7 @@
"yup": "*"
},
"peerDependenciesMeta": {
"@edx/frontend-app-course-authoring": {
"@edx/frontend-app-authoring": {
"optional": true
}
}

View File

@@ -1,4 +1,3 @@
/* eslint-disable import/prefer-default-export */
import { getConfig } from '@edx/frontend-platform';
import { GroupTypes } from 'CourseAuthoring/data/constants';

View File

@@ -1,4 +1,4 @@
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import React from 'react';
import * as Yup from 'yup';
@@ -8,7 +8,8 @@ import { useAppSetting } from 'CourseAuthoring/utils';
import AppSettingsModal from 'CourseAuthoring/pages-and-resources/app-settings-modal/AppSettingsModal';
import messages from './messages';
const WikiSettings = ({ intl, onClose }) => {
const WikiSettings = ({ onClose }) => {
const intl = useIntl();
const [enablePublicWiki, saveSetting] = useAppSetting('allowPublicWikiAccess');
const handleSettingsSave = (values) => saveSetting(values.enablePublicWiki);
@@ -32,7 +33,7 @@ const WikiSettings = ({ intl, onClose }) => {
label={intl.formatMessage(messages.enablePublicWikiLabel)}
helpText={intl.formatMessage(messages.enablePublicWikiHelp)}
onChange={handleChange}
onBlue={handleBlur}
onBlur={handleBlur}
checked={values.enablePublicWiki}
/>
)
@@ -42,8 +43,7 @@ const WikiSettings = ({ intl, onClose }) => {
};
WikiSettings.propTypes = {
intl: intlShape.isRequired,
onClose: PropTypes.func.isRequired,
};
export default injectIntl(WikiSettings);
export default WikiSettings;

View File

@@ -26,8 +26,8 @@ const messages = defineMessages({
},
enablePublicWikiHelp: {
id: 'course-authoring.pages-resources.wiki.enable-public-wiki.help',
defaultMessage: `If enabled, edX users can view the course wiki even when
they're not enrolled in the course.`,
defaultMessage: `If enabled, any registered user can view the course wiki
even if they are not enrolled in the course`,
},
});

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"description": "Wiki configuration for courses using it",
"peerDependencies": {
"@edx/frontend-app-course-authoring": "*",
"@edx/frontend-app-authoring": "*",
"@edx/frontend-platform": "*",
"@openedx/paragon": "*",
"prop-types": "*",
@@ -11,7 +11,7 @@
"yup": "*"
},
"peerDependenciesMeta": {
"@edx/frontend-app-course-authoring": {
"@edx/frontend-app-authoring": {
"optional": true
}
}

View File

@@ -1,7 +1,6 @@
import React, { useCallback, useContext, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { PagesAndResourcesContext } from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
import { useNavigate } from 'react-router-dom';
@@ -10,7 +9,8 @@ import messages from './messages';
import { fetchXpertSettings } from './data/thunks';
const XpertUnitSummarySettings = ({ intl }) => {
const XpertUnitSummarySettings = () => {
const intl = useIntl();
const { path: pagesAndResourcesPath, courseId } = useContext(PagesAndResourcesContext);
const dispatch = useDispatch();
const navigate = useNavigate();
@@ -38,8 +38,4 @@ const XpertUnitSummarySettings = ({ intl }) => {
);
};
XpertUnitSummarySettings.propTypes = {
intl: intlShape.isRequired,
};
export default injectIntl(XpertUnitSummarySettings);
export default XpertUnitSummarySettings;

View File

@@ -7,7 +7,7 @@ import {
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider, PageWrap } from '@edx/frontend-platform/react';
import {
queryByTestId, render, waitFor, getByText, fireEvent,
findByTestId, queryByTestId, render, waitFor, getByText, fireEvent,
} from '@testing-library/react';
import MockAdapter from 'axios-mock-adapter';
import PagesAndResourcesProvider from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
@@ -106,8 +106,9 @@ describe('XpertUnitSummarySettings', () => {
});
test('Shows switch on if enabled from backend', async () => {
const enableBadge = await findByTestId(container, 'enable-badge');
expect(container.querySelector('#enable-xpert-unit-summary-toggle').checked).toBeTruthy();
expect(queryByTestId(container, 'enable-badge')).toBeTruthy();
expect(enableBadge).toBeTruthy();
});
test('Shows switch on if disabled from backend', async () => {

View File

@@ -19,7 +19,7 @@ export function updateXpertSettings(courseId, state) {
}
dispatch(updateSavingStatus({ status: RequestStatus.FAILED }));
return false;
} catch (error) {
} catch {
dispatch(updateSavingStatus({ status: RequestStatus.FAILED }));
return false;
}
@@ -33,7 +33,7 @@ export function fetchXpertPluginConfigurable(courseId) {
try {
const { response } = await getXpertPluginConfigurable(courseId);
enabled = response?.enabled;
} catch (e) {
} catch {
enabled = undefined;
}
@@ -55,7 +55,7 @@ export function fetchXpertSettings(courseId) {
try {
const { response } = await getXpertSettings(courseId);
enabled = response?.enabled;
} catch (e) {
} catch {
enabled = undefined;
}
@@ -86,7 +86,7 @@ export function removeXpertSettings(courseId) {
}
dispatch(updateSavingStatus({ status: RequestStatus.FAILED }));
return false;
} catch (error) {
} catch {
dispatch(updateSavingStatus({ status: RequestStatus.FAILED }));
return false;
}
@@ -105,7 +105,7 @@ export function resetXpertSettings(courseId, state) {
}
dispatch(updateResetStatus({ status: RequestStatus.FAILED }));
return false;
} catch (error) {
} catch {
dispatch(updateResetStatus({ status: RequestStatus.FAILED }));
return false;
}

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"description": "Xpert Unit Summaries configuration for courses using it",
"peerDependencies": {
"@edx/frontend-app-course-authoring": "*",
"@edx/frontend-app-authoring": "*",
"@edx/frontend-platform": "*",
"@openedx/paragon": "*",
"formik": "*",
@@ -14,7 +14,7 @@
"react-router-dom": "*"
},
"peerDependenciesMeta": {
"@edx/frontend-app-course-authoring": {
"@edx/frontend-app-authoring": {
"optional": true
}
}

View File

@@ -1,4 +1,5 @@
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { getExternalLinkUrl } from '@edx/frontend-platform';
import {
ActionRow,
Alert,
@@ -70,38 +71,40 @@ AppSettingsForm.defaultProps = {
};
const SettingsModalBase = ({
intl, title, onClose, variant, isMobile, children, footer,
}) => (
<ModalDialog
title={title}
isOpen
onClose={onClose}
size="lg"
variant={variant}
hasCloseButton={isMobile}
isFullscreenOnMobile
>
<ModalDialog.Header>
<ModalDialog.Title data-testid="modal-title">
{title}
</ModalDialog.Title>
</ModalDialog.Header>
<ModalDialog.Body>
{children}
</ModalDialog.Body>
<ModalDialog.Footer className="p-4">
<ActionRow>
<ModalDialog.CloseButton variant="tertiary">
{intl.formatMessage(messages.cancel)}
</ModalDialog.CloseButton>
{footer}
</ActionRow>
</ModalDialog.Footer>
</ModalDialog>
);
title, onClose, variant, isMobile, children, footer,
}) => {
const intl = useIntl();
return (
<ModalDialog
title={title}
isOpen
onClose={onClose}
size="lg"
variant={variant}
hasCloseButton={isMobile}
isFullscreenOnMobile
>
<ModalDialog.Header>
<ModalDialog.Title data-testid="modal-title">
{title}
</ModalDialog.Title>
</ModalDialog.Header>
<ModalDialog.Body>
{children}
</ModalDialog.Body>
<ModalDialog.Footer className="p-4">
<ActionRow>
<ModalDialog.CloseButton variant="tertiary">
{intl.formatMessage(messages.cancel)}
</ModalDialog.CloseButton>
{footer}
</ActionRow>
</ModalDialog.Footer>
</ModalDialog>
);
};
SettingsModalBase.propTypes = {
intl: intlShape.isRequired,
title: PropTypes.string.isRequired,
onClose: PropTypes.func.isRequired,
variant: PropTypes.oneOf(['default', 'dark']).isRequired,
@@ -115,11 +118,11 @@ SettingsModalBase.defaultProps = {
};
const ResetUnitsButton = ({
intl,
courseId,
checked,
visible,
}) => {
const intl = useIntl();
const resetStatusRequestStatus = useSelector(getResetStatus);
const dispatch = useDispatch();
@@ -137,12 +140,12 @@ const ResetUnitsButton = ({
const getResetButtonState = () => {
switch (resetStatusRequestStatus) {
case RequestStatus.PENDING:
return 'pending';
case RequestStatus.SUCCESSFUL:
return 'finish';
default:
return 'default';
case RequestStatus.PENDING:
return 'pending';
case RequestStatus.SUCCESSFUL:
return 'finish';
default:
return 'default';
}
};
@@ -185,7 +188,6 @@ const ResetUnitsButton = ({
};
ResetUnitsButton.propTypes = {
intl: intlShape.isRequired,
courseId: PropTypes.string.isRequired,
checked: PropTypes.oneOf(['true', 'false']).isRequired,
visible: PropTypes.bool,
@@ -196,7 +198,6 @@ ResetUnitsButton.defaultProps = {
};
const SettingsModal = ({
intl,
appId,
title,
children,
@@ -213,6 +214,7 @@ const SettingsModal = ({
allUnitsEnabledText,
noUnitsEnabledText,
}) => {
const intl = useIntl();
const { courseId } = useContext(PagesAndResourcesContext);
const loadingStatus = useSelector(getLoadingStatus);
const updateSettingsRequestStatus = useSelector(getSavingStatus);
@@ -237,8 +239,10 @@ const SettingsModal = ({
const values = { ...rest, enabled: enabled ? checked === 'true' : undefined };
if (enabled) {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
success = await dispatch(updateXpertSettings(courseId, values));
} else {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
success = await dispatch(removeXpertSettings(courseId));
}
@@ -246,7 +250,7 @@ const SettingsModal = ({
success = success && await onSettingsSave(values);
}
setSaveError(!success);
!success && alertRef?.current.scrollIntoView(); // eslint-disable-line no-unused-expressions
!success && alertRef?.current.scrollIntoView(); // eslint-disable-line @typescript-eslint/no-unused-expressions
};
const handleFormikSubmit = ({ handleSubmit, errors }) => async (event) => {
@@ -275,7 +279,7 @@ const SettingsModal = ({
<div className="py-1">
<Hyperlink
className="text-primary-500"
destination="https://openai.com/api-data-privacy"
destination={getExternalLinkUrl('https://openai.com/api-data-privacy')}
target="_blank"
rel="noreferrer noopener"
>
@@ -372,7 +376,6 @@ const SettingsModal = ({
>
{allUnitsEnabledText}
<ResetUnitsButton
intl={intl}
courseId={courseId}
checked={formikProps.values.checked}
visible={formikProps.values.checked === 'true'}
@@ -385,7 +388,6 @@ const SettingsModal = ({
>
{noUnitsEnabledText}
<ResetUnitsButton
intl={intl}
courseId={courseId}
checked={formikProps.values.checked}
visible={formikProps.values.checked === 'false'}
@@ -423,7 +425,6 @@ const SettingsModal = ({
};
SettingsModal.propTypes = {
intl: intlShape.isRequired,
title: PropTypes.string.isRequired,
appId: PropTypes.string.isRequired,
children: PropTypes.func,
@@ -450,4 +451,4 @@ SettingsModal.defaultProps = {
enableReinitialize: false,
};
export default injectIntl(SettingsModal);
export default SettingsModal;

View File

@@ -1,5 +1,4 @@
@import "~@edx/brand/paragon/variables";
@import "~@openedx/paragon/scss/core/utilities-only";
@import "~@openedx/paragon/styles/scss/core/utilities-only";
.summary-radio {
display: flex;

View File

@@ -19,15 +19,6 @@
"matchPackagePatterns": ["@edx", "@openedx"],
"matchUpdateTypes": ["minor", "patch"],
"automerge": false
},
{
"matchPackagePatterns": ["@edx/frontend-lib-content-components"],
"matchUpdateTypes": ["minor", "patch"],
"automerge": false,
"schedule": [
"after 1am",
"before 11pm"
]
}
]
}

View File

@@ -0,0 +1,172 @@
import { getConfig } from '@edx/frontend-platform';
import {
createContext, useContext, useMemo, useState,
} from 'react';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { useCreateCourseBlock } from '@src/course-outline/data/apiHooks';
import { useSelector } from 'react-redux';
import { useNavigate } from 'react-router';
import { getOutlineIndexData } from '@src/course-outline/data/selectors';
import { useToggleWithValue } from '@src/hooks';
import { SelectionState, type UnitXBlock, type XBlock } from '@src/data/types';
import { CourseDetailsData } from './data/api';
import { useCourseDetails, useWaffleFlags } from './data/apiHooks';
import { RequestStatusType } from './data/constants';
type ModalState = {
value?: XBlock | UnitXBlock;
subsectionId?: string;
sectionId?: string;
};
export type CourseAuthoringContextData = {
/** The ID of the current course */
courseId: string;
courseUsageKey: string;
courseDetails?: CourseDetailsData;
courseDetailStatus: RequestStatusType;
canChangeProviders: boolean;
handleAddAndOpenUnit: ReturnType<typeof useCreateCourseBlock>;
handleAddBlock: ReturnType<typeof useCreateCourseBlock>;
openUnitPage: (locator: string) => void;
getUnitUrl: (locator: string) => string;
isUnlinkModalOpen: boolean;
currentUnlinkModalData?: ModalState;
openUnlinkModal: (value: ModalState) => void;
closeUnlinkModal: () => void;
isPublishModalOpen: boolean;
currentPublishModalData?: ModalState;
openPublishModal: (value: ModalState) => void;
closePublishModal: () => void;
currentSelection?: SelectionState;
setCurrentSelection: React.Dispatch<React.SetStateAction<SelectionState | undefined>>;
};
/**
* Course Authoring Context.
* Always available when we're in the context of a single course.
*
* Get this using `useCourseAuthoringContext()`
*
*/
const CourseAuthoringContext = createContext<CourseAuthoringContextData | undefined>(undefined);
type CourseAuthoringProviderProps = {
children?: React.ReactNode;
courseId: string;
};
export const CourseAuthoringProvider = ({
children,
courseId,
}: CourseAuthoringProviderProps) => {
const navigate = useNavigate();
const waffleFlags = useWaffleFlags();
const { data: courseDetails, status: courseDetailStatus } = useCourseDetails(courseId);
const canChangeProviders = getAuthenticatedUser().administrator || new Date(courseDetails?.start ?? 0) > new Date();
const { courseStructure } = useSelector(getOutlineIndexData);
const { id: courseUsageKey } = courseStructure || {};
const [
isUnlinkModalOpen,
currentUnlinkModalData,
openUnlinkModal,
closeUnlinkModal,
] = useToggleWithValue<ModalState>();
const [
isPublishModalOpen,
currentPublishModalData,
openPublishModal,
closePublishModal,
] = useToggleWithValue<ModalState>();
/**
* This will hold the state of current item that is being operated on,
* For example:
* - the details of container that is being edited.
* - the details of container of which see more dropdown is open.
* It is mostly used in modals which should be soon be replaced with its equivalent in sidebar.
*/
const [currentSelection, setCurrentSelection] = useState<SelectionState | undefined>();
const getUnitUrl = (locator: string) => {
if (getConfig().ENABLE_UNIT_PAGE === 'true' && waffleFlags.useNewUnitPage) {
// instanbul ignore next
return `/course/${courseId}/container/${locator}`;
}
return `${getConfig().STUDIO_BASE_URL}/container/${locator}`;
};
/**
* Open the unit page for a given locator.
*/
const openUnitPage = async (locator: string) => {
const url = getUnitUrl(locator);
if (getConfig().ENABLE_UNIT_PAGE === 'true' && waffleFlags.useNewUnitPage) {
// instanbul ignore next
navigate(url);
} else {
window.location.assign(url);
}
};
/**
* import a unit block from library and redirect user to this unit page.
*/
const handleAddAndOpenUnit = useCreateCourseBlock(courseId, openUnitPage);
const handleAddBlock = useCreateCourseBlock(courseId);
const context = useMemo<CourseAuthoringContextData>(() => ({
courseId,
courseUsageKey,
courseDetails,
courseDetailStatus,
canChangeProviders,
handleAddBlock,
handleAddAndOpenUnit,
getUnitUrl,
openUnitPage,
isUnlinkModalOpen,
openUnlinkModal,
closeUnlinkModal,
currentUnlinkModalData,
isPublishModalOpen,
currentPublishModalData,
openPublishModal,
closePublishModal,
currentSelection,
setCurrentSelection,
}), [
courseId,
courseUsageKey,
courseDetails,
courseDetailStatus,
canChangeProviders,
handleAddBlock,
handleAddAndOpenUnit,
getUnitUrl,
openUnitPage,
isUnlinkModalOpen,
openUnlinkModal,
closeUnlinkModal,
currentUnlinkModalData,
isPublishModalOpen,
currentPublishModalData,
openPublishModal,
closePublishModal,
currentSelection,
setCurrentSelection,
]);
return (
<CourseAuthoringContext.Provider value={context}>
{children}
</CourseAuthoringContext.Provider>
);
};
export function useCourseAuthoringContext(): CourseAuthoringContextData {
const ctx = useContext(CourseAuthoringContext);
if (ctx === undefined) {
/* istanbul ignore next */
throw new Error('useCourseAuthoringContext() was used in a component without a <CourseAuthoringProvider> ancestor.');
}
return ctx;
}

View File

@@ -1,100 +0,0 @@
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import {
useLocation,
} from 'react-router-dom';
import { StudioFooter } from '@edx/frontend-component-footer';
import Header from './header';
import { fetchCourseDetail } from './data/thunks';
import { useModel } from './generic/model-store';
import NotFoundAlert from './generic/NotFoundAlert';
import PermissionDeniedAlert from './generic/PermissionDeniedAlert';
import { getCourseAppsApiStatus } from './pages-and-resources/data/selectors';
import { RequestStatus } from './data/constants';
import Loading from './generic/Loading';
const AppHeader = ({
courseNumber, courseOrg, courseTitle, courseId,
}) => (
<Header
courseNumber={courseNumber}
courseOrg={courseOrg}
courseTitle={courseTitle}
courseId={courseId}
/>
);
AppHeader.propTypes = {
courseId: PropTypes.string.isRequired,
courseNumber: PropTypes.string,
courseOrg: PropTypes.string,
courseTitle: PropTypes.string.isRequired,
};
AppHeader.defaultProps = {
courseNumber: null,
courseOrg: null,
};
const CourseAuthoringPage = ({ courseId, children }) => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchCourseDetail(courseId));
}, [courseId]);
const courseDetail = useModel('courseDetails', courseId);
const courseNumber = courseDetail ? courseDetail.number : null;
const courseOrg = courseDetail ? courseDetail.org : null;
const courseTitle = courseDetail ? courseDetail.name : courseId;
const courseAppsApiStatus = useSelector(getCourseAppsApiStatus);
const courseDetailStatus = useSelector(state => state.courseDetail.status);
const inProgress = courseDetailStatus === RequestStatus.IN_PROGRESS;
const { pathname } = useLocation();
const isEditor = pathname.includes('/editor');
if (courseDetailStatus === RequestStatus.NOT_FOUND && !isEditor) {
return (
<NotFoundAlert />
);
}
if (courseAppsApiStatus === RequestStatus.DENIED) {
return (
<PermissionDeniedAlert />
);
}
return (
<div className={pathname.includes('/editor/') ? '' : 'bg-light-200'}>
{/* While V2 Editors are temporarily served from their own pages
using url pattern containing /editor/,
we shouldn't have the header and footer on these pages.
This functionality will be removed in TNL-9591 */}
{inProgress ? !isEditor && <Loading />
: (!isEditor && (
<AppHeader
courseNumber={courseNumber}
courseOrg={courseOrg}
courseTitle={courseTitle}
courseId={courseId}
/>
)
)}
{children}
{!inProgress && !isEditor && <StudioFooter />}
</div>
);
};
CourseAuthoringPage.propTypes = {
children: PropTypes.node,
courseId: PropTypes.string.isRequired,
};
CourseAuthoringPage.defaultProps = {
children: null,
};
export default CourseAuthoringPage;

View File

@@ -1,18 +1,12 @@
import React from 'react';
import { getConfig } from '@edx/frontend-platform';
import { render } from '@testing-library/react';
import { getConfig, initializeMockApp } from '@edx/frontend-platform';
import MockAdapter from 'axios-mock-adapter';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider } from '@edx/frontend-platform/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import initializeStore from './store';
import CourseAuthoringPage from './CourseAuthoringPage';
import PagesAndResources from './pages-and-resources/PagesAndResources';
import { executeThunk } from './utils';
import { fetchCourseApps } from './pages-and-resources/data/thunks';
import { fetchCourseDetail } from './data/thunks';
import { getApiWaffleFlagsUrl } from './data/api';
import { initializeMocks, render } from './testUtils';
import { CourseAuthoringProvider } from './CourseAuthoringContext';
const courseId = 'course-v1:edX+TestX+Test_Course';
let mockPathname = '/evilguy/';
@@ -25,17 +19,19 @@ jest.mock('react-router-dom', () => ({
let axiosMock;
let store;
beforeEach(() => {
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: true,
roles: [],
},
});
store = initializeStore();
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
const renderComponent = children => render(
<CourseAuthoringProvider courseId={courseId}>
{children}
</CourseAuthoringProvider>,
);
beforeEach(async () => {
const mocks = initializeMocks();
store = mocks.reduxStore;
axiosMock = mocks.axiosMock;
axiosMock
.onGet(getApiWaffleFlagsUrl(courseId))
.reply(200, {});
});
describe('Editor Pages Load no header', () => {
@@ -45,19 +41,14 @@ describe('Editor Pages Load no header', () => {
axiosMock.onGet(`${courseAppsApiUrl}/${courseId}`).reply(200, {
response: { status: 200 },
});
await executeThunk(fetchCourseApps(courseId), store.dispatch);
};
test('renders no loading wheel on editor pages', async () => {
mockPathname = '/editor/';
await mockStoreSuccess();
const wrapper = render(
<AppProvider store={store}>
<IntlProvider locale="en">
<CourseAuthoringPage courseId={courseId}>
<PagesAndResources courseId={courseId} />
</CourseAuthoringPage>
</IntlProvider>
</AppProvider>
const wrapper = renderComponent(
<CourseAuthoringPage>
<PagesAndResources />
</CourseAuthoringPage>
,
);
expect(wrapper.queryByRole('status')).not.toBeInTheDocument();
@@ -65,14 +56,10 @@ describe('Editor Pages Load no header', () => {
test('renders loading wheel on non editor pages', async () => {
mockPathname = '/evilguy/';
await mockStoreSuccess();
const wrapper = render(
<AppProvider store={store}>
<IntlProvider locale="en">
<CourseAuthoringPage courseId={courseId}>
<PagesAndResources courseId={courseId} />
</CourseAuthoringPage>
</IntlProvider>
</AppProvider>
const wrapper = renderComponent(
<CourseAuthoringPage>
<PagesAndResources />
</CourseAuthoringPage>
,
);
expect(wrapper.queryByRole('status')).toBeInTheDocument();
@@ -88,7 +75,6 @@ describe('Course authoring page', () => {
).reply(404, {
response: { status: 404 },
});
await executeThunk(fetchCourseDetail(courseId), store.dispatch);
};
const mockStoreError = async () => {
axiosMock.onGet(
@@ -96,18 +82,10 @@ describe('Course authoring page', () => {
).reply(500, {
response: { status: 500 },
});
await executeThunk(fetchCourseDetail(courseId), store.dispatch);
};
test('renders not found page on non-existent course key', async () => {
await mockStoreNotFound();
const wrapper = render(
<AppProvider store={store}>
<IntlProvider locale="en">
<CourseAuthoringPage courseId={courseId} />
</IntlProvider>
</AppProvider>
,
);
const wrapper = renderComponent(<CourseAuthoringPage />);
expect(await wrapper.findByTestId('notFoundAlert')).toBeInTheDocument();
});
test('does not render not found page on other kinds of error', async () => {
@@ -117,17 +95,29 @@ describe('Course authoring page', () => {
// IN_PROGRESS but also not NOT_FOUND or DENIED- then check that the not
// found alert is not present.
const contentTestId = 'courseAuthoringPageContent';
const wrapper = render(
<AppProvider store={store}>
<IntlProvider locale="en">
<CourseAuthoringPage courseId={courseId}>
<div data-testid={contentTestId} />
</CourseAuthoringPage>
</IntlProvider>
</AppProvider>
const wrapper = renderComponent(
<CourseAuthoringPage>
<div data-testid={contentTestId} />
</CourseAuthoringPage>
,
);
expect(await wrapper.findByTestId(contentTestId)).toBeInTheDocument();
expect(wrapper.queryByTestId('notFoundAlert')).not.toBeInTheDocument();
});
const mockStoreDenied = async () => {
const studioApiBaseUrl = getConfig().STUDIO_BASE_URL;
const courseAppsApiUrl = `${studioApiBaseUrl}/api/course_apps/v1/apps`;
axiosMock.onGet(
`${courseAppsApiUrl}/${courseId}`,
).reply(403);
await executeThunk(fetchCourseApps(courseId), store.dispatch);
};
test('renders PermissionDeniedAlert when courseAppsApiStatus is DENIED', async () => {
mockPathname = '/editor/';
await mockStoreDenied();
const wrapper = renderComponent(<CourseAuthoringPage />);
expect(await wrapper.findByTestId('permissionDeniedAlert')).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,72 @@
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
useLocation,
} from 'react-router-dom';
import { StudioFooterSlot } from '@edx/frontend-component-footer';
import Header from './header';
import NotFoundAlert from './generic/NotFoundAlert';
import PermissionDeniedAlert from './generic/PermissionDeniedAlert';
import { fetchOnlyStudioHomeData } from './studio-home/data/thunks';
import { getCourseAppsApiStatus } from './pages-and-resources/data/selectors';
import { RequestStatus } from './data/constants';
import Loading from './generic/Loading';
import { useCourseAuthoringContext } from './CourseAuthoringContext';
interface Props {
children?: React.ReactNode;
}
const CourseAuthoringPage = ({ children }: Props) => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchOnlyStudioHomeData());
}, []);
const { courseId, courseDetails, courseDetailStatus } = useCourseAuthoringContext();
const courseNumber = courseDetails?.number;
const courseOrg = courseDetails?.org;
const courseTitle = courseDetails?.name;
const inProgress = courseDetailStatus === RequestStatus.IN_PROGRESS || courseDetailStatus === RequestStatus.PENDING;
const courseAppsApiStatus = useSelector(getCourseAppsApiStatus);
const { pathname } = useLocation();
const isEditor = pathname.includes('/editor');
if (courseDetailStatus === RequestStatus.NOT_FOUND && !isEditor) {
return (
<NotFoundAlert />
);
}
if (courseAppsApiStatus === RequestStatus.DENIED) {
return (
<PermissionDeniedAlert />
);
}
return (
<div>
{/* While V2 Editors are temporarily served from their own pages
using url pattern containing /editor/,
we shouldn't have the header and footer on these pages.
This functionality will be removed in TNL-9591 */}
{inProgress ? !isEditor && <Loading />
: (!isEditor && (
<Header
number={courseNumber}
org={courseOrg}
title={courseTitle}
contextId={courseId}
containerProps={{
size: 'fluid',
}}
/>
)
)}
{children}
{!inProgress && !isEditor && <StudioFooterSlot />}
</div>
);
};
export default CourseAuthoringPage;

View File

@@ -1,123 +0,0 @@
import React from 'react';
import {
Navigate, Routes, Route, useParams,
} from 'react-router-dom';
import { getConfig } from '@edx/frontend-platform';
import { PageWrap } from '@edx/frontend-platform/react';
import CourseAuthoringPage from './CourseAuthoringPage';
import { PagesAndResources } from './pages-and-resources';
import EditorContainer from './editors/EditorContainer';
import VideoSelectorContainer from './selectors/VideoSelectorContainer';
import CustomPages from './custom-pages';
import { FilesPage, VideosPage } from './files-and-videos';
import { AdvancedSettings } from './advanced-settings';
import { CourseOutline } from './course-outline';
import ScheduleAndDetails from './schedule-and-details';
import { GradingSettings } from './grading-settings';
import CourseTeam from './course-team/CourseTeam';
import { CourseUpdates } from './course-updates';
import { CourseUnit } from './course-unit';
import CourseExportPage from './export-page/CourseExportPage';
import CourseImportPage from './import-page/CourseImportPage';
import { DECODED_ROUTES } from './constants';
import CourseChecklist from './course-checklist';
/**
* As of this writing, these routes are mounted at a path prefixed with the following:
*
* /course/:courseId
*
* Meaning that their absolute paths look like:
*
* /course/:courseId/course-pages
* /course/:courseId/proctored-exam-settings
* /course/:courseId/editor/:blockType/:blockId
*
* This component and CourseAuthoringPage should maybe be combined once we no longer need to have
* CourseAuthoringPage split out for use in LegacyProctoringRoute. Once that route is removed, we
* can move the Header/Footer rendering to this component and likely pull the course detail loading
* in as well, and it'd feel a bit better-factored and the roles would feel more clear.
*/
const CourseAuthoringRoutes = () => {
const { courseId } = useParams();
return (
<CourseAuthoringPage courseId={courseId}>
<Routes>
<Route
path="/"
element={<PageWrap><CourseOutline courseId={courseId} /></PageWrap>}
/>
<Route
path="course_info"
element={<PageWrap><CourseUpdates courseId={courseId} /></PageWrap>}
/>
<Route
path="assets"
element={<PageWrap><FilesPage courseId={courseId} /></PageWrap>}
/>
<Route
path="videos"
element={getConfig().ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN === 'true' ? <PageWrap><VideosPage courseId={courseId} /></PageWrap> : null}
/>
<Route
path="pages-and-resources/*"
element={<PageWrap><PagesAndResources courseId={courseId} /></PageWrap>}
/>
<Route
path="proctored-exam-settings"
element={<Navigate replace to={`/course/${courseId}/pages-and-resources`} />}
/>
<Route
path="custom-pages/*"
element={<PageWrap><CustomPages courseId={courseId} /></PageWrap>}
/>
{DECODED_ROUTES.COURSE_UNIT.map((path) => (
<Route
key={path}
path={path}
element={<PageWrap><CourseUnit courseId={courseId} /></PageWrap>}
/>
))}
<Route
path="editor/course-videos/:blockId"
element={getConfig().ENABLE_NEW_EDITOR_PAGES === 'true' ? <PageWrap><VideoSelectorContainer courseId={courseId} /></PageWrap> : null}
/>
<Route
path="editor/:blockType/:blockId?"
element={getConfig().ENABLE_NEW_EDITOR_PAGES === 'true' ? <PageWrap><EditorContainer courseId={courseId} /></PageWrap> : null}
/>
<Route
path="settings/details"
element={<PageWrap><ScheduleAndDetails courseId={courseId} /></PageWrap>}
/>
<Route
path="settings/grading"
element={<PageWrap><GradingSettings courseId={courseId} /></PageWrap>}
/>
<Route
path="course_team"
element={<PageWrap><CourseTeam courseId={courseId} /></PageWrap>}
/>
<Route
path="settings/advanced"
element={<PageWrap><AdvancedSettings courseId={courseId} /></PageWrap>}
/>
<Route
path="import"
element={<PageWrap><CourseImportPage courseId={courseId} /></PageWrap>}
/>
<Route
path="export"
element={<PageWrap><CourseExportPage courseId={courseId} /></PageWrap>}
/>
<Route
path="checklists"
element={<PageWrap><CourseChecklist courseId={courseId} /></PageWrap>}
/>
</Routes>
</CourseAuthoringPage>
);
};
export default CourseAuthoringRoutes;

View File

@@ -1,116 +0,0 @@
import React from 'react';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeMockApp } from '@edx/frontend-platform';
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import CourseAuthoringRoutes from './CourseAuthoringRoutes';
import initializeStore from './store';
const courseId = 'course-v1:edX+TestX+Test_Course';
const pagesAndResourcesMockText = 'Pages And Resources';
const editorContainerMockText = 'Editor Container';
const videoSelectorContainerMockText = 'Video Selector Container';
const customPagesMockText = 'Custom Pages';
let store;
const mockComponentFn = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => ({
courseId,
}),
}));
// Mock the TinyMceWidget from frontend-lib-content-components
jest.mock('@edx/frontend-lib-content-components', () => ({
TinyMceWidget: () => <div>Widget</div>,
Footer: () => <div>Footer</div>,
prepareEditorRef: jest.fn(() => ({
refReady: true,
setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'),
})),
}));
jest.mock('./pages-and-resources/PagesAndResources', () => (props) => {
mockComponentFn(props);
return pagesAndResourcesMockText;
});
jest.mock('./editors/EditorContainer', () => (props) => {
mockComponentFn(props);
return editorContainerMockText;
});
jest.mock('./selectors/VideoSelectorContainer', () => (props) => {
mockComponentFn(props);
return videoSelectorContainerMockText;
});
jest.mock('./custom-pages/CustomPages', () => (props) => {
mockComponentFn(props);
return customPagesMockText;
});
describe('<CourseAuthoringRoutes>', () => {
beforeEach(() => {
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: true,
roles: [],
},
});
store = initializeStore();
});
fit('renders the PagesAndResources component when the pages and resources route is active', () => {
render(
<AppProvider store={store} wrapWithRouter={false}>
<MemoryRouter initialEntries={['/pages-and-resources']}>
<CourseAuthoringRoutes />
</MemoryRouter>
</AppProvider>,
);
expect(screen.getByText(pagesAndResourcesMockText)).toBeVisible();
expect(mockComponentFn).toHaveBeenCalledWith(
expect.objectContaining({
courseId,
}),
);
});
it('renders the EditorContainer component when the course editor route is active', () => {
render(
<AppProvider store={store} wrapWithRouter={false}>
<MemoryRouter initialEntries={['/editor/video/block-id']}>
<CourseAuthoringRoutes />
</MemoryRouter>
</AppProvider>,
);
expect(screen.queryByText(editorContainerMockText)).toBeInTheDocument();
expect(screen.queryByText(pagesAndResourcesMockText)).not.toBeInTheDocument();
expect(mockComponentFn).toHaveBeenCalledWith(
expect.objectContaining({
courseId,
}),
);
});
it('renders the VideoSelectorContainer component when the course videos route is active', () => {
render(
<AppProvider store={store} wrapWithRouter={false}>
<MemoryRouter initialEntries={['/editor/course-videos/block-id']}>
<CourseAuthoringRoutes />
</MemoryRouter>
</AppProvider>,
);
expect(screen.queryByText(videoSelectorContainerMockText)).toBeInTheDocument();
expect(screen.queryByText(pagesAndResourcesMockText)).not.toBeInTheDocument();
expect(mockComponentFn).toHaveBeenCalledWith(
expect.objectContaining({
courseId,
}),
);
});
});

View File

@@ -0,0 +1,99 @@
import CourseAuthoringRoutes from './CourseAuthoringRoutes';
import { getApiWaffleFlagsUrl } from './data/api';
import {
screen, initializeMocks, render, waitFor,
} from './testUtils';
const courseId = 'course-v1:edX+TestX+Test_Course';
const pagesAndResourcesMockText = 'Pages And Resources';
const editorContainerMockText = 'Editor Container';
const videoSelectorContainerMockText = 'Video Selector Container';
const customPagesMockText = 'Custom Pages';
const mockComponentFn = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => ({
courseId,
}),
}));
// Mock the TinyMceWidget
jest.mock('./editors/sharedComponents/TinyMceWidget', () => ({
__esModule: true, // Required to mock a default export
default: () => <div>Widget</div>,
Footer: () => <div>Footer</div>,
prepareEditorRef: jest.fn(() => ({
refReady: true,
setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'),
})),
}));
jest.mock('./pages-and-resources/PagesAndResources', () => (props) => {
mockComponentFn(props);
return pagesAndResourcesMockText;
});
jest.mock('./editors/EditorContainer', () => (props) => {
mockComponentFn(props);
return editorContainerMockText;
});
jest.mock('./selectors/VideoSelectorContainer', () => (props) => {
mockComponentFn(props);
return videoSelectorContainerMockText;
});
jest.mock('./custom-pages/CustomPages', () => (props) => {
mockComponentFn(props);
return customPagesMockText;
});
describe('<CourseAuthoringRoutes>', () => {
beforeEach(async () => {
const user = {
userId: 1,
username: 'username',
};
const { axiosMock } = initializeMocks({ user });
axiosMock
.onGet(getApiWaffleFlagsUrl(courseId))
.reply(200, {});
});
it('renders the PagesAndResources component when the pages and resources route is active', async () => {
render(
<CourseAuthoringRoutes />,
{ routerProps: { initialEntries: ['/pages-and-resources'] } },
);
await waitFor(() => {
expect(screen.getByText(pagesAndResourcesMockText)).toBeVisible();
expect(mockComponentFn).toHaveBeenCalled();
});
});
it('renders the EditorContainer component when the course editor route is active', async () => {
render(
<CourseAuthoringRoutes />,
{ routerProps: { initialEntries: ['/editor/video/block-id'] } },
);
await waitFor(() => {
expect(screen.queryByText(editorContainerMockText)).toBeInTheDocument();
expect(screen.queryByText(pagesAndResourcesMockText)).not.toBeInTheDocument();
expect(mockComponentFn).toHaveBeenCalledWith(
expect.objectContaining({
learningContextId: courseId,
}),
);
});
});
it('renders the VideoSelectorContainer component when the course videos route is active', async () => {
render(
<CourseAuthoringRoutes />,
{ routerProps: { initialEntries: ['/editor/course-videos/block-id'] } },
);
await waitFor(() => {
expect(screen.queryByText(videoSelectorContainerMockText)).toBeInTheDocument();
expect(screen.queryByText(pagesAndResourcesMockText)).not.toBeInTheDocument();
expect(mockComponentFn).toHaveBeenCalled();
});
});
});

View File

@@ -0,0 +1,186 @@
import {
Navigate, Routes, Route, useParams,
} from 'react-router-dom';
import { getConfig } from '@edx/frontend-platform';
import { PageWrap } from '@edx/frontend-platform/react';
import { Textbooks } from './textbooks';
import CourseAuthoringPage from './CourseAuthoringPage';
import { PagesAndResources } from './pages-and-resources';
import EditorContainer from './editors/EditorContainer';
import VideoSelectorContainer from './selectors/VideoSelectorContainer';
import CustomPages from './custom-pages';
import { FilesPage, VideosPage } from './files-and-videos';
import { AdvancedSettings } from './advanced-settings';
import {
CourseOutline,
OutlineSidebarProvider,
OutlineSidebarPagesProvider,
} from './course-outline';
import ScheduleAndDetails from './schedule-and-details';
import { GradingSettings } from './grading-settings';
import CourseTeam from './course-team/CourseTeam';
import { CourseUpdates } from './course-updates';
import { CourseUnit, SubsectionUnitRedirect } from './course-unit';
import { Certificates } from './certificates';
import CourseExportPage from './export-page/CourseExportPage';
import CourseOptimizerPage from './optimizer-page/CourseOptimizerPage';
import CourseImportPage from './import-page/CourseImportPage';
import { DECODED_ROUTES } from './constants';
import CourseChecklist from './course-checklist';
import GroupConfigurations from './group-configurations';
import { CourseLibraries } from './course-libraries';
import { IframeProvider } from './generic/hooks/context/iFrameContext';
import { CourseAuthoringProvider } from './CourseAuthoringContext';
import { CourseImportProvider } from './import-page/CourseImportContext';
import { CourseExportProvider } from './export-page/CourseExportContext';
/**
* As of this writing, these routes are mounted at a path prefixed with the following:
*
* /course/:courseId
*
* Meaning that their absolute paths look like:
*
* /course/:courseId/course-pages
* /course/:courseId/proctored-exam-settings
* /course/:courseId/editor/:blockType/:blockId
*
* This component and CourseAuthoringPage should maybe be combined once we no longer need to have
* CourseAuthoringPage split out for use in LegacyProctoringRoute. Once that route is removed, we
* can move the Header/Footer rendering to this component and likely pull the course detail loading
* in as well, and it'd feel a bit better-factored and the roles would feel more clear.
*/
const CourseAuthoringRoutes = () => {
const { courseId } = useParams();
if (courseId === undefined) {
// istanbul ignore next - This shouldn't be possible; it's just here to satisfy the type checker.
throw new Error('Error: route is missing courseId.');
}
return (
<CourseAuthoringProvider courseId={courseId}>
<CourseAuthoringPage>
<Routes>
<Route
path="/"
element={(
<PageWrap>
<OutlineSidebarPagesProvider>
<OutlineSidebarProvider>
<CourseOutline />
</OutlineSidebarProvider>
</OutlineSidebarPagesProvider>
</PageWrap>
)}
/>
<Route
path="course_info"
element={<PageWrap><CourseUpdates /></PageWrap>}
/>
<Route
path="libraries"
element={<PageWrap><CourseLibraries /></PageWrap>}
/>
<Route
path="assets"
element={<PageWrap><FilesPage /></PageWrap>}
/>
<Route
path="videos"
element={getConfig().ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN === 'true' ? <PageWrap><VideosPage /></PageWrap> : null}
/>
<Route
path="pages-and-resources/*"
element={<PageWrap><PagesAndResources /></PageWrap>}
/>
<Route
path="proctored-exam-settings"
element={<Navigate replace to={`/course/${courseId}/pages-and-resources`} />}
/>
<Route
path="custom-pages/*"
element={<PageWrap><CustomPages /></PageWrap>}
/>
<Route
path="/subsection/:subsectionId"
element={<PageWrap><SubsectionUnitRedirect /></PageWrap>}
/>
{DECODED_ROUTES.COURSE_UNIT.map((path) => (
<Route
key={path}
path={path}
element={<PageWrap><IframeProvider><CourseUnit /></IframeProvider></PageWrap>}
/>
))}
<Route
path="editor/course-videos/:blockId"
element={<PageWrap><VideoSelectorContainer /></PageWrap>}
/>
<Route
path="editor/:blockType/:blockId?"
element={<PageWrap><EditorContainer learningContextId={courseId} /></PageWrap>}
/>
<Route
path="settings/details"
element={<PageWrap><ScheduleAndDetails /></PageWrap>}
/>
<Route
path="settings/grading"
element={<PageWrap><GradingSettings /></PageWrap>}
/>
<Route
path="course_team"
element={<PageWrap><CourseTeam /></PageWrap>}
/>
<Route
path="group_configurations"
element={<PageWrap><GroupConfigurations /></PageWrap>}
/>
<Route
path="settings/advanced"
element={<PageWrap><AdvancedSettings /></PageWrap>}
/>
<Route
path="import"
element={(
<PageWrap>
<CourseImportProvider>
<CourseImportPage />
</CourseImportProvider>
</PageWrap>
)}
/>
<Route
path="export"
element={(
<PageWrap>
<CourseExportProvider>
<CourseExportPage />
</CourseExportProvider>
</PageWrap>
)}
/>
<Route
path="optimizer"
element={<PageWrap><CourseOptimizerPage /></PageWrap>}
/>
<Route
path="checklists"
element={<PageWrap><CourseChecklist /></PageWrap>}
/>
<Route
path="certificates"
element={getConfig().ENABLE_CERTIFICATE_PAGE === 'true' ? <PageWrap><Certificates /></PageWrap> : null}
/>
<Route
path="textbooks"
element={<PageWrap><Textbooks /></PageWrap>}
/>
</Routes>
</CourseAuthoringPage>
</CourseAuthoringProvider>
);
};
export default CourseAuthoringRoutes;

View File

@@ -0,0 +1,16 @@
export default {
content: {
id: 67,
userId: 3,
created: '2024-01-16T13:09:11.540615Z',
purpose: 'clipboard',
status: 'ready',
blockType: 'chapter',
blockTypeDisplay: 'Section',
olxUrl: 'http://localhost:18010/api/content-staging/v1/staged-content/67/olx',
displayName: 'Chapter 1',
},
sourceUsageKey: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@chapter_0270f6de40fc',
sourceContextTitle: 'Demonstration Course',
sourceEditUrl: 'http://localhost:18010/container/block-v1:edX+DemoX+Demo_Course+type@chapter+block@chapter_0270f6de40fc',
};

View File

@@ -0,0 +1,16 @@
export default {
content: {
id: 67,
userId: 3,
created: '2024-01-16T13:09:11.540615Z',
purpose: 'clipboard',
status: 'ready',
blockType: 'sequential',
blockTypeDisplay: 'Subsection',
olxUrl: 'http://localhost:18010/api/content-staging/v1/staged-content/67/olx',
displayName: 'Sequences',
},
sourceUsageKey: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@sequential_0270f6de40fc',
sourceContextTitle: 'Demonstration Course',
sourceEditUrl: 'http://localhost:18010/container/block-v1:edX+DemoX+Demo_Course+type@sequential+block@sequential_0270f6de40fc',
};

View File

@@ -0,0 +1,16 @@
export default {
content: {
id: 67,
userId: 3,
created: '2024-01-16T13:09:11.540615Z',
purpose: 'clipboard',
status: 'ready',
blockType: 'vertical',
blockTypeDisplay: 'Unit',
olxUrl: 'http://localhost:18010/api/content-staging/v1/staged-content/67/olx',
displayName: 'Introduction: Video and Sequences',
},
sourceUsageKey: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_0270f6de40fc',
sourceContextTitle: 'Demonstration Course',
sourceEditUrl: 'http://localhost:18010/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical_0270f6de40fc',
};

View File

@@ -0,0 +1,16 @@
export default {
content: {
id: 69,
userId: 3,
created: '2024-01-16T13:33:21.314439Z',
purpose: 'clipboard',
status: 'ready',
blockType: 'html',
blockTypeDisplay: 'Text',
olxUrl: 'http://localhost:18010/api/content-staging/v1/staged-content/69/olx',
displayName: 'Blank HTML Page',
},
sourceUsageKey: 'block-v1:edX+DemoX+Demo_Course+type@html+block@html1',
sourceContextTitle: 'Demonstration Course',
sourceEditUrl: 'http://localhost:18010/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical1',
};

4
src/__mocks__/index.ts Normal file
View File

@@ -0,0 +1,4 @@
export { default as clipboardUnit } from './clipboardUnit';
export { default as clipboardSubsection } from './clipboardSubsection';
export { default as clipboardXBlock } from './clipboardXBlock';
export { default as clipboardSection } from './clipboardSection';

View File

@@ -1,46 +0,0 @@
import {
render,
screen,
} from '@testing-library/react';
import { AppProvider } from '@edx/frontend-platform/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { initializeMockApp } from '@edx/frontend-platform';
import initializeStore from '../../store';
import AccessibilityBody from './index';
let store;
const renderComponent = () => {
render(
<IntlProvider locale="en">
<AppProvider store={store}>
<AccessibilityBody
communityAccessibilityLink="http://example.com"
email="example@example.com"
/>
</AppProvider>
</IntlProvider>,
);
};
describe('<AccessibilityBody />', () => {
describe('renders', () => {
beforeEach(async () => {
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: false,
roles: [],
},
});
store = initializeStore({});
});
it('contains links', () => {
renderComponent();
expect(screen.getAllByTestId('email-element')).toHaveLength(2);
expect(screen.getAllByTestId('accessibility-page-link')).toHaveLength(1);
});
});
});

View File

@@ -0,0 +1,29 @@
import {
initializeMocks,
render,
screen,
} from '@src/testUtils';
import AccessibilityBody from './index';
const renderComponent = () => {
render(
<AccessibilityBody
communityAccessibilityLink="http://example.com"
email="example@example.com"
/>,
);
};
describe('<AccessibilityBody />', () => {
describe('renders', () => {
beforeEach(async () => {
initializeMocks();
});
it('contains links', () => {
renderComponent();
expect(screen.getAllByTestId('email-element')).toHaveLength(2);
expect(screen.getAllByTestId('accessibility-page-link')).toHaveLength(1);
});
});
});

View File

@@ -1,6 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { Hyperlink, MailtoLink, Stack } from '@openedx/paragon';
import messages from './messages';
@@ -8,6 +6,9 @@ import messages from './messages';
const AccessibilityBody = ({
communityAccessibilityLink,
email,
}: {
communityAccessibilityLink: string,
email: string,
}) => (
<div className="mt-5">
<header>
@@ -90,9 +91,4 @@ const AccessibilityBody = ({
</div>
);
AccessibilityBody.propTypes = {
communityAccessibilityLink: PropTypes.string.isRequired,
email: PropTypes.string.isRequired,
};
export default injectIntl(AccessibilityBody);
export default AccessibilityBody;

View File

@@ -1,57 +1,31 @@
import {
initializeMocks,
render,
act,
screen,
} from '@testing-library/react';
} from '@src/testUtils';
import userEvent from '@testing-library/user-event';
import { initializeMockApp } from '@edx/frontend-platform';
import MockAdapter from 'axios-mock-adapter';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { AppProvider } from '@edx/frontend-platform/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import initializeStore from '../../store';
import { RequestStatus } from '../../data/constants';
import AccessibilityForm from './index';
import { getZendeskrUrl } from '../data/api';
import messages from './messages';
let axiosMock;
let store;
const defaultProps = {
accessibilityEmail: 'accessibilityTest@test.com',
};
const initialState = {
accessibilityPage: {
savingStatus: '',
},
};
const renderComponent = () => {
render(
<IntlProvider locale="en">
<AppProvider store={store}>
<AccessibilityForm {...defaultProps} />
</AppProvider>
</IntlProvider>,
<AccessibilityForm {...defaultProps} />,
);
};
describe('<AccessibilityPolicyForm />', () => {
beforeEach(async () => {
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: false,
roles: [],
},
});
store = initializeStore(initialState);
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
const mocks = initializeMocks();
axiosMock = mocks.axiosMock;
});
describe('renders', () => {
@@ -74,24 +48,35 @@ describe('<AccessibilityPolicyForm />', () => {
describe('statusAlert', () => {
let formSections;
let submitButton;
let user;
beforeEach(async () => {
user = userEvent.setup();
renderComponent();
formSections = screen.getAllByRole('textbox');
await act(async () => {
userEvent.type(formSections[0], 'email@email.com');
userEvent.type(formSections[1], 'test name');
userEvent.type(formSections[2], 'feedback message');
});
await user.type(formSections[0], 'email@email.com');
await user.type(formSections[1], 'test name');
await user.type(formSections[2], 'feedback message');
submitButton = screen.getByText(messages.accessibilityPolicyFormSubmitLabel.defaultMessage);
});
it('renders in progress state', async () => {
axiosMock.onPost(getZendeskrUrl()).reply(
() => new Promise(() => {
// always in pending
}),
);
await user.click(submitButton);
expect(screen.getByRole('button', { name: /submitting/i })).toBeInTheDocument();
});
it('shows correct success message', async () => {
axiosMock.onPost(getZendeskrUrl()).reply(200);
await act(async () => {
userEvent.click(submitButton);
});
const { savingStatus } = store.getState().accessibilityPage;
expect(savingStatus).toEqual(RequestStatus.SUCCESSFUL);
await user.click(submitButton);
expect(screen.getAllByRole('alert')).toHaveLength(1);
@@ -104,11 +89,8 @@ describe('<AccessibilityPolicyForm />', () => {
it('shows correct rate limiting message', async () => {
axiosMock.onPost(getZendeskrUrl()).reply(429);
await act(async () => {
userEvent.click(submitButton);
});
const { savingStatus } = store.getState().accessibilityPage;
expect(savingStatus).toEqual(RequestStatus.FAILED);
await user.click(submitButton);
expect(screen.getAllByRole('alert')).toHaveLength(1);
@@ -123,23 +105,24 @@ describe('<AccessibilityPolicyForm />', () => {
describe('input validation', () => {
let formSections;
let submitButton;
let user;
beforeEach(async () => {
user = userEvent.setup();
renderComponent();
formSections = screen.getAllByRole('textbox');
await act(async () => {
userEvent.type(formSections[0], 'email@email.com');
userEvent.type(formSections[1], 'test name');
userEvent.type(formSections[2], 'feedback message');
});
await user.type(formSections[0], 'email@email.com');
await user.type(formSections[1], 'test name');
await user.type(formSections[2], 'feedback message');
submitButton = screen.getByText(messages.accessibilityPolicyFormSubmitLabel.defaultMessage);
});
it('adds validation checking on each input field', async () => {
await act(async () => {
userEvent.clear(formSections[0]);
userEvent.clear(formSections[1]);
userEvent.clear(formSections[2]);
});
await user.clear(formSections[0]);
await user.clear(formSections[1]);
await user.clear(formSections[2]);
const emailError = screen.getByTestId('error-feedback-email');
expect(emailError).toBeVisible();
@@ -151,12 +134,10 @@ describe('<AccessibilityPolicyForm />', () => {
});
it('sumbit button is disabled when trying to submit with all empty fields', async () => {
await act(async () => {
userEvent.clear(formSections[0]);
userEvent.clear(formSections[1]);
userEvent.clear(formSections[2]);
userEvent.click(submitButton);
});
await user.clear(formSections[0]);
await user.clear(formSections[1]);
await user.clear(formSections[2]);
await user.click(submitButton);
expect(submitButton.closest('button')).toBeDisabled();
});

View File

@@ -1,33 +1,26 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
injectIntl, FormattedMessage, intlShape, FormattedDate, FormattedTime,
FormattedMessage, FormattedDate, FormattedTime, useIntl,
} from '@edx/frontend-platform/i18n';
import {
ActionRow, Alert, Form, Stack, StatefulButton,
} from '@openedx/paragon';
import { RequestStatus } from '../../data/constants';
import { STATEFUL_BUTTON_STATES } from '../../constants';
import submitAccessibilityForm from '../data/thunks';
import { STATEFUL_BUTTON_STATES } from '@src/constants';
import useAccessibility from './hooks';
import messages from './messages';
const AccessibilityForm = ({
accessibilityEmail,
// injected
intl,
}) => {
const AccessibilityForm = ({ accessibilityEmail }: { accessibilityEmail: string }) => {
const intl = useIntl();
const {
errors,
values,
isFormFilled,
dispatch,
mutation,
handleBlur,
handleChange,
hasErrorField,
savingStatus,
} = useAccessibility({ name: '', email: '', message: '' }, intl);
} = useAccessibility({ name: '', email: '', message: '' });
const formFields = [
{
@@ -56,7 +49,7 @@ const AccessibilityForm = ({
};
const handleSubmit = () => {
dispatch(submitAccessibilityForm(values));
mutation.mutateAsync(values).catch(() => {});
};
const start = new Date('Mon Jan 29 2018 13:00:00 GMT (UTC)');
@@ -67,7 +60,7 @@ const AccessibilityForm = ({
<h2 className="my-4">
<FormattedMessage {...messages.accessibilityPolicyFormHeader} />
</h2>
{savingStatus === RequestStatus.SUCCESSFUL && (
{savingStatus === 'success' && (
<Alert variant="success">
<Stack gap={2}>
<div className="mb-2">
@@ -87,7 +80,7 @@ const AccessibilityForm = ({
</Stack>
</Alert>
)}
{savingStatus === RequestStatus.FAILED && (
{savingStatus === 'error' && (
<Alert variant="danger">
<div data-testid="rate-limit-alert">
<FormattedMessage
@@ -126,7 +119,7 @@ const AccessibilityForm = ({
onClick={handleSubmit}
disabled={!isFormFilled}
state={
savingStatus === RequestStatus.IN_PROGRESS
savingStatus === 'pending'
? STATEFUL_BUTTON_STATES.pending
: STATEFUL_BUTTON_STATES.default
}
@@ -137,10 +130,4 @@ const AccessibilityForm = ({
);
};
AccessibilityForm.propTypes = {
accessibilityEmail: PropTypes.string.isRequired,
// injected
intl: intlShape.isRequired,
};
export default injectIntl(AccessibilityForm);
export default AccessibilityForm;

View File

@@ -1,14 +1,14 @@
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useFormik } from 'formik';
import * as Yup from 'yup';
import { RequestStatus } from '../../data/constants';
import messages from './messages';
import { useSubmitAccessibilityForm } from '../data/apiHooks';
import { AccessibilityFormData } from '../data/api';
const useAccessibility = (initialValues, intl) => {
const dispatch = useDispatch();
const savingStatus = useSelector(state => state.accessibilityPage.savingStatus);
const useAccessibility = (initialValues: AccessibilityFormData) => {
const intl = useIntl();
const [isFormFilled, setFormFilled] = useState(false);
const validationSchema = Yup.object().shape({
name: Yup.string().required(
@@ -29,29 +29,27 @@ const useAccessibility = (initialValues, intl) => {
enableReinitialize: true,
validateOnBlur: false,
validationSchema,
/* istanbul ignore next */
onSubmit: () => {},
});
const mutation = useSubmitAccessibilityForm(handleReset);
useEffect(() => {
setFormFilled(Object.values(values).every((i) => i));
}, [values]);
useEffect(() => {
if (savingStatus === RequestStatus.SUCCESSFUL) {
handleReset();
}
}, [savingStatus]);
const hasErrorField = (fieldName) => !!errors[fieldName] && !!touched[fieldName];
return {
errors,
values,
isFormFilled,
dispatch,
mutation,
handleBlur,
handleChange,
hasErrorField,
savingStatus,
savingStatus: mutation.status,
};
};

View File

@@ -1,42 +0,0 @@
import React from 'react';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { Helmet } from 'react-helmet';
import { Container } from '@openedx/paragon';
import { StudioFooter } from '@edx/frontend-component-footer';
import Header from '../header';
import messages from './messages';
import AccessibilityBody from './AccessibilityBody';
import AccessibilityForm from './AccessibilityForm';
const AccessibilityPage = ({
// injected
intl,
}) => {
const communityAccessibilityLink = 'https://www.edx.org/accessibility';
const email = 'accessibility@edx.org';
return (
<>
<Helmet>
<title>
{intl.formatMessage(messages.pageTitle, {
siteName: process.env.SITE_NAME,
})}
</title>
</Helmet>
<Header isHiddenMainMenu />
<Container size="xl" classNamae="px-4">
<AccessibilityBody {...{ email, communityAccessibilityLink }} />
<AccessibilityForm accessibilityEmail={email} />
</Container>
<StudioFooter />
</>
);
};
AccessibilityPage.propTypes = {
// injected
intl: intlShape.isRequired,
};
export default injectIntl(AccessibilityPage);

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