Skip to content

[FE] Competency Management Course Search/View #670

Open
1 of 5 issues completed
Open

Description

@thelmick-unicon

Use Case

As a Platform Administrator configuring Competency Criteria associations, I want to select a competency from the taxonomy's competency tree and then search the courses I have access to (filtered by course-run start date), browse a course's sections and gradeable subsections, so that I can find the exact gradeable subsection to attach criteria to without opening each course individually.

Acceptance Criteria

Scenario: Competency tree lists the taxonomy's competencies
  Given I open the Manage & Apply Competencies page for a competency taxonomy
  Then the left panel shows that taxonomy's competencies as a nested tree

Scenario: Selecting a competency drives the right-hand panel
  Given the competency tree is shown
  When I select any competency in the tree
  Then it becomes the active competency
  And the right-hand course-browse panel loads for that competency
  And this is true for every row in the tree, whether or not it has sub-competencies

Scenario: A competency with sub-competencies is selectable like any other
  Given the competency tree shows a competency that has sub-competencies beneath it
  When I click that competency's row
  Then it becomes the active competency
  And the right-hand course-browse panel loads for it
  And it behaves no differently from clicking a competency that has no sub-competencies

Scenario: Clicking a row selects it without expanding it
  Given a collapsed competency that has sub-competencies
  When I click its row
  Then it becomes the active competency
  And its sub-competencies stay collapsed

Scenario: The expand/collapse control only expands and collapses
  Given a competency that has sub-competencies
  When I click its expand/collapse arrow
  Then its sub-competencies show or hide
  And the active competency does not change
  And the right-hand panel does not change or reload

Scenario: A row's two controls are separately reachable and distinguishable
  Given the competency tree is shown
  When I move through a row that has sub-competencies using a keyboard
  Then I can reach both selecting the competency and expanding it as distinct controls
  And each is announced as a distinct action

Scenario: No competency selected yet
  Given I open the page and have not selected a competency
  Then the right-hand column is not rendered at all
  And nothing occupies that space: no panel, no background, no border, and no prompt
  And the competency tree is the only content on the page
  And no course search runs

Scenario: The right-hand column appears on the first selection
  Given I have not selected a competency and the right-hand column is absent
  When I select a competency
  Then the right-hand column renders for the first time
  And it shows the course-browse panel for that competency

Scenario: Search courses by title
  Given I have selected a competency and am viewing the course-browse panel
  When I enter a title filter
  Then the course list narrows to accessible courses whose title matches

Scenario: Filter courses by start-date range
  Given I am viewing the panel
  When I set a start and end boundary in the date-range picker
  Then the list shows only courses whose course-run start date falls within that range
  And the UI makes clear the filter is on course start date

Scenario: Default view shows all accessible courses
  Given I have entered no title filter and no date range
  When the panel loads
  Then it shows all courses I have access to

Scenario: Expand a course to browse its gradeable subsections
  Given a course appears in the results
  When I expand it
  Then its sections and gradeable subsections are displayed
  And the course and section rows are navigation only, not selectable as association targets

Scenario: Course search fails
  Given the #669 course-search call fails
  Then an inline error state is shown, distinct from an empty-results state

Scenario: No matching courses
  Given the search/filter matches no accessible course
  Then an empty state is shown

Scenario: Small-screen rendering
  Given I view the page on a small screen
  Then the competency tree, search, date picker, and expand/collapse remain usable

Designs

Figma Link

Image

Description

Current state

No implementation exists. #623 built only a placeholder Competency Management page (/taxonomy/:taxonomyId/competencies) whose real content is deferred to future tickets; this is one. There is no left-hand competency tree in code yet: #648 designs the shell and that tree, but no implementation ticket builds it, and this is the first ticket that needs a competency actually selected. Studio's existing StudioHome course listing is general and competency-unaware, with no date-range filter and no drill-down into a course's gradeable structure.

Requested change

Build the Manage & Apply Competencies associations workspace: a minimal two-panel layout with a competency-selection tree on the left and the course-browsing panel on the right, driven by the selected competency.

  1. Minimal competency-selection tree (left panel). Render the current taxonomy's competencies as a selectable tree (nested competencies with their codes). Selecting a competency sets the active competency and populates/refreshes the right-hand panel against it. Reuse the existing tag-tree rendering; this is the minimal functional tree, not the finished shell. Expand/collapse polish, switcher styling, empty-state design, and responsive spec are [UXD] Build the UI for Competency Criteria Associations #648's; the Competency ID badge on rows is a separate ticket's. Neither is built here.
  2. Course search with a start-date range filter (right panel). A title search plus a date-range picker, scoped to the selected competency. Use React Date Picker lightly styled with Paragon (Paragon has no native range picker). For MVP the range filters on course-run start date only; make that explicit to the user ("courses whose start date falls between X and Y"). Results come from [BE] Add start-date range filter and outline delivery for accessible courses (Competency Criteria Associations) #669 (paginated accessible courses).
  3. Browse each course's outline. Expanding a course reveals its sections and gradeable subsections (from the course outline — see [BE] Add start-date range filter and outline delivery for accessible courses (Competency Criteria Associations) #669 / CourseIndexView). Sections are navigation; only gradeable subsections are the actionable leaves. For this ticket the subsections are read-only (browse only); making them actionable for association is [FE] Create & View Competency Criteria #672.

Out of scope

Open Questions
  • [non-blocking, owner: architect] Boundary with the [UXD] Build the UI for Competency Criteria Associations #648 shell implementation. [UXD] Build the UI for Competency Criteria Associations #648 is being reframed as a parent UX-design ticket with implementation children, one of which builds the full shell + competency tree. If that shell-implementation child lands, this ticket's minimal tree should be absorbed/superseded by it, not duplicated. Until it exists, the minimal tree lives here. Confirm the intended sequencing so the tree is built once.
  • [BLOCKING, owner: BA] What was this ticket's "different confusion"? An earlier note flagged this ticket for redoing "due to a different confusion" without specifying what. This rewrite assumes it's the course-vs-subsection level correction (associate at gradeable-subsection level; courses/sections are navigation). Confirm before this is treated as final.
  • [BLOCKING, owner: architect/implementer] Where does the outline come from? Either [BE] Add start-date range filter and outline delivery for accessible courses (Competency Criteria Associations) #669 returns outlines inline, or this UI lazily calls the existing CourseIndexView (GET /api/contentstore/v1/course_index/{course_id}) per expanded course. This ticket's data layer should be written to whichever [BE] Add start-date range filter and outline delivery for accessible courses (Competency Criteria Associations) #669 lands on. [recommended: lazy per-course CourseIndexView call on expand — lighter, reuses an existing endpoint]
  • [non-blocking, owner: designer] Figma refresh. The Figma is being updated (date picker representation; removing Programs button / P icon / course-associate button). Low rework risk for the tree/search/outline structure; re-verify the out-of-scope removal list against the refreshed Figma before build.
Context
  • Decision: [UXD] Build the UI for Competency Criteria Associations #648 is being reframed as a parent UX-design ticket with implementation children. Because this is the first ticket that needs a competency selected, the minimal tree + selection belongs here rather than deferred to a later ticket.
  • Decision (MVP): the course filter is on course-run start date only; end-date filtering is deferred. React Date Picker (lightly styled with Paragon) fills the gap since Paragon has no native range picker.
  • Decision: criteria are associated only at the gradeable-subsection level; courses and sections are navigation, not association targets.
  • Competency tree data: the taxonomy tags list API already returns a competency taxonomy's tags (already satisfied, no backend work); the MFE data layer already carries them (TagData via useTagListData in src/taxonomy/data/apiHooks.ts, nested by TagTree in src/taxonomy/tag-list/tagTree.ts). No backend or data-layer change for the tree.
  • CourseIndexView (GET /api/contentstore/v1/course_index/{course_id}, openedx-platform): existing full course-outline endpoint (sections→subsections, with graded flag); the likely per-course outline source.
  • Tree-rendering precedents (frontend; none a drop-in): src/taxonomy/tag-list/tagTree.ts (TagTree nests a taxonomy's tags — the competency tree's basis); src/taxonomy/tree-table/ NestedRows/getSubRows (arbitrary-depth recursion, bundled with tag-CRUD context to strip); src/course-outline/OutlineTree.tsx (real 3-level course tree, hardcoded depth and dnd/XBlock-coupled). Reuse TagTree for the competency tree; borrow the recursion pattern for the course outline.
  • src/generic/datepicker-control/DatepickerControl.jsx (wraps react-datepicker): the single-date picker to compose into a from/to range.
  • [Placeholder for FE] Add Competency Management entry point to taxonomy actions menu #623: the placeholder Competency Management page this workspace lives inside.
Technical Notes

Files to Create

File Purpose
src/taxonomy/competency-management/associations/CompetencyAssociationsPanel.tsx Two-panel container: left competency tree + right course-browse panel; owns the selected-competency state that drives the right panel
src/taxonomy/competency-management/associations/CompetencyTree.tsx Minimal selectable competency tree for the current taxonomy; reuses TagTree/tree-table recursion; emits the selected competency. No ID badge (separate ticket), no CRUD affordances
src/taxonomy/competency-management/course-search/index.ts Public interface exporting the browse panel component
src/taxonomy/competency-management/course-search/CourseSearchBrowse.tsx Search + date-range filter + paginated course list; each row expands to the outline tree; takes the active competency as input
src/taxonomy/competency-management/course-search/CourseOutlineTree.tsx Recursive section→gradeable-subsection renderer; borrows NestedRows' recursion pattern, no TanStack/CRUD context
src/taxonomy/competency-management/*/messages.ts i18n strings
src/taxonomy/competency-management/course-search/data/api.ts getCourseSearchResults(params) (#669), getCourseOutline(courseKey) (CourseIndexView or #669 inline, per decision)
src/taxonomy/competency-management/course-search/data/apiHooks.ts React Query hooks for course search and outline
src/taxonomy/competency-management/course-search/data/queryKeys.ts Query-key factory
src/taxonomy/competency-management/**/*.test.tsx RTL: tree renders + selection drives the panel + nothing rendered for the right-hand column before a selection; search, date filter (start-date semantics), expand, empty/error states

Files to Modify

File Nature
src/taxonomy/competency-management/index.ts Re-export CompetencyAssociationsPanel alongside CompetencyManagementPage (from #623)
the #623 Competency Management page component Mount CompetencyAssociationsPanel as the page's real content, replacing the placeholder

Implementation Notes

Competency tree (minimal). Reuse useTagListData (src/taxonomy/data/apiHooks.ts), which already returns a taxonomy's tags, and TagTree (src/taxonomy/tag-list/tagTree.ts) to render the current taxonomy's competencies as a nested, selectable tree. The taxonomy id comes from the /taxonomy/:taxonomyId/competencies route (#623). Track the selected competency in CompetencyAssociationsPanel state and pass it (tag id / external_id) to the browse panel as its active competency. Keep it minimal: no ID badge (separate ticket), no create/remove or other CRUD affordances, no switcher/empty-state/responsive polish (#648). Until a selection is made, the right panel is not rendered at all: no container, no background, no border, and no placeholder or prompt inside it. The right-hand column mounts only once a competency is selected, and no course query runs before that.

Course browse. Compose two data sources client-side: #669 for the course list (start-date filter, pagination) and the outline per course (lazily on expand, via CourseIndexView unless #669 returns it inline).

Date filter: compose two DatepickerControl instances into a from/to range bound to #669's start-date parameter; label it as filtering on course start date. Don't send an end-date filter (MVP).

Build CourseOutlineTree as a plain recursive component (borrow NestedRows' childRowsData/depth shape; skip its TanStack table and CRUD context). Filter outline nodes to sections (navigation) and gradeable subsections (the actionable leaves) using the outline's graded flag; don't render unit/component levels. Subsections are read-only here and emit nothing: no row click handler and no selection callback. #672 adds its own per-subsection select control to these rows when it lands, calling associateSubsection(objectId, courseId) and hiding that control per subsection according to the author's write access to the course. Neither the course id nor that permission is expressible through an always-on click on the whole row, so do not build one here in anticipation of #672.

MFE-only; no ADR. Reuses frontend-app-authoring conventions (React Query, feature-folder, Paragon, defineMessages).

Example Resolution Prompt

In frontend-app-authoring, build the Competency Criteria associations workspace at src/taxonomy/competency-management/. CompetencyAssociationsPanel.tsx: a two-panel layout that owns the selected-competency state. Left panel CompetencyTree.tsx: render the current taxonomy's competencies (taxonomy id from the /taxonomy/:taxonomyId/competencies route, #623) as a minimal selectable nested tree, reusing useTagListData (src/taxonomy/data/apiHooks.ts) and TagTree (src/taxonomy/tag-list/tagTree.ts); selecting a competency sets it active and drives the right panel; no ID badge (a separate ticket), no CRUD, no shell polish (#648). Right panel course-search/CourseSearchBrowse.tsx: until a competency is selected the whole right-hand column is not rendered at all (no container, background, border, or prompt) and no query runs; once selected, a title search + a from/to date-range filter built from two src/generic/datepicker-control/DatepickerControl.jsx instances, bound to #669's course-search endpoint (accessible courses filtered by course-run start date only; label it as such;). Paginated course list; each row expands. On expand, render CourseOutlineTree.tsx: fetch the course outline (via the existing CourseIndexView, GET /api/contentstore/v1/course_index/{course_id}, unless the team has #669 return it inline — confirm), a plain recursive renderer (model on src/taxonomy/tree-table/NestedRows.tsx's recursion, without its TanStack table or TreeTableContext) showing sections (navigation) and gradeable subsections (read-only leaves, filtered by the outline graded flag). Gradeable subsections are read-only leaves with no click handler and no selection callback; #672 adds its own select control to these rows later. Mount the panel as the #623 page's real content. Do NOT build any backend endpoint, any course-level or section-level association, a Programs button, or a course-associate button. Tests: tree renders and selection drives the panel, nothing rendered for the right-hand column before a selection, title search, start-date filtering, expand-to-outline, empty and error states, small-screen.

Blocked by: #669 (the accessible-courses-by-date endpoint + course outlines) — a TBD contract; wire against it and flag real paths as fill-in-later. The competency tree itself has no new backend dependency — it reuses the existing taxonomy tags list API (a competency is a Tag in a competency taxonomy; that endpoint already returns them).

Repo: frontend-app-authoring. MFE-only. This ticket is #670; the select/deselect-association UI is #672.

Activity

  1. changed the title [-][Placeholder for FE] Build the Course Search and gradeable-subsection browse UI for Competency Criteria Associations[/-] [+][FE] Build the competency-selection tree, Course Search, and gradeable-subsection browse UI for Competency Criteria Associations[/+] on Jul 21, 2026
  2. moved this from Needs additional details to Ready for Community Review in Competency Criteria and Student Progresson Jul 21, 2026
  3. jmakowski1123 commented on Jul 21, 2026

    @jmakowski1123

    @arbrandes This is the main functionality that would be part of the new competency association page. This is the page for admins to go to associate competency tags to content. This is a brand new page. Should it be a new MFE?

  4. moved this from Ready for Community Review to Final Axim Review in Competency Criteria and Student Progresson Jul 28, 2026
  5. thelmick-unicon commented on Jul 28, 2026

    @thelmick-unicon
    Author

    The discussion period for this ticket is now complete, and we appreciate all the feedback. We'll be moving forward with development based on the current ticket pending final Axim sign-off. That said, the conversation doesn't have to stop. If you still have feedback, please continue to add to this ticket. We'll review anything new and determine whether it fits within the current timeline or makes more sense as its own ticket for future work. Thanks again for helping make this better!

    @jmakowski1123 This is ready for your review, thank you!

  6. jmakowski1123 commented on Aug 7, 2026

    @jmakowski1123

    I think the one dependency on this ticket is the set of comments regarding Paragon alignment here.

  7. 20 remaining items

  8. dvarenikqaconsultant commented on Sep 26, 2026

    @dvarenikqaconsultant

    Environment: Master Sandbox, https://apps.master.openedx.io/authoring/taxonomy/45/competencies (taxonomy "QA Competency Taxonomy", type Competency)
    Test users: dmitryvarenikqa (staff) for all scenarios; test670 (no roles, no course access) for the no-access part of scenario 14
    Test type: UI testing. Requests were checked in the browser Network panel, and the error state was produced by blocking the course list request.
    Result: All 15 scenarios from the acceptance criteria pass. Testing found 3 bugs, and they are filed as separate issues (listed at the end of this report).

    Test data

    Beyond the existing sandbox courses, the following courses were created for this ticket:

    Course Start date (UTC) Purpose
    QA670+ALPHA+2026, QA670+BETA+2026, QA670+CONTROL+2026 2026-03-15 Title search
    QA670+DATEIN+2026 2026-03-15 Inside the tested date range
    QA670+DATEOUT+2026 2024-01-10 Outside the tested date range
    QA670+OUTLINE+2026 2026-03-15 Section A holds "Graded Homework 1" (graded) and "Ungraded Reading"; Section B holds only "Ungraded Notes"
    QA670+NOGRADED+2026 2026-03-15 One section with one ungraded subsection

    Competency tree (left panel)

    # Scenario Result Notes
    01 Tree lists the taxonomy's competencies PASS The tree is nested: "Communication" has two sub-competencies and "Critical Thinking" has none.
    02 Selecting a competency drives the right-hand panel PASS Clicking a row with and without sub-competencies behaves the same way. The row gets aria-selected=true, and the right panel opens for that competency.
    03 A competency with sub-competencies is selectable like any other PASS Clicking the "Communication" label, not its arrow, makes it the active competency.
    04 Clicking a row selects it without expanding it PASS "Communication" stays collapsed after its label is clicked.
    05 The expand/collapse control only expands and collapses PASS With "Critical Thinking" selected, the "Communication" arrow expands and collapses the branch. The selection stays on "Critical Thinking", and no new course request is sent.
    06 A row's two controls are separately reachable and distinguishable PASS Tab focuses the row, and Enter or Space selects it without expanding it. The next Tab moves to a separate Expand button, and Enter or Space expands the branch without changing the selection. A screen reader announces the row and the Expand button as two distinct controls.

    Right-hand panel before and after the first selection

    # Scenario Result Notes
    07 No competency selected yet PASS On a freshly opened page the right-hand column is not rendered, and no GET /api/contentstore/v2/home/courses request is sent. Only the feature flag, taxonomy and tag requests go out.
    08 The right-hand column appears on the first selection PASS After a competency is selected, the right column appears with the search field, the "Start Date" button, the "Competency Criteria Associations" block and the paginated course list.

    Course search and date filter

    # Scenario Result Notes
    09 Search courses by title PASS Searching "Alpha" leaves only "QA Search Alpha Course", and Beta and Control disappear. The lowercase query "alpha" gives the same result.
    10 Filter courses by start-date range PASS The range 2026-01-01 to 2026-12-31 is sent as start_date_on_or_after=2026-01-01&start_date_on_or_before=2026-12-31. DATEIN stays in the list and DATEOUT is excluded. With the range 2024-01-01 to 2024-01-31, only DATEOUT is shown. The button is labeled "Start Date", so the UI makes clear which date the filter uses. Changing the range or pressing "Clear dates" returns the list to page 1, and "Clear dates" restores the full list. See bug 1 below for a time zone issue at day boundaries.
    11 Default view shows all accessible courses PASS With no search text and no date range, all accessible courses are shown: 5 pages of 10, which matches count: 50 in the API response.

    Course outline

    12. Expand a course to browse its gradeable subsections: PASS

    • "QA Outline Course" expands into "Section A" and "Section B".
    • Section A shows only "Graded Homework 1". The ungraded subsection "Ungraded Reading" is not shown.
    • Section B has no gradeable subsections, so it is rendered as plain text without an expand arrow.
    • Clicking the course title, both section headers and the subsection does not change the selected competency, the URL or the panel, and no new requests are sent.
    • "QA No Graded Course" and "QA Search Alpha Course" show "This course has no gradeable subsections."

    Error and empty states

    13. Course search fails: PASS

    • With the course list request blocked, a red inline block with role=alert appears with the text "There was a problem loading courses. Please try again."
    • This state differs from "No courses match your search." both in text and in appearance.

    14. No matching courses: PASS

    • As the staff user, the search "zzqq" shows "No courses match your search." with a "Clear search" button.
    • As test670, a user with no course access (the course API returns count: 0), the panel shows "You do not have access to any courses." without a "Clear search" button. For this check the taxonomy was switched to "All organizations" so that a user without roles can open it.

    Small screen

    15. Small-screen rendering: PASS

    • At 800px and 375px wide, the two columns stack vertically and the page has no horizontal scroll.
    • The competency tree, the search field, the "Start Date" button and the expand arrows stay usable at both widths.

    Bugs found

    The following bugs are filed as separate issues:

    1. Date filter compares dates in UTC, while the course page shows the start date in the user's time zone. The course Axim+DC2+2026_T1 starts at 2027-06-30T22:00:00Z, and in the tester's time zone the course page shows July 1, 2027. Filtering by July 1 does not find this course, and filtering by June 30 does. The front end ([FE] Competency Management Course Search/View #670) sends the selected local calendar day, and the back end ([BE] Add start-date range filter and outline delivery for accessible courses (Competency Criteria Associations) #669) interprets it as a UTC day.
    2. The competency tree and course panel columns have no fixed height. The left column ends shorter than the right one. When all competencies are expanded, the left column grows far below the right one and leaves an empty white area next to it. The right column also shrinks when a search returns fewer results. On desktop, both columns should have the same fixed height, sized to hold 10 courses, and the tree should scroll within that height.
    3. Some controls differ from the Paragon components and tokens specified in the design. The "Start Date" button uses the primary/outline-primary variants at the default size with the calendar icon after the label, while the design uses the tertiary variant at small size with the icon before the label. The pagination uses the default size instead of small. The left padding of section cards is 8px instead of spacer/3 (16px). The gap between the search field and the "Start Date" button is 16px instead of 8px. Several hard-coded values also have exact Paragon tokens, for example the card shadow (--pgn-elevation-box-shadow-centered-1) and the search field radius (--pgn-size-border-radius-base).
  9. illiphilli commented on Oct 12, 2026

    @illiphilli

    @thelmick-unicon @AShatsila screenshot refresh only: the trash icons are now ⋮ menus (#775). This replaces the one in the description. It's the same Figma frame.

    Image
  10. moved this from Community Code Review to Ready for QA in Competency Criteria and Student Progresson Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions